Compare commits

...
291 Commits
Author SHA1 Message Date
AndrewandGitHub 0bf07c2703 Update README.md 2024-03-30 13:26:13 +05:30
prafull-opensignlabsandGitHub 10a0c60056 Merge pull request #540 from OpenSignLabs/opensign_drive_move
fix: document list sorting issue on scroll down in opensign-drive issue, disable recipient's list and field after send request
2024-03-28 13:55:06 +05:30
RaktimaNXG 036c9b8d4a fix: open-sign drive sorting issue by name 2024-03-28 12:46:15 +05:30
RaktimaNXG 1f50368259 fix: open-sign drive sorting issue by date and name 2024-03-28 12:30:28 +05:30
RaktimaNXG 6d5e07dac7 fix: sorting issue in open-sign drive 2024-03-28 11:03:54 +05:30
RaktimaNXG 3656175f11 fix: drive details sorting, signature and intial widgets signature url isuue 2024-03-27 20:31:30 +05:30
RaktimaNXG febb50c3cd fix: expired document message 2024-03-27 18:09:06 +05:30
RaktimaNXG f8ba0d357b fix: mismatch between signature URL in the signature widget and the initial widget on the signature pad. 2024-03-27 17:31:11 +05:30
RaktimaNXG 5a25b2d874 fix: disable tour message for completed document 2024-03-27 13:54:12 +05:30
RaktimaNXG d1e7b9a2ab fix: document list sorting issue on scroll down in opensign-drive issue, disable recipient's list and field after send request 2024-03-27 12:19:17 +05:30
AmolandGitHub 60140885e0 Merge pull request #537 from OpenSignLabs/tooltip_pos 2024-03-27 11:12:18 +05:30
prafull-opensignlabs a06723ff3f refactor: reduce size of tooltip and adjust it's position 2024-03-27 11:05:24 +05:30
AmolandGitHub 12a6a84450 Merge pull request #535 from OpenSignLabs/premium_alert 2024-03-26 20:49:51 +05:30
prafull-opensignlabs 1f350fc459 fix: move document to folder in opensigndrive not working 2024-03-26 20:48:41 +05:30
AmolandGitHub d9fd2a5531 Merge pull request #533 from OpenSignLabs/premium_alert 2024-03-26 20:14:41 +05:30
prafull-opensignlabs cd4fd6e3de refactor: change help message of contact report 2024-03-26 19:12:38 +05:30
prafull-opensignlabs 49cd30de96 refactor: update help message 2024-03-26 19:00:51 +05:30
prafull-opensignlabsandGitHub a24ebe25a8 Merge pull request #534 from OpenSignLabs/widget_copy
feat: implement feature of copy widget to next of that widget for any widgets except `signature,text,stamp,initial` widgets.
2024-03-26 18:36:11 +05:30
RaktimaNXG 3e664bf677 fix: checkbox position issue 2024-03-26 17:29:26 +05:30
prafull-opensignlabs 6161e975fb refactor: add help buttons for all sections 2024-03-26 17:03:08 +05:30
RaktimaNXG c2a45c230b fix: widget copy issue in sign-yourself flow 2024-03-26 16:02:03 +05:30
RaktimaNXG a629aa0bff Merge branch 'widget_copy' of https://github.com/OpenSignLabs/OpenSign into widget_copy 2024-03-26 14:42:54 +05:30
RaktimaNXG 899678d98a feat: implement feature of copy widget to next of that widget for any widgets except signature,text,stamp,initial widgets 2024-03-26 14:31:48 +05:30
prafull-opensignlabsandGitHub 076a0f54c5 Merge pull request #522 from OpenSignLabs/signature_pad
fix: change dashboard icon of signyour-self & request sign, add pen color for text signature
2024-03-26 10:48:22 +05:30
RaktimaNXG a94e67cd7c fix:signature pad pen color issue 2024-03-26 10:12:07 +05:30
RaktimaNXG e78a3991f0 fix: remoove unnecessary code 2024-03-26 09:50:46 +05:30
prafull-opensignlabs 593a8499f4 refactor: add premium features warning 2024-03-25 22:12:58 +05:30
AndrewandGitHub 70d643a5e2 Merge pull request #524 from OpenSignLabs/prafull-opensignlabs-patch-5 2024-03-23 19:35:07 +05:30
prafull-opensignlabsandGitHub f2b1a54695 change mongdb url in .env.local_dev 2024-03-23 19:33:14 +05:30
AndrewandGitHub 4353a4f732 Merge pull request #523 from OpenSignLabs/fix_localdocker 2024-03-23 17:38:39 +05:30
RaktimaNXG 34c99edf1a fix: increase text area height on press enter and fix text widget embeding issue on finished button 2024-03-23 17:08:09 +05:30
prafull-opensignlabs 91f3bdb299 fix: issue of cannot post /login in local docker setup 2024-03-23 17:06:40 +05:30
RaktimaNXG 276fc974fa fix: change dashboard icon of signyour-self & request sign,other minor issue fixed 2024-03-22 21:20:49 +05:30
prafull-opensignlabsandGitHub 081e11f9af Merge pull request #518 from OpenSignLabs/send_In_Order
feat: implement of draggable recipient's list to modify recipient's sequence when enable send-in-order during edit document
2024-03-22 18:08:34 +05:30
RaktimaandGitHub 4f056cc9d3 Update RecipientList.js 2024-03-22 18:06:18 +05:30
RaktimaNXG d9da25e908 fix: increase gap between up and down arrow icon 2024-03-22 16:42:51 +05:30
RaktimaNXG 99b3436c8c feat: add up and down key to change sequence of recipient's list 2024-03-22 16:29:08 +05:30
prafull-opensignlabsandGitHub 452d4d7a1d Merge pull request #519 from OpenSignLabs/signyourself-textinput
fix: change text-input widget to text in signyour-self flow
2024-03-22 12:46:52 +05:30
RaktimaNXG ed613c3424 fix: set default option field value oftextInput widget issue in signyourself 2024-03-22 12:30:53 +05:30
RaktimaNXG bf70fa0b11 fix: drag icon image select issue in ios 2024-03-22 12:01:27 +05:30
RaktimaNXG 8684197d49 fix: drag icon image select issue in ios 2024-03-22 11:55:55 +05:30
RaktimaNXG 648d1224b3 fix: disable default menu open on press on drag icon in mobile view 2024-03-21 18:30:46 +05:30
RaktimaNXG 126b6ad355 fix: change text-input widget to text in signyour-self flow 2024-03-21 18:01:02 +05:30
RaktimaNXG 0512f27e2e change drag icon 2024-03-21 17:41:48 +05:30
prafull-opensignlabsandGitHub 2c61630017 Update signature.css 2024-03-21 17:19:25 +05:30
prafull-opensignlabsandGitHub 72c2b2dde6 change size of custom cursor icon 2024-03-21 17:11:56 +05:30
prafull-opensignlabsandGitHub 29eb78c960 Update signature.css 2024-03-21 17:01:18 +05:30
prafull-opensignlabsandGitHub aa9ba05dde Update move cursor icon 2024-03-21 16:45:28 +05:30
RaktimaNXG 365b074f62 fix: change default value of send in order,dragging functionality to change sequence of signers list in mobile 2024-03-21 16:08:07 +05:30
RaktimaNXG af6cb4c17d feat: implement dragging functionality on recipient's list to modify sequence of send-in-order during edit document 2024-03-21 12:39:00 +05:30
prafull-opensignlabsandGitHub 6bcad91b0f Merge pull request #517 from OpenSignLabs/openSign_drive
feat: updated draft document query
2024-03-20 19:16:46 +05:30
RaktimaNXG 1aa2b003b2 feat: updated draft document query 2024-03-20 19:14:20 +05:30
prafull-opensignlabsandGitHub 1a27e9addf Merge pull request #515 from OpenSignLabs/openSign_drive
fix: data fetching issue in openSign_drive
2024-03-20 18:21:20 +05:30
RaktimaNXG c2891a0858 refactor code 2024-03-20 16:43:56 +05:30
RaktimaNXG c1b226db96 fix: handle condition of fetching opensign details 2024-03-20 15:59:06 +05:30
RaktimaNXG 62e1a1bd9b fix: refactor code 2024-03-20 15:02:08 +05:30
RaktimaNXG 58eb71c52d fix: refactor code 2024-03-20 14:50:48 +05:30
RaktimaNXG c1e6f2b5ab add comment 2024-03-20 12:49:07 +05:30
RaktimaNXG ba0c18b591 fix: data fetching issue in openSign_drive 2024-03-20 12:38:34 +05:30
prafull-opensignlabsandGitHub c3a902dcc7 Merge pull request #514 from OpenSignLabs/unuse_package
Refactor: remove warning
2024-03-20 11:40:46 +05:30
prafull-opensignlabs 5ece3c0694 Refactor: remov warning 2024-03-20 11:38:15 +05:30
AmolandGitHub 1053540410 Merge pull request #513 from OpenSignLabs/unuse_package 2024-03-20 11:14:09 +05:30
prafull-opensignlabs 24773759c2 Refactor: Add LazyPage Component for Lazy Loading of Pages & update dependcies 2024-03-20 11:11:37 +05:30
AmolandGitHub 7a6de70169 Merge pull request #510 from OpenSignLabs/unuse_package 2024-03-19 19:52:34 +05:30
prafull-opensignlabs 04b2c7c4da build(deps): update dependencies 2024-03-19 19:51:20 +05:30
AmolandGitHub d11171e91c Merge pull request #508 from OpenSignLabs/migrate_redux 2024-03-19 18:52:44 +05:30
prafull-opensignlabs a4a78cb96c fix: stuck on loader in login screen after guest login 2024-03-19 18:51:04 +05:30
prafull-opensignlabs dfdcde8fcc Refactor: Implement Lazy Loading for OpenSign Drive 2024-03-19 18:03:13 +05:30
prafull-opensignlabs 5e1b84d2e6 refactor: migrate redux to redux-toolkit 2024-03-19 17:29:48 +05:30
prafull-opensignlabsandGitHub e643d96797 Merge pull request #506 from OpenSignLabs/api_signembed
fix: handle uncaught error in createdocument and createmplate API
2024-03-19 13:24:05 +05:30
prafull-opensignlabs 1ff4160ca4 fix: handle uncaught error in createdocument and createmplate API 2024-03-19 13:23:10 +05:30
prafull-opensignlabsandGitHub 62f66bf524 Merge pull request #505 from OpenSignLabs/api_signembed
fix: widgets are not embedding in pdf using API
2024-03-19 13:12:46 +05:30
prafull-opensignlabs de3bc37fa5 fix: widgets are not embeding in pdf using API 2024-03-19 13:11:23 +05:30
AmolandGitHub ea660384c3 Merge pull request #504 from OpenSignLabs/prafull-opensignlabs-patch-4
chore: Update mongo url in local env
2024-03-19 12:01:08 +05:30
prafull-opensignlabsandGitHub 210cb5e754 chore: Update mongo url in local env 2024-03-19 12:00:28 +05:30
AmolandGitHub ed45bfef84 Merge pull request #503 from OpenSignLabs/prafull-opensignlabs-patch-1 2024-03-19 10:59:23 +05:30
prafull-opensignlabsandGitHub a8e77e93f7 chore: change serverURL 2024-03-19 10:58:32 +05:30
prafull-opensignlabsandGitHub 969071bb28 Merge pull request #501 from OpenSignLabs/placeholder_sign
fix: show warning on placeholder_sign page for document already send to signers for signature
2024-03-19 10:29:33 +05:30
RaktimaNXG 76491a77f1 fix: add comment 2024-03-19 10:27:41 +05:30
AmolandGitHub 9a51eed2bc Merge pull request #502 from OpenSignLabs/fix_maxupload 2024-03-19 10:09:48 +05:30
prafull-opensignlabs a675a3c8fd refactor: change console dir to console log 2024-03-18 19:49:13 +05:30
prafull-opensignlabs fea30930eb fix: handle uncaught err of max upload pdf in form 2024-03-18 19:47:56 +05:30
RaktimaNXG 7373b086e4 fix: change warning messages 2024-03-18 19:00:02 +05:30
RaktimaNXG 2fc1eda761 fix: remove console 2024-03-18 18:22:14 +05:30
RaktimaNXG 2c100ad399 fix: show warning on placeholder_sign page for document already send to signers for signature 2024-03-18 17:40:27 +05:30
prafull-opensignlabsandGitHub 1cefe01aee Merge pull request #499 from OpenSignLabs/fix_mobile_issue
fix:  width issue of text widget & default data for widgets information pop-ups in mobile display.
2024-03-18 17:09:17 +05:30
RaktimaNXG f1cf395761 fix: textInput widget popup select arrow key design 2024-03-18 17:05:15 +05:30
RaktimaNXG 4af3d8f78b fix: dragging issue of text widget in mobile view 2024-03-18 16:21:14 +05:30
AmolandGitHub cf21ac7405 Merge pull request #500 from OpenSignLabs/fix_Smtp 2024-03-18 15:16:27 +05:30
prafull-opensignlabs 5f11e92c0c fix: handle uncaught error of SMTP 2024-03-18 15:14:23 +05:30
RaktimaNXG c3ffda4dd2 fix: resolving width inconsistencies with of text widgets & default data for widgets information pop-ups in mobile display. 2024-03-18 12:45:08 +05:30
AmolandGitHub c929b6b7a9 Update Dockerhubfile 2024-03-18 00:19:06 +05:30
AmolandGitHub eb2abd3e6d Merge pull request #493 from OpenSignLabs/widget_modal 2024-03-15 19:33:53 +05:30
prafull-opensignlabs 1c4c2e87b4 refactor: change design of widgets in mobile 2024-03-15 19:30:33 +05:30
prafull-opensignlabs 4fda5b4531 refactor: stop showing initial popup when wdigets drag 2024-03-15 19:04:02 +05:30
AmolandGitHub df61e143af Merge pull request #492 from OpenSignLabs/update_menu 2024-03-15 14:27:06 +05:30
prafull-opensignlabs 3a55c35445 feat: add create document btn in dashboard, update menu & change Root to Opensign™ drive in folder input 2024-03-15 14:25:50 +05:30
prafull-opensignlabsandGitHub 08476ba3d6 Merge pull request #490 from OpenSignLabs/feat_label
fix: date is not changable in signyourself flow of mobile
2024-03-14 21:40:40 +05:30
prafull-opensignlabs db9ae71d67 fix: date is not changable in signyourself flow of mobile 2024-03-14 21:39:22 +05:30
prafull-opensignlabsandGitHub 39806e3ad6 Merge pull request #489 from OpenSignLabs/feat_label
fix: checkbox not embeding in pdf
2024-03-14 21:25:18 +05:30
prafull-opensignlabs 7882c61b81 fix: checkbox not embeding in pdf 2024-03-14 21:22:48 +05:30
AndrewandGitHub b8f886902f Merge pull request #488 from OpenSignLabs/feat_label 2024-03-14 20:38:38 +05:30
prafull-opensignlabs 17660dae21 fix: border of radio button & checkbox is not proper 2024-03-14 20:12:41 +05:30
prafull-opensignlabs 7584667643 fix: when click on label in radio or checkbox widget it's border not visible 2024-03-14 18:35:40 +05:30
AndrewandGitHub b47d1cff07 Merge pull request #487 from OpenSignLabs/feat_label 2024-03-14 17:00:22 +05:30
prafull-opensignlabs b99d8e6d6e feat: add show/hide label in checkbox and radio widget 2024-03-14 16:50:46 +05:30
prafull-opensignlabsandGitHub 8b15bceac8 Merge pull request #472 from OpenSignLabs/signature_setting
fix: already placed signature widget setting icon issue with old data
2024-03-14 10:04:24 +05:30
RaktimaNXG 86b0e90948 fix: date z-index and default data of email,name,company name, job title widgets in guest login flow 2024-03-13 20:25:18 +05:30
prafull-opensignlabsandGitHub 3bc57a999c Merge pull request #486 from OpenSignLabs/fix_formreset
fix: reset button not working in forms
2024-03-13 20:18:33 +05:30
prafull-opensignlabs 27730c89e8 fix: signers not get reset in request signature form on reset button 2024-03-13 20:17:22 +05:30
prafull-opensignlabs 82eeffa6e4 fix: reset button not working in forms 2024-03-13 18:36:24 +05:30
RaktimaNXG 53147caebc fix: checkbox checked issue in signyour-self flow 2024-03-13 17:47:31 +05:30
RaktimaNXG 6004522d5c feat: change radio widgets name radio to radio button 2024-03-13 16:36:03 +05:30
AndrewandGitHub 266c2463c9 Merge pull request #485 from OpenSignLabs/update_tour 2024-03-13 15:19:55 +05:30
prafull-opensignlabs 1b215f53e7 feat: add help for select folder input 2024-03-13 15:17:04 +05:30
RaktimaNXG 73b2ba6abd fix: default date issue and remove commented code, unnecessary using useEffect 2024-03-13 14:30:25 +05:30
RaktimaNXG c04fd80a38 feat: change label widget name to text and text widget name to text input 2024-03-13 11:40:17 +05:30
prafull-opensignlabs 61b123cb61 refator: update dashboard tour messages 2024-03-13 10:31:49 +05:30
RaktimaNXG 08e805569f fix: disable date change in placeholder and template flow 2024-03-13 09:56:59 +05:30
RaktimaNXG 375aa0b7e7 fix: invalid date issue for indian format 2024-03-12 20:02:11 +05:30
RaktimaNXG b94e0fa052 refactor: change order of minimum & maximum input in checkbox setting 2024-03-12 16:50:50 +05:30
prafull-opensignlabsandGitHub b6752549ed Merge pull request #484 from OpenSignLabs/fix_e_sign
fix: E-sign is not available in completed document
2024-03-11 17:42:40 +05:30
prafull-opensignlabs 51505af6d8 fix: E-sign is not available in completed document 2024-03-11 17:35:20 +05:30
RaktimaNXG 0e5cffa1fa fix: widgets issue after placing on multiple pages 2024-03-11 16:59:10 +05:30
RaktimaNXG 885b5287b4 fix: condition of render setting icon for widgets 2024-03-08 18:39:02 +05:30
RaktimaNXG 5348c6620a fix: signature widget setting icon for placed with old data 2024-03-08 17:51:00 +05:30
prafull-opensignlabsandGitHub 73c219fa4d Merge pull request #470 from OpenSignLabs/date_issue
feat: year and month selection feature add on date widgets, wrong date embed on pdf issue fix
2024-03-08 17:00:30 +05:30
RaktimaNXG f4090c0c61 fix: label widgets hint, date default format issue 2024-03-08 16:57:43 +05:30
RaktimaNXG cd2be94d29 fix: change template react-tour message 2024-03-08 16:40:22 +05:30
prafull-opensignlabsandGitHub 878dca3cd6 Merge pull request #471 from OpenSignLabs/fix_signing_alert
fix: signing alert for send in order
2024-03-08 16:37:22 +05:30
prafull-opensignlabsandGitHub 90cba26904 fix: signing alert for send in order 2024-03-08 16:29:30 +05:30
RaktimaNXG c5c001f030 feat: year and month selection feature add on date widgets, wrong date embed on pdf issue fix 2024-03-08 16:21:54 +05:30
prafull-opensignlabsandGitHub a3ba4e26c3 Merge pull request #469 from OpenSignLabs/fix_managesign
fix: signature not saving in managesign
2024-03-08 14:58:08 +05:30
prafull-opensignlabs dd95862d5a refactor: remove unncessary code 2024-03-08 14:57:20 +05:30
prafull-opensignlabs 5d3de41e63 fix: signature not saving in managesign 2024-03-08 14:51:31 +05:30
prafull-opensignlabsandGitHub 5cad0a96cd Merge pull request #465 from OpenSignLabs/remove_mfcra
fix: already placed signature for signers signature embed issue in pdf
2024-03-08 11:04:35 +05:30
AndrewandGitHub e74fd79efc Merge pull request #467 from OpenSignLabs/prafull-opensignlabs-patch-3 2024-03-08 10:42:34 +05:30
prafull-opensignlabsandGitHub 6f49fc9126 fix: update Ip address to allow masterkey 2024-03-08 10:41:03 +05:30
prafull-opensignlabsandGitHub bbf3cc2f44 Merge pull request #466 from OpenSignLabs/dependabot/npm_and_yarn/apps/OpenSign/react-router-dom-6.22.3
build(deps): bump react-router-dom from 6.16.0 to 6.22.3 in /apps/OpenSign
2024-03-08 10:24:32 +05:30
prafull-opensignlabsandGitHub 7bf196ef75 Merge pull request #447 from OpenSignLabs/dependabot/npm_and_yarn/apps/OpenSign/reduxjs/toolkit-2.2.1
build(deps): bump @reduxjs/toolkit from 1.9.7 to 2.2.1 in /apps/OpenSign
2024-03-08 10:23:47 +05:30
prafull-opensignlabsandGitHub 4b5b3aff49 Merge pull request #458 from OpenSignLabs/dependabot/npm_and_yarn/apps/OpenSignServer/aws-sdk-2.1569.0
build(deps): bump aws-sdk from 2.1475.0 to 2.1569.0 in /apps/OpenSignServer
2024-03-08 10:21:05 +05:30
prafull-opensignlabsandGitHub 15b0cb132c Merge pull request #464 from OpenSignLabs/dependabot/npm_and_yarn/apps/OpenSignServer/npm_and_yarn-security-group-df030c3c04
build(deps): bump the npm_and_yarn group group in /apps/OpenSignServer with 7 updates
2024-03-08 10:18:57 +05:30
RaktimaNXG e67f91ea90 fix: remove console log 2024-03-08 10:10:16 +05:30
dependabot[bot]andGitHub 59350f02fb build(deps): bump react-router-dom in /apps/OpenSign
Bumps [react-router-dom](https://github.com/remix-run/react-router/tree/HEAD/packages/react-router-dom) from 6.16.0 to 6.22.3.
- [Release notes](https://github.com/remix-run/react-router/releases)
- [Changelog](https://github.com/remix-run/react-router/blob/main/packages/react-router-dom/CHANGELOG.md)
- [Commits](https://github.com/remix-run/react-router/commits/react-router-dom@6.22.3/packages/react-router-dom)

---
updated-dependencies:
- dependency-name: react-router-dom
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-03-08 04:31:40 +00:00
prafull-opensignlabsandGitHub 32cde66d64 Merge pull request #456 from OpenSignLabs/dependabot/npm_and_yarn/apps/OpenSign/autoprefixer-10.4.18
build(deps-dev): bump autoprefixer from 10.4.16 to 10.4.18 in /apps/OpenSign
2024-03-08 10:01:24 +05:30
prafull-opensignlabsandGitHub 7ba111a275 Merge pull request #445 from OpenSignLabs/dependabot/npm_and_yarn/apps/OpenSign/react-select-5.8.0
build(deps): bump react-select from 5.7.7 to 5.8.0 in /apps/OpenSign
2024-03-08 10:00:42 +05:30
dependabot[bot]andGitHub 8d3fa6cef8 build(deps): bump the npm_and_yarn group group
Bumps the npm_and_yarn group group in /apps/OpenSignServer with 7 updates:

| Package | From | To |
| --- | --- | --- |
| [parse-server](https://github.com/parse-community/parse-server) | `6.3.1` | `6.5.0` |
| [jsonwebtoken](https://github.com/auth0/node-jsonwebtoken) | `8.5.1` | `9.0.0` |
| [follow-redirects](https://github.com/follow-redirects/follow-redirects) | `1.15.2` | `1.15.5` |
| [es5-ext](https://github.com/medikoo/es5-ext) | `0.10.62` | `0.10.64` |
| [graphql](https://github.com/graphql/graphql-js) | `16.6.0` | `16.8.1` |
| [ip](https://github.com/indutny/node-ip) | `2.0.0` | `2.0.1` |
| [jose](https://github.com/panva/jose) | `2.0.6` | `4.15.5` |


Updates `parse-server` from 6.3.1 to 6.5.0
- [Release notes](https://github.com/parse-community/parse-server/releases)
- [Changelog](https://github.com/parse-community/parse-server/blob/alpha/CHANGELOG.md)
- [Commits](https://github.com/parse-community/parse-server/compare/6.3.1...6.5.0)

Updates `jsonwebtoken` from 8.5.1 to 9.0.0
- [Changelog](https://github.com/auth0/node-jsonwebtoken/blob/master/CHANGELOG.md)
- [Commits](https://github.com/auth0/node-jsonwebtoken/compare/v8.5.1...v9.0.0)

Updates `follow-redirects` from 1.15.2 to 1.15.5
- [Release notes](https://github.com/follow-redirects/follow-redirects/releases)
- [Commits](https://github.com/follow-redirects/follow-redirects/compare/v1.15.2...v1.15.5)

Updates `es5-ext` from 0.10.62 to 0.10.64
- [Release notes](https://github.com/medikoo/es5-ext/releases)
- [Changelog](https://github.com/medikoo/es5-ext/blob/main/CHANGELOG.md)
- [Commits](https://github.com/medikoo/es5-ext/compare/v0.10.62...v0.10.64)

Updates `graphql` from 16.6.0 to 16.8.1
- [Release notes](https://github.com/graphql/graphql-js/releases)
- [Commits](https://github.com/graphql/graphql-js/compare/v16.6.0...v16.8.1)

Updates `ip` from 2.0.0 to 2.0.1
- [Commits](https://github.com/indutny/node-ip/compare/v2.0.0...v2.0.1)

Updates `jose` from 2.0.6 to 4.15.5
- [Release notes](https://github.com/panva/jose/releases)
- [Changelog](https://github.com/panva/jose/blob/v4.15.5/CHANGELOG.md)
- [Commits](https://github.com/panva/jose/compare/v2.0.6...v4.15.5)

---
updated-dependencies:
- dependency-name: parse-server
  dependency-type: direct:production
  dependency-group: npm_and_yarn-security-group
- dependency-name: jsonwebtoken
  dependency-type: indirect
  dependency-group: npm_and_yarn-security-group
- dependency-name: follow-redirects
  dependency-type: indirect
  dependency-group: npm_and_yarn-security-group
- dependency-name: es5-ext
  dependency-type: indirect
  dependency-group: npm_and_yarn-security-group
- dependency-name: graphql
  dependency-type: indirect
  dependency-group: npm_and_yarn-security-group
- dependency-name: ip
  dependency-type: indirect
  dependency-group: npm_and_yarn-security-group
- dependency-name: jose
  dependency-type: indirect
  dependency-group: npm_and_yarn-security-group
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-03-08 04:30:29 +00:00
RaktimaNXG ef7aede146 fix: already placed signature for signers signature embed issue in pdf 2024-03-08 10:00:28 +05:30
prafull-opensignlabsandGitHub 11ae58aad3 Merge pull request #459 from OpenSignLabs/dependabot/npm_and_yarn/apps/OpenSignServer/nodemailer-6.9.11
build(deps): bump nodemailer from 6.9.7 to 6.9.11 in /apps/OpenSignServer
2024-03-08 09:58:58 +05:30
prafull-opensignlabsandGitHub 05e30a5d19 Merge pull request #437 from OpenSignLabs/dependabot/npm_and_yarn/apps/OpenSignServer/mongoose-8.2.0
build(deps): bump mongoose from 8.1.3 to 8.2.0 in /apps/OpenSignServer
2024-03-08 09:54:46 +05:30
prafull-opensignlabsandGitHub 64773cafec Merge pull request #436 from OpenSignLabs/dependabot/npm_and_yarn/apps/OpenSignServer/parse-server-api-mail-adapter-3.1.1
build(deps): bump parse-server-api-mail-adapter from 3.0.0 to 3.1.1 in /apps/OpenSignServer
2024-03-08 09:53:49 +05:30
prafull-opensignlabsandGitHub c6be39ffc3 Merge pull request #435 from OpenSignLabs/dependabot/npm_and_yarn/apps/OpenSignServer/nodemon-3.1.0
build(deps-dev): bump nodemon from 2.0.22 to 3.1.0 in /apps/OpenSignServer
2024-03-08 09:51:24 +05:30
AndrewandGitHub 376d4293c2 Merge pull request #462 from OpenSignLabs/remove_mfcra 2024-03-07 19:28:21 +05:30
prafull-opensignlabs 67b3752297 fix: print button not working, declined popup should be at top 2024-03-07 19:04:50 +05:30
prafull-opensignlabs f463ffc8ed fix: old gustlogin not wowrking 2024-03-07 18:35:22 +05:30
prafull-opensignlabs 6e2aac51b4 fix: change appId of server 2024-03-07 17:21:43 +05:30
dependabot[bot]andGitHub a9a3c25dfd build(deps): bump react-select from 5.7.7 to 5.8.0 in /apps/OpenSign
Bumps [react-select](https://github.com/JedWatson/react-select) from 5.7.7 to 5.8.0.
- [Release notes](https://github.com/JedWatson/react-select/releases)
- [Changelog](https://github.com/JedWatson/react-select/blob/master/docs/CHANGELOG.md)
- [Commits](https://github.com/JedWatson/react-select/compare/react-select@5.7.7...react-select@5.8.0)

---
updated-dependencies:
- dependency-name: react-select
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-03-07 11:19:40 +00:00
dependabot[bot]andGitHub 645898ab14 build(deps): bump @reduxjs/toolkit from 1.9.7 to 2.2.1 in /apps/OpenSign
Bumps [@reduxjs/toolkit](https://github.com/reduxjs/redux-toolkit) from 1.9.7 to 2.2.1.
- [Release notes](https://github.com/reduxjs/redux-toolkit/releases)
- [Commits](https://github.com/reduxjs/redux-toolkit/compare/v1.9.7...v2.2.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-03-07 11:18:24 +00:00
AndrewandGitHub 3ad1c46455 Merge pull request #461 from OpenSignLabs/remove_mfcra 2024-03-07 16:47:28 +05:30
prafull-opensignlabs d3d33c85d9 fix: date is not visible in templateplaceholer 2024-03-07 16:44:02 +05:30
prafull-opensignlabs c2796f66fb fix: add default value for checkbox in templateplaceholder & change tour message in self sign 2024-03-07 15:09:56 +05:30
prafull-opensignlabs f57fcd25c9 fix: change randomId generator 2024-03-07 13:20:26 +05:30
prafull-opensignlabs 9bda7dee7f refactor: update components 2024-03-07 12:56:15 +05:30
prafull-opensignlabs 7e1f21b02b refactor: dropbox file path correction 2024-03-06 19:20:55 +05:30
prafull-opensignlabs a83acabf1a refactor: remove unncessary images and organize folders 2024-03-06 19:18:58 +05:30
prafull-opensignlabs fb99c76b0c refactor: replace name of folder from routes to pages & remove unncessary css 2024-03-06 14:24:41 +05:30
prafull-opensignlabs cc0ff1f5e7 refactor: remove mulitple initialization of parse 2024-03-06 12:56:08 +05:30
prafull-opensignlabs afbfd9ed43 refactor: remove unnecessary component 2024-03-06 11:08:42 +05:30
prafull-opensignlabs fcad04461f refactor: remove microfrontend 2024-03-05 21:33:07 +05:30
prafull-opensignlabs ca98b5a210 refactor: remove mf-cra & change routes 2024-03-05 21:21:45 +05:30
RaktimaNXG bd72ef84ed fix: checkbox default options issue, add default data functionality, fix checbox position issue signyour-self flow,change sequence of widgets 2024-03-04 09:58:53 +05:30
dependabot[bot]andGitHub cb3c62fb6c build(deps): bump nodemailer in /apps/OpenSignServer
Bumps [nodemailer](https://github.com/nodemailer/nodemailer) from 6.9.7 to 6.9.11.
- [Release notes](https://github.com/nodemailer/nodemailer/releases)
- [Changelog](https://github.com/nodemailer/nodemailer/blob/master/CHANGELOG.md)
- [Commits](https://github.com/nodemailer/nodemailer/compare/v6.9.7...v6.9.11)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-03-04 01:26:05 +00:00
dependabot[bot]andGitHub 2976220e4d build(deps): bump aws-sdk in /apps/OpenSignServer
Bumps [aws-sdk](https://github.com/aws/aws-sdk-js) from 2.1475.0 to 2.1569.0.
- [Release notes](https://github.com/aws/aws-sdk-js/releases)
- [Commits](https://github.com/aws/aws-sdk-js/compare/v2.1475.0...v2.1569.0)

---
updated-dependencies:
- dependency-name: aws-sdk
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-03-04 01:25:19 +00:00
dependabot[bot]andGitHub 192371c07b build(deps-dev): bump autoprefixer in /apps/OpenSign
Bumps [autoprefixer](https://github.com/postcss/autoprefixer) from 10.4.16 to 10.4.18.
- [Release notes](https://github.com/postcss/autoprefixer/releases)
- [Changelog](https://github.com/postcss/autoprefixer/blob/main/CHANGELOG.md)
- [Commits](https://github.com/postcss/autoprefixer/compare/10.4.16...10.4.18)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-03-04 01:02:47 +00:00
RaktimaNXG 708a3f4ad9 Merge branch 'staging' of https://github.com/OpenSignLabs/OpenSign into feat_widget 2024-03-02 14:46:42 +05:30
RaktimaNXG fbcdfa97cf fix: text input widgets issue after set default values 2024-03-02 11:57:35 +05:30
RaktimaNXG 4e39762b46 feat: add default value validation of regex 2024-03-01 17:04:08 +05:30
RaktimaNXG 4239e8d5fb fix: import useEffect issue 2024-02-29 17:58:32 +05:30
RaktimaNXG c8ee455865 feat: add name, default value and status for widgets in placeholder and template flow 2024-02-29 17:53:30 +05:30
RaktimaNXG d5be7b8c57 fix: input text type regex issue 2024-02-29 16:23:08 +05:30
RaktimaNXG bc2f4f1ef3 feat: implement validation for checkbox min and max count and resolve issue of embed chebox position 2024-02-29 12:26:15 +05:30
RaktimaNXG e72baf3c1f fix: uncommented funtion of signpdf 2024-02-28 20:54:16 +05:30
RaktimaNXG b2b52b6af7 fix: checkbox optional type issue 2024-02-28 20:48:27 +05:30
AmolandGitHub 4f417ccf0f Merge pull request #452 from OpenSignLabs/fix_filename_form 2024-02-28 18:26:44 +05:30
prafull-opensignlabsandGitHub 780c3f5f6d fix: file name is not visible in form for local development 2024-02-28 18:22:14 +05:30
RaktimaNXG f9eff12f94 feat: implement multiple checkbox feature , hint for input placeholder,dd/mm/yyyy format ,fix isssue of user details popup open onclick widgets 2024-02-28 15:56:42 +05:30
dependabot[bot]andGitHub e912a8d4e0 build(deps): bump mongoose from 8.1.3 to 8.2.0 in /apps/OpenSignServer
Bumps [mongoose](https://github.com/Automattic/mongoose) from 8.1.3 to 8.2.0.
- [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.1.3...8.2.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-02-26 00:44:17 +00:00
dependabot[bot]andGitHub 224af292d6 build(deps): bump parse-server-api-mail-adapter in /apps/OpenSignServer
Bumps [parse-server-api-mail-adapter](https://github.com/parse-community/parse-server-api-mail-adapter) from 3.0.0 to 3.1.1.
- [Release notes](https://github.com/parse-community/parse-server-api-mail-adapter/releases)
- [Changelog](https://github.com/parse-community/parse-server-api-mail-adapter/blob/release/CHANGELOG.md)
- [Commits](https://github.com/parse-community/parse-server-api-mail-adapter/compare/3.0.0...3.1.1)

---
updated-dependencies:
- dependency-name: parse-server-api-mail-adapter
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-02-26 00:43:56 +00:00
dependabot[bot]andGitHub e07a4457ec build(deps-dev): bump nodemon in /apps/OpenSignServer
Bumps [nodemon](https://github.com/remy/nodemon) from 2.0.22 to 3.1.0.
- [Release notes](https://github.com/remy/nodemon/releases)
- [Commits](https://github.com/remy/nodemon/compare/v2.0.22...v3.1.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-02-26 00:43:42 +00:00
AmolandGitHub 58cd0495e6 Merge pull request #434 from OpenSignLabs/prafull-opensignlabs-patch-2
Update Dockerhubfile
2024-02-23 16:04:15 +05:30
prafull-opensignlabsandGitHub 6b9b2afbef Update Dockerhubfile 2024-02-23 16:03:48 +05:30
AmolandGitHub c55a8d09a2 Merge pull request #433 from OpenSignLabs/prafull-opensignlabs-patch-11
Update Dockerhubfile
2024-02-23 15:36:27 +05:30
prafull-opensignlabsandGitHub 71b06f92ec Update Dockerhubfile 2024-02-23 15:36:11 +05:30
AmolandGitHub 692ec8ecbf Merge pull request #432 from OpenSignLabs/revert-431-fix_server_route
Revert "fix: mount server app on /api for local development"
2024-02-23 14:31:14 +05:30
AmolandGitHub 523ea7f314 Revert "fix: mount server app on /api for local development" 2024-02-23 14:31:00 +05:30
AmolandGitHub f48444f21d Merge pull request #431 from OpenSignLabs/fix_server_route 2024-02-23 12:37:31 +05:30
prafull-opensignlabs b4c5b3cbe6 fix: mount server app on /api for local development 2024-02-23 12:34:24 +05:30
AndrewandGitHub ed88ae013d Merge pull request #429 from OpenSignLabs/prafull-opensignlabs-patch-9 2024-02-23 11:02:30 +05:30
RaktimaNXG 0fe7937808 fix: input regex validation issue 2024-02-23 09:50:15 +05:30
prafull-opensignlabsandGitHub 564f57b879 Update Dockerfile 2024-02-22 20:19:35 +05:30
prafull-opensignlabsandGitHub a47dc8e767 Update Dockerfile 2024-02-22 20:19:17 +05:30
prafull-opensignlabsandGitHub 41e192acb0 Update Dockerhubfile 2024-02-22 20:18:59 +05:30
prafull-opensignlabsandGitHub ff4fb191b8 Update Dockerhubfile 2024-02-22 20:18:42 +05:30
AndrewandGitHub 2feee80168 Merge pull request #428 from OpenSignLabs/prafull-opensignlabs-patch-9 2024-02-22 20:15:49 +05:30
prafull-opensignlabsandGitHub 59fed8a9cc Update Dockerhubfile 2024-02-22 20:15:02 +05:30
AndrewandGitHub 7cfca0a650 Merge pull request #427 from OpenSignLabs/prafull-opensignlabs-patch-9 2024-02-22 20:12:39 +05:30
prafull-opensignlabsandGitHub 6f1a5fd3a9 Update package.json 2024-02-22 20:11:49 +05:30
prafull-opensignlabsandGitHub cd6869778a Update package.json 2024-02-22 20:11:18 +05:30
AndrewandGitHub 2e8d84430e Merge pull request #426 from OpenSignLabs/prafull-opensignlabs-patch-9 2024-02-22 20:08:32 +05:30
prafull-opensignlabsandGitHub b8f32a6d8d Update Dockerhubfile 2024-02-22 20:08:10 +05:30
prafull-opensignlabsandGitHub 11ab37baf1 Update package.json 2024-02-22 20:05:47 +05:30
AndrewandGitHub 9dbde43a44 Merge pull request #425 from OpenSignLabs/prafull-opensignlabs-patch-8 2024-02-22 19:43:53 +05:30
prafull-opensignlabsandGitHub 2a24d71ee3 Update Dockerhubfile 2024-02-22 19:43:23 +05:30
prafull-opensignlabsandGitHub 134444c20a chore: add build command for docker-hub 2024-02-22 19:40:52 +05:30
AndrewandGitHub 44b87f178e Merge pull request #423 from OpenSignLabs/prafull-opensignlabs-patch-6 2024-02-22 18:49:32 +05:30
AndrewandGitHub 666636d554 Merge pull request #424 from OpenSignLabs/prafull-opensignlabs-patch-7 2024-02-22 18:49:20 +05:30
prafull-opensignlabsandGitHub 5ec9d59382 Update Dockerhubfile 2024-02-22 18:48:36 +05:30
prafull-opensignlabsandGitHub addc7622ab Create Dockerhubfile 2024-02-22 18:46:43 +05:30
prafull-opensignlabsandGitHub 1c7c3a4777 Create Dockerhubfile 2024-02-22 18:44:07 +05:30
prafull-opensignlabsandGitHub 2a46b02487 Update Docker.yml 2024-02-22 18:40:21 +05:30
AndrewandGitHub 5974515362 Merge pull request #422 from OpenSignLabs/prafull-opensignlabs-patch-5 2024-02-22 18:31:43 +05:30
prafull-opensignlabsandGitHub 3fab1d9c6f Update Docker.yml 2024-02-22 18:30:57 +05:30
AndrewandGitHub a283f2ee5d Merge pull request #418 from OpenSignLabs/prafull-opensignlabs-patch-2 2024-02-22 18:25:07 +05:30
AmolandGitHub 934823fad4 Merge pull request #419 from OpenSignLabs/prafull-opensignlabs-patch-2-1 2024-02-22 18:24:43 +05:30
AmolandGitHub 351ed795ca Merge pull request #420 from OpenSignLabs/prafull-opensignlabs-patch-3 2024-02-22 18:24:32 +05:30
prafull-opensignlabsandGitHub a335d02156 Update Docker.yml 2024-02-22 18:23:55 +05:30
RaktimaNXG 3e0747164a feat: widgets information is saved in the server-side options field 2024-02-22 17:36:50 +05:30
prafull-opensignlabsandGitHub 8ad396d3ba Update INSTALLATION.md 2024-02-22 17:36:45 +05:30
prafull-opensignlabsandGitHub 26b54f0c00 Update INSTALLATION.md 2024-02-22 17:32:15 +05:30
prafull-opensignlabsandGitHub de5b58fff6 Update .env.local_dev 2024-02-22 17:27:54 +05:30
prafull-opensignlabsandGitHub b9b329dde4 Merge pull request #388 from OpenSignLabs/dependabot/npm_and_yarn/microfrontends/SignDocuments/react-pdf/renderer-3.3.8
build(deps): bump @react-pdf/renderer from 3.1.12 to 3.3.8 in /microfrontends/SignDocuments
2024-02-22 15:38:30 +05:30
prafull-opensignlabsandGitHub 2581500307 Merge pull request #405 from OpenSignLabs/dependabot/npm_and_yarn/apps/OpenSignServer/mongoose-8.1.3
build(deps): bump mongoose from 7.2.1 to 8.1.3 in /apps/OpenSignServer
2024-02-22 15:36:57 +05:30
prafull-opensignlabsandGitHub ef5c20a9f2 Merge pull request #389 from OpenSignLabs/dependabot/npm_and_yarn/apps/OpenSign/lint-staged-15.2.2
build(deps-dev): bump lint-staged from 15.0.1 to 15.2.2 in /apps/OpenSign
2024-02-22 15:33:39 +05:30
AmolandGitHub 01aee7c028 Merge pull request #417 from OpenSignLabs/remove_openai 2024-02-22 15:31:32 +05:30
prafull-opensignlabs 569c7f4b48 refactor: update jwt-decode package 2024-02-22 15:30:33 +05:30
prafull-opensignlabsandGitHub bb849f175c Merge pull request #358 from OpenSignLabs/dependabot/npm_and_yarn/apps/OpenSign/babel/runtime-corejs2-7.23.9
build(deps-dev): bump @babel/runtime-corejs2 from 7.23.2 to 7.23.9 in /apps/OpenSign
2024-02-22 15:13:50 +05:30
prafull-opensignlabsandGitHub ede0eea944 Merge pull request #291 from OpenSignLabs/dependabot/npm_and_yarn/microfrontends/SignDocuments/npm_and_yarn-security-group-d4599f4155
chore(deps): bump the npm_and_yarn group group in /microfrontends/SignDocuments with 1 update
2024-02-22 15:12:01 +05:30
prafull-opensignlabsandGitHub 47150cca41 Merge pull request #361 from OpenSignLabs/dependabot/npm_and_yarn/apps/OpenSignServer/axios-1.6.7
build(deps): bump axios from 1.3.5 to 1.6.7 in /apps/OpenSignServer
2024-02-22 15:08:08 +05:30
dependabot[bot]andGitHub 86df98a6a4 build(deps): bump axios from 1.3.5 to 1.6.7 in /apps/OpenSignServer
Bumps [axios](https://github.com/axios/axios) from 1.3.5 to 1.6.7.
- [Release notes](https://github.com/axios/axios/releases)
- [Changelog](https://github.com/axios/axios/blob/v1.x/CHANGELOG.md)
- [Commits](https://github.com/axios/axios/compare/v1.3.5...v1.6.7)

---
updated-dependencies:
- dependency-name: axios
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-02-22 09:32:54 +00:00
dependabot[bot]andGitHub 8dd5e90f8b build(deps): bump mongoose from 7.2.1 to 8.1.3 in /apps/OpenSignServer
Bumps [mongoose](https://github.com/Automattic/mongoose) from 7.2.1 to 8.1.3.
- [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/7.2.1...8.1.3)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-02-22 09:32:40 +00:00
prafull-opensignlabsandGitHub f31023e2ed Merge pull request #415 from OpenSignLabs/dependabot/npm_and_yarn/apps/OpenSign/npm_and_yarn-security-group-abd453e921
build(deps): bump the npm_and_yarn group across 3 directories with 9 updates
2024-02-22 15:01:52 +05:30
dependabot[bot]andGitHub 740d2e5a6c build(deps): bump the npm_and_yarn group across 3 directories with 9 updates
Bumps the npm_and_yarn group with 4 updates in the /apps/OpenSign directory: [axios](https://github.com/axios/axios), [parse](https://github.com/parse-community/Parse-SDK-JS), [@babel/traverse](https://github.com/babel/babel/tree/HEAD/packages/babel-traverse) and [follow-redirects](https://github.com/follow-redirects/follow-redirects).
Bumps the npm_and_yarn group with 7 updates in the /apps/OpenSignServer directory:

| Package | From | To |
| --- | --- | --- |
| [axios](https://github.com/axios/axios) | `1.3.5` | `1.6.0` |
| [parse](https://github.com/parse-community/Parse-SDK-JS) | `4.1.0` | `4.3.1` |
| [semver](https://github.com/npm/node-semver) | `5.7.1` | `5.7.2` |
| [@babel/traverse](https://github.com/babel/babel/tree/HEAD/packages/babel-traverse) | `7.21.5` | `7.23.9` |
| [minimist](https://github.com/minimistjs/minimist) | `0.0.8` | `1.2.8` |
| [mongodb-runner](https://github.com/mongodb-js/devtools-shared) | `4.10.0` | `5.5.3` |
| [word-wrap](https://github.com/jonschlinkert/word-wrap) | `1.2.3` | `1.2.5` |
Bumps the npm_and_yarn group with 3 updates in the /microfrontends/SignDocuments directory: [axios](https://github.com/axios/axios), [@babel/traverse](https://github.com/babel/babel/tree/HEAD/packages/babel-traverse) and [follow-redirects](https://github.com/follow-redirects/follow-redirects).


Updates `axios` from 1.5.1 to 1.6.0
- [Release notes](https://github.com/axios/axios/releases)
- [Changelog](https://github.com/axios/axios/blob/v1.x/CHANGELOG.md)
- [Commits](https://github.com/axios/axios/compare/v1.5.1...v1.6.0)

Updates `parse` from 4.2.0 to 4.3.1
- [Release notes](https://github.com/parse-community/Parse-SDK-JS/releases)
- [Changelog](https://github.com/parse-community/Parse-SDK-JS/blob/alpha/CHANGELOG.md)
- [Commits](https://github.com/parse-community/Parse-SDK-JS/compare/4.2.0...4.3.1)

Updates `@babel/traverse` from 7.23.0 to 7.23.9
- [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.23.9/packages/babel-traverse)

Updates `crypto-js` from 4.1.1 to 4.2.0
- [Commits](https://github.com/brix/crypto-js/compare/4.1.1...4.2.0)

Updates `follow-redirects` from 1.15.3 to 1.15.5
- [Release notes](https://github.com/follow-redirects/follow-redirects/releases)
- [Commits](https://github.com/follow-redirects/follow-redirects/compare/v1.15.3...v1.15.5)

Updates `axios` from 1.3.5 to 1.6.0
- [Release notes](https://github.com/axios/axios/releases)
- [Changelog](https://github.com/axios/axios/blob/v1.x/CHANGELOG.md)
- [Commits](https://github.com/axios/axios/compare/v1.5.1...v1.6.0)

Updates `parse` from 4.1.0 to 4.3.1
- [Release notes](https://github.com/parse-community/Parse-SDK-JS/releases)
- [Changelog](https://github.com/parse-community/Parse-SDK-JS/blob/alpha/CHANGELOG.md)
- [Commits](https://github.com/parse-community/Parse-SDK-JS/compare/4.2.0...4.3.1)

Updates `semver` from 5.7.1 to 5.7.2
- [Release notes](https://github.com/npm/node-semver/releases)
- [Changelog](https://github.com/npm/node-semver/blob/v5.7.2/CHANGELOG.md)
- [Commits](https://github.com/npm/node-semver/compare/v5.7.1...v5.7.2)

Updates `@babel/traverse` from 7.21.5 to 7.23.9
- [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.23.9/packages/babel-traverse)

Updates `minimist` from 0.0.8 to 1.2.8
- [Changelog](https://github.com/minimistjs/minimist/blob/main/CHANGELOG.md)
- [Commits](https://github.com/minimistjs/minimist/compare/v0.0.8...v1.2.8)

Updates `mongodb-runner` from 4.10.0 to 5.5.3
- [Commits](https://github.com/mongodb-js/devtools-shared/commits/mongodb-runner@5.5.3)

Updates `word-wrap` from 1.2.3 to 1.2.5
- [Release notes](https://github.com/jonschlinkert/word-wrap/releases)
- [Commits](https://github.com/jonschlinkert/word-wrap/compare/1.2.3...1.2.5)

Updates `axios` from 1.5.1 to 1.6.0
- [Release notes](https://github.com/axios/axios/releases)
- [Changelog](https://github.com/axios/axios/blob/v1.x/CHANGELOG.md)
- [Commits](https://github.com/axios/axios/compare/v1.5.1...v1.6.0)

Updates `@babel/traverse` from 7.23.6 to 7.23.9
- [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.23.9/packages/babel-traverse)

Updates `follow-redirects` from 1.15.3 to 1.15.5
- [Release notes](https://github.com/follow-redirects/follow-redirects/releases)
- [Commits](https://github.com/follow-redirects/follow-redirects/compare/v1.15.3...v1.15.5)

---
updated-dependencies:
- dependency-name: axios
  dependency-type: direct:production
  dependency-group: npm_and_yarn-security-group
- dependency-name: parse
  dependency-type: direct:production
  dependency-group: npm_and_yarn-security-group
- dependency-name: "@babel/traverse"
  dependency-type: indirect
  dependency-group: npm_and_yarn-security-group
- dependency-name: crypto-js
  dependency-type: indirect
  dependency-group: npm_and_yarn-security-group
- dependency-name: follow-redirects
  dependency-type: indirect
  dependency-group: npm_and_yarn-security-group
- dependency-name: axios
  dependency-type: direct:production
  dependency-group: npm_and_yarn-security-group
- dependency-name: parse
  dependency-type: direct:production
  dependency-group: npm_and_yarn-security-group
- dependency-name: semver
  dependency-type: indirect
  dependency-group: npm_and_yarn-security-group
- dependency-name: "@babel/traverse"
  dependency-type: indirect
  dependency-group: npm_and_yarn-security-group
- dependency-name: minimist
  dependency-type: indirect
  dependency-group: npm_and_yarn-security-group
- dependency-name: mongodb-runner
  dependency-type: direct:development
  dependency-group: npm_and_yarn-security-group
- dependency-name: word-wrap
  dependency-type: indirect
  dependency-group: npm_and_yarn-security-group
- dependency-name: axios
  dependency-type: direct:production
  dependency-group: npm_and_yarn-security-group
- dependency-name: "@babel/traverse"
  dependency-type: indirect
  dependency-group: npm_and_yarn-security-group
- dependency-name: follow-redirects
  dependency-type: indirect
  dependency-group: npm_and_yarn-security-group
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-02-22 09:07:19 +00:00
AmolandGitHub 20d37e1ac9 Merge pull request #416 from OpenSignLabs/remove_openai 2024-02-22 14:33:04 +05:30
prafull-opensignlabs f3f79ed499 refactor: remove openai pacakge 2024-02-22 14:31:57 +05:30
dependabot[bot]andGitHub c581222022 build(deps-dev): bump lint-staged in /apps/OpenSign
Bumps [lint-staged](https://github.com/okonet/lint-staged) from 15.0.1 to 15.2.2.
- [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.0.1...v15.2.2)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-02-22 07:42:15 +00:00
prafull-opensignlabsandGitHub a3fd738b46 Merge pull request #390 from OpenSignLabs/dependabot/npm_and_yarn/apps/OpenSign/postcss-8.4.35
build(deps-dev): bump postcss from 8.4.31 to 8.4.35 in /apps/OpenSign
2024-02-22 13:10:46 +05:30
prafull-opensignlabsandGitHub 3f16e973eb Merge pull request #325 from OpenSignLabs/dependabot/npm_and_yarn/microfrontends/SignDocuments/react-pdf-7.7.0
chore(deps): bump react-pdf from 7.4.0 to 7.7.0 in /microfrontends/SignDocuments
2024-02-22 13:09:37 +05:30
dependabot[bot]andGitHub cb1013762f build(deps): bump @react-pdf/renderer in /microfrontends/SignDocuments
Bumps [@react-pdf/renderer](https://github.com/diegomura/react-pdf/tree/HEAD/packages/renderer) from 3.1.12 to 3.3.8.
- [Release notes](https://github.com/diegomura/react-pdf/releases)
- [Changelog](https://github.com/diegomura/react-pdf/blob/master/packages/renderer/CHANGELOG.md)
- [Commits](https://github.com/diegomura/react-pdf/commits/@react-pdf/renderer@3.3.8/packages/renderer)

---
updated-dependencies:
- dependency-name: "@react-pdf/renderer"
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-02-22 07:20:59 +00:00
prafull-opensignlabsandGitHub 74e275c5d0 Merge pull request #266 from OpenSignLabs/dependabot/npm_and_yarn/microfrontends/SignDocuments/parse-4.3.1
chore(deps): bump parse from 4.2.0 to 4.3.1 in /microfrontends/SignDocuments
2024-02-22 12:49:52 +05:30
prafull-opensignlabsandGitHub dbeb513f65 Merge pull request #262 from OpenSignLabs/dependabot/npm_and_yarn/microfrontends/SignDocuments/babel/traverse-7.23.6
chore(deps): bump @babel/traverse from 7.23.0 to 7.23.6 in /microfrontends/SignDocuments
2024-02-22 12:47:26 +05:30
RaktimaNXG 84b545c37d fix: placeholder visibility issue after placed in signyourself flow 2024-02-21 18:47:50 +05:30
RaktimaNXG 8308376f53 fix: date widgets issue after place change all widgets details which are already placed 2024-02-21 15:22:17 +05:30
RaktimaNXG d4fabf0fe9 fix: unsigned widget's reactour message 2024-02-21 09:40:31 +05:30
RaktimaNXG 439ac7eac6 fix: checkbox onclick border issue 2024-02-20 14:51:17 +05:30
RaktimaNXG ef1b82f426 feat: implement react-tour alert for unsigned widgets 2024-02-16 22:04:37 +05:30
RaktimaNXG 987a4bd04c feat: remove widgets border on click pdf 2024-02-15 19:55:30 +05:30
RaktimaNXG ce86510d8e feat: implement disable documentId stamp setting for Admin users 2024-02-15 09:48:52 +05:30
RaktimaNXG 156a05f6ed fix: placeholder flow widget's issue 2024-02-14 20:33:24 +05:30
RaktimaNXG b35d8406a3 fix: input text validation issue 2024-02-13 20:04:22 +05:30
RaktimaNXG 3910486b17 fix: signyourself pdf render issue 2024-02-12 19:02:33 +05:30
RaktimaNXG 60ba77a06f fix: remove user icon for label widget 2024-02-12 17:45:43 +05:30
RaktimaNXG f86ea04a02 feat: label widget for prefill data 2024-02-12 17:36:23 +05:30
dependabot[bot]andGitHub db4b5f0452 build(deps-dev): bump postcss from 8.4.31 to 8.4.35 in /apps/OpenSign
Bumps [postcss](https://github.com/postcss/postcss) from 8.4.31 to 8.4.35.
- [Release notes](https://github.com/postcss/postcss/releases)
- [Changelog](https://github.com/postcss/postcss/blob/main/CHANGELOG.md)
- [Commits](https://github.com/postcss/postcss/compare/8.4.31...8.4.35)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-02-12 01:12:11 +00:00
RaktimaNXG c0ae0c7ffa fix: template flow dropdown and radio issue, date setting icon ,expired document issue 2024-02-09 17:11:32 +05:30
RaktimaNXG 6a0788c2a1 fix: radio widgets position and email widgets width issue 2024-02-09 10:50:19 +05:30
RaktimaNXG 4a52d327ce fix: date issue in mobile view 2024-02-07 18:45:52 +05:30
RaktimaNXG ef68fe1c85 fix: radio button options and selecting issue 2024-02-07 17:36:07 +05:30
RaktimaNXG 83fa9c9ebd fix: radio widget embeding issue in pdf 2024-02-07 15:28:18 +05:30
RaktimaNXG 5736306f8c feat: implement radio button functionality 2024-02-06 21:28:54 +05:30
RaktimaNXG 67cb508944 fix: date format issue in placeholder flow 2024-02-06 09:54:49 +05:30
RaktimaNXG 87fe5cdd6f feat: implement input box validation functionality 2024-02-02 10:00:39 +05:30
dependabot[bot]andGitHub ca17f1cfc9 chore(deps): bump react-pdf in /microfrontends/SignDocuments
Bumps [react-pdf](https://github.com/wojtekmaj/react-pdf/tree/HEAD/packages/react-pdf) from 7.4.0 to 7.7.0.
- [Release notes](https://github.com/wojtekmaj/react-pdf/releases)
- [Commits](https://github.com/wojtekmaj/react-pdf/commits/v7.7.0/packages/react-pdf)

---
updated-dependencies:
- dependency-name: react-pdf
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-02-01 11:04:47 +00:00
RaktimaNXG 048629dd32 fix: widgets text select issue in mobile view 2024-01-31 19:55:06 +05:30
RaktimaNXG fe03da1d97 feat : multiple date format added 2024-01-31 17:12:08 +05:30
RaktimaNXG 0a3d89d0e2 fix: on press widgets select functionality trigger issue in mobile view 2024-01-31 09:56:46 +05:30
RaktimaNXG 882b97da5e fix: widgets dragging issue in mobile view 2024-01-30 17:12:29 +05:30
dependabot[bot]andGitHub 07a57969ac 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.23.2 to 7.23.9.
- [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.23.9/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-01-29 01:09:53 +00:00
RaktimaNXG bc90da4cf2 feat: checkbox widget status,fix image emabed and upload issue 2024-01-25 16:18:37 +05:30
RaktimaNXG ad5776cfba feat: implement initial signature feature, fix signature drag and sign-your self issue 2024-01-24 18:01:06 +05:30
RaktimaNXG 1f16123865 fix: draft type document in open-sign drive & disable placeholder click behavior for other signers in mobile view 2024-01-19 21:17:38 +05:30
RaktimaNXG e85bbb7bd9 fix: widget scrolling issue in mobile view, on delete placeholder user remove issue,dropdown & checkbox disappear after complete signature by two signers issue 2024-01-19 18:12:21 +05:30
RaktimaNXG f4e907de36 fix: initial signature issue 2024-01-17 19:28:33 +05:30
RaktimaNXG 72f7e1fb27 fix: handle widgets functionality for mobile view in placeholder and template creation flow 2024-01-17 17:36:56 +05:30
RaktimaNXG bb732d7606 feat: add dropdown,initial sign,name,job title in placeholder flow 2024-01-16 19:47:07 +05:30
RaktimaNXG 221a49bb4a remove hard coded local storage data 2024-01-15 19:36:48 +05:30
RaktimaNXG babe17838b feat:implement new widgets- initial signature,name,company,job title & date in sign-yourself flow 2024-01-15 19:09:18 +05:30
RaktimaNXG f5d11f9ba6 feat:implement new widgets- initial signature,name,company,job title & date in sign-yourself flow 2024-01-15 19:05:46 +05:30
RaktimaNXG 939d917b7b feat: implement changes to ensure compatibility with multiple widgets 2024-01-12 22:01:20 +05:30
dependabot[bot]andGitHub 288365b74b chore(deps): bump parse in /microfrontends/SignDocuments
Bumps [parse](https://github.com/parse-community/Parse-SDK-JS) from 4.2.0 to 4.3.1.
- [Release notes](https://github.com/parse-community/Parse-SDK-JS/releases)
- [Changelog](https://github.com/parse-community/Parse-SDK-JS/blob/alpha/CHANGELOG.md)
- [Commits](https://github.com/parse-community/Parse-SDK-JS/compare/4.2.0...4.3.1)

---
updated-dependencies:
- dependency-name: parse
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-12-27 12:15:31 +00:00
dependabot[bot]andGitHub b57e17c01c chore(deps): bump the npm_and_yarn group group
Bumps the npm_and_yarn group group in /microfrontends/SignDocuments with 1 update: [parse](https://github.com/parse-community/Parse-SDK-JS).


Updates `parse` from 4.2.0 to 4.3.1
- [Release notes](https://github.com/parse-community/Parse-SDK-JS/releases)
- [Changelog](https://github.com/parse-community/Parse-SDK-JS/blob/alpha/CHANGELOG.md)
- [Commits](https://github.com/parse-community/Parse-SDK-JS/compare/4.2.0...4.3.1)

---
updated-dependencies:
- dependency-name: parse
  dependency-type: direct:production
  dependency-group: npm_and_yarn-security-group
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-12-27 12:15:12 +00:00
dependabot[bot]andGitHub 92527e5847 chore(deps): bump @babel/traverse in /microfrontends/SignDocuments
Bumps [@babel/traverse](https://github.com/babel/babel/tree/HEAD/packages/babel-traverse) from 7.23.0 to 7.23.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.23.6/packages/babel-traverse)

---
updated-dependencies:
- dependency-name: "@babel/traverse"
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-12-15 08:00:41 +00:00
206 changed files with 21446 additions and 36041 deletions
+3 -4
View File
@@ -1,6 +1,5 @@
# Frontend config ************************************************************************************************************************************************************************************************
# Set CI to false while running the app locally
CI=false
# Set it to the URL form where the app home page will be accessed
PUBLIC_URL=https://app.opensignlabs.com/
# Set it to true if you want to generate the Sourcemap for debugging
@@ -8,13 +7,13 @@ GENERATE_SOURCEMAP=false
# Set it to the URL from where APIs will be accessible, for local development it should be localhost:3000/api/app (use your local port number instead)
REACT_APP_SERVERURL=https://app.opensignlabs.com/api/app
# A 12 character long random app identifier. The value of this should be same as APP_ID which is a variable used by backend API.
REACT_APP_APPID=aDsADsqweqwe
REACT_APP_APPID=opensign
# Google tag manager container id for configuring GTM on all pages of the app
REACT_APP_GTM=GTM-123N7LD
# Backend ExpressJS config ****************************************************************************************************************************************************************************************
# A 12 character long random app identifier. The value of this should be same as REACT_APP_APPID which is a variable used by Frontend React App.
APP_ID=aDsADsqweqwe
APP_ID=opensign
# Name of the app. It will be visible in the verification emails sent out.
appName=open_sign_server
# A 12 character long random secret key that allows access to all the data. It is used in Parse dashboard config to view all the data in the database.
+1 -3
View File
@@ -2,8 +2,6 @@
# When used as it is, this env config will connect to our hosted UAT backend
# Note that any data in staging will get cleared from time to time and you may have to sign up again and again
# Set CI to false while running the app locally
CI=false
# Set it to the URL form where the app home page will be accessed
PUBLIC_URL=http://localhost:3000
# Set it to true if you want to generate the Sourcemap for debugging
@@ -11,4 +9,4 @@ GENERATE_SOURCEMAP=false
# Set it to the URL from where APIs will be accessible, for local development it should be localhost:3000/api/app (use your local port number instead)
REACT_APP_SERVERURL=https://staging-app.opensignlabs.com/api/app
# A 12 character long random app identifier. The value of this should be same as APP_ID which is a variable used by backend API.
REACT_APP_APPID=opensignstgn
REACT_APP_APPID=opensign
+4 -6
View File
@@ -2,8 +2,6 @@
# When used as it is, this env config will connect to our hosted UAT backend
# Note that any data in staging will get cleared from time to time and you may have to sign up again and again
# Set CI to false while running the app locally
CI=false
# Set it to the URL form where the app home page will be accessed
PUBLIC_URL=http://localhost:3000
# Set it to true if you want to generate the Sourcemap for debugging
@@ -11,18 +9,18 @@ GENERATE_SOURCEMAP=false
# Set it to the URL from where APIs will be accessible, for local development it should be localhost:3000/api/app (use your local port number instead)
REACT_APP_SERVERURL=http://localhost:8080/app
# A 12 character long random app identifier. The value of this should be same as APP_ID which is a variable used by backend API.
REACT_APP_APPID=opensignstgn
REACT_APP_APPID=opensign
# Backend ExpressJS config ****************************************************************************************************************************************************************************************
# A 12 character long random app identifier. The value of this should be same as REACT_APP_APPID which is a variable used by Frontend React App.
APP_ID=opensignstgn
APP_ID=opensign
# Name of the app. It will be visible in the verification emails sent out.
appName=open_sign_server
# A 12 character long random secret key that allows access to all the data. It is used in Parse dashboard config to view all the data in the database.
MASTER_KEY=XnAadwKxxByMr
# Mongodb URI to connect to
MONGODB_URI=mongodb://host.docker.internal:27017/OpenSignDB
MONGODB_URI=mongodb://mongo:27017/OpenSignDB
# Path on which APIs should be mounted. Do not change this. This variable shall be removed & value hardcoded in the source code in coming versions.
PARSE_MOUNT=/app
# Set it to the URL from where APIs will be accessible to the NodeJS functions, for local development it should be localhost:3000/api/app (use your local port number instead)
@@ -52,7 +50,7 @@ SMTP_ENABLE=
SMTP_HOST=smtp.yourhost.com
SMTP_PORT=443
SMTP_USER_EMAIL=mailer@yourdomain.com
SMTP_PASS=password
SMTP_PASS=password # if your password includes spaces then write password in single quotes ('asdf pasd asdf bgds').
# Base64 encoded PFX or p12 document signing certificate file *********************************************************************************************************************
+7 -4
View File
@@ -2,7 +2,7 @@ name: ci
on:
push:
branches:
- 'main'
- 'staging'
jobs:
docker:
@@ -11,9 +11,9 @@ jobs:
matrix:
include:
- image: amolshejole/OpenSign
dockerfile: apps/OpenSign/Dockerfile
dockerfile: apps/OpenSign/Dockerhubfile
- image: amolshejole/OpenSignServer
dockerfile: apps/OpenSignServer/Dockerfile
dockerfile: apps/OpenSignServer/Dockerhubfile
steps:
-
name: Checkout
@@ -31,8 +31,11 @@ jobs:
with:
images: ${{ matrix.image }}
-
name: Debug - List files
name: Debug - List files opensign
run: ls -R apps/OpenSign/ # Adjust the path as needed
-
name: Debug - List files opensignserver
run: ls -R apps/OpenSignServer/ # Adjust the path as needed
-
name: Build and push
uses: docker/build-push-action@v4
+16 -136
View File
@@ -1,149 +1,29 @@
# INSTALLATON INSTRUCTIONS
# INSTALLATON INSTRUCTIONS HAS A NEW HOME
You can use our app as a cloud version from [OpenSignLabs](https://www.opensignlabs.com)
We've updated our installation instructions and moved them to our dedicated documentation portal to provide you with a better experience and updated guidance. Whether you're looking to self-host OpenSign™ or contribute to its development, you can find detailed instructions tailored to your needs at [docs.opensignlabs.com](https://docs.opensignlabs.com).
or follow below instructions to install it on your own infrastructure.
## Self Hosting
- Localhost(Frontend only)
- Digital Ocean
- Localhost(Docker)
If you're interested in self-hosting OpenSign™, our new documentation portal provides comprehensive, step-by-step instructions to help you set up OpenSign™ in your own environment. This section is designed for system administrators and those looking to deploy OpenSign™ within their organization or for personal use.
## Localhost(Frontend only)
- **Access Self Hosting Instructions:** [Self Hosting Guide](https://docs.opensignlabs.com/docs/category/docker)
This is the easiest way to run the frontend application for development or testing purpose without the hassle of installing backend & DB. All the features including document upload, signing, email notifications will work seamlessly from staging backend.
## Contributors
**Warning:** All data, including user accounts and documents, is stored in the staging backend. This data will be erased every time there is a merge to the main branch. As a result, you may need to recreate user accounts repeatedly. If you find that login attempts are failing, it is likely because the data has been cleared due to a recent merge.
For developers and contributors who are looking to build upon or contribute to OpenSign™, we've prepared a separate section that covers the setup, development environment configuration, and guidelines for contributing to the OpenSign™ project.
Below are the steps to follow -
- [Clone the repository](https://help.github.com/articles/cloning-a-repository/) to your local machine using below command -
```
git clone https://github.com/OpenSignLabs/OpenSign.git
```
- Copy the .env.frontend_dev file to apps/OpenSign/.env using below command(on mac & linux). For windows use COPY command instead.
```
cp .env.frontend_dev apps/OpenSign/.env
```
- CD to /apps/OpenSign directory
- Install NPM packages using
```
npm install
```
- Run the project locally using
```
npm run start
```
You should be able to access the application from http://localhost:3000 after this.
Create an account by signing-up and start contributing.
- **Access Contributor Instructions:** [Contributors Guide](https://docs.opensignlabs.com/docs/contribute/INSTALLATION)
## Additional Resources
## Digital Ocean
Should you need further assistance or have any questions, please feel free to reach out to us through our support channels:
OpenSign application consistes of 3 components -
- ReactJS frontend
- NodeJS API
- MongoDB database
- **Twitter:** [OpenSignHQ on Twitter](https://twitter.com/OpenSignHQ)
- **Facebook:** [OpenSign on Facebook](https://www.facebook.com/profile.php?id=61551030403669)
- **LinkedIn:** [OpenSign™ on LinkedIn](https://www.linkedin.com/company/opensign%E2%84%A2/)
- **Discord:** [Join our Discord Community](https://discord.com/invite/opensign)
- **YouTube:** [OpenSignHQ on YouTube](https://www.youtube.com/@opensignhq)
You can install all 3 components on digital ocean using the button below -
We are committed to providing you with the support you need to successfully install and use OpenSign™. Visit our website at [www.opensignlabs.com](https://www.opensignlabs.com) for more information about our project and its features.
[![Deploy on DigitalOcean](https://www.deploytodo.com/do-btn-blue.svg)](https://cloud.digitalocean.com/apps/new?repo=https://github.com/OpenSignLabs/Deploy-OpenSign-to-Digital-Ocean/tree/main&refcode=30db1c901ab0)
## You will need to create an AWS S3 bucket or digital ocean space in order to store your uploaded documents
### AWS S3 -
- Step 1 : Create a S3 bucket
- Login to AWS console
- Navigate to S3 under services
- Hit "Create Bucket" button on upper right corner
- Remove the check from "block all public access" checkbox(we need this in order to provide access to not-logged in users after OTP verification)
- Set bucket versioning and tags as per your requirements
- Hit "Create bucket" button
- Step 2 : Create IAM user and provide access to AWS bucket
- Search for "IAM" on the search bar in AWS console
- On IAM dashboard, click the number of users(count) under IAM resources table
- Hit "create user" button on the upper right corner of the page
- Enter the user name & click next
- Click create policy, search for S3 and provide the Read, Write & list permissions
- Click next and click "Create user"
- Step 3 : Generate Credentials
- Go to IAM/Users in AWS console
- Hit the hyperlink for the user created in the previous step
- Click the "Security credentials" tab
- Scroll down to "Access keys" and hit "Create access key"
- In the next step select "Application running outside AWS"
- Add a description tag if needed & hit "Create access key"
- In the next step you will see "Access key" and "Secret Access key". Copy both the values.
- Set the value of "Access key" to "DO_ACCESS_KEY_ID" environment variable
- Set the value of "Secret Access key" to "DO_SECRET_ACCESS_KEY" environment variable
- Step 3 : Copy bucket credentials
- Visit "Amazon S3 -> Buckets" in aws console
- Click the bucket created in previous steps & visit the properties tab
- Under "Bucket overview" you will find the value of AWS region(for ex. ap-south-1). Set that value to env variable "DO_REGION"
- You can create the value for "DO_ENDPOINT" env variable by appending the region value to amazonaws.com (for ex. s3.ap-south-1.amazonaws.com)
- You can create the value for "DO_BASEURL" by adding the bucketname in front of the endpoint value(for ex. https://bucketname.s3.ap-south-1.amazonaws.com)
Visit below link if you face any issues while following the above instructions -
- https://repost.aws/knowledge-center/create-access-key
## Localhost(Docker)
For local Setup we need to need following prerequisite:
Environment Varaibles:
| Environment Varibale | Value | Description |
| ------------- | ------------- | ------------- |
| CI | false | Set CI to false while running the app locally |
| PUBLIC_URL | http://localhost:3000 | Set it to the URL form where the app home page will be accessed |
| GENERATE_SOURCEMAP | false | Set it to true if you want to generate the Sourcemap for debugging |
| REACT_APP_SERVERURL | http://localhost:8080/app | Set it to the URL from where APIs will be accessible, for local development it should be localhost:3000/api/app (use your local port number instead) |
| REACT_APP_APPID | opensignstgn | A 12 character long random app identifier. The value of this should be same as APP_ID which is a variable used by backend API. |
| APP_ID | opensignstgn | A 12 character long random app identifier. The value of this should be same as REACT_APP_APPID which is a variable used by Frontend React App. |
| appName | open_sign_server | Name of the app. It will be visible in the verification emails sent out. |
| MASTER_KEY | XnAadwKxxByMr | A 12 character long random secret key that allows access to all the data. It is used in Parse dashboard config to view all the data in the database. |
| MONGODB_URI | mongodb://host.docker.internal:27017/OpenSignDB | Mongodb URI to connect to |
| PARSE_MOUNT |/app | Path on which APIs should be mounted. Do not change this. This variable shall be removed & value hardcoded in the source code in coming versions. |
| SERVER_URL | http://127.0.0.1:8080/app | Set it to the URL from where APIs will be accessible to the NodeJS functions, for local development it should be localhost:3000/api/app (use your local port number instead) |
| DO_SPACE | DOSPACENAME | Digital ocean space name or AWS S3 bucket name for uploading documents |
| DO_ENDPOINT | ams3.digitaloceanspaces.com | Digital ocean spaces endpoint or AWS S3 endpoint for uploading documents |
| DO_BASEURL |https://DOSPACENAME.ams3.digitaloceanspaces.com | Digital ocean baseurl or AWS S3 base URL |
| DO_ACCESS_KEY_ID | YOUR_S3_ACCESS_ID | Digital ocean spaces access key ID or AWS s3 Access key ID for uploading the docs |
| DO_SECRET_ACCESS_KEY | YOUR_S3_ACCESS_KEY | Digital ocean spaces secret access key or AWS s3 secret access key for uploading the docs |
| DO_REGION | YOUR_S3_REGION | Digital ocean spaces region or AWS s3 region |
| USE_LOCAL | FALSE | To use local file storage to save file |
| MAILGUN_API_KEY | YOUR_MAILGUNAPI_KEY | Mailgun API Key |
| MAILGUN_DOMAIN | YOUR_MAILGUNAPI_DOMAIN | Mailgun API Domain |
| MAILGUN_SENDER | - | Mailgun Sender Mail ID |
| PFX_BASE64 | - | Base64 encoded PFX or p12 document signing certificate file. You can generate base64 encoded self sign certificate using the passphrase `emudhra` |
# Steps to Generate Self Sign Certificate
```
# execute below command and use passphrase emudhra
openssl genrsa -des3 -out ./cert/local_dev.key 2048
openssl req -key ./cert/local_dev.key -new -x509 -days 365 -out ./cert/local_dev.crt
openssl pkcs12 -inkey ./cert/local_dev.key -in ./cert/local_dev.crt -export -out ./cert/local_dev.pfx
openssl base64 -in ./cert/local_dev.pfx -out ./cert/base64_pfx
```
# CORS Configuration
As document storage is delegated to S3-compatible services that reside in a different host than the OpenSign one, document operations (loading, storing, deleting) are subject to [Cross-Origin Resource Sharing](https://en.wikipedia.org/wiki/Cross-origin_resource_sharing) restriction policies; as a consequence, OpenSign app may fail with (browser console) errors like the following:
```
Access to fetch at 'https://foo.nyc3.digitaloceanspaces.com/exported_file_4627_0000-00-00T00%3A45%3A43.344Z.pdf'
from origin 'http://localhost:3000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header
is present on the requested resource. If an opaque response serves your needs, set the request's mode to
'no-cors' to fetch the resource with CORS disabled.
```
In order to address this, your document storage system must be instructed to accept requests from other hosts; below the relevant documentation links:
- [How to Configure CORS on DigitalOcean Spaces](https://docs.digitalocean.com/products/spaces/how-to/configure-cors/)
- [Configuring cross-origin resource sharing on AWS S3](https://docs.aws.amazon.com/AmazonS3/latest/userguide/enabling-cors-examples.html)
# Build Local Environment
Command to build project -
- Execute `make build`
Command to run project -
- Execute `make run`
+1 -2
View File
@@ -1,7 +1,6 @@
build:
cp .env.local_dev .env
rm -rf apps/OpenSign/public/mfbuild
cd microfrontends/SignDocuments && npm install && npm run build
cd apps/OpenSign && cp ../../.env.local_dev .env && npm install && npm run build
docker compose up --build --force-recreate
run:
+11 -11
View File
@@ -42,24 +42,24 @@ Please star ⭐ the repo to support us! 😀
### Introduction
Welcome to OpenSign, the premier open-source docusign alternative - document e-signing solution designed to provide a secure, reliable, and free alternative to commercial platforms like DocuSign, PandaDoc, SignNow, Adobe Sign, Smartwaiver, SignRequest, HelloSign & Zoho sign. Developed under the OpenSignLabs organization, our mission is to democratize the e-signing process, making it accessible and straightforward for everyone.
Welcome to OpenSign, the premier open source docusign alternative - document e-signing solution designed to provide a secure, reliable and free alternative to commercial esign platforms like DocuSign, PandaDoc, SignNow, Adobe Sign, Smartwaiver, SignRequest, HelloSign & Zoho sign. Our mission is to democratize the e-signing process, making it accessible and straightforward for everyone.
---
### Features
- **Secure PDF E-Signing:** With the help of Robust encryption algorithms, OpenSign™ ensures maximum security, privacy & compatibility.
- **Annotate Documents:** OpenSign™ allows you to annotate PDF documents with an advanced signing pad that comes with hand drawn signatures support as well as uploaded images & saved signatures for the simplest signing experience.
- **User-Friendly Interface:** OpenSign™ was built while keeping Intuitive design in mind for ease of use. Features like "Sign yourself", "One click signatures" and "OpenSign Drive" makes it stand out of the crowd and even makes it better than a lot of so-called industry leaders.
- **Multi-signer Support:** OpenSign's ability to invite multiple signers for signing along with the ability to invite witnesses & being able to enforce signing in a sequence makes it the only open source solution that is fully loaded and allows it to compete head-to-head with established players.
- **Secure PDF E-Signing:** With the help of robust encryption algorithms, OpenSign™ ensures maximum security, privacy & compatibility.
- **Annotate Documents:** OpenSign™ allows you to annotate PDF documents with an advanced signing pad that allows hand drawn signatures, uploaded images, typed signatures & saved signatures for the simplest signing experience ever.
- **User-Friendly Interface:** OpenSign™ was built while keeping Intuitive design in mind for ease of use. Features like "Sign yourself", "Templates", "One click signatures" and "OpenSign Drive" makes it stand out of the crowd and even makes it better than a lot of so-called industry leaders.
- **Multi-signer Support:** OpenSign's ability to invite multiple signers for signing along with the ability to invite witnesses & being able to enforce signing in a sequence makes it the only open source solution that is fully loaded and allows it to compete head-to-head with established players in e-signature space.
- **Email Unique Code(OTP) verification support for guest signers:** With OpenSign™, your documents are fully secure even when being signed by guest users. Guest signers can only sign the document after entering a unique code sent to their email address. 
- **"Expiring Docs" & "Rejection":** You can set documents to expire after certain number of days after which nobody will be able to sign it. Not just this, OpenSign also allows signers to reject signing a document.
- **"Expiring Docs" & "Rejection":** You can set documents to expire after certain number of days after which nobody will be able to sign. Not just this, OpenSign also allows signers to reject signing a document.
- **Beautiful email templates:** All document signing invitations, completion notifications & reminders are formatted using great looking email templates.
- **PDF Template Creation(coming soon):** OpenSign™ allows you to create and store PDF document templates for repeated use thereby saving you a lot of time.
- **OpenSign™ Drive:** It is a centralised secure vault for your signed documents that makes storing, signing, organizing, sharing & achieving your docs a breeze.
- **PDF Template Creation:** OpenSign™ allows you to create and store PDF document templates for repeated use thereby saving you a lot of time & collect e-signatures seamlessly.
- **OpenSign™ Drive:** It is a centralised secure vault for your digital documents that makes storing, signing, organizing, sharing & achieving your docs a breeze.
- **Audit Trails & completion certificate:** Being a security focused solution, OpenSign™ makes it a top priority to save detailed logs for tracking document activities along with time-stamps, IP addresses, email IDs & phone numbers. A completion certificate is generated as soon as document is completed which contains all the document related logs for added safety.
- **API Support(coming soon):** OpenSign™ API allows seamless integration into existing systems and software. APIs will soon be available as a cloud hosted solution.
- **Integrations:** Seamless integrations with various Cloud storage systems, CRMs & enterprise platforms is coming soon.
- **API Support:** OpenSign™ API allows seamless integration into existing systems and software. You can generate an API key from the app and refer the [docs](https://docs.opensignlabs.com) to start integrating it in your existing applications.
- **Integrations:** Seamless integrations with various Cloud storage systems, CRMs & enterprise platforms is available. We also have a Zapier integration that allows you to integrate it with virtually any application.
<img src=https://github.com/OpenSignLabs/OpenSign/assets/5486116/b37ff443-7099-4273-9aeb-21c46d7154cf height='200'>
<img src=https://github.com/OpenSignLabs/OpenSign/assets/5486116/86db91b7-6c2f-4885-a33c-58f4fd35ec89 height='200'>
@@ -76,7 +76,7 @@ Please refer to the [Installation Guide](INSTALLATION.md) for detailed instructi
### Usage
For comprehensive guidelines on how to use OpenSign, please consult our [User Manual](USAGE.md).
For comprehensive guidelines on how to use OpenSign, please consult our [User Manual](USAGE.md).
---
+2 -2
View File
@@ -1,5 +1,5 @@
# Use an official Node runtime as the base image
FROM node:16
FROM node:18
# Set the working directory inside the container
WORKDIR /usr/src/app
@@ -21,5 +21,5 @@ EXPOSE 3000
# ENV NODE_ENV production
# Run the application
ENTRYPOINT npm run start-dev
ENTRYPOINT npm run start
+27
View File
@@ -0,0 +1,27 @@
# Use an official Node runtime as the base image
FROM node:18
# Set the working directory inside the container
WORKDIR /usr/src/app
# Copy package.json and package-lock.json first to leverage Docker cache
COPY apps/OpenSign/package*.json ./
# Install application dependencies
RUN npm install
# Copy the current directory contents into the container
COPY apps/OpenSign/ .
COPY apps/OpenSign/.husky .
# build
RUN npm run build
# Make port 3000 available to the world outside this container
EXPOSE 3000
# Define environment variables if needed
# ENV NODE_ENV production
# Run the application
CMD ["npm", "start"]
-25
View File
@@ -1,25 +0,0 @@
const { dependencies } = require("./package.json");
module.exports = {
name: "shell_app", // change me
filename: "remoteEntry.js",
exposes: {},
remotes: {},
shared: {
...dependencies,
react: {
singleton: true,
import: "react", // fallback is also react
shareScope: "default",
requiredVersion: dependencies.react
},
"react-dom": {
singleton: true,
requiredVersion: dependencies["react-dom"]
},
"react-router-dom": {
singleton: true,
requiredVersion: dependencies["react-router-dom"]
}
}
};
+3683 -981
View File
File diff suppressed because it is too large Load Diff
+38 -28
View File
@@ -3,44 +3,54 @@
"version": "0.1.0",
"private": true,
"dependencies": {
"@reduxjs/toolkit": "^1.9.7",
"axios": "^1.5.1",
"daisyui": "^3.9.2",
"@formkit/auto-animate": "^0.8.1",
"@radix-ui/themes": "^2.0.3",
"@react-pdf/renderer": "^3.4.0",
"@reduxjs/toolkit": "^2.2.1",
"axios": "^1.6.8",
"file-saver": "^2.0.5",
"html-react-parser": "^4.2.2",
"json-rules-engine-simplified": "^0.1.17",
"jwt-decode": "^3.1.2",
"mf-cra": "^0.0.5",
"moment": "^2.29.4",
"parse": "^4.2.0",
"jwt-decode": "^4.0.0",
"moment": "^2.30.1",
"parse": "^4.3.1",
"pdf-lib": "^1.17.1",
"print-js": "^1.6.0",
"radix-ui": "^1.0.1",
"react": "^18.2.0",
"react-bootstrap": "^2.9.0",
"react-bootstrap": "^2.10.2",
"react-datepicker": "^6.4.0",
"react-dnd": "^16.0.1",
"react-dnd-html5-backend": "^16.0.1",
"react-dnd-multi-backend": "^8.0.3",
"react-dnd-touch-backend": "^16.0.1",
"react-dom": "^18.2.0",
"react-drag-listview": "^2.0.0",
"react-gtm-module": "^2.0.11",
"react-helmet": "^6.1.0",
"react-konva": "^18.2.10",
"react-modal": "^3.16.1",
"react-redux": "^8.1.3",
"react-router-dom": "^6.16.0",
"react-pdf": "^7.7.1",
"react-redux": "^9.1.0",
"react-rnd": "^10.4.1",
"react-router-dom": "^6.22.3",
"react-scripts": "5.0.1",
"react-select": "^5.7.7",
"react-scrollbars-custom": "^4.1.1",
"react-select": "^5.8.0",
"react-signature-canvas": "^1.0.6",
"react-tooltip": "^5.26.3",
"reactour": "^1.19.2",
"redux": "^4.2.1",
"redux-thunk": "^2.4.2",
"redux": "^5.0.1",
"redux-thunk": "^3.1.0",
"regex-parser": "^2.3.0",
"serve": "^14.2.1",
"styled-components": "^4.4.1",
"web-vitals": "^2.1.4"
},
"scripts": {
"start": "serve -s build",
"start-dev": "mf-cra start",
"start-dev": "react-scripts start",
"version": "curl -s https://api.github.com/repos/opensignlabs/opensign/releases/latest | grep '\"tag_name\":' | awk -F '\"' '{print $4}' > ./public/version.txt",
"build": "npm run version && rm -rf public/mfbuild && npm run micro && CI=false && mf-cra build",
"micro": "cd ../../microfrontends/SignDocuments && npm install && npm run build",
"version-win": "powershell -Command \"Invoke-RestMethod -Uri 'https://api.github.com/repos/opensignlabs/opensign/releases/latest' | Select-Object -ExpandProperty tag_name | Out-File -FilePath ./public/version.txt\"",
"build": "npm run version && react-scripts build",
"build-win": "npm run version-win && react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject",
"release": "standard-version",
@@ -70,16 +80,16 @@
}
},
"devDependencies": {
"@babel/runtime-corejs2": "^7.23.2",
"autoprefixer": "^10.4.16",
"@babel/runtime-corejs2": "^7.24.1",
"autoprefixer": "^10.4.18",
"commitizen": "^4.3.0",
"eslint": "^8.51.0",
"eslint": "^8.57.0",
"eslint-plugin-prettier": "^4.2.1",
"eslint-plugin-react": "^7.33.2",
"lint-staged": "^15.0.1",
"postcss": "^8.4.31",
"prettier": "^2.8.0",
"pretty-quick": "^3.1.3",
"tailwindcss": "^3.3.3"
"eslint-plugin-react": "^7.34.1",
"lint-staged": "^15.2.2",
"postcss": "^8.4.37",
"prettier": "^2.8.8",
"pretty-quick": "^3.3.1",
"tailwindcss": "^3.4.1"
}
}
Binary file not shown.
+137 -50
View File
@@ -1,25 +1,54 @@
import React, { useState, useEffect } from "react";
import React, { useState, useEffect, lazy } from "react";
import { Routes, Route, BrowserRouter } from "react-router-dom";
import Pgsignup from "./routes/Pgsignup";
import Login from "./routes/Login";
import Microapp from "./routes/RemoteApp";
import Signup from "./routes/Signup";
import Form from "./routes/Form";
import Report from "./routes/Report";
import Dashboard from "./routes/Dashboard";
import Subscriptions from "./routes/PlanSubscriptions";
import { pdfjs } from "react-pdf";
import Login from "./pages/Login";
import Form from "./pages/Form";
import Report from "./pages/Report";
import Dashboard from "./pages/Dashboard";
import HomeLayout from "./layout/HomeLayout";
import UserProfile from "./routes/UserProfile";
import PageNotFound from "./routes/PageNotFound";
import ForgetPassword from "./routes/ForgetPassword";
import ChangePassword from "./routes/ChangePassword";
import ReportMicroapp from "./components/ReportMicroapp";
import LoadMf from "./routes/LoadMf";
import GenerateToken from "./routes/GenerateToken";
import PageNotFound from "./pages/PageNotFound";
import ValidateRoute from "./primitives/ValidateRoute";
import Webhook from "./routes/Webhook";
import Validate from "./primitives/Validate";
import TemplatePlaceholder from "./pages/TemplatePlaceholder";
import SignYourSelf from "./pages/SignyourselfPdf";
import DraftDocument from "./components/pdf/DraftDocument";
import PlaceHolderSign from "./pages/PlaceHolderSign";
import PdfRequestFiles from "./pages/PdfRequestFiles";
import LazyPage from "./primitives/LazyPage";
const DebugPdf = lazy(() => import("./pages/DebugPdf"));
const ForgetPassword = lazy(() => import("./pages/ForgetPassword"));
const GuestLogin = lazy(() => import("./pages/GuestLogin"));
const Pgsignup = lazy(() => import("./pages/Pgsignup"));
const Subscriptions = lazy(() => import("./pages/PlanSubscriptions"));
const ChangePassword = lazy(() => import("./pages/ChangePassword"));
const UserProfile = lazy(() => import("./pages/UserProfile"));
const Signup = lazy(() => import("./pages/Signup"));
const Opensigndrive = lazy(() => import("./pages/Opensigndrive"));
const ManageSign = lazy(() => import("./pages/Managesign"));
const GenerateToken = lazy(() => import("./pages/GenerateToken"));
const Webhook = lazy(() => import("./pages/Webhook"));
pdfjs.GlobalWorkerOptions.workerSrc = `//cdnjs.cloudflare.com/ajax/libs/pdf.js/${pdfjs.version}/pdf.worker.js`;
const Loader = () => {
return (
<div
style={{
height: "100vh",
display: "flex",
alignItems: "center",
justifyContent: "center"
}}
>
<div
style={{
fontSize: "45px",
color: "#3dd3e0"
}}
className="loader-37"
></div>
</div>
);
};
function App() {
const [isloading, setIsLoading] = useState(true);
useEffect(() => {
@@ -27,12 +56,16 @@ function App() {
}, []);
const handleCredentials = () => {
const appId = process.env.REACT_APP_APPID;
const baseurl = process.env.REACT_APP_SERVERURL;
const appId = process.env.REACT_APP_APPID
? process.env.REACT_APP_APPID
: "opensign";
const baseurl = process.env.REACT_APP_SERVERURL
? process.env.REACT_APP_SERVERURL
: window.location.origin + "/api/app";
const appName = "contracts";
try {
localStorage.setItem("BaseUrl12", `${baseurl}/`);
localStorage.setItem("AppID12", appId);
localStorage.setItem("baseUrl", `${baseurl}/`);
localStorage.setItem("parseAppId", appId);
localStorage.setItem("domain", appName);
setIsLoading(false);
} catch (error) {
@@ -43,51 +76,105 @@ function App() {
return (
<div className="bg-[#eef1f5]">
{isloading ? (
<div
style={{
height: "100vh",
display: "flex",
alignItems: "center",
justifyContent: "center"
}}
>
<div
style={{
fontSize: "45px",
color: "#3dd3e0"
}}
className="loader-37"
></div>
</div>
<Loader />
) : (
<BrowserRouter>
<Routes>
<Route element={<ValidateRoute />}>
<Route exact path="/" element={<Login />} />
<Route exact path="/signup" element={<Signup />} />
<Route path="/signup" element={<LazyPage Page={Signup} />} />
</Route>
<Route element={<Validate />}>
<Route exact path="/load/:remoteApp/*" element={<LoadMf />} />
<Route
path="/load/template/:templateId"
element={<TemplatePlaceholder />}
/>
<Route
exact
path="/load/placeholdersign/:docId"
element={<PlaceHolderSign />}
/>
<Route
exact
path="/load/recipientSignPdf/:docId/:contactBookId"
element={<PdfRequestFiles />}
/>
</Route>
<Route exact path="/loadmf/:remoteApp/*" element={<LoadMf />} />
<Route exact path="/forgetpassword" element={<ForgetPassword />} />
<Route
path="/loadmf/signmicroapp/login/:id/:userMail/:contactBookId/:serverUrl"
element={<LazyPage Page={GuestLogin} />}
/>
<Route
path="/login/:id/:userMail/:contactBookId/:serverUrl"
element={<LazyPage Page={GuestLogin} />}
/>
<Route path="/debugpdf" element={<LazyPage Page={DebugPdf} />} />
<Route
path="/forgetpassword"
element={<LazyPage Page={ForgetPassword} />}
/>
{process.env.REACT_APP_ENABLE_SUBSCRIPTION && (
<>
<Route exact path="/pgsignup" element={<Pgsignup />} />
<Route exact path="/subscription" element={<Subscriptions />} />
<Route
path="/pgsignup"
element={<LazyPage Page={Pgsignup} />}
/>
<Route
path="/subscription"
element={<LazyPage Page={Subscriptions} />}
/>
</>
)}
<Route element={<HomeLayout />}>
<Route path="/changepassword" element={<ChangePassword />} />
<Route path="/mf/:remoteApp/*" element={<Microapp />} />
<Route path="/asmf/:remoteApp/*" element={<Microapp />} />
<Route path="/rpmf/:remoteApp/*" element={<ReportMicroapp />} />
<Route
path="/changepassword"
element={<LazyPage Page={ChangePassword} />}
/>
<Route path="/form/:id" element={<Form />} />
<Route path="/report/:id" element={<Report />} />
<Route path="/dashboard/:id" element={<Dashboard />} />
<Route path="/profile" element={<UserProfile />} />
<Route path="/generatetoken" element={<GenerateToken />} />
<Route path="/webhook" element={<Webhook />} />
<Route
path="/profile"
element={<LazyPage Page={UserProfile} />}
/>
<Route
path="/opensigndrive"
element={<LazyPage Page={Opensigndrive} />}
/>
<Route
path="/managesign"
element={<LazyPage Page={ManageSign} />}
/>
<Route
path="/generatetoken"
element={<LazyPage Page={GenerateToken} />}
/>
<Route path="/webhook" element={<LazyPage Page={Webhook} />} />
<Route
path="/template/:templateId"
element={<TemplatePlaceholder />}
/>
{/* signyouself route with no rowlevel data using docId from url */}
<Route path="/signaturePdf/:docId" element={<SignYourSelf />} />
{/* draft document route to handle and navigate route page accordiing to document status */}
<Route path="/draftDocument" element={<DraftDocument />} />
{/* recipient placeholder set route with no rowlevel data using docId from url*/}
<Route
path="/placeHolderSign/:docId"
element={<PlaceHolderSign />}
/>
{/* for user signature (need your sign route) with row level data */}
<Route path="/pdfRequestFiles" element={<PdfRequestFiles />} />
{/* for user signature (need your sign route) with no row level data */}
<Route
path="/pdfRequestFiles/:docId"
element={<PdfRequestFiles />}
/>
{/* recipient signature route with no rowlevel data using docId from url */}
<Route
path="/recipientSignPdf/:docId/:contactBookId"
element={<PdfRequestFiles />}
/>
</Route>
<Route path="*" element={<PageNotFound />} />
</Routes>
-62
View File
@@ -1,62 +0,0 @@
import React from "react";
import ReactDOM from "react-dom/client";
import "./index.css";
import App from "./App";
import { Provider } from "react-redux";
import { store } from "./redux/store";
import { HTML5Backend } from "react-dnd-html5-backend";
import { TouchBackend } from "react-dnd-touch-backend";
import {
DndProvider,
TouchTransition,
MouseTransition,
Preview
} from "react-dnd-multi-backend";
import DragElement from "./microappComponent/DragElement";
import TagManager from "react-gtm-module";
const HTML5toTouch = {
backends: [
{
id: "html5",
backend: HTML5Backend,
transition: MouseTransition
},
{
id: "touch",
backend: TouchBackend,
options: { enableMouseEvents: true },
preview: true,
transition: TouchTransition
}
]
};
const generatePreview = (props) => {
const { item, style } = props;
const newStyle = {
...style
};
return (
<div style={newStyle}>
<DragElement {...item} />
</div>
);
};
if (process.env.REACT_APP_GTM) {
const tagManagerArgs = {
gtmId: process.env.REACT_APP_GTM
};
TagManager.initialize(tagManagerArgs);
}
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
<Provider store={store}>
<DndProvider options={HTML5toTouch}>
<Preview>{generatePreview}</Preview>
<App />
</DndProvider>
</Provider>
);

Before

Width:  |  Height:  |  Size: 4.4 KiB

After

Width:  |  Height:  |  Size: 4.4 KiB

Before

Width:  |  Height:  |  Size: 61 KiB

After

Width:  |  Height:  |  Size: 61 KiB

Before

Width:  |  Height:  |  Size: 234 KiB

After

Width:  |  Height:  |  Size: 234 KiB

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

@@ -3,7 +3,7 @@ import Parse from "parse";
import axios from "axios";
import { modalCancelBtnColor, modalSubmitBtnColor } from "../constant/const";
const AppendFormInForm = (props) => {
const AddSigner = (props) => {
const [name, setName] = useState("");
const [phone, setPhone] = useState("");
const [email, setEmail] = useState("");
@@ -49,8 +49,6 @@ const AppendFormInForm = (props) => {
e.preventDefault();
e.stopPropagation();
setIsLoader(true);
Parse.serverURL = parseBaseUrl;
Parse.initialize(parseAppId);
try {
const contactQuery = new Parse.Object("contracts_Contactbook");
contactQuery.set("Name", name);
@@ -314,4 +312,4 @@ const AppendFormInForm = (props) => {
);
};
export default AppendFormInForm;
export default AddSigner;
-2
View File
@@ -12,8 +12,6 @@ const AddUser = (props) => {
const [isUserExist, setIsUserExist] = useState(false);
const parseBaseUrl = localStorage.getItem("baseUrl");
const parseAppId = localStorage.getItem("parseAppId");
Parse.serverURL = parseBaseUrl;
Parse.initialize(parseAppId);
const checkUserExist = async () => {
try {
@@ -1,49 +0,0 @@
import React, { Component } from "react";
export class ErrorBoundary extends Component {
constructor(props) {
super(props);
this.state = { hasError: false };
}
static getDerivedStateFromError() {
return {
hasError: true
};
}
componentDidCatch(error, info) {
console.log(error);
console.log(info);
}
render() {
if (this.state.hasError) {
return (
<div className="p-2">
<div
style={{
height: "100vh",
display: "flex",
flexFlow: "column"
}}
>
<h1
style={{
fontSize: "2em",
fontFamily: "sans-serif",
textShadow: "0 0 20px black"
}}
>
Something went wrong.
</h1>
</div>
</div>
);
}
return this.props.children;
}
}
export default ErrorBoundary;
+4 -8
View File
@@ -11,8 +11,6 @@ const Header = ({ showSidebar }) => {
let applogo = localStorage.getItem("appLogo") || "";
let username = localStorage.getItem("username");
const image = localStorage.getItem("profileImg") || dp;
const [parseBaseUrl] = useState(localStorage.getItem("baseUrl"));
const [parseAppId] = useState(localStorage.getItem("parseAppId"));
const [isOpen, setIsOpen] = useState(false);
@@ -22,8 +20,6 @@ const Header = ({ showSidebar }) => {
const closeDropdown = () => {
setIsOpen(false);
Parse.serverURL = parseBaseUrl;
Parse.initialize(parseAppId);
Parse.User.logOut();
let appdata = localStorage.getItem("userSettings");
let applogo = localStorage.getItem("appLogo");
@@ -32,8 +28,8 @@ const Header = ({ showSidebar }) => {
let PageLanding = localStorage.getItem("PageLanding");
let domain = localStorage.getItem("domain");
let _appName = localStorage.getItem("_appName");
let baseUrl = localStorage.getItem("BaseUrl12");
let appid = localStorage.getItem("AppID12");
let baseUrl = localStorage.getItem("baseUrl");
let appid = localStorage.getItem("parseAppId");
localStorage.clear();
@@ -44,8 +40,8 @@ const Header = ({ showSidebar }) => {
localStorage.setItem("PageLanding", PageLanding);
localStorage.setItem("domain", domain);
localStorage.setItem("userSettings", appdata);
localStorage.setItem("BaseUrl12", baseUrl);
localStorage.setItem("AppID12", appid);
localStorage.setItem("baseUrl", baseUrl);
localStorage.setItem("parseAppId", appid);
navigation("/");
};
+9 -9
View File
@@ -1,6 +1,6 @@
import React, { useState, useRef } from "react";
import Parse from "parse";
import jwtDecode from "jwt-decode";
import { jwtDecode } from "jwt-decode";
import { useScript } from "../hook/useScript";
import ModalUi from "../primitives/ModalUi";
import { modalCancelBtnColor, modalSubmitBtnColor } from "../constant/const";
@@ -48,8 +48,8 @@ const GoogleSignInBtn = ({
if (Parse.User.current()) {
await Parse.User.logOut();
}
let baseUrl = localStorage.getItem("BaseUrl12");
let appid = localStorage.getItem("AppID12");
let baseUrl = localStorage.getItem("baseUrl");
let appid = localStorage.getItem("parseAppId");
let applogo = localStorage.getItem("appLogo");
let domain = localStorage.getItem("domain");
let appversion = localStorage.getItem("appVersion");
@@ -63,8 +63,8 @@ const GoogleSignInBtn = ({
localStorage.clear();
localStorage.setItem("BaseUrl12", baseUrl);
localStorage.setItem("AppID12", appid);
localStorage.setItem("baseUrl", baseUrl);
localStorage.setItem("parseAppId", appid);
localStorage.setItem("appLogo", applogo);
localStorage.setItem("domain", domain);
localStorage.setItem("appversion", appversion);
@@ -191,8 +191,8 @@ const GoogleSignInBtn = ({
let PageLanding = localStorage.getItem("PageLanding");
let domain = localStorage.getItem("domain");
let _appName = localStorage.getItem("_appName");
let baseUrl = localStorage.getItem("BaseUrl12");
let appid = localStorage.getItem("AppID12");
let baseUrl = localStorage.getItem("baseUrl");
let appid = localStorage.getItem("parseAppId");
localStorage.clear();
@@ -203,8 +203,8 @@ const GoogleSignInBtn = ({
localStorage.setItem("PageLanding", PageLanding);
localStorage.setItem("domain", domain);
localStorage.setItem("userSettings", appdata);
localStorage.setItem("BaseUrl12", baseUrl);
localStorage.setItem("AppID12", appid);
localStorage.setItem("baseUrl", baseUrl);
localStorage.setItem("parseAppId", appid);
};
return (
<div style={{ position: "relative" }}>
@@ -1,9 +1,7 @@
import React from "react";
import { Document, Page, pdfjs } from "react-pdf";
import { Document, Page } from "react-pdf";
import { Stage, Layer, Rect } from "react-konva";
const RenderDebugPdf = (props) => {
pdfjs.GlobalWorkerOptions.workerSrc = `//cdnjs.cloudflare.com/ajax/libs/pdf.js/${pdfjs.version}/pdf.worker.js`;
return (
<div>
<div
@@ -29,7 +27,7 @@ const RenderDebugPdf = (props) => {
onMouseMove={props.handleMouseMoveDiv}
>
<Document
onLoadError={(e) => {
onLoadError={() => {
const load = {
status: false,
type: "failed"
@@ -66,6 +64,7 @@ const RenderDebugPdf = (props) => {
.map((value) => {
return (
<Rect
key={value.key}
x={value.x}
y={value.y}
width={value.width}
@@ -1,66 +0,0 @@
import useFederatedComponent from "mf-cra";
import React, { Suspense, useEffect } from "react";
import { useParams } from "react-router-dom";
const MicroappModal = () => {
const { remoteApp } = useParams();
useEffect(() => {
return () => localStorage.removeItem("rowlevel");
}, []);
let paramString = remoteApp;
let queryString = new URLSearchParams(paramString);
let obj = {};
for (const [key, value] of queryString.entries()) {
// console.log("value ", key + ":" + value);
if (key === "remoteUrl") {
const url = window.location.origin + "/mfbuild/remoteEntry.js";
// console.log("atob(value) ", atob(value))
obj = { ...obj, [key]: url };
} else {
if (key === "moduleToLoad") {
obj = { ...obj, [key]: "./" + value };
} else {
obj = { ...obj, [key]: value };
}
}
}
// console.log("app ", remoteApp);
const { Component: RemoteComponent } = useFederatedComponent(obj);
// console.log("RemoteComponent ", RemoteComponent);
return (
<div className="w-full h-full flex items-center justify-center ">
<div className="w-full">
<Suspense
fallback={
<div style={{ height: "300px" }}>
<div
style={{
marginLeft: "45%",
marginTop: "150px",
fontSize: "45px",
color: "#3dd3e0"
}}
className="loader-37"
></div>
</div>
}
>
<div
style={{
backgroundColor: "#ffffff",
width: "100%",
overflow: "hidden",
minHeight: "50vh"
}}
>
{RemoteComponent && <RemoteComponent />}
</div>
</Suspense>
</div>
</div>
);
};
export default MicroappModal;
+3 -13
View File
@@ -1,21 +1,11 @@
import React from "react";
import { Helmet } from "react-helmet";
function Title(props) {
function Title({ title, drive }) {
return (
<Helmet>
<title>{`${props.title} - OpenSign™`}</title>
{/* <title>
{`${localStorage.getItem("appTitle") ? localStorage.getItem("appTitle") : ""} - ${props.title}`}
</title> */}
<meta
name="description"
content={`${props.title} - OpenSign™`}
/>
{/* <meta
name="description"
content={`${localStorage.getItem("appTitle")} - ${props.title}`}
/> */}
<title>{drive ? title : `${title} - OpenSign™`}</title>
<meta name="description" content={`${title} - OpenSign™`} />
<link
rel="icon"
type="image/png"
@@ -0,0 +1,47 @@
import React from "react";
import "../../styles/loader.css";
import { useNavigate } from "react-router-dom";
import { openInNewTab } from "../../constant/Utils";
const DashboardButton = (props) => {
const navigate = useNavigate();
function openReport() {
if (props.Data && props.Data.Redirect_type) {
const Redirect_type = props.Data.Redirect_type;
const id = props.Data.Redirect_id;
if (Redirect_type === "Form") {
navigate(`/form/${id}`);
} else if (Redirect_type === "Report") {
navigate(`/report/${id}`);
} else if (Redirect_type === "Url") {
openInNewTab(id);
}
}
}
return (
<div
onClick={() => openReport()}
className={`${
props.Data && props.Data.Redirect_type
? "cursor-pointer"
: "cursor-default"
} w-full px-3 py-2 flex text-white rounded-md shadow overflow-hidden`}
>
<div className="flex items-center justify-start gap-5">
<span className="rounded-full bg-black bg-opacity-20 w-[60px] h-[60px] self-start flex justify-center items-center">
<i
className={`${
props.Icon ? props.Icon : "fa fa-solid fa-info"
} text-[25px] lg:text-[30px]`}
></i>
</span>
<div className="">
<div className="text-base lg:text-lg text-black"> {props.Label}</div>
</div>
</div>
</div>
);
};
export default DashboardButton;
@@ -4,6 +4,7 @@ import Parse from "parse";
import getReplacedHashQuery from "../../constant/getReplacedHashQuery";
import "../../styles/loader.css";
import { useNavigate } from "react-router-dom";
import Tooltip from "../../primitives/Tooltip";
const DashboardCard = (props) => {
const navigate = useNavigate();
@@ -24,9 +25,6 @@ const DashboardCard = (props) => {
};
let body = {};
let currentUser;
Parse.serverURL = parseBaseUrl;
Parse.initialize(parseAppId);
let currentUser1 = Parse.User.current();
currentUser = currentUser1.id;
let res;
@@ -82,8 +80,6 @@ const DashboardCard = (props) => {
} else {
setLoading(true);
try {
Parse.serverURL = parseBaseUrl;
Parse.initialize(parseAppId);
const currentUser = Parse.User.current();
let reg1 = /(\#.*?\#)/gi; // eslint-disable-line
let _query = props.Data.query;
@@ -223,8 +219,6 @@ const DashboardCard = (props) => {
if (restr.includes("#")) {
try {
Parse.serverURL = parseBaseUrl;
Parse.initialize(parseAppId);
const currentUser = Parse.User.current();
let res;
if (localStorage.getItem("Extand_Class")) {
@@ -342,7 +336,7 @@ const DashboardCard = (props) => {
props.Data && props.Data.Redirect_type
? "cursor-pointer"
: "cursor-default"
} w-full h-[140px] px-3 pt-4 pb-10 text-white rounded-md shadow overflow-hidden`}
} 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">
<span className="rounded-full bg-black bg-opacity-20 w-[60px] h-[60px] self-start flex justify-center items-center">
@@ -359,6 +353,9 @@ const DashboardCard = (props) => {
</div>
</div>
</div>
<div className="text-xs absolute top-2 right-1">
<Tooltip id={props.Label} iconColor={"white"} message={props?.Data?.tourMessage} />
</div>
</div>
);
};
@@ -45,18 +45,16 @@ function DashboardReport(props) {
setActions(json.actions);
setReportName(json.reportName);
setHeading(json.heading);
Parse.serverURL = localStorage.getItem("BaseUrl12");
Parse.initialize(localStorage.getItem("AppID12"));
const currentUser = Parse.User.current().id;
const headers = {
"Content-Type": "application/json",
"X-Parse-Application-Id": localStorage.getItem("AppID12"),
"X-Parse-Application-Id": localStorage.getItem("parseAppId"),
sessiontoken: localStorage.getItem("accesstoken")
};
try {
const params = { reportId: id, skip: skipUserRecord, limit: limit };
const url = `${localStorage.getItem("BaseUrl12")}/functions/getReport`;
const url = `${localStorage.getItem("baseUrl")}/functions/getReport`;
const res = await axios.post(url, params, {
headers: headers,
signal: abortController.signal // is used to cancel fetch query
@@ -1,21 +1,71 @@
import React, { Suspense, lazy } from "react";
import ErrorBoundary from "../ErrorBoundary";
const DashboardButton = lazy(() => import("./DashboardButton"));
const DashboardCard = lazy(() => import("./DashboardCard"));
const DashboardReport = lazy(() => import("./DashboardReport"));
const buttonList = [
{
label: "Sign yourself",
redirectId: "sHAnZphf69",
redirectType: "Form",
icon: "fas fa-pen-nib"
},
{
label: "Request signature",
redirectId: "8mZzFxbG1z",
redirectType: "Form",
icon: "fa-solid fa-paper-plane"
}
];
const GetDashboard = (props) => {
const Button = ({ label, redirectId, redirectType, icon }) => (
<div className={"bg-white rounded-md shadow w-full"}>
<Suspense
fallback={
<div style={{ height: "300px" }}>
<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) => {
switch (col.widget.type) {
case "Card":
return (
<div
className={"bg-[#2ed8b6] rounded-md shadow mb-4 md:mb-0"}
className={"bg-[#2ed8b6] rounded-md shadow mb-3 md:mb-0"}
data-tut={col.widget.data.tourSection}
style={{ background: col.widget.bgColor }}
>
<Suspense fallback={<div>please wait</div>}>
<Suspense
fallback={
<div style={{ height: "300px" }}>
<div
style={{
marginLeft: "45%",
marginTop: "150px",
fontSize: "45px",
color: "#3dd3e0"
}}
className="loader-37"
></div>
</div>
}
>
<DashboardCard
Icon={col.widget.icon}
Label={col.widget.label}
@@ -31,7 +81,7 @@ const GetDashboard = (props) => {
return (
<div data-tut={col.widget.data.tourSection}>
<Suspense fallback={<div>please wait</div>}>
<div className="mb-4 md:mb-0">
<div className="mb-3 md:mb-0">
<DashboardReport Record={col.widget} />
</div>
</Suspense>
@@ -47,7 +97,7 @@ const GetDashboard = (props) => {
case "Card":
return (
<div
className={"bg-[#2ed8b6] rounded-md shadow mb-4 md:mb-0"}
className={"bg-[#2ed8b6] rounded-md shadow mb-3 md:mb-0"}
style={{ background: col.widget.bgColor }}
>
<Suspense fallback={<div>please wait</div>}>
@@ -65,7 +115,7 @@ const GetDashboard = (props) => {
case "report": {
return (
<Suspense fallback={<div>please wait</div>}>
<div className="mb-4 md:mb-0">
<div className="mb-3 md:mb-0">
<DashboardReport Record={col.widget} />
</div>
</Suspense>
@@ -76,25 +126,39 @@ const GetDashboard = (props) => {
}
};
return (
<ErrorBoundary>
<div>
{props.dashboard.map((val, key) => (
<div key={"a" + key} className="row">
{val.columns.map((col, i) =>
col.widget.data && col.widget.data.tourSection ? (
<div key={i} className={props.classnameArray[key][i]}>
{renderSwitchWithTour(col)}
</div>
) : (
<div key={i} className={props.classnameArray[key][i]}>
{renderSwitch(col)}
</div>
)
)}
</div>
))}
<div>
<div className="mb-3">
<div
data-tut={"tourbutton"}
className="flex flex-col md:flex-row gap-6 md:gap-8"
>
{buttonList.map((btn) => (
<Button
key={btn.label}
label={btn.label}
redirectType={btn.redirectType}
redirectId={btn.redirectId}
icon={btn.icon}
/>
))}
</div>
</div>
</ErrorBoundary>
{props.dashboard.map((val, key) => (
<div key={"a" + key} className="row">
{val.columns.map((col, i) =>
col.widget.data && col.widget.data.tourSection ? (
<div key={i} className={props.classnameArray[key][i]}>
{renderSwitchWithTour(col)}
</div>
) : (
<div key={i} className={props.classnameArray[key][i]}>
{renderSwitch(col)}
</div>
)
)}
</div>
))}
</div>
);
};
@@ -1,28 +1,18 @@
import React, { useState, useEffect, useRef } from "react";
import folder from "../../../assests/folder.png";
import "../LegaDrive.css";
import draftDoc from "../../../assests/draftDoc1.png";
import pdfLogo from "../../../assests/pdf3.png";
import folder from "../../assets/images/folder.png";
import "../../styles/opensigndrive.css";
import pdfLogo from "../../assets/images/pdf3.png";
import axios from "axios";
import * as ContextMenu from "@radix-ui/react-context-menu";
import { saveAs } from "file-saver";
import { getHostUrl } from "../../../utils/Utils";
import { useNavigate } from "react-router-dom";
import Table from "react-bootstrap/Table";
import * as HoverCard from "@radix-ui/react-hover-card";
import SelectFolder from "../../../premitives/SelectFolder";
import ModalUi from "../../../premitives/ModalUi";
import { themeColor } from "../../../utils/ThemeColor/backColor";
import ModalUi from "../../primitives/ModalUi";
import { themeColor } from "../../constant/const";
import FolderModal from "../shared/fields/FolderModal";
function PdfFileComponent({
pdfData,
setFolderName,
setDocId,
setIsLoading,
setPdfData,
isList,
setIsAlert
}) {
function DriveBody(props) {
const [rename, setRename] = useState("");
const [renameValue, setRenameValue] = useState("");
const inputRef = useRef(null);
@@ -40,7 +30,6 @@ function PdfFileComponent({
//to focus input box on press rename to change doc name
useEffect(() => {
if (rename && inputRef.current) {
// console.log("ref", inputRef.current)
setTimeout(() => {
inputRef.current.focus();
}, 10);
@@ -53,28 +42,25 @@ function PdfFileComponent({
name: data.Name,
objectId: data.objectId
};
setFolderName((prev) => [...prev, folderData]);
const loadObj = {
props.setFolderName((prev) => [...prev, folderData]);
props.setIsLoading({
isLoad: true,
message: "This might take some time"
};
setIsLoading(loadObj);
setDocId(data.objectId);
});
props.setDocId(data.objectId);
props.setPdfData([]);
props.setSkip(0);
};
//function for change doc name and update doc name in _document class
const handledRenameDoc = async (data) => {
setRename("");
const trimmedValue = renameValue.trim();
if (trimmedValue.length > 0) {
const updateName = {
Name: renameValue
};
const docId = data.objectId;
const docData = pdfData;
const docData = props.pdfData;
const updatedData = docData.map((item) => {
if (item.objectId === docId) {
// If the item's ID matches the target ID, update the name
@@ -83,8 +69,7 @@ function PdfFileComponent({
// If the item's ID doesn't match, keep it unchanged
return item;
});
setPdfData(updatedData);
props.setPdfData(updatedData);
await axios
.put(
`${localStorage.getItem("baseUrl")}classes/${localStorage.getItem(
@@ -99,12 +84,13 @@ function PdfFileComponent({
}
}
)
.then((result) => {
.then(() => {
// const res = result.data;
// console.log("res", res);
})
.catch((err) => {
setIsAlert({
console.log("Err ", err);
props.setIsAlert({
isShow: true,
alertMessage: "something went wrong"
});
@@ -114,57 +100,66 @@ function PdfFileComponent({
//function for navigate user to microapp-signature component
const checkPdfStatus = async (data) => {
const hostUrl = getHostUrl();
const signerExist = data.Signers && data.Signers;
const isDecline = data.IsDeclined && data.IsDeclined;
const isPlaceholder = data.Placeholders && data.Placeholders;
const signedUrl = data.SignedUrl;
//checking if document has completed and request signature flow
if (data?.IsCompleted && signerExist?.length > 0) {
navigate(`${hostUrl}pdfRequestFiles/${data.objectId}`);
navigate(`/pdfRequestFiles/${data.objectId}`);
}
//checking if document has completed and signyour-self flow
else if (!signerExist && !isPlaceholder) {
navigate(`${hostUrl}signaturePdf/${data.objectId}`);
navigate(`/signaturePdf/${data.objectId}`);
}
//checking if document has declined by someone
else if (isDecline) {
navigate(`${hostUrl}pdfRequestFiles/${data.objectId}`);
navigate(`/pdfRequestFiles/${data.objectId}`);
//checking draft type document
} else if (
signerExist?.length > 0 &&
isPlaceholder?.length > 0 &&
!signedUrl
) {
navigate(`/placeHolderSign/${data.objectId}`);
}
//Inprogress document
else if (isPlaceholder?.length > 0 && signerExist?.length > 0) {
navigate(`${hostUrl}pdfRequestFiles/${data.objectId}`);
navigate(`/pdfRequestFiles/${data.objectId}`);
} //placeholder draft document
else if (
(signerExist?.length > 0 &&
(!isPlaceholder || isPlaceholder?.length === 0)) ||
((!signerExist || signerExist?.length === 0) && isPlaceholder?.length > 0)
) {
navigate(`${hostUrl}placeHolderSign/${data.objectId}`);
navigate(`/placeHolderSign/${data.objectId}`);
}
};
const handleMenuItemClick = (selectType, data) => {
switch (selectType) {
case "Download":
case "Download": {
const pdfName = data && data.Name;
const pdfUrl = data && data.SignedUrl ? data.SignedUrl : data.URL;
saveAs(pdfUrl, `${sanitizeFileName(pdfName)}_signed_by_OpenSign™.pdf`);
break;
case "Rename":
}
case "Rename": {
setRenameValue(data.Name);
setRename(data.objectId);
break;
case "Delete":
}
case "Delete": {
setIsDeleteDoc(true);
setSelectDoc(data);
break;
case "Move":
}
case "Move": {
handleMoveDocument(data);
break;
}
default:
null;
}
};
//function for delete document
@@ -192,12 +187,13 @@ function PdfFileComponent({
.then((result) => {
const res = result.data;
if (res) {
const updatedData = pdfData.filter((x) => x.objectId !== docId);
setPdfData(updatedData);
const updatedData = props.pdfData.filter((x) => x.objectId !== docId);
props.setPdfData(updatedData);
}
})
.catch((err) => {
setIsAlert({
console.log("Err ", err);
props.setIsAlert({
isShow: true,
alertMessage: "something went wrong"
});
@@ -218,8 +214,8 @@ function PdfFileComponent({
? true
: false
: selecFolderId
? false
: true;
? false
: true;
if (!checkExist) {
if (moveFolderId) {
updateData = {
@@ -254,10 +250,10 @@ function PdfFileComponent({
// console.log("Listdata ", Listdata);
const res = Listdata.data;
if (res) {
const updatedData = pdfData.filter(
const updatedData = props.pdfData.filter(
(x) => x.objectId !== updateDocId
);
setPdfData(updatedData);
props.setPdfData(updatedData);
}
})
.catch((err) => {
@@ -282,21 +278,17 @@ function PdfFileComponent({
}
};
const handleDraftDoc = (data) => {
window.location.hash = `/mf/remoteUrl=aHR0cHM6Ly9xaWstYWktb3JnLmdpdGh1Yi5pby9MZWdhR2VuaWUtTWljcm9hcHBWMi9yZW1vdGVFbnRyeS5qcw==&moduleToLoad=AppRoutes&remoteName=legageniemicroapp/legagenie?${data.objectId}`;
};
//component to handle type of document and render according to type
const handleFolderData = (data, ind, listType) => {
let createddate, status, isDecline, signerExist, isComplete, isPlaceholder;
let createddate, status, isDecline, signerExist, isComplete;
if (data.Type !== "Folder") {
const expireDate = data.ExpiryDate && data.ExpiryDate.iso;
const createdDate = data.createdAt && data.createdAt;
createddate = new Date(createdDate).toLocaleDateString();
isComplete = data.IsCompleted && data.IsCompleted ? true : false;
isDecline = data.IsDeclined && data.IsDeclined;
isPlaceholder = data.Placeholders && data.Placeholders;
signerExist = data.Signers && data.Signers;
const signedUrl = data.SignedUrl;
const expireUpdateDate = new Date(expireDate).getTime();
const currDate = new Date().getTime();
@@ -309,12 +301,7 @@ function PdfFileComponent({
status = "Completed";
} else if (isDecline) {
status = "Declined";
} else if (!signerExist || signerExist?.length === 0) {
status = "Draft";
} else if (
signerExist?.length > 0 &&
(!isPlaceholder || isPlaceholder?.length === 0)
) {
} else if (!signedUrl) {
status = "Draft";
} else if (isExpire) {
status = "Expired";
@@ -357,25 +344,6 @@ function PdfFileComponent({
<td>_</td>
<td>_</td>
</tr>
) : data.Type === "AIDoc" ? (
<tr onClick={() => handleDraftDoc(data)}>
<td
style={{ cursor: "pointer", display: "flex", alignItems: "center" }}
>
<i
className="fa fa-file-text"
style={{ color: "#0ea3ed", marginRight: "8px", fontSize: "26px" }}
></i>
<span style={{ fontSize: "12px", fontWeight: "500" }}>
{data.Name}
</span>
</td>
<td>{createddate}</td>
<td>LegaGenie Draft</td>
<td>_</td>
<td>_</td>
</tr>
) : (
<tr onClick={() => checkPdfStatus(data)}>
<td
@@ -464,72 +432,7 @@ function PdfFileComponent({
onClick={() => handleMenuItemClick("Rename", data)}
className="ContextMenuItem"
>
<i class="fa-solid fa-font"></i>
<span style={{ marginLeft: "8px" }}>Rename</span>
</ContextMenu.Item>
</ContextMenu.Content>
</ContextMenu.Portal>
</ContextMenu.Root>
</div>
) : data.Type === "AIDoc" ? (
<div key={ind} className="folderBox">
<ContextMenu.Root>
<ContextMenu.Trigger className="ContextMenuTrigger">
<div
style={{
display: "flex",
flexDirection: "column",
cursor: "pointer"
}}
>
<img
alt="no img"
onClick={() => handleDraftDoc(data)}
src={draftDoc}
width={100}
height={103}
/>
{rename === data.objectId ? (
<input
onFocus={() => {
inputRef.current.setSelectionRange(0, 0);
const input = inputRef.current;
if (input) {
input.select();
}
}}
autoFocus={true}
type="text"
onBlur={() => handledRenameDoc(data)}
onKeyDown={(e) => handleEnterPress(e, data)}
ref={inputRef}
defaultValue={renameValue}
// value={renameValue}
onChange={(e) => setRenameValue(e.target.value)}
style={{
width: "100px",
border: "1.5px solid black",
borderRadius: "2px",
fontSize: "10px"
}}
/>
) : (
<span className="foldName">{data.Name}</span>
)}
</div>
</ContextMenu.Trigger>
<ContextMenu.Portal>
<ContextMenu.Content
className="ContextMenuContent"
sideOffset={5}
align="end"
>
<ContextMenu.Item
onClick={() => handleMenuItemClick("Rename", data)}
className="ContextMenuItem"
>
<i class="fa-solid fa-font"></i>
<i className="fa-solid fa-font"></i>
<span style={{ marginLeft: "8px" }}>Rename</span>
</ContextMenu.Item>
</ContextMenu.Content>
@@ -615,7 +518,7 @@ function PdfFileComponent({
onClick={() => handleMenuItemClick(menu.type, data)}
className="ContextMenuItem"
>
<i class={menu.icon}></i>
<i className={menu.icon}></i>
<span style={{ marginLeft: "8px" }}>{menu.type}</span>
</ContextMenu.Item>
);
@@ -657,7 +560,7 @@ function PdfFileComponent({
//component to handle type of document and render according to type
return (
<>
{isList ? (
{props.isList ? (
<div className="container" style={{ overflowX: "auto" }}>
<Table striped bordered hover>
<thead>
@@ -670,7 +573,7 @@ function PdfFileComponent({
</tr>
</thead>
<tbody>
{pdfData.map((data, ind) => {
{props.pdfData.map((data, ind) => {
return (
<React.Fragment key={ind}>
{handleFolderData(data, ind, "table")}
@@ -682,7 +585,7 @@ function PdfFileComponent({
</div>
) : (
<div className="pdfContainer">
{pdfData.map((data, ind) => {
{props.pdfData.map((data, ind) => {
return (
<div className="box" key={ind}>
{handleFolderData(data, ind, "list")}
@@ -691,18 +594,19 @@ function PdfFileComponent({
})}
</div>
)}
{isOpenMoveModal && (
<SelectFolder
<FolderModal
onSuccess={handleMoveFolder}
isOpenModal={isOpenMoveModal}
folderCls={"contracts_Document"}
setIsOpenMoveModal={setIsOpenMoveModal}
setPdfData={setPdfData}
setPdfData={props.setPdfData}
/>
)}
<ModalUi
isOpen={isDeleteDoc}
headerColor={themeColor()}
headerColor={themeColor}
title={"Delete Document"}
handleClose={() => {
setIsDeleteDoc(false);
@@ -726,7 +630,7 @@ function PdfFileComponent({
handleDeleteDocument(selectDoc);
}}
style={{
background: themeColor(),
background: themeColor,
color: "white"
}}
type="button"
@@ -749,4 +653,4 @@ function PdfFileComponent({
);
}
export default PdfFileComponent;
export default DriveBody;
@@ -1,5 +1,5 @@
import React from "react";
import ModalUi from "../../premitives/ModalUi";
import ModalUi from "../../primitives/ModalUi";
const AddRoleModal = (props) => {
return (
@@ -1,7 +1,5 @@
import React, { useEffect, useState } from "react";
import "./certificate.css";
import opensignLogo from "../../assests/open-sign-logo.png";
import opensignLogo from "../../assets/images/logo.png";
import {
Page,
Text,
@@ -18,6 +16,7 @@ function Certificate({ pdfData }) {
useEffect(() => {
handleSignerData();
// eslint-disable-next-line
}, []);
const handleSignerData = () => {
@@ -1,11 +1,6 @@
import React from "react";
function DefaultSignature({
themeColor,
defaultSignImg,
xyPostion,
setDefaultSignAlert
}) {
import { themeColor } from "../../constant/const";
function DefaultSignature({ defaultSignImg, xyPostion, setDefaultSignAlert }) {
const confirmToaddDefaultSign = () => {
if (xyPostion.length > 0) {
setDefaultSignAlert({
@@ -25,7 +20,7 @@ function DefaultSignature({
<div>
<div
style={{
background: themeColor(),
background: themeColor,
color: "white",
padding: "5px",
fontFamily: "sans-serif",
@@ -58,7 +53,7 @@ function DefaultSignature({
</div>
<button
style={{
background: themeColor(),
background: themeColor,
color: "white",
marginTop: "20px",
cursor: "pointer",
@@ -1,12 +1,12 @@
import React, { useEffect, useState } from "react";
import { useNavigate } from "react-router-dom";
import Loader from "./component/loader";
import { contractDocument, getHostUrl } from "../utils/Utils";
import Loader from "../../primitives/LoaderWithMsg";
import { contractDocument } from "../../constant/Utils";
import HandleError from "../../primitives/HandleError";
function DraftDocument() {
const navigate = useNavigate();
const [pdfDetails, setPdfDetails] = useState([]);
const [isLoading, setIsLoading] = useState({
isLoad: true,
isLoader: true,
message: "This might take some time"
});
@@ -19,68 +19,77 @@ function DraftDocument() {
: rowLevel?.objectId && rowLevel.objectId;
useEffect(() => {
if (docId) {
getDocumentDetails();
}
getDocumentDetails();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
//get document details
const getDocumentDetails = async () => {
//getting document details
const documentData = await contractDocument(docId);
if (documentData && documentData.length > 0) {
setPdfDetails(documentData);
const loadObj = {
isLoad: false
};
setIsLoading(loadObj);
handleDraftDoc(documentData);
} else if (
documentData === "Error: Something went wrong!" ||
(documentData.result && documentData.result.error)
) {
alert("Error: Something went wrong!");
setIsLoading({
isLoader: false,
message: "Error: Something went wrong!"
});
} else {
alert("No data found!");
setIsLoading({
isLoader: false,
message: "No data found!"
});
}
};
//check document type and render on signyour self and placeholder route
const handleDraftDoc = () => {
const data = pdfDetails[0];
const hostUrl = getHostUrl();
const handleDraftDoc = (documentData) => {
const data = documentData[0];
const signerExist = data.Signers && data.Signers;
const isDecline = data.IsDeclined && data.IsDeclined;
const isPlaceholder = data.Placeholders && data.Placeholders;
const signedUrl = data.SignedUrl;
//checking if document has completed and request signature flow
if (data?.IsCompleted && signerExist?.length > 0) {
navigate(`${hostUrl}pdfRequestFiles/${data.objectId}`);
navigate(`/pdfRequestFiles/${data.objectId}`);
}
//checking if document has completed and signyour-self flow
else if (!signerExist && !isPlaceholder) {
navigate(`${hostUrl}signaturePdf/${data.objectId}`);
navigate(`/signaturePdf/${data.objectId}`);
}
//checking if document has declined by someone
else if (isDecline) {
navigate(`${hostUrl}pdfRequestFiles/${data.objectId}`);
navigate(`/pdfRequestFiles/${data.objectId}`);
//checking draft type document
} else if (
signerExist?.length > 0 &&
isPlaceholder?.length > 0 &&
!signedUrl
) {
navigate(`/placeHolderSign/${data.objectId}`);
}
//Inprogress document
else if (isPlaceholder?.length > 0 && signerExist?.length > 0) {
navigate(`${hostUrl}pdfRequestFiles/${data.objectId}`);
navigate(`/pdfRequestFiles/${data.objectId}`);
} //placeholder draft document
else if (
(signerExist?.length > 0 &&
(!isPlaceholder || isPlaceholder?.length === 0)) ||
((!signerExist || signerExist?.length === 0) && isPlaceholder?.length > 0)
) {
navigate(`${hostUrl}placeHolderSign/${data.objectId}`);
navigate(`/placeHolderSign/${data.objectId}`);
}
};
return (
<div>
{isLoading.isLoad ? <Loader isLoading={isLoading} /> : handleDraftDoc()}
{isLoading.isLoader ? (
<Loader isLoading={isLoading} />
) : (
<HandleError handleError={isLoading.message} />
)}
</div>
);
}
@@ -0,0 +1,13 @@
import React from "react";
import { getWidgetType, widgets } from "../../constant/Utils";
function DragElement(item) {
const getWidgets = widgets;
const filterWidgetPreview = getWidgets.filter(
(data) => data.type === item?.text
);
return <div>{getWidgetType(filterWidgetPreview[0])}</div>;
}
export default DragElement;
@@ -0,0 +1,425 @@
import React, { useEffect, useState } from "react";
import { themeColor } from "../../constant/const";
import ModalUi from "../../primitives/ModalUi";
import { radioButtonWidget } from "../../constant/Utils";
import PremiumAlertHeader from "../../primitives/PremiumAlertHeader";
function DropdownWidgetOption(props) {
const [dropdownOptionList, setDropdownOptionList] = useState([
"option-1",
"option-2"
]);
const [minCount, setMinCount] = useState(0);
const [maxCount, setMaxCount] = useState(0);
const [dropdownName, setDropdownName] = useState(props.type);
const [isReadOnly, setIsReadOnly] = useState(false);
const [isHideLabel, setIsHideLabel] = useState(false);
const [status, setStatus] = useState("required");
const [defaultValue, setDefaultValue] = useState("");
const statusArr = ["required", "optional"];
const [defaultCheckbox, setDefaultCheckbox] = useState([]);
const resetState = () => {
setDropdownOptionList(["option-1", "option-2"]);
setDropdownName(props.type);
setIsReadOnly(false);
setIsHideLabel(false);
setMinCount(0);
setMaxCount(0);
setDefaultCheckbox([]);
setDefaultValue("");
};
useEffect(() => {
if (
props.currWidgetsDetails?.options?.name &&
props.currWidgetsDetails?.options?.values
) {
setDropdownName(props.currWidgetsDetails?.options?.name);
setDropdownOptionList(props.currWidgetsDetails?.options?.values);
setMinCount(
props.currWidgetsDetails?.options?.validation?.minRequiredCount
);
setMaxCount(
props.currWidgetsDetails?.options?.validation?.maxRequiredCount
);
setIsReadOnly(props.currWidgetsDetails?.options?.isReadOnly);
setIsHideLabel(props.currWidgetsDetails?.options?.isHideLabel);
setStatus(props.currWidgetsDetails?.options?.status || "required");
setDefaultValue(props.currWidgetsDetails?.options?.defaultValue || "");
setDefaultCheckbox(props.currWidgetsDetails?.options?.defaultValue || []);
} else {
setStatus("required");
resetState();
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [props.currWidgetsDetails]);
const handleInputChange = (index, value) => {
setDropdownOptionList((prevInputs) => {
const newInputs = [...prevInputs];
newInputs[index] = value;
return newInputs;
});
};
//function add add checkbox option and add width of checkbox
const handleAddInput = () => {
const deleteOption = false;
const addOption = true;
setDropdownOptionList((prevInputs) => [...prevInputs, ""]);
props.handleSaveWidgetsOptions(
null,
null,
null,
null,
null,
addOption,
deleteOption
);
};
//function add add checkbox option and delete width of checkbox
const handleDeleteInput = (ind) => {
const deleteOption = true;
const addOption = false;
const getUpdatedOptions = dropdownOptionList.filter(
(data, index) => index !== ind
);
setDropdownOptionList(getUpdatedOptions);
props.handleSaveWidgetsOptions(
null,
null,
null,
null,
null,
addOption,
deleteOption
);
};
const handleSaveOption = () => {
const defaultData =
defaultCheckbox && defaultCheckbox.length > 0
? defaultCheckbox
: defaultValue;
props.handleSaveWidgetsOptions(
dropdownName,
dropdownOptionList,
minCount,
maxCount,
isReadOnly,
null,
null,
status,
defaultData,
isHideLabel
);
// props.setShowDropdown(false);
setDropdownOptionList(["option-1", "option-2"]);
setDropdownName(props.type);
// props.setCurrWidgetsDetails({});
setIsReadOnly(false);
setIsHideLabel(false);
setMinCount(0);
setMaxCount(0);
setDefaultCheckbox([]);
setDefaultValue("");
};
const handleSetMinMax = (e) => {
const minValue = e.target.value;
if (minValue > dropdownOptionList.length) {
return "";
} else {
return minValue;
}
};
const handleDefaultCheck = (index) => {
const getDefaultCheck = defaultCheckbox.includes(index);
if (getDefaultCheck) {
return true;
} else {
return false;
}
};
return (
<ModalUi isOpen={props.showDropdown} title={props.title} showClose={false}>
<div className="h-full p-[15px]">
<form
onSubmit={(e) => {
e.preventDefault();
handleSaveOption();
}}
>
<div>
<label style={{ fontSize: "13px", fontWeight: "600" }}>
Name<span style={{ color: "red", fontSize: 13 }}> *</span>
</label>
<input
required
defaultValue={dropdownName}
value={dropdownName}
onChange={(e) => setDropdownName(e.target.value)}
className="drodown-input"
/>
<label
style={{ fontSize: "13px", fontWeight: "600", marginTop: "5px" }}
>
Options
</label>
<div
style={{
display: "flex",
flexDirection: "column"
}}
>
{dropdownOptionList.map((option, index) => (
<div
key={index}
style={{
display: "flex",
flexDirection: "row",
marginBottom: "5px",
alignItems: "center"
}}
>
{props.type === "checkbox" && !props.isSignYourself && (
<input
type="checkbox"
checked={handleDefaultCheck(index)}
onChange={(e) => {
if (e.target.checked) {
const getDefaultCheck =
defaultCheckbox?.includes(index);
if (!getDefaultCheck) {
setDefaultCheckbox((prev) => [...prev, index]);
}
} else {
const removeOption = defaultCheckbox.filter(
(data) => data !== index
);
setDefaultCheckbox(removeOption);
}
}}
style={{
width: "23px",
height: "19px",
marginRight: "5px"
}}
/>
)}
<input
required
className="drodown-input"
type="text"
value={option}
onChange={(e) => handleInputChange(index, e.target.value)}
/>
<i
className="fa-solid fa-rectangle-xmark"
onClick={() => handleDeleteInput(index)}
style={{
color: "red",
fontSize: "25px",
marginLeft: "10px"
}}
></i>
</div>
))}
<i
onClick={handleAddInput}
style={{
cursor: "pointer",
color: themeColor,
fontSize: "25px",
marginLeft: "10px"
}}
className="fa-solid fa-square-plus"
></i>
{props.type === "checkbox" && !props.isSignYourself && (
<>
<label style={{ fontSize: "13px", fontWeight: "600" }}>
Minimun check
</label>
<input
required
defaultValue={0}
value={minCount}
onChange={(e) => {
const count = handleSetMinMax(e);
setMinCount(count);
}}
className="drodown-input"
/>
<label style={{ fontSize: "13px", fontWeight: "600" }}>
Maximum check
</label>
<input
required
defaultValue={0}
value={maxCount}
onChange={(e) => {
const count = handleSetMinMax(e);
setMaxCount(count);
}}
className="drodown-input"
/>
</>
)}
</div>
{["dropdown", radioButtonWidget].includes(props.type) && (
<>
<label
style={{
fontSize: "13px",
fontWeight: "600",
marginTop: "5px"
}}
>
Default value
</label>
<select
onChange={(e) => setDefaultValue(e.target.value)}
className="drodown-input"
name="defaultvalue"
value={defaultValue}
placeholder="select default value"
>
<option value="" disabled hidden style={{ fontSize: "13px" }}>
Select...
</option>
{dropdownOptionList.map((data, ind) => {
return (
<option
style={{ fontSize: "13px" }}
key={ind}
value={data}
>
{data}
</option>
);
})}
</select>
</>
)}
{props.type !== "checkbox" && props.type !== radioButtonWidget && (
<>
<div
style={{
display: "flex",
flexDirection: "row",
gap: 10,
marginTop: "0.5rem"
}}
>
{statusArr.map((data, ind) => {
return (
<div
key={ind}
style={{
display: "flex",
flexDirection: "row",
gap: 5,
alignItems: "center"
}}
>
<input
style={{ accentColor: "red" }}
type="radio"
name="status"
onChange={() => setStatus(data.toLowerCase())}
checked={status.toLowerCase() === data.toLowerCase()}
/>
<div style={{ fontSize: "13px", fontWeight: "500" }}>
{data}
</div>
</div>
);
})}
</div>
</>
)}
{["checkbox", radioButtonWidget].includes(props.type) && (
<div className="flex flex-row gap-5 mt-2 items-center text-center">
{!props.isSignYourself && (
<div>
<input
id="isreadonly"
type="checkbox"
checked={isReadOnly}
onChange={(e) => {
setIsReadOnly(e.target.checked);
}}
/>
<label className="ml-1" htmlFor="isreadonly">
Is read only
</label>
</div>
)}
<div>
<input
id="ishidelabel"
type="checkbox"
checked={isHideLabel}
onChange={(e) => {
setIsHideLabel(e.target.checked);
}}
/>
<label className="ml-1" htmlFor="ishidelabel">
Hide labels
</label>
</div>
</div>
)}
</div>
{props.type === "checkbox" && !props.isSignYourself && (
<PremiumAlertHeader
message={
"Field validations are free in beta, this feature will incur a fee later."
}
/>
)}
<div
className={`${
props.type === "checkbox" && !props.isSignYourself
? "mb-[15px]"
: "my-[15px]"
} w-full h-[1px] bg-[#9f9f9f]`}
></div>
<button
disabled={dropdownOptionList.length === 0 && true}
style={{
background: themeColor,
color: "white"
}}
type="submit"
className={"finishBtn"}
>
Save
</button>
{props.currWidgetsDetails?.options?.values?.length > 0 && (
<button
type="submit"
className="finishBtn cancelBtn"
onClick={() => {
props.handleClose && props.handleClose();
resetState();
}}
>
Cancel
</button>
)}
</form>
</div>
</ModalUi>
);
}
export default DropdownWidgetOption;
@@ -1,5 +1,5 @@
import React, { useState } from "react";
import "../../css/AddUser.css";
import "../../styles/AddUser.css";
// import SelectFolder from "../../premitives/SelectFolder";
const EditTemplate = ({ template, onSuccess }) => {
@@ -45,7 +45,7 @@ const EditTemplate = ({ template, onSuccess }) => {
fontWeight: "700"
}}
>
{template.URL?.split("/")[3]?.split("_")[1]}
{template.URL?.split("/")?.pop()?.split("_")[1]}
</div>
</div>
<div className="form-section">
@@ -1,11 +1,11 @@
import React, { useState } from "react";
import { saveAs } from "file-saver";
import celebration from "../../assests/newCeleb.gif";
import celebration from "../../assets/images/newCeleb.gif";
import axios from "axios";
import { getBase64FromUrl } from "../../utils/Utils";
import { themeColor } from "../../utils/ThemeColor/backColor";
import { getBase64FromUrl } from "../../constant/Utils";
import { themeColor } from "../../constant/const";
import printModule from "print-js";
import loader from "../../assests/loader2.gif";
import loader from "../../assets/images/loader2.gif";
function EmailComponent({
isEmail,
@@ -28,7 +28,6 @@ function EmailComponent({
try {
const imgPng =
"https://qikinnovation.ams3.digitaloceanspaces.com/logo.png";
// "https://qikinnovation.ams3.digitaloceanspaces.com/mailLogo_2023-08-18T12%3A51%3A31.573Z.png";
let url = `${localStorage.getItem("baseUrl")}functions/sendmailv3/`;
const headers = {
@@ -37,7 +36,7 @@ function EmailComponent({
sessionToken: localStorage.getItem("accesstoken")
};
const openSignUrl = "https://www.opensignlabs.com/contact-us";
const themeBGcolor = themeColor();
const themeBGcolor = themeColor;
let params = {
pdfName: pdfName,
url: pdfUrl,
@@ -362,7 +361,7 @@ function EmailComponent({
>
<i
style={{
backgroundColor: themeColor(),
backgroundColor: themeColor,
padding: "5px 7px",
marginTop: "10px",
color: "white",
@@ -399,7 +398,7 @@ function EmailComponent({
<button
disabled={emailList.length === 0 && true}
style={{
background: themeColor(),
background: themeColor,
color: "white"
}}
type="button"
@@ -1,14 +1,14 @@
import React from "react";
import PrevNext from "./prevNext";
import PrevNext from "./PrevNext";
import { PDFDownloadLink } from "@react-pdf/renderer";
import Certificate from "../Certificate/Certificate";
import Certificate from "./Certificate";
import printModule from "print-js";
import { getBase64FromUrl } from "../../utils/Utils";
import { getBase64FromUrl } from "../../constant/Utils";
import { saveAs } from "file-saver";
import "../../css/signature.css";
import "../../styles/signature.css";
import * as DropdownMenu from "@radix-ui/react-dropdown-menu";
import { useNavigate } from "react-router-dom";
import { themeColor } from "../../utils/ThemeColor/backColor";
import { themeColor } from "../../constant/const";
function Header({
isPdfRequestFiles,
@@ -21,7 +21,7 @@ function Header({
changePage,
pdfUrl,
documentStatus,
embedImages,
embedWidgetsData,
pdfDetails,
signerPos,
signersdata,
@@ -38,6 +38,8 @@ function Header({
completeBtnTitle,
setIsEditTemplate
}) {
const filterPrefill =
signerPos && signerPos?.filter((data) => data.Role !== "prefill");
const isMobile = window.innerWidth < 767;
const navigate = useNavigate();
const isGuestSigner = localStorage.getItem("isGuestSigner");
@@ -119,7 +121,7 @@ function Header({
style={{ textDecoration: "none", zIndex: "35" }}
document={<Certificate pdfData={pdfDetails} />}
>
{({ blob, url, loading, error }) => (
{({ blob, loading }) => (
<>
{loading ? (
<div
@@ -129,20 +131,15 @@ function Header({
}}
>
<i
className="fa fa-certificate"
style={{
marginRight: "2px"
}}
className="fa-solid fa-award"
style={{ marginRight: "2px" }}
aria-hidden="true"
></i>
Certificate
</div>
) : (
<div
style={{
border: "none",
backgroundColor: "#fff"
}}
style={{ border: "none", backgroundColor: "#fff" }}
onClick={() =>
handleDownload(
blob,
@@ -153,10 +150,8 @@ function Header({
}
>
<i
className="fa fa-certificate"
style={{
marginRight: "2px"
}}
className="fa-solid fa-award"
style={{ marginRight: "2px" }}
aria-hidden="true"
></i>
Certificate
@@ -176,51 +171,29 @@ function Header({
pdfDetails[0] && pdfDetails[0].Name
}.pdf`}
>
{({ blob, url, loading, error }) =>
loading ? (
<button
type="button"
className="defaultBtn certificateBtn"
{({ loading }) => (
<button
type="button"
className="defaultBtn certificateBtn"
disabled={loading}
style={{
display: "flex",
flexDirection: "row",
alignItems: "center"
}}
>
<i
className="fa-solid fa-award"
style={{
display: "flex",
flexDirection: "row",
alignItems: "center"
color: "white",
fontSize: "15px",
marginRight: "3px"
}}
>
<i
className="fa fa-certificate"
style={{
color: "white",
fontSize: "15px",
marginRight: "3px"
}}
aria-hidden="true"
></i>
Certificate
</button>
) : (
<button
type="button"
className="defaultBtn certificateBtn"
style={{
display: "flex",
flexDirection: "row",
alignItems: "center"
}}
>
<i
className="fa fa-certificate"
style={{
color: "white",
fontSize: "15px",
marginRight: "3px"
}}
aria-hidden="true"
></i>
Certificate
</button>
)
}
aria-hidden="true"
></i>
Certificate
</button>
)}
</PDFDownloadLink>
);
};
@@ -245,7 +218,7 @@ function Header({
<i
className="fa fa-arrow-left"
aria-hidden="true"
style={{ color: themeColor(), cursor: "pointer" }}
style={{ color: themeColor, cursor: "pointer" }}
></i>
</div>
<div>
@@ -283,7 +256,7 @@ function Header({
<DropdownMenu.Trigger asChild>
<div
style={{
color: themeColor(),
color: themeColor,
border: "none",
fontWeight: "650",
fontSize: "16px",
@@ -407,7 +380,7 @@ function Header({
}
}}
style={{
color: isMailSend ? "gray" : themeColor(),
color: isMailSend ? "gray" : themeColor,
border: "none",
fontWeight: "650",
fontSize: "16px"
@@ -421,13 +394,13 @@ function Header({
data-tut="reactourThird"
onClick={() => {
if (!pdfUrl) {
embedImages();
embedWidgetsData();
} else if (isPdfRequestFiles) {
embedImages();
embedWidgetsData();
}
}}
style={{
color: themeColor(),
color: themeColor,
border: "none",
fontWeight: "650",
fontSize: "16px"
@@ -453,7 +426,7 @@ function Header({
{recipient ? (
pdfUrl || isAlreadySign.mssg ? (
<div style={{ display: "flex", flexDirection: "row" }}>
{pdfDetails[0] && pdfDetails.length > 0 && (
{pdfDetails && pdfDetails.length > 0 && (
<CertificateComponent />
)}
<button
@@ -521,7 +494,7 @@ function Header({
className="finishBtn sendHover"
onClick={() => {
if (!pdfUrl) {
embedImages();
embedWidgetsData();
}
}}
>
@@ -533,16 +506,16 @@ function Header({
<>
{!isMailSend &&
signersdata.length > 0 &&
signersdata.length !== signerPos.length && (
signersdata.length !== filterPrefill.length && (
<div>
{signerPos.length === 0 ? (
{filterPrefill.length === 0 ? (
<span style={{ fontSize: "13px", color: "#f5405e" }}>
Add {signersdata.length - signerPos.length} recipients
signature
Add {signersdata.length - filterPrefill.length}{" "}
recipients signature
</span>
) : (
<span style={{ fontSize: "13px", color: "#f5405e" }}>
Add {signersdata.length - signerPos.length} more
Add {signersdata.length - filterPrefill.length} more
recipients signature
</span>
)}
@@ -667,7 +640,7 @@ function Header({
type="button"
className="finishBtn sendHover"
onClick={() => {
embedImages();
embedWidgetsData();
}}
>
Finish
@@ -765,7 +738,7 @@ function Header({
className="finishBtn sendHover"
onClick={() => {
if (!pdfUrl) {
embedImages();
embedWidgetsData();
}
}}
>
@@ -0,0 +1,751 @@
import React, { useState, useEffect } from "react";
import BorderResize from "./BorderResize";
import PlaceholderBorder from "./PlaceholderBorder";
import { Rnd } from "react-rnd";
import {
defaultWidthHeight,
handleCopyNextToWidget,
isMobile,
onChangeInput,
radioButtonWidget,
textInputWidget,
textWidget
} from "../../constant/Utils";
import PlaceholderType from "./PlaceholderType";
import moment from "moment";
import "../../styles/opensigndrive.css";
const selectFormat = (data) => {
switch (data) {
case "L":
return "MM/dd/yyyy";
case "DD-MM-YYYY":
return "dd-MM-yyyy";
case "DD/MM/YYYY":
return "dd/MM/yyyy";
case "LL":
return "MMMM dd, yyyy";
case "DD MMM, YYYY":
return "dd MMM, yyyy";
case "YYYY-MM-DD":
return "yyyy-MM-dd";
case "MM-DD-YYYY":
return "MM-dd-yyyy";
case "MM.DD.YYYY":
return "MM.dd.yyyy";
case "MMM DD, YYYY":
return "MMM dd, yyyy";
case "DD MMMM, YYYY":
return "dd MMMM, yyyy";
default:
return "MM/dd/yyyy";
}
};
const changeDateToMomentFormat = (format) => {
switch (format) {
case "MM/dd/yyyy":
return "L";
case "dd-MM-yyyy":
return "DD-MM-YYYY";
case "dd/MM/yyyy":
return "DD/MM/YYYY";
case "MMMM dd, yyyy":
return "LL";
case "dd MMM, yyyy":
return "DD MMM, YYYY";
case "yyyy-MM-dd":
return "YYYY-MM-DD";
case "MM-dd-yyyy":
return "MM-DD-YYYY";
case "MM.dd.yyyy":
return "MM.DD.YYYY";
case "MMM dd, yyyy":
return "MMM DD, YYYY";
case "dd MMMM, yyyy":
return "DD MMMM, YYYY";
default:
return "L";
}
};
//function to get default date
const getDefaultdate = (selectedDate, format = "dd-MM-yyyy") => {
let date;
if (format && format === "dd-MM-yyyy") {
const newdate = selectedDate
? selectedDate
: moment(new Date()).format(changeDateToMomentFormat(format));
const [day, month, year] = newdate.split("-");
date = new Date(`${year}-${month}-${day}`);
} else {
date = new Date(selectedDate);
}
const value = date;
return value;
};
//function to get default format
const getDefaultFormat = (dateFormat) => dateFormat || "MM/dd/yyyy";
function Placeholder(props) {
const [isDraggingEnabled, setDraggingEnabled] = useState(true);
const [isShowDateFormat, setIsShowDateFormat] = useState(false);
const [selectDate, setSelectDate] = useState({
date:
props.pos.type === "date"
? moment(
getDefaultdate(
props?.pos?.options?.response,
props.pos?.options?.validation?.format
).getTime()
).format(
changeDateToMomentFormat(props.pos?.options?.validation?.format)
)
: "",
format:
props.pos.type === "date"
? getDefaultFormat(props.pos?.options?.validation?.format)
: ""
});
const [dateFormat, setDateFormat] = useState([]);
const [startDate, setStartDate] = useState(
props.pos.type === "date" &&
getDefaultdate(
props?.pos?.options?.response,
props.pos?.options?.validation?.format
)
);
const [getCheckboxRenderWidth, setGetCheckboxRenderWidth] = useState({
width: null,
height: null
});
const dateFormatArr = [
"L",
"DD-MM-YYYY",
"YYYY-MM-DD",
"MM.DD.YYYY",
"MM-DD-YYYY",
"MMM DD, YYYY",
"LL",
"DD MMM, YYYY",
"DD MMMM, YYYY"
];
useEffect(() => {
const updateWidth = () => {
const rndElement = document.getElementById(props.pos.key);
if (rndElement) {
const { width, height } = rndElement.getBoundingClientRect();
setGetCheckboxRenderWidth({ width: width, height: height });
}
};
// Delay to ensure rendering is complete
const timer = setTimeout(updateWidth, 0);
return () => clearTimeout(timer);
}, [props.pos]);
useEffect(() => {
const closeMenuOnOutsideClick = (e) => {
if (!isDraggingEnabled && !e.target.closest("#changeIsDragging")) {
setDraggingEnabled(true);
}
};
document.addEventListener("click", closeMenuOnOutsideClick);
return () => {
// Cleanup the event listener when the component unmounts
document.removeEventListener("click", closeMenuOnOutsideClick);
};
}, [isDraggingEnabled]);
//function change format array list with selected date and format
const changeDateFormat = () => {
const updateDate = [];
dateFormatArr.map((data) => {
let date;
if (selectDate && selectDate.format === "dd-MM-yyyy") {
const [day, month, year] = selectDate.date.split("-");
date = new Date(`${year}-${month}-${day}`);
} else {
date = new Date(selectDate?.date);
}
const milliseconds = date.getTime();
const newDate = moment(milliseconds).format(data);
const dateObj = {
date: newDate,
format: selectFormat(data)
};
updateDate.push(dateObj);
});
setDateFormat(updateDate);
};
useEffect(() => {
if (props.isPlaceholder || props.isSignYourself) {
selectDate && changeDateFormat();
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [selectDate]);
//it detect outside click of date dropdown menu
useEffect(() => {
const closeMenuOnOutsideClick = (e) => {
if (isShowDateFormat && !e.target.closest("#menu-container")) {
setIsShowDateFormat(!isShowDateFormat);
}
};
document.addEventListener("click", closeMenuOnOutsideClick);
return () => {
// Cleanup the event listener when the component unmounts
document.removeEventListener("click", closeMenuOnOutsideClick);
};
}, [isShowDateFormat]);
//`handleWidgetIdandPopup` is used to set current widget id and open relative popup
const handleWidgetIdandPopup = () => {
if (props.setSelectWidgetId) {
props.setSelectWidgetId(props.pos.key);
}
const widgetTypeExist = [
textInputWidget,
"checkbox",
"name",
"company",
"job title",
"date",
"email",
textWidget
].includes(props.pos.type);
if (widgetTypeExist) {
setDraggingEnabled(false);
}
if ((props.isNeedSign || props.isSignYourself) && !props.isDragging) {
if (props.pos.type) {
if (
props.pos.type === "signature" ||
props.pos.type === "stamp" ||
props.pos.type === "image"
) {
props.setIsSignPad(true);
props.setSignKey(props.pos.key);
props.setIsStamp(props.pos.isStamp);
} else if (props.pos.type === "initials") {
props.setIsSignPad(true);
props.setSignKey(props.pos.key);
props.setIsStamp(props.pos.isStamp);
props.setIsInitial(true);
}
} else {
props.setIsSignPad(true);
props.setSignKey(props.pos.key);
props.setIsStamp(props.pos?.isStamp ? props.pos.isStamp : false);
}
} else if (
props.isPlaceholder &&
!props.isDragging &&
props.pos.type !== textWidget
) {
if (props.pos.key === props.selectWidgetId) {
props.handleLinkUser(props.data.Id);
props.setUniqueId(props.data.Id);
}
} else if (!props.pos.type) {
if (
!props.pos.type &&
props.isNeedSign &&
props.data.signerObjId === props.signerObjId
) {
props.setIsSignPad(true);
props.setSignKey(props.pos.key);
props.setIsStamp(props.pos.isStamp);
} else if (
(props.isNeedSign && props.pos.type === "signature") ||
props.pos.type === "stamp"
) {
props.setIsSignPad(true);
props.setSignKey(props.pos.key);
props.setIsStamp(props.pos.isStamp);
} else if (props.isNeedSign && props.pos.type === "dropdown") {
props.setSignKey(props.pos.key);
}
}
};
const handleOnClickPlaceholder = () => {
props.setCurrWidgetsDetails && props.setCurrWidgetsDetails(props.pos);
if (!props.isNeedSign) {
props.setWidgetType(props.pos.type);
}
if (props.isNeedSign && props.data?.signerObjId === props.signerObjId) {
handleWidgetIdandPopup();
} else if (props.isPlaceholder || props.isSignYourself) {
handleWidgetIdandPopup();
}
};
//`handleOnClickSettingIcon` is used set current widget details and open setting of it
const handleOnClickSettingIcon = () => {
if (props.pos.type === radioButtonWidget) {
props.setIsRadio(true);
} else if (props.pos.type === "dropdown") {
props?.setShowDropdown(true);
} else if (props.pos.type === "checkbox") {
props?.setIsCheckbox(true);
} else {
props?.handleNameModal(true);
}
if (props.isPlaceholder && props.type !== textWidget) {
props.setUniqueId(props.data.Id);
}
props.setSignKey(props.pos.key);
props.setWidgetType(props.pos.type);
props.setCurrWidgetsDetails(props.pos);
};
//function to set required state value onclick on widget's copy icon
const handleCopyPlaceholder = (e) => {
e.stopPropagation();
//condition to handle text widget signer obj id and unique id
//when user click on copy icon of text widget in that condition text widget does not have any signerObjId
//in that case i have to save in tempSignerId as a unique id of previous select signer's unique id
//and on save or cancel button of copy all page popup i have set this temp signer Id in unique id
if (props.data && props?.pos?.type !== textWidget) {
props.setSignerObjId(props?.data?.signerObjId);
props.setUniqueId(props?.data?.Id);
} else if (props.data && props.pos.type === textWidget) {
props.setTempSignerId(props.uniqueId);
props.setSignerObjId(props?.data?.signerObjId);
props.setUniqueId(props?.data?.Id);
}
//checking widget's type and open widget copy modal for required widgets
if (
["signature", textWidget, "stamp", "initial"].includes(props.pos.type)
) {
props.setIsPageCopy(true);
props.setSignKey(props.pos.key);
} else {
//function to create new widget next to just widget
handleCopyNextToWidget(
props.pos,
props.pos.type,
props.xyPostion,
props.index,
props.setXyPostion,
props.data && props.data?.Id
);
}
};
//function to save date and format on local array onchange date and onclick format
const handleSaveDate = (data, isDateChange) => {
let updateDate = data.date;
//check if date change by user
if (isDateChange) {
//`changeDateToMomentFormat` is used to convert date as per required to moment package
updateDate = moment(data.date).format(
changeDateToMomentFormat(data.format)
);
}
//using moment package is used to change date as per the format provided in selectDate obj e.g. - MM/dd/yyyy -> 03/12/2024
//`getDefaultdate` is used to convert update date in new Date() format
const date = moment(
getDefaultdate(updateDate, data?.format).getTime()
).format(changeDateToMomentFormat(data?.format));
//`onChangeInput` is used to save data related to date in a placeholder field
onChangeInput(
date,
props.pos.key,
props.xyPostion,
props.index,
props.setXyPostion,
props.data && props.data.Id,
false,
data?.format
);
setSelectDate({ date: date, format: data?.format });
};
const PlaceholderIcon = () => {
return (
props.isShowBorder && (
<>
{(props.isPlaceholder || props.isSignYourself) && (
<>
{props.pos.type === "checkbox" && props.isSignYourself ? (
<i
onClick={(e) => {
e.stopPropagation();
handleOnClickSettingIcon();
}}
onTouchEnd={(e) => {
e.stopPropagation();
handleOnClickSettingIcon();
}}
className="fa-solid fa-gear settingIcon"
style={{
color: "#188ae2",
right: "29px",
top: "-19px"
}}
></i>
) : (
((!props?.pos?.type && props.pos.isStamp) ||
(props?.pos?.type &&
!["date", textWidget, "signature"].includes(
props.pos.type
) &&
!props.isSignYourself)) && (
<i
onClick={(e) => {
e.stopPropagation();
handleOnClickSettingIcon();
}}
onTouchEnd={(e) => {
e.stopPropagation();
handleOnClickSettingIcon();
}}
className="fa-solid fa-gear settingIcon"
style={{ color: "#188ae2", right: "47px", top: "-19px" }}
></i>
)
)}
{props.pos.type !== textWidget && !props.isSignYourself && (
<i
data-tut="reactourLinkUser"
className="fa-regular fa-user signUserIcon"
onClick={(e) => {
e.stopPropagation();
props.handleLinkUser(props.data.Id);
props.setUniqueId(props.data.Id);
}}
onTouchEnd={(e) => {
e.stopPropagation();
props.handleLinkUser(props.data.Id);
props.setUniqueId(props.data.Id);
}}
style={{ color: "#188ae2", right: "32px", top: "-18px" }}
></i>
)}
</>
)}
{props.pos.type === "date" && selectDate && (
<div
id="menu-container"
style={{
zIndex: "99",
top: "-19px",
right: props.isPlaceholder ? "60px" : "44px"
}}
className={
isShowDateFormat
? "dropdown signUserIcon show"
: "dropdown signUserIcon"
}
onClick={(e) => {
setIsShowDateFormat(!isShowDateFormat);
e.stopPropagation();
if (props.data) {
props.setSignKey(props.pos.key);
props.setUniqueId(props.data.Id);
}
}}
onTouchEnd={(e) => {
e.stopPropagation();
setIsShowDateFormat(!isShowDateFormat);
if (props.data) {
props.setSignKey(props.pos.key);
props.setUniqueId(props.data.Id);
}
}}
>
<i
className="fa-solid fa-gear settingIcon"
style={{
color: "#188ae2",
fontSize: "14px"
}}
></i>
<div
className={
isShowDateFormat ? "dropdown-menu show" : "dropdown-menu"
}
aria-labelledby="dropdownMenuButton"
aria-expanded={isShowDateFormat ? "true" : "false"}
>
{dateFormat.map((data, ind) => {
return (
<span
key={ind}
onTouchEnd={(e) => {
e.stopPropagation();
setIsShowDateFormat(!isShowDateFormat);
setSelectDate(data);
handleSaveDate(data);
}}
onClick={() => {
setIsShowDateFormat(!isShowDateFormat);
setSelectDate(data);
handleSaveDate(data);
}}
className="dropdown-item itemColor"
style={{ fontSize: "12px" }}
>
{data?.date ? data?.date : "nodata"}
</span>
);
})}
</div>
</div>
)}
<i
className="fa-regular fa-copy signCopy"
onClick={(e) => handleCopyPlaceholder(e)}
onTouchEnd={(e) => handleCopyPlaceholder(e)}
style={{ color: "#188ae2", right: "12px", top: "-18px" }}
></i>
<i
className="fa-regular fa-circle-xmark signCloseBtn"
onClick={(e) => {
e.stopPropagation();
if (props.data) {
props.handleDeleteSign(props.pos.key, props.data.Id);
} else {
props.handleDeleteSign(props.pos.key);
props.setIsStamp(false);
}
}}
onTouchEnd={(e) => {
e.stopPropagation();
if (props.data) {
props.handleDeleteSign(props.pos.key, props.data?.Id);
} else {
props.handleDeleteSign(props.pos.key);
props.setIsStamp(false);
}
}}
style={{ color: "#188ae2", right: "-8px", top: "-18px" }}
></i>
</>
)
);
};
return (
<Rnd
id={props.pos.key}
data-tut={props.pos.key === props.unSignedWidgetId ? "IsSigned" : ""}
key={props.pos.key}
lockAspectRatio={
props.pos.type !== textWidget &&
(props.pos.Width
? props.pos.Width / props.pos.Height
: defaultWidthHeight(props.pos.type).width /
defaultWidthHeight(props.pos.type).height)
}
enableResizing={{
top: false,
right: false,
bottom: false,
left: false,
topRight: false,
bottomRight:
props.data && props.isNeedSign
? props.data?.signerObjId === props.signerObjId &&
props.pos.type !== "checkbox" &&
props.pos.type !== radioButtonWidget
? true
: false
: props.pos.type !== radioButtonWidget &&
props.pos.type !== "checkbox" &&
props.pos.key === props.selectWidgetId &&
true,
bottomLeft: false,
topLeft: false
}}
bounds="parent"
className="signYourselfBlock"
style={{
border: "1px solid #007bff",
borderRadius: "2px",
textAlign:
props.pos.type !== "name" &&
props.pos.type !== "company" &&
props.pos.type !== "job title" &&
"center",
cursor:
props.data && props.isNeedSign
? props.data?.signerObjId === props.signerObjId
? "pointer"
: "not-allowed"
: "all-scroll",
zIndex:
props.pos.type === "date"
? props.pos.key === props.selectWidgetId
? 99 + 1
: 99
: props?.pos?.zIndex
? props.pos.zIndex
: "5",
background: props.data ? props.data.blockColor : "rgb(203 233 237)"
}}
onDrag={() => {
setDraggingEnabled(true);
props.handleTabDrag && props.handleTabDrag(props.pos.key);
}}
size={{
width:
props.pos.type === radioButtonWidget || props.pos.type === "checkbox"
? "auto"
: props.posWidth(props.pos, props.isSignYourself),
height:
props.pos.type === radioButtonWidget || props.pos.type === "checkbox"
? "auto"
: props.posHeight(props.pos, props.isSignYourself)
}}
onResizeStart={() => {
setDraggingEnabled(true);
props.setIsResize && props.setIsResize(true);
}}
onResizeStop={() => {
props.setIsResize && props.setIsResize(false);
}}
disableDragging={
props.isNeedSign
? true
: props.isPlaceholder && ![textWidget].includes(props.pos.type)
? false
: !isDraggingEnabled
}
onDragStop={(event, dragElement) =>
props.handleStop &&
props.handleStop(event, dragElement, props.data?.Id, props.pos?.key)
}
default={{
x: props.xPos(props.pos, props.isSignYourself),
y: props.yPos(props.pos, props.isSignYourself)
}}
onResize={(e, direction, ref) => {
props.handleSignYourselfImageResize &&
props.handleSignYourselfImageResize(
ref,
props.pos.key,
props.xyPostion,
props.setXyPostion,
props.index,
props.data && props.data.Id,
false
);
}}
onClick={() => handleOnClickPlaceholder()}
>
{props.isShowBorder &&
props.pos.type !== radioButtonWidget &&
props.pos.type !== "checkbox" &&
props.pos.key === props.selectWidgetId ? (
<BorderResize right={-12} top={-11} />
) : props.data && props.isNeedSign && props.pos.type !== "checkbox" ? (
props.data?.signerObjId === props.signerObjId &&
props.pos.type !== radioButtonWidget &&
props.pos.type !== "checkbox" ? (
<BorderResize />
) : (
<></>
)
) : (
props.pos.type !== radioButtonWidget &&
props.pos.type !== "checkbox" &&
props.pos.key === props.selectWidgetId && <BorderResize />
)}
{props.isShowBorder && props.pos.key === props.selectWidgetId && (
<PlaceholderBorder
setDraggingEnabled={setDraggingEnabled}
pos={props.pos}
isPlaceholder={props.isPlaceholder}
getCheckboxRenderWidth={getCheckboxRenderWidth}
/>
)}
{isMobile ? (
<div
style={{
left: props.xPos(props.pos, props.isSignYourself),
top: props.yPos(props.pos, props.isSignYourself),
width:
props.pos.type === radioButtonWidget ||
props.pos.type === "checkbox"
? "auto"
: props.posWidth(props.pos, props.isSignYourself),
// "auto", //props.posWidth(props.pos, props.isSignYourself),
// height: props.posHeight(props.pos, props.isSignYourself),
height:
props.pos.type === radioButtonWidget ||
props.pos.type === "checkbox"
? "auto"
: props.posHeight(props.pos, props.isSignYourself),
zIndex: "10"
}}
onTouchEnd={() => handleOnClickPlaceholder()}
>
{props.pos.key === props.selectWidgetId && <PlaceholderIcon />}
<PlaceholderType
pos={props.pos}
xyPostion={props.xyPostion}
index={props.index}
setXyPostion={props.setXyPostion}
data={props.data}
setSignKey={props.setSignKey}
isShowDropdown={props?.isShowDropdown}
isPlaceholder={props.isPlaceholder}
isSignYourself={props.isSignYourself}
signerObjId={props.signerObjId}
handleUserName={props.handleUserName}
setDraggingEnabled={setDraggingEnabled}
pdfDetails={props?.pdfDetails && props?.pdfDetails[0]}
isNeedSign={props.isNeedSign}
setSelectDate={setSelectDate}
selectDate={selectDate}
setValidateAlert={props.setValidateAlert}
setStartDate={setStartDate}
startDate={startDate}
handleSaveDate={handleSaveDate}
/>
</div>
) : (
<>
{props.pos.key === props.selectWidgetId && <PlaceholderIcon />}
<PlaceholderType
pos={props.pos}
xyPostion={props.xyPostion}
index={props.index}
setXyPostion={props.setXyPostion}
data={props.data}
setSignKey={props.setSignKey}
isShowDropdown={props?.isShowDropdown}
isPlaceholder={props.isPlaceholder}
isSignYourself={props.isSignYourself}
signerObjId={props.signerObjId}
handleUserName={props.handleUserName}
setDraggingEnabled={setDraggingEnabled}
pdfDetails={props?.pdfDetails && props?.pdfDetails[0]}
isNeedSign={props.isNeedSign}
setSelectDate={setSelectDate}
selectDate={selectDate}
setValidateAlert={props.setValidateAlert}
setStartDate={setStartDate}
startDate={startDate}
handleSaveDate={handleSaveDate}
/>
</>
)}
</Rnd>
);
}
export default Placeholder;
@@ -0,0 +1,52 @@
import React from "react";
import { themeColor } from "../../constant/const";
import {
defaultWidthHeight,
isMobile,
radioButtonWidget,
resizeBorderExtraWidth,
textWidget
} from "../../constant/Utils";
function PlaceholderBorder(props) {
const getResizeBorderExtraWidth = resizeBorderExtraWidth();
const defaultWidth = defaultWidthHeight(props.pos.type).width;
const defaultHeight = defaultWidthHeight(props.pos.type).height;
const handleMinWidth = () => {
if (props.pos.type === "checkbox" || props.pos.type === radioButtonWidget) {
return props.getCheckboxRenderWidth.width + getResizeBorderExtraWidth;
} else {
return props.pos.Width
? props.pos.Width + getResizeBorderExtraWidth
: defaultWidth + getResizeBorderExtraWidth;
}
};
const handleMinHeight = () => {
if (props.pos.type === "checkbox" || props.pos.type === radioButtonWidget) {
return props.getCheckboxRenderWidth.height + getResizeBorderExtraWidth;
} else {
return props.pos.Height
? props.pos.Height + getResizeBorderExtraWidth
: defaultHeight + getResizeBorderExtraWidth;
}
};
return (
<div
onMouseEnter={() => !isMobile && props?.setDraggingEnabled(true)}
onTouchEnd={() =>
props.pos.type === textWidget && props?.setDraggingEnabled(true)
}
className="borderResize"
style={{
borderColor: themeColor,
borderStyle: "dashed",
minWidth: handleMinWidth(),
minHeight: handleMinHeight(),
borderWidth: "0.2px",
overflow: "hidden"
}}
></div>
);
}
export default PlaceholderBorder;
@@ -1,62 +1,55 @@
import React, { useState } from "react";
import { themeColor } from "../../utils/ThemeColor/backColor";
import ModalUi from "../../premitives/ModalUi";
import { themeColor } from "../../constant/const";
import ModalUi from "../../primitives/ModalUi";
import { randomId, textWidget } from "../../constant/Utils";
function PlaceholderCopy(props) {
const copyType = ["All pages", "All pages but last", "All pages but first"];
const [selectCopyType, setSelectCopyType] = useState("");
//get RandomKey Id
const randomKey = () => {
const randomId = Math.floor(1000 + Math.random() * 9000);
return randomId;
};
//function for get copy placeholder position
const getCopyPlaceholderPosition = (
type,
rest,
currentPlaceholder,
newPageNumber,
existPlaceholderPosition
) => {
let obj;
const filterPosition =
existPlaceholderPosition &&
existPlaceholderPosition.filter(
(data) => data.xPosition !== rest.xPosition
(data) => data.xPosition !== currentPlaceholder.xPosition
);
//copy all page placeholder at requested position except first page
if (newPageNumber === 1 && type === "first") {
if (filterPosition && filterPosition.length > 0) {
return (obj = {
return {
pageNumber: newPageNumber,
pos: [...filterPosition]
});
};
}
}
//copy all page placeholder at requested position except last page
else if (newPageNumber === props.allPages && type === "last") {
if (existPlaceholderPosition) {
return (obj = {
return {
pageNumber: newPageNumber,
pos: [...filterPosition]
});
};
}
}
//copy all page placeholder at requested position with existing placeholder position
else if (existPlaceholderPosition) {
return (obj = {
return {
pageNumber: newPageNumber,
pos: [...filterPosition, rest]
});
pos: [...filterPosition, currentPlaceholder]
};
}
//copy all page placeholder at requested position
else {
return (obj = {
return {
pageNumber: newPageNumber,
pos: [rest]
});
pos: [currentPlaceholder]
};
}
};
@@ -66,6 +59,7 @@ function PlaceholderCopy(props) {
let newPageNumber = 1;
const signerPosition = props.xyPostion;
const signerId = props.signerObjId ? props.signerObjId : props.Id;
//handle placeholder array and copy for multiple signers placeholder at requested location
if (signerId) {
//get current signers data
@@ -84,13 +78,13 @@ function PlaceholderCopy(props) {
(data) => data.pageNumber === props.pageNumber
);
//get current placeholder position data which user want to copy
const currentPlaceholder = placeholderPosition[0].pos.filter(
const currentPlaceholder = placeholderPosition[0].pos.find(
(position) => position.key === props.signKey
);
const { key, ...rest } = currentPlaceholder[0];
for (let i = 0; i < props.allPages; i++) {
const newId = randomKey();
rest.key = newId;
const newId = randomId();
currentPlaceholder.key = newId;
//get exist placeholder position for particular page
const existPlaceholder = filterSignerPosition[0].placeHolder.filter(
(data) => data.pageNumber === newPageNumber
@@ -101,7 +95,7 @@ function PlaceholderCopy(props) {
//function for get copy to requested location of placeholder position
const getPlaceholderObj = getCopyPlaceholderPosition(
type,
rest,
currentPlaceholder,
newPageNumber,
existPlaceholderPosition
);
@@ -112,7 +106,7 @@ function PlaceholderCopy(props) {
}
let updatedSignerPlaceholder;
if (props?.signerObjId) {
updatedSignerPlaceholder = signerPosition.map((signersData, ind) => {
updatedSignerPlaceholder = signerPosition.map((signersData) => {
if (signersData.signerObjId === props.signerObjId) {
return {
...signersData,
@@ -122,7 +116,7 @@ function PlaceholderCopy(props) {
return signersData;
});
} else {
updatedSignerPlaceholder = signerPosition.map((signersData, ind) => {
updatedSignerPlaceholder = signerPosition.map((signersData) => {
if (signersData.Id === props.Id) {
return {
...signersData,
@@ -132,17 +126,6 @@ function PlaceholderCopy(props) {
return signersData;
});
}
// const updatedSignerPlaceholder = signerPosition.map(
// (signersData, ind) => {
// if (signersData.signerObjId === props.signerObjId) {
// return {
// ...signersData,
// placeHolder: newPlaceholderPosition
// };
// }
// return signersData;
// }
// );
const signersData = signerPosition;
signersData.splice(0, signerPosition.length, ...updatedSignerPlaceholder);
@@ -156,10 +139,10 @@ function PlaceholderCopy(props) {
(data) => data.pageNumber === props.pageNumber
);
//get current placeholder position data which user want to copy
const currentPlaceholder = placeholderPosition[0].pos.filter(
const currentPlaceholder = placeholderPosition[0].pos.find(
(pos) => pos.key === props.signKey
);
const { key, ...rest } = currentPlaceholder[0];
for (let i = 0; i < props.allPages; i++) {
//get exist placeholder position for particular page
const existPlaceholder = xyPostion.filter(
@@ -168,12 +151,12 @@ function PlaceholderCopy(props) {
const existPlaceholderPosition =
existPlaceholder[0] && existPlaceholder[0].pos;
const newId = randomKey();
rest.key = newId;
const newId = randomId();
currentPlaceholder.key = newId;
//function for get copy to requested location of placeholder position
const getPlaceholderObj = getCopyPlaceholderPosition(
type,
rest,
currentPlaceholder,
newPageNumber,
existPlaceholderPosition
);
@@ -197,7 +180,13 @@ function PlaceholderCopy(props) {
copyPlaceholder("first");
}
};
const handleUniqueId = () => {
if (props.widgetType === textWidget) {
props.setUniqueId(props?.tempSignerId);
props.setTempSignerId("");
}
props.setIsPageCopy(false);
};
return (
<ModalUi
isOpen={props.isPageCopy}
@@ -237,11 +226,9 @@ function PlaceholderCopy(props) {
<button
onClick={() => {
handleApplyCopy();
props.setIsPageCopy(false);
}}
style={{
background: themeColor()
handleUniqueId();
}}
style={{ background: themeColor }}
type="button"
disabled={!selectCopyType}
className="finishBtn"
@@ -251,7 +238,9 @@ function PlaceholderCopy(props) {
<button
type="button"
className="finishBtn cancelBtn"
onClick={() => props.setIsPageCopy(false)}
onClick={() => {
handleUniqueId();
}}
>
Cancel
</button>
@@ -0,0 +1,819 @@
import React, { useEffect, useState, forwardRef, useRef } from "react";
import {
getMonth,
getYear,
isMobile,
onChangeHeightOfTextArea,
onChangeInput,
radioButtonWidget,
range,
textInputWidget,
textWidget
} from "../../constant/Utils";
import DatePicker from "react-datepicker";
import "react-datepicker/dist/react-datepicker.css";
import "../../styles/signature.css";
import RegexParser from "regex-parser";
function PlaceholderType(props) {
const type = props?.pos?.type;
const [selectOption, setSelectOption] = useState("");
const [validatePlaceholder, setValidatePlaceholder] = useState("");
const inputRef = useRef(null);
const [textValue, setTextValue] = useState();
const [selectedCheckbox, setSelectedCheckbox] = useState([]);
const years = range(1990, getYear(new Date()) + 16, 1);
const months = [
"January",
"February",
"March",
"April",
"May",
"June",
"July",
"August",
"September",
"October",
"November",
"December"
];
const validateExpression = (regexValidation) => {
let regexObject = regexValidation;
if (props.pos?.options.validation.type === "regex") {
regexObject = RegexParser(regexValidation);
}
// new RegExp(regexValidation);
let isValidate = regexObject.test(textValue);
if (!isValidate) {
props?.setValidateAlert(true);
inputRef.current.focus();
}
};
const handleInputBlur = () => {
props.setDraggingEnabled(true);
const validateType = props.pos?.options?.validation?.type;
let regexValidation;
if (validateType) {
switch (validateType) {
case "email":
regexValidation = /^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;
validateExpression(regexValidation);
break;
case "number":
regexValidation = /^\d+$/;
validateExpression(regexValidation);
break;
case "text":
regexValidation = /^[a-zA-Z\s]+$/;
validateExpression(regexValidation);
break;
default:
regexValidation = props.pos?.options.validation.pattern;
validateExpression(regexValidation);
}
}
};
const handleTextValid = (e) => {
const textInput = e.target.value;
setTextValue(textInput);
};
function checkRegularExpress(validateType) {
switch (validateType) {
case "email":
setValidatePlaceholder("demo@gmail.com");
break;
case "number":
setValidatePlaceholder("12345");
break;
case textInputWidget:
setValidatePlaceholder("enter text");
break;
default:
setValidatePlaceholder("enter text");
}
}
useEffect(() => {
if (type && type === "checkbox" && props.isNeedSign) {
const isDefaultValue = props.pos.options?.defaultValue;
if (isDefaultValue) {
setSelectedCheckbox(isDefaultValue);
}
} else if (props.pos?.options?.hint) {
setValidatePlaceholder(props.pos?.options.hint);
} else if (props.pos?.options?.validation?.type) {
checkRegularExpress(props.pos?.options?.validation?.type);
}
setTextValue(
props.pos?.options?.response
? props.pos?.options?.response
: props.pos?.options?.defaultValue
? props.pos?.options?.defaultValue
: ""
);
setSelectOption(
props.pos?.options?.response
? props.pos?.options?.response
: props.pos?.options?.defaultValue
? props.pos?.options?.defaultValue
: ""
);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
useEffect(() => {
if (
["name", "email", "job title", "company"].includes(props.pos?.type) &&
props.isNeedSign &&
props.data?.signerObjId === props?.signerObjId
) {
const defaultData = props.pos?.options?.defaultValue;
if (defaultData) {
setTextValue(defaultData);
}
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [props.pos]);
const ExampleCustomInput = forwardRef(({ value, onClick }, ref) => (
<div
className="inputPlaceholder"
style={{ overflow: "hidden", fontSize: calculateFontSize() }}
onClick={onClick}
ref={ref}
>
{value}
<i className="fa-regular fa-calendar" style={{ marginLeft: "5px" }}></i>
</div>
));
ExampleCustomInput.displayName = "ExampleCustomInput";
useEffect(() => {
if (
["name", "email", "job title", "company"].includes(type) &&
props.isNeedSign &&
props.data?.signerObjId === props.signerObjId
) {
const isDefault = true;
const senderUser = localStorage.getItem(`Extand_Class`);
const jsonSender = JSON.parse(senderUser);
onChangeInput(
jsonSender && jsonSender[0],
null,
props.xyPostion,
null,
props.setXyPostion,
props.data.Id,
isDefault
);
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [type]);
const calculateFontSize = () => {
const fontSize = 10 + Math.min(props.pos.Width, props.pos.Height) * 0.1;
const size = fontSize ? fontSize : 12;
return size + "px";
};
//function for show checked checkbox
const selectCheckbox = (ind) => {
const res = props.pos.options?.response;
const defaultCheck = props.pos.options?.defaultValue;
if (res && res?.length > 0) {
const isSelectIndex = res.indexOf(ind);
if (isSelectIndex > -1) {
return true;
} else {
return false;
}
// }
} else if (defaultCheck) {
const isSelectIndex = defaultCheck.indexOf(ind);
if (isSelectIndex > -1) {
return true;
} else {
return false;
}
} else {
return false;
}
};
const handleRadioCheck = (data) => {
const defaultData = props.pos.options?.defaultValue;
if (textValue === data) {
return true;
} else if (defaultData === data) {
return true;
} else {
return false;
}
};
//function for set checked and unchecked value of checkbox
const handleCheckboxValue = (isChecked, ind) => {
let updateSelectedCheckbox = [],
checkedList;
let isDefaultValue, isDefaultEmpty;
if (type === "checkbox") {
updateSelectedCheckbox = selectedCheckbox ? selectedCheckbox : [];
if (isChecked) {
updateSelectedCheckbox.push(ind);
setSelectedCheckbox(updateSelectedCheckbox);
} else {
checkedList = selectedCheckbox.filter((data) => data !== ind);
setSelectedCheckbox(checkedList);
}
if (props.isNeedSign) {
isDefaultValue = props.pos.options?.defaultValue;
}
if (isDefaultValue && isDefaultValue.length > 0) {
isDefaultEmpty = true;
}
onChangeInput(
checkedList ? checkedList : updateSelectedCheckbox,
props.pos.key,
props.xyPostion,
props.index,
props.setXyPostion,
props.data && props.data.Id,
false,
null,
isDefaultEmpty
);
}
};
//function to handle select radio widget and set value seletced by user
const handleCheckRadio = (isChecked, data) => {
let isDefaultValue,
isDefaultEmpty,
isRadio = true;
if (props.isNeedSign) {
isDefaultValue = props.pos.options?.defaultValue;
}
if (isDefaultValue) {
isDefaultEmpty = true;
}
if (isChecked) {
setTextValue(data);
} else {
setTextValue("");
}
onChangeInput(
data,
props.pos.key,
props.xyPostion,
props.index,
props.setXyPostion,
props.data && props.data.Id,
false,
null,
isDefaultEmpty,
isRadio
);
};
//function to set onchange date
const handleOnDateChange = (date) => {
props.setStartDate(date);
const isDateChange = true;
const dateObj = {
date: date,
format: props.selectDate.format
};
props.handleSaveDate(dateObj, isDateChange);
};
//handle height on enter press in text area
const handleEnterPress = (e) => {
const height = 15;
if (e.key === "Enter") {
//function to save height of text area
onChangeHeightOfTextArea(
height,
props.pos.type,
props.pos.key,
props.xyPostion,
props.index,
props.setXyPostion,
props.data && props.data?.Id
);
}
};
switch (type) {
case "signature":
return props.pos.SignUrl ? (
<img
alt="signimg"
draggable="false"
src={props.pos.SignUrl}
style={{
width: "99%",
height: "100%",
objectFit: "contain"
}}
/>
) : (
<div style={{ fontSize: 11, color: "black", justifyContent: "center" }}>
{props?.handleUserName &&
props?.handleUserName(
props?.data?.Id,
props?.data?.Role,
props?.pos?.type
)}
</div>
);
case "stamp":
return props.pos.SignUrl ? (
<img
alt="signimg"
draggable="false"
src={props.pos.SignUrl}
style={{
width: "99%",
height: "100%",
objectFit: "contain"
}}
/>
) : (
<div style={{ fontSize: 11, color: "black", justifyContent: "center" }}>
{props?.handleUserName &&
props?.handleUserName(
props?.data?.Id,
props?.data?.Role,
props?.pos?.type
)}
</div>
);
case "checkbox":
return (
<div style={{ zIndex: props.isSignYourself && "99" }}>
{props.pos.options?.values?.map((data, ind) => {
return (
<div key={ind} className="flex items-center text-center gap-0.5">
<input
style={{
// width: props.pos.Width,
display: "flex",
justifyContent: "center",
marginTop: ind === 0 ? 0 : "5px"
}}
onBlur={handleInputBlur}
disabled={
props.isNeedSign &&
(props.pos.options?.isReadOnly ||
props.data?.signerObjId !== props.signerObjId)
}
type="checkbox"
checked={selectCheckbox(ind)}
onChange={(e) => {
if (e.target.checked) {
if (!props.isPlaceholder) {
const maxRequired =
props.pos.options?.validation?.maxRequiredCount;
const maxCountInt =
maxRequired && parseInt(maxRequired);
if (maxCountInt > 0) {
if (
selectedCheckbox &&
selectedCheckbox?.length <= maxCountInt - 1
) {
handleCheckboxValue(e.target.checked, ind);
}
} else {
handleCheckboxValue(e.target.checked, ind);
}
}
} else {
handleCheckboxValue(e.target.checked, ind);
}
}}
/>
{!props.pos.options?.isHideLabel && (
<label className="text-xs mb-0 text-center">{data}</label>
)}
</div>
);
})}
</div>
);
case textInputWidget:
return props.isSignYourself ||
(props.isNeedSign && props.data?.signerObjId === props.signerObjId) ? (
<input
className="inputPlaceholder"
ref={inputRef}
placeholder={validatePlaceholder}
style={{ fontSize: calculateFontSize() }}
value={textValue}
type="text"
tabIndex="0"
disabled={
props.isNeedSign && props.data?.signerObjId !== props.signerObjId
? true
: props.isPlaceholder
}
onBlur={handleInputBlur}
onChange={(e) => {
setTextValue(e.target.value);
onChangeInput(
e.target.value,
props.pos.key,
props.xyPostion,
props.index,
props.setXyPostion,
props.data && props.data?.Id,
false
);
}}
/>
) : (
<div
style={{
color: "black",
fontSize: calculateFontSize()
}}
>
<span>{type}</span>
</div>
);
case "dropdown":
return props.data?.signerObjId === props.signerObjId ? (
<select
className="inputPlaceholder"
id="myDropdown"
style={{ fontSize: "12px" }}
value={selectOption}
onChange={(e) => {
setSelectOption(e.target.value);
onChangeInput(
e.target.value,
props.pos.key,
props.xyPostion,
props.index,
props.setXyPostion,
props.data && props.data?.Id,
false
);
}}
>
{/* Default/Title option */}
<option value="" disabled hidden>
{props?.pos?.options?.name}
</option>
{props.pos?.options?.values.map((data, ind) => {
return (
<option key={ind} value={data}>
{data}
</option>
);
})}
</select>
) : (
<div
className="inputPlaceholder"
style={{ fontSize: calculateFontSize() }}
>
{props.pos?.options?.name ? props.pos.options.name : type}
</div>
);
case "initials":
return props.pos.SignUrl ? (
<img
alt="signimg"
draggable="false"
src={props.pos.SignUrl}
style={{
width: "99%",
height: "100%",
objectFit: "contain"
}}
/>
) : (
<div style={{ fontSize: 11, color: "black", justifyContent: "center" }}>
{props?.handleUserName &&
props?.handleUserName(
props?.data?.Id,
props?.data?.Role,
props?.pos?.type
)}
</div>
);
case "name":
return props.isSignYourself ||
(props.isNeedSign && props.data?.signerObjId === props.signerObjId) ? (
<input
tabIndex="0"
ref={inputRef}
placeholder={"name"}
style={{ fontSize: calculateFontSize() }}
className="inputPlaceholder"
type="text"
value={textValue}
onBlur={handleInputBlur}
onChange={(e) => {
const isDefault = false;
handleTextValid(e);
onChangeInput(
e.target.value,
props.pos.key,
props.xyPostion,
props.index,
props.setXyPostion,
props.data && props.data?.Id,
isDefault
);
}}
/>
) : (
<div
style={{
color: "black",
fontSize: calculateFontSize()
}}
>
<span>{type}</span>
</div>
);
case "company":
return props.isSignYourself ||
(props.isNeedSign && props.data?.signerObjId === props.signerObjId) ? (
<input
className="inputPlaceholder"
type="text"
ref={inputRef}
placeholder={"company"}
style={{ fontSize: calculateFontSize() }}
value={textValue}
onBlur={handleInputBlur}
onChange={(e) => {
handleTextValid(e);
onChangeInput(
e.target.value,
props.pos.key,
props.xyPostion,
props.index,
props.setXyPostion,
props.data && props.data?.Id,
false
);
}}
/>
) : (
<div
style={{
color: "black",
fontSize: calculateFontSize()
}}
>
<span>{type}</span>
</div>
);
case "job title":
return props.isSignYourself ||
(props.isNeedSign && props.data?.signerObjId === props.signerObjId) ? (
<input
className="inputPlaceholder"
type="text"
ref={inputRef}
placeholder={"job title"}
style={{ fontSize: calculateFontSize() }}
value={textValue}
onBlur={handleInputBlur}
onChange={(e) => {
handleTextValid(e);
onChangeInput(
e.target.value,
props.pos.key,
props.xyPostion,
props.index,
props.setXyPostion,
props.data && props.data?.Id,
false
);
}}
/>
) : (
<div
style={{
color: "black",
fontSize: calculateFontSize()
}}
>
<span>{type}</span>
</div>
);
case "date":
return (
<div>
<DatePicker
renderCustomHeader={({ date, changeYear, changeMonth }) => (
<div className="flex justify-start ml-2 ">
<select
className="bg-transparent outline-none"
value={months[getMonth(date)]}
onChange={({ target: { value } }) =>
changeMonth(months.indexOf(value))
}
>
{months.map((option) => (
<option key={option} value={option}>
{option}
</option>
))}
</select>
<select
className="bg-transparent outline-none"
value={getYear(date)}
onChange={({ target: { value } }) => changeYear(value)}
>
{years.map((option) => (
<option key={option} value={option}>
{option}
</option>
))}
</select>
</div>
)}
disabled={
props.isPlaceholder ||
(props.isNeedSign &&
props.data?.signerObjId !== props.signerObjId)
}
onBlur={handleInputBlur}
closeOnScroll={true}
className="inputPlaceholder"
style={{ outlineColor: "#007bff" }}
selected={
props?.startDate
? props?.startDate
: props.pos.options?.response &&
new Date(props.pos.options.response)
}
onChange={(date) => handleOnDateChange(date)}
popperPlacement="top-end"
customInput={<ExampleCustomInput />}
dateFormat={
props.selectDate
? props.selectDate?.format
: props.pos?.options?.validation?.format
? props.pos?.options?.validation?.format
: "MM/dd/yyyy"
}
/>
</div>
);
case "image":
return props.pos.SignUrl ? (
<img
alt="signimg"
draggable="false"
src={props.pos.SignUrl}
style={{
width: "99%",
height: "100%",
objectFit: "contain"
}}
/>
) : (
<div style={{ fontSize: 11, color: "black", justifyContent: "center" }}>
{props?.handleUserName &&
props?.handleUserName(
props?.data?.Id,
props?.data?.Role,
props?.pos?.type
)}
</div>
);
case "email":
return props.isSignYourself ||
(props.isNeedSign && props.data?.signerObjId === props.signerObjId) ? (
<input
className="inputPlaceholder"
type="text"
ref={inputRef}
placeholder={"email"}
style={{ fontSize: calculateFontSize() }}
value={textValue}
onBlur={handleInputBlur}
onChange={(e) => {
handleTextValid(e);
onChangeInput(
e.target.value,
props.pos.key,
props.xyPostion,
props.index,
props.setXyPostion,
props.data && props.data?.Id,
false
);
}}
/>
) : (
<div
style={{
color: "black",
fontSize: calculateFontSize()
}}
>
<span>{type}</span>
</div>
);
case radioButtonWidget:
return (
<div>
{props.pos.options?.values.map((data, ind) => {
return (
<div key={ind} className="flex items-center text-center gap-0.5">
<input
style={{
width: props.pos.Width,
display: "flex",
justifyContent: "center",
marginTop: ind === 0 ? 0 : "5px"
}}
type="radio"
disabled={
props.isNeedSign &&
(props.pos.options?.isReadOnly ||
props.data?.signerObjId !== props.signerObjId)
}
checked={handleRadioCheck(data)}
onChange={(e) => {
if (!props.isPlaceholder) {
handleCheckRadio(e.target.checked, data);
}
}}
/>
{!props.pos.options?.isHideLabel && (
<label className="text-xs mb-0">{data}</label>
)}
</div>
);
})}
</div>
);
case textWidget:
return (
<textarea
placeholder="Enter label"
rows={1}
onKeyDown={handleEnterPress}
value={textValue}
onBlur={handleInputBlur}
onChange={(e) => {
setTextValue(e.target.value);
onChangeInput(
e.target.value,
props.pos.key,
props.xyPostion,
props.index,
props.setXyPostion,
props.data && props.data?.Id,
false
);
}}
className={
isMobile
? "labelTextArea labelWidthMobile"
: "labelTextArea labelWidthDesktop"
}
style={{ whiteSpace: "pre-wrap" }}
cols="50"
/>
);
default:
return props.pos.SignUrl ? (
<div style={{ pointerEvents: "none" }}>
<img
alt="signimg"
draggable="false"
src={props.pos.SignUrl}
style={{
width: "99%",
height: "100%",
objectFit: "contain"
}}
/>
</div>
) : (
<div
style={{
fontSize: "10px",
color: "black",
justifyContent: "center"
}}
>
{props.pos.isStamp ? <div>stamp</div> : <div>signature</div>}
{props?.handleUserName &&
props?.handleUserName(props?.data?.Id, props?.data?.Role)}
</div>
);
}
}
export default PlaceholderType;
@@ -21,7 +21,7 @@ function PrevNext({ pageNumber, allPages, changePage }) {
fontWeight: "600",
border: "0px",
marginRight: "5px",
marginRight: "5px"
}}
disabled={pageNumber <= 1}
onClick={previousPage}
@@ -31,7 +31,7 @@ function PrevNext({ pageNumber, allPages, changePage }) {
<span
style={{
fontSize: "13px",
fontWeight: "600",
fontWeight: "600"
}}
>
{pageNumber || (allPages ? 1 : "--")} of {allPages || "--"}
@@ -43,7 +43,7 @@ function PrevNext({ pageNumber, allPages, changePage }) {
background: "#d3edeb",
fontWeight: "600",
marginLeft: "5px",
border: "0px",
border: "0px"
}}
disabled={pageNumber >= allPages}
onClick={nextPage}
@@ -0,0 +1,291 @@
import React, { useRef, useState } from "react";
import { useAutoAnimate } from "@formkit/auto-animate/react";
import {
color,
darkenColor,
getFirstLetter,
isMobile,
nameColor
} from "../../constant/Utils";
const RecipientList = (props) => {
const [animationParent] = useAutoAnimate();
const [isHover, setIsHover] = useState();
const [isEdit, setIsEdit] = useState(false);
//function for onhover signer name change background color
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) => {
return props.signerPos.some((x) => x.Id === Id);
};
//handle drag start
const handleDragStart = (e, id) => {
// `e.dataTransfer.setData('text/plain')`is used to set the data to be transferred during a drag operation.
// The first argument specifies the type of data being set, and the second argument is the actual data you want to transfer.
e.dataTransfer.setData("text/plain", id);
};
//handleDragOver prevents the default behavior of the dragover event, which is necessary for the drop event to be triggered.
const handleDragOver = (e) => {
e.preventDefault();
};
//handle draggable element drop and also used in mobile view on up and down key to chnage sequence of recipient's list
const handleChangeSequence = (e, ind, isUp, isDown) => {
e.preventDefault();
let draggedItemId;
let index = ind;
//if isUp true then set item's id and index in mobile view
if (isUp) {
draggedItemId = index;
index = index - 1;
}
//if isDown true then set item's id and index in mobile view
else if (isDown) {
draggedItemId = index;
index = index + 1;
} //else set id on drag element in desktop viiew
else {
//`e.dataTransfer.getData('text/plain')` is used to get data that you have saved.
draggedItemId = e.dataTransfer.getData("text/plain");
}
//convert string to number
const intDragId = parseInt(draggedItemId);
//get that item to change position
const draggedItem = props.signersdata.filter((_, ind) => ind === intDragId);
const remainingItems = props.signersdata.filter(
(_, ind) => ind !== intDragId
);
//splice method is used to replace or add new value in array at specific index
remainingItems.splice(index, 0, ...draggedItem);
//set current draggable recipient details,objectId,index,contract_className ... after replace recipient list
props.setSignersData(remainingItems);
props.setSignerObjId(remainingItems[index]?.objectId || "");
props.setIsSelectId(index);
props.setContractName(remainingItems[index]?.className || "");
props.setUniqueId(remainingItems[index]?.Id);
props.setRoleName(remainingItems[index]?.Role);
props.setBlockColor(remainingItems[index]?.blockColor);
};
return (
<>
{props.signersdata.length > 0 &&
props.signersdata.map((obj, ind) => {
return (
<div
ref={animationParent}
key={ind}
draggable={props.sendInOrder && !isMobile ? true : false}
onDragStart={(e) =>
props.sendInOrder && !isMobile && handleDragStart(e, ind)
}
onDragOver={(e) =>
props.sendInOrder && !isMobile && handleDragOver(e)
}
onDrop={(e) =>
props.sendInOrder && !isMobile && handleChangeSequence(e, ind)
}
data-tut="reactourFirst"
onMouseEnter={() => setIsHover(ind)}
onMouseLeave={() => setIsHover(null)}
className={
props.sendInOrder
? props.isMailSend
? "disabled"
: "dragCursor"
: props.isMailSend && "disabled"
}
style={
(!isMobile && isHover === ind) || props.isSelectListId === ind
? onHoverStyle(ind, obj?.blockColor)
: nonHoverStyle(ind)
}
onClick={(e) => {
e.preventDefault();
props.setSignerObjId(obj?.objectId || "");
props.setIsSelectId(ind);
props.setContractName(obj?.className || "");
props.setUniqueId(obj.Id);
props.setRoleName(obj.Role);
props.setBlockColor(obj?.blockColor);
if (props.handleModal) {
props.handleModal();
}
}}
>
<div
style={{
display: "flex",
flexDirection: "row",
alignItems: "center",
width: "100%"
}}
>
<div
style={{
background: obj?.blockColor
? darkenColor(obj?.blockColor, 0.4)
: nameColor[ind % nameColor.length],
width: 30,
height: 30,
display: "flex",
borderRadius: 30 / 2,
justifyContent: "center",
alignItems: "center",
marginRight: "12px"
}}
>
<span
className={props.sendInOrder && "dragCursor"}
style={{
fontSize: "12px",
textAlign: "center",
fontWeight: "bold",
color: "white",
textTransform: "uppercase"
}}
>
{isWidgetExist(obj.Id) ? (
<i className="fa-solid fa-check"></i>
) : (
<>
{obj.Name
? getFirstLetter(obj.Name)
: getFirstLetter(obj.Role)}
</>
)}
</span>
</div>
<div
style={{
display: "flex",
flexDirection: obj.Name ? "column" : "row",
alignItems: "center"
}}
>
{obj.Name ? (
<span className={"userName"}>{obj.Name}</span>
) : (
<>
<span
className="userName"
style={{ cursor: "pointer" }}
onClick={() => {
setIsEdit({ [obj.Id]: true });
props.setRoleName(obj.Role);
}}
>
{isEdit?.[obj.Id] && props.handleRoleChange ? (
<input
ref={inputRef}
style={{
backgroundColor: "transparent",
width: "inherit",
padding: "3px"
}}
value={obj.Role}
onChange={(e) => props.handleRoleChange(e, obj.Id)}
onBlur={() => {
setIsEdit({});
props.handleOnBlur(obj.Role, obj.Id);
}}
onKeyDown={(e) => {
if (e.key === "Enter") {
e.preventDefault();
inputRef.current.blur();
}
}}
/>
) : (
<span style={{ padding: "3px" }}>{obj.Role}</span>
)}
</span>
</>
)}
{obj.Name && <span className={"useEmail"}>{obj.Role}</span>}
</div>
</div>
{isMobile && props.sendInOrder && (
<div
style={{
display: "flex",
flexDirection: "row",
alignItems: "center",
gap: 5
}}
>
<div
onClick={(e) => {
if (ind !== 0) {
e.stopPropagation();
handleChangeSequence(e, ind, "up");
}
}}
style={{ color: ind === 0 ? "gray" : "black" }}
>
</div>
<div
onClick={(e) => {
if (ind !== props.signersdata.length - 1) {
e.stopPropagation();
handleChangeSequence(e, ind, null, "down");
}
}}
style={{
color:
ind === props.signersdata.length - 1 ? "gray" : "black"
}}
>
</div>
</div>
)}
{props.handleDeleteUser && (
<div
onClick={(e) => {
e.stopPropagation();
props.handleDeleteUser(obj.Id);
}}
style={{ cursor: "pointer", marginLeft: "5px" }}
>
<i className="fa-regular fa-trash-can"></i>
</div>
)}
<hr />
</div>
);
})}
</>
);
};
export default RecipientList;
@@ -1,7 +1,7 @@
import React from "react";
import RSC from "react-scrollbars-custom";
import { Document, Page, pdfjs } from "react-pdf";
import { themeColor } from "../../utils/ThemeColor/backColor";
import { Document, Page } from "react-pdf";
import { themeColor } from "../../constant/const";
function RenderAllPdfPage({
pdfUrl,
@@ -12,8 +12,6 @@ function RenderAllPdfPage({
setSignBtnPosition,
pageNumber
}) {
pdfjs.GlobalWorkerOptions.workerSrc = `//cdnjs.cloudflare.com/ajax/libs/pdf.js/${pdfjs.version}/pdf.worker.js`;
//set all number of pages after load pdf
function onDocumentLoad({ numPages }) {
setAllPages(numPages);
@@ -33,7 +31,7 @@ function RenderAllPdfPage({
<div style={{ width: "140px" }}>
<div
style={{
background: themeColor()
background: themeColor
// color:"white"
}}
className="signedStyle"
@@ -0,0 +1,694 @@
import React from "react";
import RSC from "react-scrollbars-custom";
import { Document, Page } from "react-pdf";
import {
defaultWidthHeight,
handleImageResize,
handleSignYourselfImageResize
} from "../../constant/Utils";
import Placeholder from "./Placeholder";
import Alert from "../../primitives/Alert";
function RenderPdf({
pageNumber,
pdfOriginalWidth,
pdfNewWidth,
drop,
signerPos,
successEmail,
handleTabDrag,
handleStop,
isDragging,
setIsSignPad,
setIsStamp,
handleDeleteSign,
setSignKey,
pdfDetails,
xyPostion,
pdfUrl,
numPages,
pageDetails,
pdfRequest,
setCurrentSigner,
signerObjectId,
signedSigners,
setPdfLoadFail,
placeholder,
pdfLoadFail,
setSignerPos,
setXyPostion,
index,
containerWH,
setIsResize,
handleLinkUser,
setUniqueId,
signersdata,
setIsPageCopy,
setSignerObjId,
setShowDropdown,
setIsInitial,
setIsValidate,
setWidgetType,
setValidateAlert,
setIsRadio,
setCurrWidgetsDetails,
setSelectWidgetId,
selectWidgetId,
unSignedWidgetId,
setIsCheckbox,
handleNameModal,
setTempSignerId,
uniqueId
}) {
const isMobile = window.innerWidth < 767;
const newWidth = containerWH.width;
const scale = isMobile ? pdfOriginalWidth / newWidth : 1;
//check isGuestSigner is present in local if yes than handle login flow header in mobile view
const isGuestSigner = localStorage.getItem("isGuestSigner");
// handle signature block width and height according to screen
const posWidth = (pos, signYourself) => {
const defaultWidth = defaultWidthHeight(pos.type).width;
const posWidth = pos.Width ? pos.Width : defaultWidth;
let width;
if (signYourself) {
width = posWidth;
return width;
} else {
if (isMobile) {
if (!pos.isMobile) {
if (pos.IsResize) {
width = posWidth ? posWidth : defaultWidth;
return width;
} else {
width = (posWidth || defaultWidth) / scale;
return width;
}
} else {
width = posWidth;
return width;
}
} else {
if (pos.isMobile) {
if (pos.IsResize) {
width = posWidth ? posWidth : defaultWidth;
return width;
} else {
width = (posWidth || defaultWidth) * pos.scale;
return width;
}
} else {
width = posWidth ? posWidth : defaultWidth;
return width;
}
}
}
};
const posHeight = (pos, signYourself) => {
let height;
const posHeight = pos.Height;
const defaultHeight = defaultWidthHeight(pos.type).height;
if (signYourself) {
height = posHeight ? posHeight : defaultHeight;
return height;
} else {
if (isMobile) {
if (!pos.isMobile) {
if (pos.IsResize) {
height = posHeight ? posHeight : defaultHeight;
return height;
} else {
height = (posHeight || defaultHeight) / scale;
return height;
}
} else {
height = posHeight ? posHeight : defaultHeight;
return height;
}
} else {
if (pos.isMobile) {
if (pos.IsResize) {
height = posHeight ? posHeight : defaultHeight;
return height;
} else {
height = (posHeight || defaultHeight) * pos.scale;
return height;
}
} else {
height = posHeight ? posHeight : defaultHeight;
return height;
}
}
}
};
const xPos = (pos, signYourself) => {
const resizePos = pos.xPosition;
if (signYourself) {
return resizePos;
} else {
//checking both condition mobile and desktop view
if (isMobile) {
//if pos.isMobile false -- placeholder saved from desktop view then handle position in mobile view divided by scale
if (!pos.isMobile) {
return resizePos / scale;
}
//pos.isMobile true -- placeholder save from mobile view(small device) handle position in mobile view(small screen) view divided by scale
else {
return resizePos * (pos.scale / scale);
}
} else {
//else if pos.isMobile true -- placeholder saved from mobile or tablet view then handle position in desktop view divide by scale
if (pos.isMobile) {
return pos.scale && resizePos * pos.scale;
}
//else placeholder save from desktop(bigscreen) and show in desktop(bigscreen)
else {
return resizePos;
}
}
}
};
const yPos = (pos, signYourself) => {
const resizePos = pos.yPosition;
if (signYourself) {
return resizePos;
} else {
//checking both condition mobile and desktop view
if (isMobile) {
//if pos.isMobile false -- placeholder saved from desktop view then handle position in mobile view divided by scale
if (!pos.isMobile) {
return resizePos / scale;
}
//pos.isMobile true -- placeholder save from mobile view(small device) handle position in mobile view(small screen) view divided by scale
else {
return resizePos * (pos.scale / scale);
}
} else {
//else if pos.isMobile true -- placeholder saved from mobile or tablet view then handle position in desktop view divide by scale
if (pos.isMobile) {
return pos.scale && resizePos * pos.scale;
}
//else placeholder save from desktop(bigscreen) and show in desktop(bigscreen)
else {
return resizePos;
}
}
}
};
//function for render placeholder block over pdf document
const checkSignedSignes = (data) => {
const checkSign = signedSigners.filter(
(sign) => sign.objectId === data.signerObjId
);
if (data.signerObjId === signerObjectId) {
setCurrentSigner(true);
}
const handleAllUserName = (Id, Role, type) => {
return pdfDetails[0].Signers.map((signerData, key) => {
return (
signerData.objectId === data.signerObjId && (
<React.Fragment key={key}>
{signerData?.Name && (
<div style={{ color: "black", fontSize: 8, fontWeight: "500" }}>
{signerData.Name}
</div>
)}
{type && (
<div style={{ fontWeight: "700", fontSize: 11 }}>{type}</div>
)}
{Role && (
<div style={{ color: "black", fontSize: 8, fontWeight: "500" }}>
{`(${Role})`}
</div>
)}
</React.Fragment>
)
);
});
};
return (
checkSign.length === 0 &&
data.placeHolder.map((placeData, key) => {
return (
<React.Fragment key={key}>
{placeData.pageNumber === pageNumber &&
placeData.pos.map((pos) => {
return (
pos && (
<React.Fragment key={pos.key}>
<Placeholder
pos={pos}
setSignKey={setSignKey}
setIsSignPad={setIsSignPad}
setIsStamp={setIsStamp}
handleSignYourselfImageResize={handleImageResize}
index={pageNumber}
xyPostion={signerPos}
setXyPostion={setSignerPos}
data={data}
setIsResize={setIsResize}
isShowBorder={false}
signerObjId={signerObjectId}
isShowDropdown={true}
isNeedSign={true}
isSignYourself={false}
xPos={xPos}
yPos={yPos}
posWidth={posWidth}
posHeight={posHeight}
handleUserName={handleAllUserName}
isDragging={false}
pdfDetails={pdfDetails}
setIsInitial={setIsInitial}
setValidateAlert={setValidateAlert}
unSignedWidgetId={unSignedWidgetId}
setSelectWidgetId={setSelectWidgetId}
selectWidgetId={selectWidgetId}
setCurrWidgetsDetails={setCurrWidgetsDetails}
/>
</React.Fragment>
)
);
})}
</React.Fragment>
);
})
);
};
const handleUserName = (Id, Role, type) => {
if (Id) {
const checkSign = signersdata.find((sign) => sign.Id === Id);
if (checkSign?.Name) {
return (
<>
<div style={{ color: "black", fontSize: 8, fontWeight: "500" }}>
{checkSign?.Name}
</div>
{type && (
<div style={{ fontWeight: "700", fontSize: 11 }}>{type}</div>
)}
<div style={{ color: "black", fontSize: 8, fontWeight: "500" }}>
{`(${Role})`}
</div>
</>
);
} else {
return (
<>
{type && (
<div style={{ fontWeight: "700", fontSize: 11 }}>{type}</div>
)}
<div style={{ color: "black", fontSize: 8, fontWeight: "500" }}>
{Role}
</div>
</>
);
}
} else {
return (
<>
{type && (
<div style={{ fontWeight: "700", fontSize: 11 }}>{type}</div>
)}
<div style={{ color: "black", fontSize: 8, fontWeight: "500" }}>
{Role}
</div>
</>
);
}
};
return (
<>
{successEmail && <Alert type={"success"}>Email sent successfully!</Alert>}
{isMobile && scale ? (
<div
style={{
border: "0.1px solid #ebe8e8",
marginTop: isGuestSigner && "30px"
}}
ref={drop}
id="container"
>
{pdfLoadFail.status &&
(pdfRequest
? signerPos.map((data, key) => {
return (
<React.Fragment key={key}>
{checkSignedSignes(data)}
</React.Fragment>
);
})
: placeholder // placeholder mobile
? signerPos.map((data, ind) => {
return (
<React.Fragment key={ind}>
{data.placeHolder.map((placeData, index) => {
return (
<React.Fragment key={index}>
{placeData.pageNumber === pageNumber &&
placeData.pos.map((pos) => {
return (
<React.Fragment key={pos.key}>
<Placeholder
pos={pos}
setIsPageCopy={setIsPageCopy}
setSignKey={setSignKey}
handleDeleteSign={handleDeleteSign}
setIsStamp={setIsStamp}
handleTabDrag={handleTabDrag}
handleStop={handleStop}
handleSignYourselfImageResize={
handleImageResize
}
index={pageNumber}
xyPostion={signerPos}
setXyPostion={setSignerPos}
setSignerObjId={setSignerObjId}
data={data}
setIsResize={setIsResize}
setShowDropdown={setShowDropdown}
isShowBorder={true}
isPlaceholder={true}
setUniqueId={setUniqueId}
handleLinkUser={handleLinkUser}
handleUserName={handleUserName}
isSignYourself={false}
xPos={xPos}
yPos={yPos}
posWidth={posWidth}
posHeight={posHeight}
isDragging={isDragging}
setIsValidate={setIsValidate}
setWidgetType={setWidgetType}
setIsRadio={setIsRadio}
setIsCheckbox={setIsCheckbox}
setCurrWidgetsDetails={
setCurrWidgetsDetails
}
setSelectWidgetId={setSelectWidgetId}
selectWidgetId={selectWidgetId}
handleNameModal={handleNameModal}
setTempSignerId={setTempSignerId}
uniqueId={uniqueId}
/>
</React.Fragment>
);
})}
</React.Fragment>
);
})}
</React.Fragment>
);
})
: xyPostion.map((data, ind) => {
return (
<React.Fragment key={ind}>
{data.pageNumber === pageNumber &&
data.pos.map((pos) => {
return (
pos && (
<Placeholder
pos={pos}
setIsPageCopy={setIsPageCopy}
setSignKey={setSignKey}
handleDeleteSign={handleDeleteSign}
setIsStamp={setIsStamp}
handleTabDrag={handleTabDrag}
handleStop={handleStop}
handleSignYourselfImageResize={
handleSignYourselfImageResize
}
index={index}
xyPostion={xyPostion}
setXyPostion={setXyPostion}
pdfOriginalWidth={pdfOriginalWidth}
containerWH={containerWH}
setIsSignPad={setIsSignPad}
isShowBorder={true}
isSignYourself={true}
xPos={xPos}
yPos={yPos}
posWidth={posWidth}
posHeight={posHeight}
pdfDetails={pdfDetails[0]}
isDragging={isDragging}
setIsInitial={setIsInitial}
setWidgetType={setWidgetType}
setSelectWidgetId={setSelectWidgetId}
selectWidgetId={selectWidgetId}
handleUserName={handleUserName}
setIsCheckbox={setIsCheckbox}
setValidateAlert={setValidateAlert}
setCurrWidgetsDetails={setCurrWidgetsDetails}
/>
)
);
})}
</React.Fragment>
);
}))}
{/* this component for render pdf document is in middle of the component */}
<div
style={{
display: "flex",
justifyContent: "center",
alignItems: "center"
}}
>
<Document
onLoadError={() => {
setPdfLoadFail(true);
}}
loading={"Loading Document.."}
onLoadSuccess={pageDetails}
// ref={pdfRef}'
onClick={() => {
if (setSelectWidgetId) {
setSelectWidgetId("");
}
}}
file={
pdfUrl
? pdfUrl
: pdfDetails[0] && pdfDetails[0].SignedUrl
? pdfDetails[0].SignedUrl
: pdfDetails[0].URL
}
>
{Array.from(new Array(numPages), (el, index) => (
<Page
key={index}
pageNumber={pageNumber}
width={containerWH.width}
height={containerWH.height}
renderAnnotationLayer={false}
renderTextLayer={false}
onGetAnnotationsError={(error) => {
console.log("annotation error", error);
}}
/>
))}
</Document>
</div>
</div>
) : (
<RSC
style={{
position: "relative",
boxShadow: "rgba(17, 12, 46, 0.15) 0px 48px 100px 0px",
width:
pdfOriginalWidth > pdfNewWidth ? pdfNewWidth : pdfOriginalWidth,
height: window.innerHeight - 110 + "px"
}}
noScrollY={false}
noScrollX={pdfNewWidth < pdfOriginalWidth ? false : true}
>
<div
style={{
border: "0.1px solid #ebe8e8",
width: pdfOriginalWidth
}}
ref={drop}
id="container"
>
{pdfLoadFail.status &&
(pdfRequest
? signerPos.map((data, key) => {
return (
<React.Fragment key={key}>
{checkSignedSignes(data)}
</React.Fragment>
);
})
: placeholder
? signerPos.map((data, ind) => {
return (
<React.Fragment key={ind}>
{data.placeHolder.map((placeData, index) => {
return (
<React.Fragment key={index}>
{placeData.pageNumber === pageNumber &&
placeData.pos.map((pos) => {
return (
<React.Fragment key={pos.key}>
<Placeholder
pos={pos}
setIsPageCopy={setIsPageCopy}
setSignKey={setSignKey}
handleDeleteSign={handleDeleteSign}
setIsStamp={setIsStamp}
handleTabDrag={handleTabDrag}
handleStop={handleStop}
handleSignYourselfImageResize={
handleImageResize
}
index={pageNumber}
xyPostion={signerPos}
setXyPostion={setSignerPos}
setSignerObjId={setSignerObjId}
data={data}
setIsResize={setIsResize}
setShowDropdown={setShowDropdown}
isShowBorder={true}
isPlaceholder={true}
setUniqueId={setUniqueId}
handleLinkUser={handleLinkUser}
handleUserName={handleUserName}
isSignYourself={false}
xPos={xPos}
yPos={yPos}
posWidth={posWidth}
posHeight={posHeight}
isDragging={isDragging}
setIsValidate={setIsValidate}
setWidgetType={setWidgetType}
setIsRadio={setIsRadio}
setIsCheckbox={setIsCheckbox}
setCurrWidgetsDetails={
setCurrWidgetsDetails
}
setSelectWidgetId={setSelectWidgetId}
selectWidgetId={selectWidgetId}
handleNameModal={handleNameModal}
setTempSignerId={setTempSignerId}
uniqueId={uniqueId}
/>
</React.Fragment>
);
})}
</React.Fragment>
);
})}
</React.Fragment>
);
})
: xyPostion.map((data, ind) => {
return (
<React.Fragment key={ind}>
{data.pageNumber === pageNumber &&
data.pos.map((pos) => {
return (
pos && (
<React.Fragment key={pos.key}>
<Placeholder
pos={pos}
setIsPageCopy={setIsPageCopy}
setSignKey={setSignKey}
handleDeleteSign={handleDeleteSign}
setIsStamp={setIsStamp}
handleTabDrag={handleTabDrag}
handleStop={(event, dragElement) =>
handleStop(event, dragElement, pos.type)
}
handleSignYourselfImageResize={
handleSignYourselfImageResize
}
index={index}
xyPostion={xyPostion}
setXyPostion={setXyPostion}
pdfOriginalWidth={pdfOriginalWidth}
containerWH={containerWH}
setIsSignPad={setIsSignPad}
isShowBorder={true}
isSignYourself={true}
xPos={xPos}
yPos={yPos}
posWidth={posWidth}
posHeight={posHeight}
pdfDetails={pdfDetails[0]}
isDragging={isDragging}
setIsInitial={setIsInitial}
setWidgetType={setWidgetType}
setSelectWidgetId={setSelectWidgetId}
selectWidgetId={selectWidgetId}
handleUserName={handleUserName}
setIsCheckbox={setIsCheckbox}
setValidateAlert={setValidateAlert}
setCurrWidgetsDetails={
setCurrWidgetsDetails
}
/>
</React.Fragment>
)
);
})}
</React.Fragment>
);
}))}
{/* this component for render pdf document is in middle of the component */}
<Document
onLoadError={() => {
const load = {
status: false,
type: "failed"
};
setPdfLoadFail(load);
}}
loading={"Loading Document.."}
onLoadSuccess={pageDetails}
onClick={() => {
if (setSelectWidgetId) {
setSelectWidgetId("");
}
}}
// ref={pdfRef}
file={
pdfUrl
? pdfUrl
: pdfDetails[0] && pdfDetails[0].SignedUrl
? pdfDetails[0].SignedUrl
: pdfDetails[0].URL
}
>
{Array.from(new Array(numPages), (el, index) => (
<Page
key={index}
pageNumber={pageNumber}
renderAnnotationLayer={false}
renderTextLayer={false}
onGetAnnotationsError={(error) => {
console.log("annotation error", error);
}}
/>
))}
</Document>
</div>
</RSC>
)}
</>
);
}
export default RenderPdf;
@@ -1,11 +1,6 @@
import React from "react";
import { useRef, useState } from "react";
import React, { useRef, useState, useEffect } from "react";
import SignatureCanvas from "react-signature-canvas";
import redPen from "../../assests/redPen.png";
import bluePen from "../../assests/bluePen.png";
import blackPen from "../../assests/blackPen.png";
import { themeColor } from "../../utils/ThemeColor/backColor";
import { useEffect } from "react";
import { themeColor } from "../../constant/const";
function SignPad({
isSignPad,
@@ -20,10 +15,17 @@ function SignPad({
onSaveImage,
image,
defaultSign,
setSignature
setSignature,
myInitial,
isInitial,
setIsInitial,
setIsStamp,
widgetType,
currWidgetsDetails,
setCurrWidgetsDetails
}) {
const [penColor, setPenColor] = useState("blue");
const allColor = [bluePen, redPen, blackPen];
const allColor = ["blue", "red", "black"];
const canvasRef = useRef(null);
const [isDefaultSign, setIsDefaultSign] = useState(false);
const [isTab, setIsTab] = useState("draw");
@@ -31,6 +33,7 @@ function SignPad({
const [signValue, setSignValue] = useState("");
const [textWidth, setTextWidth] = useState(null);
const [textHeight, setTextHeight] = useState(null);
const [signatureType, setSignatureType] = useState("draw");
const fontOptions = [
{ value: "Fasthand" },
{ value: "Dancing Script" },
@@ -40,23 +43,19 @@ function SignPad({
];
const [fontSelect, setFontSelect] = useState(fontOptions[0].value);
useEffect(() => {
const senderUser =
localStorage.getItem(
`Parse/${localStorage.getItem("parseAppId")}/currentUser`
) &&
localStorage.getItem(
`Parse/${localStorage.getItem("parseAppId")}/currentUser`
);
const jsonSender = JSON.parse(senderUser);
const senderUser =
localStorage.getItem(
`Parse/${localStorage.getItem("parseAppId")}/currentUser`
) &&
localStorage.getItem(
`Parse/${localStorage.getItem("parseAppId")}/currentUser`
);
const jsonSender = JSON.parse(senderUser);
const currentUserName = jsonSender && jsonSender.name;
const currentUserName = jsonSender && jsonSender.name;
//function for clear signature
setSignValue(currentUserName);
setFontSelect("Fasthand");
}, []);
//function for clear signature image
const handleClear = () => {
setCurrWidgetsDetails({});
if (isTab === "draw") {
if (canvasRef.current) {
canvasRef.current.clear();
@@ -66,12 +65,12 @@ function SignPad({
setIsSignImg("");
} else if (isTab === "uploadImage") {
setImage("");
setImage("");
}
// setIsInitial(false);
};
//function for set signature url
const handleSignatureChange = (dataURL) => {
// canvasRef.current.backgroundColor = 'rgb(165, 26, 26)'
const handleSignatureChange = () => {
setSignature(canvasRef.current.toDataURL());
setIsSignImg(canvasRef.current.toDataURL());
};
@@ -96,34 +95,40 @@ function SignPad({
<button
onClick={() => {
setCurrWidgetsDetails({});
if (!image) {
if (isDefaultSign) {
if (isTab === "mysignature") {
setIsSignImg("");
onSaveSign(isDefaultSign);
if (isInitial) {
onSaveSign(signatureType, "initials");
} else {
onSaveSign(null, "default");
}
} else {
if (isTab === "type") {
setIsSignImg("");
onSaveSign(false, textWidth, textHeight);
onSaveSign(null, false, textWidth, textHeight);
} else {
setIsSignImg("");
onSaveSign();
onSaveSign(signatureType);
}
}
setPenColor("blue");
} else {
setIsSignImg("");
onSaveImage();
onSaveImage(signatureType);
}
setIsSignPad(false);
setIsInitial(false);
setIsImageSelect(false);
setIsDefaultSign(false);
setImage();
setIsTab("draw");
setSignValue("");
setIsStamp(false);
}}
style={{
background: themeColor(),
background: themeColor,
color: "white"
}}
disabled={
@@ -141,7 +146,35 @@ function SignPad({
</div>
);
};
//useEffect for set already draw or save signature url/text url of signature text type and draw type for initial type and signature type widgets
useEffect(() => {
if (currWidgetsDetails && canvasRef.current) {
const isWidgetType = currWidgetsDetails?.type;
const signatureType = currWidgetsDetails?.signatureType;
const url = currWidgetsDetails?.SignUrl;
//checking widget type and draw type signature url
if (isInitial) {
if (isWidgetType === "initials" && signatureType === "draw" && url) {
canvasRef.current.fromDataURL(url);
}
} else if (
isWidgetType === "signature" &&
signatureType === "draw" &&
url
) {
canvasRef.current.fromDataURL(url);
}
}
const trimmedName = currentUserName.trim();
const firstCharacter = trimmedName.charAt(0);
const userName = isInitial ? firstCharacter : currentUserName;
setSignValue(userName);
setFontSelect("Fasthand");
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [isSignPad]);
useEffect(() => {
const loadFont = async () => {
try {
@@ -156,6 +189,7 @@ function SignPad({
};
loadFont();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [fontSelect]);
useEffect(() => {
@@ -164,11 +198,17 @@ function SignPad({
canvasRef.current.fromDataURL(isSignImg);
}
if (isTab === "type") {
convertToImg(fontSelect, signValue);
const trimmedName = signValue ? signValue.trim() : currentUserName.trim();
const firstCharacter = trimmedName.charAt(0);
const userName = isInitial ? firstCharacter : signValue;
setSignValue(userName);
convertToImg(fontSelect, userName);
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [isTab]);
//function for convert input text value in image
const convertToImg = async (fontStyle, text) => {
const convertToImg = async (fontStyle, text, color) => {
//get text content to convert in image
const textContent = text;
const fontfamily = fontStyle
@@ -181,6 +221,7 @@ function SignPad({
const span = document.createElement("span");
span.textContent = textContent;
span.style.font = `20px ${fontfamily}`; // here put your text size and font family
span.style.color = color ? color : penColor;
span.style.display = "hidden";
document.body.appendChild(span); // Replace 'container' with the ID of the container element
@@ -198,13 +239,9 @@ function SignPad({
canvasElement.width = width * pixelRatio;
canvasElement.height = height * pixelRatio;
// Render the content of the span onto the canvas
// ctx.fillStyle = "white"; // Set the background color of the canvas
// ctx.fillRect(0, 0, width*pixelRatio, height*pixelRatio);
// You can customize text styles if needed
ctx.font = font;
ctx.fillStyle = "black"; // Set the text color
ctx.fillStyle = color ? color : penColor; // Set the text color
ctx.textAlign = "center";
ctx.textBaseline = "middle";
ctx.scale(pixelRatio, pixelRatio);
@@ -217,6 +254,45 @@ function SignPad({
setSignature(dataUrl);
};
const PenColorComponent = (props) => {
return (
<div style={{ display: "flex", flexDirection: "row" }}>
{allColor.map((data, key) => {
return (
<i
style={{
margin: "5px",
color: data,
borderBottom:
key === 0 && penColor === "blue"
? "2px solid blue"
: key === 1 && penColor === "red"
? "2px solid red"
: key === 2 && penColor === "black"
? "2px solid black"
: "2px solid white"
}}
onClick={() => {
props?.convertToImg &&
props?.convertToImg(fontSelect, signValue, data);
if (key === 0) {
setPenColor("blue");
} else if (key === 1) {
setPenColor("red");
} else if (key === 2) {
setPenColor("black");
}
}}
key={key}
className="fa solid fa-pen-nib"
width={20}
height={20}
></i>
);
})}
</div>
);
};
return (
<div>
{isSignPad && (
@@ -246,8 +322,10 @@ function SignPad({
}}
>
{isStamp ? (
<span style={{ color: themeColor() }} className="signTab">
Upload stamp image
<span style={{ color: themeColor }} className="signTab">
{widgetType === "image"
? "Upload image"
: "Upload stamp image"}
</span>
) : (
<>
@@ -260,9 +338,7 @@ function SignPad({
setImage();
}}
style={{
color:
isTab === "draw" ? themeColor() : "#515252",
color: isTab === "draw" ? themeColor : "#515252",
marginLeft: "2px"
}}
className="signTab"
@@ -285,12 +361,11 @@ function SignPad({
setIsDefaultSign(false);
setIsImageSelect(true);
setIsTab("uploadImage");
setSignatureType("");
}}
style={{
color:
isTab === "uploadImage"
? themeColor()
: "#515252"
isTab === "uploadImage" ? themeColor : "#515252"
}}
className="signTab"
>
@@ -311,12 +386,11 @@ function SignPad({
setIsDefaultSign(false);
setIsImageSelect(false);
setIsTab("type");
setSignatureType("");
setImage();
}}
style={{
color:
isTab === "type" ? themeColor() : "#515252",
color: isTab === "type" ? themeColor : "#515252",
marginLeft: "2px"
}}
className="signTab"
@@ -333,19 +407,20 @@ function SignPad({
}}
></div>
</div>
{defaultSign && (
{!isInitial && defaultSign ? (
<div>
<span
onClick={() => {
setIsDefaultSign(true);
setIsImageSelect(true);
setIsTab("mysignature");
setSignatureType("");
setImage();
}}
style={{
color:
isTab === "mysignature"
? themeColor()
? themeColor
: "#515252"
}}
className="signTab"
@@ -361,6 +436,38 @@ function SignPad({
}}
></div>
</div>
) : (
isInitial &&
myInitial && (
<div>
<span
onClick={() => {
setIsDefaultSign(true);
setIsImageSelect(true);
setIsTab("mysignature");
setSignatureType("");
setImage();
}}
style={{
color:
isTab === "mysignature"
? themeColor
: "#515252"
}}
className="signTab"
>
My Initials
</span>
<div
style={{
border:
isTab === "mysignature"
? "1.5px solid #108783"
: "1.5px solid #ffffff"
}}
></div>
</div>
)
)}
</>
)}
@@ -373,11 +480,14 @@ function SignPad({
onClick={() => {
setPenColor("blue");
setIsSignPad(false);
setIsInitial(false);
setIsImageSelect(false);
setIsDefaultSign(false);
setImage();
setIsTab("draw");
setSignatureType("draw");
setSignValue("");
setIsStamp(false);
}}
>
&times;
@@ -386,28 +496,34 @@ function SignPad({
<div style={{ height: "100%", padding: 20 }}>
{isDefaultSign ? (
<>
<div
style={{
border: "1px solid black",
display: "flex",
flexDirection: "column",
justifyContent: "center",
alignItems: "center",
marginBottom: 6,
cursor: "pointer"
}}
className="signatureCanvas"
>
<img
alt="stamp img"
<div style={{ display: "flex", justifyContent: "center" }}>
<div
style={{
width: "100%",
height: "100%",
background: "rgb(255, 255, 255)",
objectFit: "contain"
border: "1.3px solid #007bff",
borderRadius: "2px",
display: "flex",
flexDirection: "column",
justifyContent: "center",
alignItems: "center",
marginBottom: 6,
cursor: "pointer"
}}
src={defaultSign}
/>
className={
isInitial ? "intialSignatureCanvas" : "signatureCanvas"
}
>
<img
alt="stamp img"
style={{
width: "100%",
height: "100%",
background: "rgb(255, 255, 255)",
objectFit: "contain"
}}
draggable="false"
src={isInitial ? myInitial : defaultSign}
/>
</div>
</div>
<div style={{ display: "flex", justifyContent: "flex-end" }}>
<SaveBtn />
@@ -415,52 +531,64 @@ function SignPad({
</>
) : isImageSelect || isStamp ? (
!image ? (
<div
style={{
border: "1px solid black",
<div style={{ display: "flex", justifyContent: "center" }}>
<div
style={{
border: "1.3px solid #007bff",
borderRadius: "2px",
display: "flex",
flexDirection: "column",
justifyContent: "center",
alignItems: "center",
marginBottom: 6,
cursor: "pointer"
}}
className="signatureCanvas"
onClick={() => imageRef.current.click()}
>
<input
type="file"
onChange={onImageChange}
className="filetype"
accept="image/*"
ref={imageRef}
hidden
/>
<i className="fas fa-cloud-upload-alt uploadImgLogo"></i>
<div className="uploadImg">Upload</div>
display: "flex",
flexDirection: "column",
justifyContent: "center",
alignItems: "center",
marginBottom: 6,
cursor: "pointer"
}}
className={
isInitial ? "intialSignatureCanvas" : "signatureCanvas"
}
onClick={() => imageRef.current.click()}
>
<input
type="file"
onChange={onImageChange}
className="filetype"
accept="image/*"
ref={imageRef}
hidden
/>
<i className="fas fa-cloud-upload-alt uploadImgLogo"></i>
<div className="uploadImg">Upload</div>
</div>
</div>
) : (
<>
<div
style={{
border: "1px solid black",
marginBottom: 6,
overflow: "hidden"
}}
className="signatureCanvas"
>
<img
alt="print img"
ref={imageRef}
src={image.src}
<div style={{ display: "flex", justifyContent: "center" }}>
<div
style={{
objectFit: "contain",
height: "100%",
width: "100%"
border: "1.3px solid #007bff",
borderRadius: "2px",
marginBottom: 6,
overflow: "hidden"
}}
/>
className={
isInitial
? "intialSignatureCanvas"
: "signatureCanvas"
}
>
<img
alt="print img"
ref={imageRef}
src={image.src}
draggable="false"
style={{
objectFit: "contain",
height: "100%",
width: "100%"
}}
/>
</div>
</div>
<div
style={{ display: "flex", justifyContent: "flex-end" }}
@@ -478,11 +606,13 @@ function SignPad({
alignItems: "center"
}}
>
<span className="signatureText">Signature:</span>
<span className="signatureText">
{isInitial ? "Initials" : "Signature"}:
</span>
<input
maxLength={30}
style={{ fontFamily: fontSelect }}
maxLength={isInitial ? 3 : 30}
style={{ fontFamily: fontSelect, color: penColor }}
type="text"
className="signatureInput"
placeholder="Your signature"
@@ -513,7 +643,8 @@ function SignPad({
<div
style={{
padding: "5px 10px 5px 10px",
fontSize: "20px"
fontSize: "20px",
color: penColor
}}
>
{signValue ? signValue : "Your signature"}
@@ -523,25 +654,6 @@ function SignPad({
})}
</div>
<div style={{ display: "flex", justifyContent: "flex-end" }}>
<SaveBtn />
</div>
</div>
) : (
<>
<SignatureCanvas
ref={canvasRef}
penColor={penColor}
canvasProps={{
className: "signatureCanvas"
}}
backgroundColor="rgb(255, 255, 255)"
onEnd={() =>
handleSignatureChange(canvasRef.current.toDataURL())
}
dotSize={1}
/>
<div
style={{
display: "flex",
@@ -550,41 +662,41 @@ function SignPad({
marginTop: "10px"
}}
>
<div style={{ display: "flex", flexDirection: "row" }}>
{allColor.map((data, key) => {
return (
<img
key={key}
alt="pen img"
style={{
border: "none",
margin: "5px",
borderBottom:
key === 0 && penColor === "blue"
? "2px solid blue"
: key === 1 && penColor === "red"
? "2px solid red"
: key === 2 && penColor === "black"
? "2px solid black"
: "2px solid white"
}}
onClick={() => {
if (key === 0) {
setPenColor("blue");
} else if (key === 1) {
setPenColor("red");
} else if (key === 2) {
setPenColor("black");
}
}}
src={data}
width={20}
height={20}
/>
);
})}
</div>
<PenColorComponent convertToImg={convertToImg} />
<SaveBtn />
</div>
</div>
) : (
<>
<div style={{ display: "flex", justifyContent: "center" }}>
<SignatureCanvas
ref={canvasRef}
penColor={penColor}
canvasProps={{
className: isInitial
? "intialSignatureCanvas"
: "signatureCanvas",
style: {
border: "1.6px solid #007bff",
borderRadius: "2px"
}
}}
backgroundColor="rgb(255, 255, 255)"
onEnd={() =>
handleSignatureChange(canvasRef.current.toDataURL())
}
dotSize={1}
/>
</div>
<div
style={{
display: "flex",
flexDirection: "row",
justifyContent: "space-between",
marginTop: "10px"
}}
>
<PenColorComponent />
<SaveBtn />
</div>
</>
@@ -0,0 +1,64 @@
import React from "react";
import { themeColor } from "../../constant/const";
import "../../styles/signature.css";
function Signedby({ pdfDetails }) {
const getFirstLetter = (name) => {
const firstLetter = name.charAt(0);
return firstLetter;
};
return (
<div className="signerComponent">
<div
style={{
background: themeColor,
color: "white"
}}
className="signedStyle"
>
Signed By
</div>
<div style={{ marginTop: "2px", background: "white" }}>
<div
style={{
display: "flex",
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)}
</span>
</div>
<div style={{ display: "flex", flexDirection: "column" }}>
<span className="userName">{pdfDetails.ExtUserPtr.Name}</span>
<span className="useEmail">{pdfDetails.ExtUserPtr.Email}</span>
</div>
</div>
</div>
</div>
);
}
export default Signedby;
@@ -1,14 +1,13 @@
import React from "react";
import { themeColor } from "../../utils/ThemeColor/backColor";
import "../../css/signerListPlace.css";
import RecipientList from "../../premitives/RecipientList";
import { themeColor } from "../../constant/const";
import RecipientList from "./RecipientList";
function SignerListPlace(props) {
return (
<div>
<div
style={{
background: themeColor(),
background: themeColor,
padding: "5px"
}}
>
@@ -22,8 +21,12 @@ function SignerListPlace(props) {
{props.handleAddSigner && (
<div
data-tut="reactourAddbtn"
className="addSignerBtn"
className="p-[10px] my-[2px] flex flex-row items-center justify-center border-[1px] border-[#47a3ad] hover:bg-[#47a3ad] text-[#47a3ad] hover:text-white cursor-pointer"
onClick={() => props.handleAddSigner()}
style={{
opacity: props.isMailSend && "0.5",
pointerEvents: props.isMailSend && "none"
}}
>
<i className="fa-solid fa-plus"></i>
<span style={{ marginLeft: 2 }}>Add role</span>
@@ -0,0 +1,436 @@
import React, { useState, useRef, useEffect } from "react";
import ModalUi from "../../primitives/ModalUi";
import RecipientList from "./RecipientList";
import { useDrag } from "react-dnd";
import WidgetList from "./WidgetList";
import {
radioButtonWidget,
textInputWidget,
textWidget,
widgets
} from "../../constant/Utils";
import { themeColor } from "../../constant/const";
function WidgetComponent({
dragSignature,
signRef,
handleDivClick,
handleMouseLeave,
dragStamp,
isSignYourself,
addPositionOfSignature,
signersdata,
isSelectListId,
setSignerObjId,
setIsSelectId,
setContractName,
isSigners,
dataTut,
isMailSend,
handleAddSigner,
setUniqueId,
setRoleName,
handleDeleteUser,
signerPos,
handleRoleChange,
handleOnBlur,
title,
setSignersData,
sendInOrder,
isTemplateFlow,
setBlockColor,
blockColor
}) {
const [isSignersModal, setIsSignersModal] = useState(false);
const [, dropdown] = useDrag({
type: "BOX",
item: {
type: "BOX",
id: 5,
text: "dropdown"
},
collect: (monitor) => ({
isDragDropdown: !!monitor.isDragging()
})
});
const [, checkbox] = useDrag({
type: "BOX",
item: {
type: "BOX",
id: 6,
text: "checkbox"
},
collect: (monitor) => ({
isDragCheck: !!monitor.isDragging()
})
});
const [, textInput] = useDrag({
type: "BOX",
item: {
type: "BOX",
id: 7,
text: textInputWidget
},
collect: (monitor) => ({
isDragTextInput: !!monitor.isDragging()
})
});
const [, initials] = useDrag({
type: "BOX",
item: {
type: "BOX",
id: 8,
text: "initials"
},
collect: (monitor) => ({
isDragInitial: !!monitor.isDragging()
})
});
const [, name] = useDrag({
type: "BOX",
item: {
type: "BOX",
id: 9,
text: "name"
},
collect: (monitor) => ({
isDragName: !!monitor.isDragging()
})
});
const [, company] = useDrag({
type: "BOX",
item: {
type: "BOX",
id: 10,
text: "company"
},
collect: (monitor) => ({
isDragCompany: !!monitor.isDragging()
})
});
const [, jobTitle] = useDrag({
type: "BOX",
item: {
type: "BOX",
id: 11,
text: "job title"
},
collect: (monitor) => ({
isDragJobtitle: !!monitor.isDragging()
})
});
const [, date] = useDrag({
type: "BOX",
item: {
type: "BOX",
id: 12,
text: "date"
},
collect: (monitor) => ({
isDragDate: !!monitor.isDragging()
})
});
const [, image] = useDrag({
type: "BOX",
item: {
type: "BOX",
id: 13,
text: "image"
},
collect: (monitor) => ({
isDragImage: !!monitor.isDragging()
})
});
const [, email] = useDrag({
type: "BOX",
item: {
type: "BOX",
id: 14,
text: "email"
},
collect: (monitor) => ({
isDragEmail: !!monitor.isDragging()
})
});
const [, radioButton] = useDrag({
type: "BOX",
item: {
type: "BOX",
id: 15,
text: radioButtonWidget
},
collect: (monitor) => ({
isDragRadiotton: !!monitor.isDragging()
})
});
const [, text] = useDrag({
type: "BOX",
item: {
type: "BOX",
id: 16,
text: textWidget
},
collect: (monitor) => ({
isDragText: !!monitor.isDragging()
})
});
const isMobile = window.innerWidth < 767;
const scrollContainerRef = useRef(null);
const [widget, setWidget] = useState([]);
const color = [
"#93a3db",
"#e6c3db",
"#c0e3bc",
"#bce3db",
"#b8ccdb",
"#ceb8db",
"#ffccff",
"#99ffcc",
"#cc99ff",
"#ffcc99",
"#66ccff",
"#ffffcc"
];
const handleModal = () => {
setIsSignersModal(!isSignersModal);
};
useEffect(() => {
const widgetRef = [
dragSignature,
dragStamp,
initials,
name,
jobTitle,
company,
date,
text,
textInput,
checkbox,
dropdown,
radioButton,
image,
email
];
const getWidgetArray = widgets;
const newUpdateSigner = getWidgetArray.map((obj, ind) => {
return { ...obj, ref: widgetRef[ind] };
});
setWidget(newUpdateSigner);
// eslint-disable-next-line
}, []);
const filterWidgets = widget.filter(
(data) =>
data.type !== "dropdown" &&
data.type !== radioButtonWidget &&
data.type !== textInputWidget
);
const textWidgetData = widget.filter((data) => data.type !== textWidget);
const updateWidgets = isSignYourself
? filterWidgets
: isTemplateFlow
? textWidgetData
: widget;
return (
<>
{isMobile ? (
!isMailSend && (
<div
data-tut={dataTut}
id="navbar"
className="stickyfooter"
style={{ width: window.innerWidth + "px" }}
>
{isSigners && (
<div
data-tut={dataTut}
style={{
background: blockColor
? blockColor
: isSelectListId
? color[isSelectListId % color.length]
: color[0],
padding: "10px 20px",
display: "flex",
alignItems: "center",
justifyContent: "center"
}}
onClick={() => handleModal()}
>
<span
style={{
fontSize: "13px",
fontWeight: "700",
textAlign: "center"
}}
>
{title ? title : "Recipient"}
</span>
<span
style={{
fontSize: "13px",
fontWeight: "700",
display: "flex",
alignItems: "center"
}}
>
{signersdata[isSelectListId]?.Role && (
<div>
{signersdata[isSelectListId]?.Name ? (
<>
:{" "}
{signersdata[isSelectListId]?.Name?.length > 12
? `${signersdata[isSelectListId].Name.slice(
0,
12
)}...`
: signersdata[isSelectListId]?.Name}
</>
) : (
<>
:{" "}
{signersdata[isSelectListId]?.Role?.length > 12
? `${signersdata[isSelectListId].Role.slice(
0,
12
)}...`
: signersdata[isSelectListId]?.Role}
</>
)}
</div>
)}
<div style={{ marginLeft: 6, fontSize: 16 }}>
<i className="fa-solid fa-angle-down"></i>
</div>
</span>
</div>
)}
{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>
)}
<div
ref={scrollContainerRef}
style={{
background: "white",
borderTop: `2px solid ${themeColor}`
}}
>
<div
style={{
display: "flex",
overflowX: "scroll",
whiteSpace: "nowrap",
padding: "10px 5px 10px 1px"
}}
>
<WidgetList
updateWidgets={updateWidgets}
handleDivClick={handleDivClick}
handleMouseLeave={handleMouseLeave}
signRef={signRef}
marginLeft={5}
addPositionOfSignature={addPositionOfSignature}
isMobile={isMobile}
/>
</div>
</div>
</div>
)
) : (
<div
data-tut={dataTut}
className={
isMailSend ? "disabled signerComponent " : "signerComponent"
}
>
<div
style={{
background: themeColor,
padding: "5px"
}}
>
<span className="signedStyle">Fields</span>
</div>
<div className="signLayoutContainer1">
<WidgetList
updateWidgets={updateWidgets}
handleDivClick={handleDivClick}
handleMouseLeave={handleMouseLeave}
signRef={signRef}
/>
</div>
</div>
)}
{isSignersModal && (
<ModalUi
title={"Roles"}
isOpen={isSignersModal}
handleClose={handleModal}
>
{signersdata.length > 0 ? (
<div style={{ maxHeight: "600px", overflow: "auto" }}>
<RecipientList
signerPos={signerPos}
signersdata={signersdata}
isSelectListId={isSelectListId}
setSignerObjId={setSignerObjId}
setIsSelectId={setIsSelectId}
setContractName={setContractName}
setUniqueId={setUniqueId}
setRoleName={setRoleName}
handleDeleteUser={handleDeleteUser}
handleRoleChange={handleRoleChange}
handleOnBlur={handleOnBlur}
handleModal={handleModal}
sendInOrder={sendInOrder}
setSignersData={setSignersData}
setBlockColor={setBlockColor}
/>
</div>
) : (
<div
style={{
padding: 20,
fontSize: 15,
fontWeight: "500",
textAlign: "center"
}}
>
Please add a role
</div>
)}
</ModalUi>
)}
</>
);
}
export default WidgetComponent;
@@ -0,0 +1,36 @@
import React from "react";
import { getWidgetType } from "../../constant/Utils";
function WidgetList(props) {
return props.updateWidgets.map((item, ind) => {
return (
<div key={ind} style={{ marginBottom: "5px" }}>
<div
className="widgets"
onClick={() => {
props.addPositionOfSignature &&
props.addPositionOfSignature("onclick", item);
}}
ref={(element) => {
if (!props.isMobile) {
item.ref(element);
if (element) {
if (props?.signRef) {
props.signRef.current = element;
}
}
}
}}
onMouseMove={props?.handleDivClick}
onMouseDown={() => {
props?.handleMouseLeave();
}}
>
{item.ref && getWidgetType(item, props?.marginLeft)}
</div>
</div>
);
});
}
export default WidgetList;
@@ -0,0 +1,287 @@
import React, { useEffect, useState } from "react";
import ModalUi from "../../primitives/ModalUi";
import "../../styles/AddUser.css";
import RegexParser from "regex-parser";
import { textInputWidget } from "../../constant/Utils";
import PremiumAlertHeader from "../../primitives/PremiumAlertHeader";
const WidgetNameModal = (props) => {
const [formdata, setFormdata] = useState({
name: "",
defaultValue: "",
status: "required",
hint: "",
textvalidate: "text"
});
const [isValid, setIsValid] = useState(true);
const statusArr = ["Required", "Optional"];
const inputOpt = ["text", "email", "number"];
useEffect(() => {
if (props.defaultdata) {
setFormdata({
name: props.defaultdata?.options?.name || props?.widgetName || "",
defaultValue: props.defaultdata?.options?.defaultValue || "",
status: props.defaultdata?.options?.status || "required",
hint: props.defaultdata?.options?.hint || "",
textvalidate:
props.defaultdata?.options?.validation?.type === "regex"
? props.defaultdata?.options?.validation?.pattern
: props.defaultdata?.options?.validation?.type || ""
});
} else {
setFormdata({
...formdata,
name: props.defaultdata?.options?.name || props?.widgetName || ""
});
}
// eslint-disable-next-line
}, [props.defaultdata, props.widgetName]);
const handleSubmit = (e) => {
e.preventDefault();
if (props.handleData) {
props.handleData(formdata);
setFormdata({
name: "",
defaultValue: "",
status: "required",
hint: "",
textvalidate: "text"
});
}
};
const handleChange = (e) => {
setFormdata({ ...formdata, [e.target.name]: e.target.value });
};
const handledefaultChange = (e) => {
if (formdata.textvalidate) {
const regexObject = RegexParser(handleValidation(formdata.textvalidate));
const isValidate = regexObject?.test(e.target.value);
setIsValid(isValidate);
} else {
setIsValid(true);
}
setFormdata({ ...formdata, [e.target.name]: e.target.value });
};
function handleValidation(type) {
switch (type) {
case "email":
return "/^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+.[a-zA-Z]{2,}$/";
case "number":
return "/^\\d+$/";
case "text":
return "/^[a-zA-Zs]+$/";
default:
return type;
}
}
function handleBlurRegex() {
if (!formdata.textvalidate) {
setFormdata({ ...formdata, textvalidate: "text" });
} else {
if (formdata.defaultValue) {
const regexObject = RegexParser(
handleValidation(formdata.textvalidate)
);
const isValidate = regexObject?.test(formdata.defaultValue);
if (isValidate === false) {
setFormdata({ ...formdata, defaultValue: "" });
}
}
}
}
return (
<ModalUi
isOpen={props.isOpen}
handleClose={props.handleClose && props.handleClose}
title={"Widget info"}
>
{(props.defaultdata?.type === textInputWidget ||
props.widgetName === textInputWidget) && (
<PremiumAlertHeader
message={
"Field validations are free in beta, this feature will incur a fee later."
}
/>
)}
<form
onSubmit={handleSubmit}
className={`${
props.defaultdata?.type === textInputWidget ||
props.widgetName === textInputWidget
? "pt-0"
: ""
} p-[20px]`}
>
<div className="form-section">
<label htmlFor="name" style={{ fontSize: 13 }}>
Name
<span style={{ color: "red", fontSize: 13 }}> *</span>
</label>
<input
className="addUserInput"
name="name"
value={formdata.name}
onChange={(e) => handleChange(e)}
required
/>
</div>
{(props.defaultdata?.type === textInputWidget ||
props.widgetName === textInputWidget) && (
<>
<div className="form-section">
<label htmlFor="textvalidate" style={{ fontSize: 13 }}>
Validation
</label>
<div
style={{
display: "flex",
flexDirection: "row",
gap: 10,
marginBottom: "0.5rem"
}}
>
<div style={{ width: "100%", position: "relative" }}>
<input
className="relative z-20 w-[87%] md:w-[92%] p-2.5 border-[1px] border-[#d1d5db] rounded-l-md outline-none text-xs"
name="textvalidate"
placeholder="Enter custom expression"
value={formdata.textvalidate}
onChange={(e) => handleChange(e)}
// onBlur={() => handleBlurRegex()}
/>
<select
className="validationlist addUserInput"
name="textvalidate"
value={formdata.textvalidate}
onChange={(e) => handleChange(e)}
onBlur={() => handleBlurRegex()}
>
<option disabled style={{ fontSize: "13px" }}>
Select...
</option>
{inputOpt.map((data, ind) => {
return (
<option
style={{ fontSize: "13px" }}
key={ind}
value={data}
>
{data}
</option>
);
})}
</select>
</div>
</div>
</div>
<div className="form-section">
<label htmlFor="name" style={{ fontSize: 13 }}>
Default value
</label>
<input
className="addUserInput"
name="defaultValue"
value={formdata.defaultValue}
onChange={(e) => handledefaultChange(e)}
autoComplete="off"
onBlur={() => {
if (isValid === false) {
setFormdata({ ...formdata, defaultValue: "" });
setIsValid(true);
}
}}
/>
{isValid === false && (
<div className="warning defaultvalueWarning" style={{ fontSize: 12 }}>
<i
className="fas fa-exclamation-circle"
style={{ color: "#fab005", fontSize: 15 }}
></i>{" "}
invalid default value
</div>
)}
</div>
</>
)}
<div className="form-section">
<div
style={{
display: "flex",
flexDirection: "row",
gap: 10,
marginBottom: "0.5rem"
}}
>
{statusArr.map((data, ind) => {
return (
<div
key={ind}
style={{
display: "flex",
flexDirection: "row",
gap: 5,
alignItems: "center"
}}
>
<input
style={{ accentColor: "red", marginRight: "10px" }}
type="radio"
name="status"
onChange={() =>
setFormdata({ ...formdata, status: data.toLowerCase() })
}
checked={
formdata.status.toLowerCase() === data.toLowerCase()
}
/>
<div style={{ fontSize: "13px", fontWeight: "500" }}>
{data}
</div>
</div>
);
})}
</div>
</div>
{(props.defaultdata?.type === textInputWidget ||
props?.widgetName === textInputWidget) && (
<div className="form-section">
<label htmlFor="hint" style={{ fontSize: 13 }}>
Hint
</label>
<input
className="addUserInput"
name="hint"
value={formdata.hint}
onChange={(e) => handleChange(e)}
/>
</div>
)}
<div
style={{
height: 1,
backgroundColor: "#b7b3b3",
width: "100%",
marginBottom: "16px"
}}
></div>
<button
style={{
color: "white",
padding: "5px 20px",
backgroundColor: "#32a3ac"
}}
type="submit"
className="finishBtn"
>
Save
</button>
</form>
</ModalUi>
);
};
export default WidgetNameModal;
@@ -1,6 +1,6 @@
import React, { useEffect, useState } from "react";
import Parse from "parse";
import Alert from "../../primitives/Alert";
import Alert from "../../../primitives/Alert";
const CreateFolder = ({ parentFolderId, onSuccess, folderCls }) => {
const folderPtr = {
@@ -11,6 +11,7 @@ const CreateFolder = ({ parentFolderId, onSuccess, folderCls }) => {
const [name, setName] = useState("");
const [folderList, setFolderList] = useState([]);
const [isAlert, setIsAlert] = useState(false);
const [isLoader, setIsLoader] = useState(false);
const [selectedParent, setSelectedParent] = useState();
const [alert, setAlert] = useState({ type: "info", message: "" });
useEffect(() => {
@@ -42,6 +43,7 @@ const CreateFolder = ({ parentFolderId, onSuccess, folderCls }) => {
};
const handleCreateFolder = async (event) => {
event.preventDefault();
handleLoader(true);
if (name) {
const currentUser = Parse.User.current();
const exsitQuery = new Parse.Query(folderCls);
@@ -52,7 +54,7 @@ const CreateFolder = ({ parentFolderId, onSuccess, folderCls }) => {
}
const templExist = await exsitQuery.first();
if (templExist) {
setAlert({ type: "dange", message: "Folder already exist!" });
setAlert({ type: "danger", message: "Folder already exist!" });
setIsAlert(true);
setTimeout(() => {
setIsAlert(false);
@@ -74,6 +76,7 @@ const CreateFolder = ({ parentFolderId, onSuccess, folderCls }) => {
template.set("CreatedBy", Parse.User.createWithoutData(currentUser.id));
const res = await template.save();
if (res) {
handleLoader(false);
setAlert({
type: "success",
message: "Folder created successfully!"
@@ -88,6 +91,7 @@ const CreateFolder = ({ parentFolderId, onSuccess, folderCls }) => {
}
}
} else {
handleLoader(false);
setAlert({ type: "info", message: "Please fill folder name" });
setIsAlert(true);
setTimeout(() => {
@@ -98,10 +102,21 @@ const CreateFolder = ({ parentFolderId, onSuccess, folderCls }) => {
const handleOptions = (e) => {
setSelectedParent(e.target.value);
};
const handleLoader = (status) => {
setIsLoader(status);
};
return (
<div>
{isAlert && <Alert type={alert.type}>{alert.message}</Alert>}
<div id="createFolder">
<div id="createFolder" className="relative">
{isLoader && (
<div className="absolute h-full w-full flex justify-center items-center ">
<div
style={{ fontSize: "45px", color: "#3dd3e0" }}
className="loader-37"
></div>
</div>
)}
<h1 className="text-base font-semibold">Create Folder</h1>
<div className="text-xs mt-2">
<label className="block">
@@ -133,6 +148,7 @@ const CreateFolder = ({ parentFolderId, onSuccess, folderCls }) => {
<div>
<button
onClick={handleCreateFolder}
disabled={isLoader}
className="flex items-center rounded p-2 bg-[#32a3ac] text-white mt-3"
>
<i className="fa-solid fa-plus mr-1"></i>
@@ -1,5 +1,5 @@
import React, { useCallback, useMemo } from "react";
import { useDropScript } from "../../hook/useScript";
import { useDropScript } from "../../../hook/useScript";
const DROPBOX_APP_KEY = process.env.REACT_APP_DROPBOX_API_KEY; // App key
const DROPBOX_SDK_URL = "https://www.dropbox.com/static/api/2/dropins.js";
@@ -41,12 +41,15 @@ export default function DropboxChooser({ children, onSuccess, onCancel }) {
[onSuccess, onCancel]
);
const handleChoose = useCallback((e) => {
e.preventDefault()
if (window.Dropbox) {
window.Dropbox.choose(options);
}
}, [options]);
const handleChoose = useCallback(
(e) => {
e.preventDefault();
if (window.Dropbox) {
window.Dropbox.choose(options);
}
},
[options]
);
return (
<div onClick={handleChoose}>
@@ -0,0 +1,234 @@
import React, { useEffect, useState } from "react";
import Parse from "parse";
import CreateFolder from "./CreateFolder";
import ModalUi from "../../../primitives/ModalUi";
const FolderModal = (props) => {
const [clickFolder, setClickFolder] = useState("");
const [folderList, setFolderList] = useState([]);
const [tabList, setTabList] = useState([]);
const [isLoader, setIsLoader] = useState(false);
const [isAdd, setIsAdd] = useState(false);
// below useEffect is called when user open popup
useEffect(() => {
if (props.isOpenModal) {
fetchFolder();
}
// eslint-disable-next-line
}, [props.isOpenModal]);
// `fetchFolder` is used to fetch of folder list created by user on basis of folderPtr or without folderPtr
const fetchFolder = async (folderPtr) => {
setIsLoader(true);
try {
const FolderQuery = new Parse.Query(props.folderCls);
if (folderPtr) {
FolderQuery.equalTo("Folder", folderPtr);
FolderQuery.equalTo("Type", "Folder");
} else {
FolderQuery.doesNotExist("Folder");
FolderQuery.equalTo("Type", "Folder");
}
const res = await FolderQuery.find();
if (res) {
const result = JSON.parse(JSON.stringify(res));
if (result) {
setFolderList(result);
setIsLoader(false);
}
setIsLoader(false);
}
} catch (error) {
setIsLoader(false);
}
};
// `handleSelect` is used to save pointer of folder selected by user and it's path in state
const handleSelect = (item) => {
setFolderList([]);
setClickFolder({ ObjectId: item.objectId, Name: item.Name });
if (tabList.length > 0) {
const tab = tabList.some((x) => x.objectId === item.objectId);
if (!tab) {
setTabList((tabs) => [...tabs, item]);
const folderPtr = {
__type: "Pointer",
className: props.folderCls,
objectId: item.objectId
};
fetchFolder(folderPtr);
}
} else {
setTabList((tabs) => [...tabs, item]);
const folderPtr = {
__type: "Pointer",
className: props.folderCls,
objectId: item.objectId
};
fetchFolder(folderPtr);
}
};
// `handleSubmit` is used to pass folderPtr to parent component
const handleSubmit = () => {
let url = "OpenSign™ Drive";
tabList.forEach((t) => {
url = url + " / " + t.Name;
});
if (props.onSuccess) {
props.onSuccess(clickFolder);
}
// SetIsOpen(false);
props.setIsOpenMoveModal(false);
};
// `handleCancel` is used to clear list of folder, close popup and folderUrl
const handleCancel = () => {
// SetIsOpen(false);
props.setIsOpenMoveModal(false);
setClickFolder({});
setFolderList([]);
setTabList([]);
};
// `handleCancel` is call when user click on folder name from path/tab in popup
const removeTabListItem = async (e, i) => {
e.preventDefault();
// setEditable(false);
if (!isAdd) {
setIsLoader(true);
let folderPtr;
if (i) {
setFolderList([]);
let list = tabList.filter((itm, j) => {
if (j <= i) {
return itm;
}
});
let _len = list.length - 1;
folderPtr = {
__type: "Pointer",
className: props.folderCls,
objectId: list[_len].objectId
};
setTabList(list);
} else {
setClickFolder({});
setFolderList([]);
setTabList([]);
}
fetchFolder(folderPtr);
}
};
// `handleCreate` is used to open folder creation form in popup
const handleCreate = () => {
setIsAdd(!isAdd);
};
// `handleAddFolder` is call when user folder created successfully and it fetch folder list on the basis of folderPtr or without folderPtr
const handleAddFolder = (newFolder) => {
props.setPdfData((prev) => [...prev, newFolder?.toJSON()]);
if (clickFolder && clickFolder.ObjectId) {
fetchFolder({
__type: "Pointer",
className: props.folderCls,
objectId: clickFolder.ObjectId
});
} else {
fetchFolder();
}
handleCreate();
};
return (
<div className="text-xs mt-2 ">
<ModalUi
title={"Select Folder"}
isOpen={props.isOpenModal}
handleClose={handleCancel}
>
<div className="w-full min-w-[300px] md:min-w-[500px] max-w-[500px] px-3">
<div className="py-2 text-[#ac4848] text-[14px] font-[500]">
<span
className="cursor-pointer"
title="OpenSign™ Drive"
onClick={(e) => removeTabListItem(e)}
>
OpenSign Drive /{" "}
</span>
{tabList &&
tabList.map((tab, i) => (
<React.Fragment key={`${tab.objectId}-${i}`}>
<span
className="cursor-pointer"
title={tab.Name}
onClick={(e) => removeTabListItem(e, i)}
>
{tab.Name}
</span>
{" / "}
</React.Fragment>
))}
<hr />
</div>
<div className="mt-2 mb-3">
<div className="max-h-[210px] overflow-auto">
{!isAdd &&
folderList.length > 0 &&
folderList.map((folder) => (
<div
key={folder.Name}
className="border-[1px] border-[#8a8a8a] px-2 py-2 mb-2 cursor-pointer "
onClick={() => handleSelect(folder)}
>
<div className="flex items-center gap-2">
<i
className="fa fa-folder text-[#33bbff] text-[1.4rem]"
aria-hidden="true"
></i>
<span className="font-semibold">{folder.Name}</span>
</div>
</div>
))}
</div>
{isAdd && (
<CreateFolder
parentFolderId={clickFolder && clickFolder.ObjectId}
folderCls={props.folderCls}
onSuccess={handleAddFolder}
/>
)}
{isLoader && (
<div className="flex justify-center">
<i className="fa-solid fa-spinner fa-spin-pulse text-[30px]"></i>
</div>
)}
</div>
</div>
<hr />
<div className="flex justify-between items-center py-[.75rem] px-[1.25rem]">
<div
className="text-[30px] cursor-pointer text-[#32a3ac]"
title="Save Here"
onClick={handleCreate}
>
{isAdd ? (
<i className="fa-solid fa-arrow-left" aria-hidden="true"></i>
) : (
<i className="fa-solid fa-square-plus" aria-hidden="true"></i>
)}
</div>
<div
className="text-[30px] cursor-pointer"
title="Save Here"
onClick={handleSubmit}
>
<i className="fas fa-save" aria-hidden="true"></i>
</div>
</div>
</ModalUi>
</div>
);
};
export default FolderModal;
@@ -1,9 +1,10 @@
import React, { useEffect, useState } from "react";
import Parse from "parse";
import CreateFolder from "./CreateFolder";
import ModalUi from "../../primitives/ModalUi";
import ModalUi from "../../../primitives/ModalUi";
import Tooltip from "../../../primitives/Tooltip";
const SelectFolder = ({ required, onSuccess, folderCls }) => {
const SelectFolder = ({ required, onSuccess, folderCls, isReset }) => {
const [isOpen, SetIsOpen] = useState(false);
const [clickFolder, setClickFolder] = useState("");
const [selectFolder, setSelectedFolder] = useState({});
@@ -22,6 +23,21 @@ const SelectFolder = ({ required, onSuccess, folderCls }) => {
}
// eslint-disable-next-line
}, [isOpen]);
// below useEffect is used to reset folder selection if user pass isReset = true from parent component
useEffect(() => {
if (isReset == true) {
handleReset();
}
}, [isReset]);
const handleReset = () => {
setFolderPath({});
setSelectedFolder("");
setClickFolder("");
setIsAdd(false);
setFolderList([]);
setTabList([]);
};
// `fetchFolder` is used to fetch of folder list created by user on basis of folderPtr or without folderPtr
const fetchFolder = async (folderPtr) => {
setIsLoader(true);
try {
@@ -47,6 +63,8 @@ const SelectFolder = ({ required, onSuccess, folderCls }) => {
setIsLoader(false);
}
};
// `handleSelect` is used to save pointer of folder selected by user and it's path in state
const handleSelect = (item) => {
setFolderList([]);
setClickFolder({ ObjectId: item.objectId, Name: item.Name });
@@ -73,8 +91,9 @@ const SelectFolder = ({ required, onSuccess, folderCls }) => {
}
};
// `handleSubmit` is used to pass folderPtr to parent component
const handleSubmit = () => {
let url = "Root";
let url = "OpenSign™ Drive";
tabList.forEach((t) => {
url = url + " / " + t.Name;
});
@@ -85,6 +104,8 @@ const SelectFolder = ({ required, onSuccess, folderCls }) => {
}
SetIsOpen(false);
};
// `handleCancel` is used to clear list of folder, close popup and folderUrl
const handleCancel = () => {
SetIsOpen(false);
setClickFolder({});
@@ -92,6 +113,7 @@ const SelectFolder = ({ required, onSuccess, folderCls }) => {
setTabList([]);
};
// `handleCancel` is call when user click on folder name from path/tab in popup
const removeTabListItem = async (e, i) => {
e.preventDefault();
// setEditable(false);
@@ -121,9 +143,11 @@ const SelectFolder = ({ required, onSuccess, folderCls }) => {
fetchFolder(folderPtr);
}
};
// `handleCreate` is used to open folder creation form in popup
const handleCreate = () => {
setIsAdd(!isAdd);
};
// `handleAddFolder` is call when user folder created successfully and it fetch folder list on the basis of folderPtr or without folderPtr
const handleAddFolder = () => {
setFolderList([]);
if (clickFolder && clickFolder.ObjectId) {
@@ -145,7 +169,7 @@ const SelectFolder = ({ required, onSuccess, folderCls }) => {
{required && <span className="text-red-500 text-[13px]">*</span>}
</label>
</div>
<div className="rounded px-[20px] py-[20px] bg-white border border-gray-200 shadow flex max-w-sm gap-8 items-center">
<div className="relative rounded px-[20px] py-[20px] bg-white border border-gray-200 shadow flex max-w-sm gap-8 items-center">
<div>
<i
className="far fa-folder-open text-[40px] text-[#33bbff]"
@@ -156,7 +180,9 @@ const SelectFolder = ({ required, onSuccess, folderCls }) => {
<div className="font-semibold ">
<div className="flex items-center gap-2">
<p>
{selectFolder && selectFolder.Name ? selectFolder.Name : "Root"}
{selectFolder && selectFolder.Name
? selectFolder.Name
: "OpenSign™ Drive"}
</p>
<div className="text-black text-sm" onClick={() => SetIsOpen(true)}>
<i
@@ -170,20 +196,27 @@ const SelectFolder = ({ required, onSuccess, folderCls }) => {
{selectFolder && selectFolder.Name ? `(${folderPath})` : ""}
</p>
</div>
<div className="absolute top-2 right-1 cursor-pointer">
<Tooltip
message={
"If you do not select a folder, your signed document will be saved in the Main OpenSign drive folder."
}
/>
</div>
</div>
<ModalUi
title={"Select Folder"}
isOpen={isOpen}
handleClose={handleCancel}
>
<div className="w-full min-w-[300px] md:min-w-[500px] px-3">
<div className="w-full min-w-[300px] md:min-w-[500px] max-w-[500px] px-3">
<div className="py-2 text-[#ac4848] text-[14px] font-[500]">
<span
className="cursor-pointer"
title="Root"
title="OpenSign™ Drive"
onClick={(e) => removeTabListItem(e)}
>
Root /{" "}
OpenSign Drive /{" "}
</span>
{tabList &&
tabList.map((tab, i) => (
@@ -201,23 +234,25 @@ const SelectFolder = ({ required, onSuccess, folderCls }) => {
<hr />
</div>
<div className="mt-2 mb-3">
{!isAdd &&
folderList.length > 0 &&
folderList.map((folder) => (
<div
key={folder.Name}
className="border-[1px] border-[#8a8a8a] px-2 py-2 mb-2 cursor-pointer"
onClick={() => handleSelect(folder)}
>
<div className="flex items-center gap-2">
<i
className="fa fa-folder text-[#33bbff] text-[1.4rem]"
aria-hidden="true"
></i>
<span className="font-semibold">{folder.Name}</span>
<div className="max-h-[210px] overflow-auto">
{!isAdd &&
folderList.length > 0 &&
folderList.map((folder) => (
<div
key={folder.Name}
className="border-[1px] border-[#8a8a8a] px-2 py-2 mb-2 cursor-pointer "
onClick={() => handleSelect(folder)}
>
<div className="flex items-center gap-2">
<i
className="fa fa-folder text-[#33bbff] text-[1.4rem]"
aria-hidden="true"
></i>
<span className="font-semibold">{folder.Name}</span>
</div>
</div>
</div>
))}
))}
</div>
{isAdd && (
<CreateFolder
parentFolderId={clickFolder && clickFolder.ObjectId}
@@ -1,6 +1,6 @@
import React, { useState } from "react";
import Parse from "parse";
import "../css/AddUser.css";
import "../../../styles/AddUser.css";
import AsyncSelect from "react-select/async";
const customStyles = {
@@ -17,12 +17,7 @@ const SelectSigners = (props) => {
const [userList, setUserList] = useState([]);
const [selected, setSelected] = useState();
const [userData, setUserData] = useState({});
const [isError, setIsError]= useState(false)
const parseBaseUrl = localStorage.getItem("baseUrl");
const parseAppId = localStorage.getItem("parseAppId");
Parse.serverURL = parseBaseUrl;
Parse.initialize(parseAppId);
const [isError, setIsError] = useState(false);
// `handleOptions` is used to set just save from quick form to selected option in dropdown
const handleOptions = (item) => {
setSelected(item);
@@ -32,14 +27,14 @@ const SelectSigners = (props) => {
}
};
const handleAdd = () => {
if(userData && userData.objectId){
if (userData && userData.objectId) {
props.details(userData);
if (props.closePopup) {
props.closePopup();
}
}else{
setIsError(true)
setTimeout(()=> setIsError(false), 1000)
} else {
setIsError(true);
setTimeout(() => setIsError(false), 1000);
}
};
@@ -73,8 +68,8 @@ const SelectSigners = (props) => {
return (
<div className="addusercontainer">
<div className="form-wrapper">
<div className="form-section" style={{marginBottom: 0}}>
<label style={{ fontSize: 14 , fontWeight: "700"}}>Choose User</label>
<div className="form-section" style={{ marginBottom: 0 }}>
<label style={{ fontSize: 14, fontWeight: "700" }}>Choose User</label>
<AsyncSelect
cacheOptions
defaultOptions
@@ -86,7 +81,15 @@ const SelectSigners = (props) => {
styles={customStyles}
/>
</div>
{isError ? <p style={{color:'red', fontSize: "12px", margin:"5px"}}>Please select signer</p>: <p style={{color:'transparent', fontSize: "12px", margin:"5px"}}>.</p>}
{isError ? (
<p style={{ color: "red", fontSize: "12px", margin: "5px" }}>
Please select signer
</p>
) : (
<p style={{ color: "transparent", fontSize: "12px", margin: "5px" }}>
.
</p>
)}
<div>
<button className="submitbutton" onClick={() => handleAdd()}>
Submit
@@ -1,8 +1,9 @@
import React, { useState, useEffect } from "react";
import Select from "react-select";
import AppendFormInForm from "../AppendFormInForm";
import AddSigner from "../../AddSigner";
import Modal from "react-modal";
import Parse from "parse";
import Tooltip from "../../../primitives/Tooltip";
function arrayMove(array, from, to) {
array = array.slice();
array.splice(to < 0 ? array.length + to : to, 0, array.splice(from, 1)[0]);
@@ -19,7 +20,7 @@ const SignersInput = (props) => {
Modal.setAppElement("body");
const [state, setState] = useState(undefined);
// const [editFormData, setEditFormData] = useState([]);
const [selected, setSelected] = React.useState([]);
const [selected, setSelected] = useState([]);
const [isModal, setIsModel] = useState(false);
const onChange = (selectedOptions) => setSelected(selectedOptions);
const [modalIsOpen, setModalIsOpen] = useState(false);
@@ -63,6 +64,11 @@ const SignersInput = (props) => {
useEffect(() => {
GetSelectListData();
}, []);
useEffect(() => {
if (props.isReset && props.isReset === true) {
setSelected([]);
}
}, [props.isReset]);
useEffect(() => {
if (selected && selected.length) {
@@ -99,9 +105,15 @@ const SignersInput = (props) => {
return (
<div className="text-xs mt-2 ">
<label className="block">
<label className="block relative">
Signers
{props.required && <span className="text-red-500 text-[13px]">*</span>}
<span className="absolute ml-1 text-xs z-50">
<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."}
/>
</span>
</label>
<div style={{ display: "flex", gap: 5 }}>
<div style={{ flexWrap: "wrap", width: "100%" }}>
@@ -172,7 +184,7 @@ const SignersInput = (props) => {
</div>
{isModal && (
<AppendFormInForm
<AddSigner
valueKey={"objectId"}
displayKey={"Name"}
details={handleNewDetails}
+20 -16
View File
@@ -2,20 +2,24 @@ import React from "react";
import { NavLink } from "react-router-dom";
const Menu = ({ item, isOpen, closeSidebar }) => {
return (
<li key={item.title} role="none">
<NavLink
to={`/${item.pageType}/${item.objectId}`}
className="mx-auto flex items-center hover:bg-[#eef1f5] p-3 lg:p-4"
onClick={closeSidebar}
tabIndex={isOpen ? 0 : -1}
role="menuitem"
>
<i className={`${item.icon} text-[18px]`} aria-hidden="true"></i>
<span className="ml-3 lg:ml-4">{item.title}</span>
</NavLink>
</li>
)
}
return (
<li key={item.title} role="none">
<NavLink
to={
item.pageType
? `/${item.pageType}/${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]"
onClick={closeSidebar}
tabIndex={isOpen ? 0 : -1}
role="menuitem"
>
<i className={`${item.icon} text-[18px]`} aria-hidden="true"></i>
<span className="ml-3 lg:ml-4">{item.title}</span>
</NavLink>
</li>
);
};
export default Menu;
export default Menu;
+25 -15
View File
@@ -1,8 +1,8 @@
import React, { useState, useEffect } from "react";
import Menu from './Menu';
import Menu from "./Menu";
import Submenu from "./SubMenu";
import SocialMedia from './SocialMedia';
import SocialMedia from "./SocialMedia";
import Parse from "parse";
import dp from "../../assets/images/dp.png";
@@ -20,16 +20,10 @@ const Sidebar = ({ isOpen, closeSidebar }) => {
}, []);
const menuItem = async () => {
const parseBaseUrl = localStorage.getItem("baseUrl");
const parseAppId = localStorage.getItem("parseAppId");
try {
Parse.serverURL = parseBaseUrl;
Parse.initialize(parseAppId);
var sideMenu = Parse.Object.extend("w_menu");
var query = new Parse.Query(sideMenu);
query.equalTo("objectId", localStorage.getItem("defaultmenuid"));
const results = await query.first();
const resultjson = results.toJSON();
let result = resultjson;
@@ -37,7 +31,6 @@ const Sidebar = ({ isOpen, closeSidebar }) => {
} catch (e) {
console.error("Problem", e);
}
};
return (
@@ -47,7 +40,11 @@ const Sidebar = ({ isOpen, closeSidebar }) => {
>
<div className="flex px-2 py-3 gap-2 items-center shadow-md">
<div className="w-[75px] h-[75px] rounded-full ring-[2px] ring-offset-2 ring-gray-400 overflow-hidden">
<img className="w-full h-full object-cover" src={image} alt="Profile" />
<img
className="w-full h-full object-cover"
src={image}
alt="Profile"
/>
</div>
<div>
<p className="text-[14px] font-bold">{username}</p>
@@ -57,14 +54,27 @@ const Sidebar = ({ isOpen, closeSidebar }) => {
</div>
</div>
<nav aria-label="OpenSign Sidebar Navigation">
<ul className="text-sm" role="menubar" aria-label="OpenSign Sidebar Navigation">
{menuList.map((item) => (
<ul
className="text-sm"
role="menubar"
aria-label="OpenSign Sidebar Navigation"
>
{menuList.map((item) =>
!item.children ? (
<Menu key={item.title} item={item} isOpen={isOpen} closeSidebar={closeSidebar} />
<Menu
key={item.title}
item={item}
isOpen={isOpen}
closeSidebar={closeSidebar}
/>
) : (
<Submenu key={item.title} item={item} closeSidebar={closeSidebar} />
<Submenu
key={item.title}
item={item}
closeSidebar={closeSidebar}
/>
)
))}
)}
</ul>
</nav>
<footer className="mt-4 flex justify-center items-center text-[25px] text-black gap-3">
@@ -13,7 +13,7 @@ const Submenu = ({ item, closeSidebar }) => {
<li role="none">
<button
onClick={toggleSubmenu}
className="w-full flex items-center text-left text-[#444] p-3 lg:p-4 hover:bg-[#eef1f5] focus:ring-2 focus:ring-blue-600"
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]"
aria-expanded={submenuOpen}
aria-haspopup="true"
aria-controls={`submenu-${title}`}
@@ -22,8 +22,9 @@ const Submenu = ({ item, closeSidebar }) => {
<div className="flex justify-between items-center w-full">
<span className="ml-3 lg:ml-4">{title}</span>
<i
className={`${submenuOpen ? "fa-solid fa-angle-down" : "fa-solid fa-angle-right"
}`}
className={`${
submenuOpen ? "fa-solid fa-angle-down" : "fa-solid fa-angle-right"
}`}
aria-hidden="true"
></i>
</div>
@@ -33,13 +34,20 @@ const Submenu = ({ item, closeSidebar }) => {
{children.map((childItem) => (
<li key={childItem.title} role="none">
<NavLink
to={`/${childItem.pageType}/${childItem.objectId}`}
className="block pl-6 md:pl-8 py-2 text-sm text-gray-700 hover:bg-blue-500 hover:text-white"
to={
childItem.pageType
? `/${childItem.pageType}/${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"
onClick={closeSidebar}
role="menuitem"
tabIndex={submenuOpen ? 0 : -1}
>
<i className={`${childItem.icon} text-[18px]`} aria-hidden="true"></i>
<i
className={`${childItem.icon} text-[18px]`}
aria-hidden="true"
></i>
<span className="ml-3 lg:ml-4">{childItem.title}</span>
</NavLink>
</li>
File diff suppressed because it is too large Load Diff
+4 -1
View File
@@ -3,7 +3,10 @@ export const appInfo = {
appTitle: "contracts",
applogo: logo,
appname: "contracts",
baseurl: process.env.REACT_APP_SERVERURL,
appId: process.env.REACT_APP_APPID ? process.env.REACT_APP_APPID : "opensign",
baseUrl: process.env.REACT_APP_SERVERURL
? process.env.REACT_APP_SERVERURL
: window.location.origin + "/api/app",
defaultRole: "contracts_User",
fbAppId: process.env.REACT_APP_FBAPPID
? `${process.env.REACT_APP_FBAPPID}`
+2
View File
@@ -7,3 +7,5 @@ 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 iconColor = "#686968";
+2 -5
View File
@@ -1,9 +1,6 @@
import axios from "axios";
import Parse from "parse";
const parseAppId = localStorage.getItem("AppID12");
const serverUrl = localStorage.getItem("BaseUrl12");
Parse.serverURL = serverUrl;
Parse.initialize(parseAppId);
const parseAppId = localStorage.getItem("parseAppId");
const serverUrl = localStorage.getItem("baseUrl");
export const SaveFileSize = async (size, imageUrl) => {
//checking server url and save file's size
+71 -1
View File
@@ -1 +1,71 @@
import("./Bootstrap");
import React from "react";
import ReactDOM from "react-dom/client";
import "./index.css";
import App from "./App";
import { Provider } from "react-redux";
import { store } from "./redux/store";
import { HTML5Backend } from "react-dnd-html5-backend";
import { TouchBackend } from "react-dnd-touch-backend";
import {
DndProvider,
TouchTransition,
MouseTransition,
Preview
} from "react-dnd-multi-backend";
import DragElement from "./components/pdf/DragElement";
import TagManager from "react-gtm-module";
import Parse from "parse";
const appId = process.env.REACT_APP_APPID
? process.env.REACT_APP_APPID
: "opensign";
const serverUrl = process.env.REACT_APP_SERVERURL
? process.env.REACT_APP_SERVERURL
: window.location.origin + "/api/app";
Parse.initialize(appId);
Parse.serverURL = serverUrl;
const HTML5toTouch = {
backends: [
{
id: "html5",
backend: HTML5Backend,
transition: MouseTransition
},
{
id: "touch",
backend: TouchBackend,
options: { enableMouseEvents: true },
preview: true,
transition: TouchTransition
}
]
};
const generatePreview = (props) => {
const { item, style } = props;
const newStyle = {
...style
};
return (
<div style={newStyle}>
<DragElement {...item} />
</div>
);
};
if (process.env.REACT_APP_GTM) {
const tagManagerArgs = {
gtmId: process.env.REACT_APP_GTM
};
TagManager.initialize(tagManagerArgs);
}
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
<Provider store={store}>
<DndProvider options={HTML5toTouch}>
<Preview>{generatePreview}</Preview>
<App />
</DndProvider>
</Provider>
);
+30 -30
View File
@@ -16,10 +16,10 @@ export default function reportJson(id) {
btnColor: "#4bd396",
textColor: "white",
btnIcon: "fa fa-plus",
redirectUrl:
"remoteUrl=aHR0cHM6Ly9xaWstYWktb3JnLmdpdGh1Yi5pby9TaWduLU1pY3JvYXBwVjIvcmVtb3RlRW50cnkuanM=&moduleToLoad=AppRoutes&remoteName=signmicroapp/draftDocument"
redirectUrl: "draftDocument"
}
]
],
helpMsg: "This are documents you have started but have not finalized for sending."
};
// Need your sign report
case "4Hhwbp482K":
@@ -32,10 +32,11 @@ export default function reportJson(id) {
btnColor: "#3ac9d6",
textColor: "white",
btnIcon: "fa fa-eye",
redirectUrl:
"remoteUrl=aHR0cHM6Ly9xaWstYWktb3JnLmdpdGh1Yi5pby9TaWduLU1pY3JvYXBwVjIvcmVtb3RlRW50cnkuanM=&moduleToLoad=AppRoutes&remoteName=signmicroapp/pdfRequestFiles"
redirectUrl: "pdfRequestFiles"
}
]
],
helpMsg:
"This is a list of documents that are waiting for your signature"
};
// In progess report
case "1MwEuxLEkF":
@@ -48,10 +49,11 @@ export default function reportJson(id) {
btnColor: "#3ac9d6",
textColor: "white",
btnIcon: "fa fa-eye",
redirectUrl:
"remoteUrl=aHR0cHM6Ly9xaWstYWktb3JnLmdpdGh1Yi5pby9TaWduLU1pY3JvYXBwVjIvcmVtb3RlRW50cnkuanM=&moduleToLoad=AppRoutes&remoteName=signmicroapp/pdfRequestFiles"
redirectUrl: "pdfRequestFiles"
}
]
],
helpMsg:
"This is a list of documents you've sent to other parties for signature."
};
// completed documents report
case "kQUoW4hUXz":
@@ -64,10 +66,10 @@ export default function reportJson(id) {
btnColor: "#4bd396",
textColor: "white",
btnIcon: "fa fa-eye",
redirectUrl:
"remoteUrl=aHR0cHM6Ly9xaWstYWktb3JnLmdpdGh1Yi5pby9TaWduLU1pY3JvYXBwVjIvcmVtb3RlRW50cnkuanM=&moduleToLoad=AppRoutes&remoteName=signmicroapp/draftDocument"
redirectUrl: "draftDocument"
}
]
],
helpMsg: "This is a list of documents that have been signed by all parties."
};
// declined documents report
case "UPr2Fm5WY3":
@@ -80,10 +82,10 @@ export default function reportJson(id) {
btnColor: "#4bd396",
textColor: "white",
btnIcon: "fa fa-eye",
redirectUrl:
"remoteUrl=aHR0cHM6Ly9xaWstYWktb3JnLmdpdGh1Yi5pby9TaWduLU1pY3JvYXBwVjIvcmVtb3RlRW50cnkuanM=&moduleToLoad=AppRoutes&remoteName=signmicroapp/draftDocument"
redirectUrl: "draftDocument"
}
]
],
helpMsg: "This is a list of documents that have been declined by one of the signers."
};
// Expired Documents report
case "zNqBHXHsYH":
@@ -96,10 +98,10 @@ export default function reportJson(id) {
btnColor: "#4bd396",
textColor: "white",
btnIcon: "fa fa-eye",
redirectUrl:
"remoteUrl=aHR0cHM6Ly9xaWstYWktb3JnLmdpdGh1Yi5pby9TaWduLU1pY3JvYXBwVjIvcmVtb3RlRW50cnkuanM=&moduleToLoad=AppRoutes&remoteName=signmicroapp/draftDocument"
redirectUrl: "draftDocument"
}
]
],
helpMsg: "This is a list of documents that have reached their expiration date."
};
// Recently sent for signatures report show on dashboard
case "d9k3UfYHBc":
@@ -112,8 +114,7 @@ export default function reportJson(id) {
btnColor: "#4bd396",
textColor: "white",
btnIcon: "fa fa-eye",
redirectUrl:
"remoteUrl=aHR0cHM6Ly9xaWstYWktb3JnLmdpdGh1Yi5pby9TaWduLU1pY3JvYXBwVjIvcmVtb3RlRW50cnkuanM=&moduleToLoad=AppRoutes&remoteName=signmicroapp/pdfRequestFiles"
redirectUrl: "pdfRequestFiles"
}
]
};
@@ -128,8 +129,7 @@ export default function reportJson(id) {
btnColor: "#4bd396",
textColor: "white",
btnIcon: "fa fa-eye",
redirectUrl:
"remoteUrl=aHR0cHM6Ly9xaWstYWktb3JnLmdpdGh1Yi5pby9TaWduLU1pY3JvYXBwVjIvcmVtb3RlRW50cnkuanM=&moduleToLoad=AppRoutes&remoteName=signmicroapp/pdfRequestFiles"
redirectUrl: "pdfRequestFiles"
}
]
};
@@ -144,8 +144,7 @@ export default function reportJson(id) {
btnColor: "#4bd396",
textColor: "white",
btnIcon: "fa fa-plus",
redirectUrl:
"remoteUrl=aHR0cHM6Ly9xaWstYWktb3JnLmdpdGh1Yi5pby9TaWduLU1pY3JvYXBwVjIvcmVtb3RlRW50cnkuanM=&moduleToLoad=AppRoutes&remoteName=signmicroapp/draftDocument"
redirectUrl: "draftDocument"
}
]
};
@@ -162,7 +161,8 @@ export default function reportJson(id) {
btnIcon: "fa-solid fa-trash"
}
],
form: "ContactBook"
form: "ContactBook",
helpMsg: "This is a list of contacts/signers added by you. These will appear as suggestions when you try to add signers to a new document."
};
// template report
case "6TeaPr321t":
@@ -175,18 +175,18 @@ export default function reportJson(id) {
btnColor: "#4bd396",
textColor: "white",
btnIcon: "fa fa-plus",
redirectUrl:
"remoteUrl=aHR0cHM6Ly9xaWstYWktb3JnLmdpdGh1Yi5pby9TaWduLU1pY3JvYXBwVjIvcmVtb3RlRW50cnkuanM=&moduleToLoad=AppRoutes&remoteName=signmicroapp/placeHolderSign"
redirectUrl: "placeHolderSign"
},
{
btnLabel: "Edit",
btnColor: "#00c9d5",
textColor: "white",
btnIcon: "fa fa-plus",
redirectUrl:
"remoteUrl=aHR0cHM6Ly9xaWstYWktb3JnLmdpdGh1Yi5pby9TaWduLU1pY3JvYXBwVjIvcmVtb3RlRW50cnkuanM=&moduleToLoad=AppRoutes&remoteName=signmicroapp/template"
redirectUrl: "template"
}
]
],
helpMsg:
"This is a list of templates that are available to you for creating documents. You can click the 'use' button to create a new document using a template, modify the document & add signers in the next step."
};
default:
return null;
+12 -3
View File
@@ -94,10 +94,16 @@ const HomeLayout = () => {
position: "top"
// style: { backgroundColor: "#abd4d2" },
},
{
selector: '[data-tut="tourbutton"]',
content: `To upload documents for self-signing or to request others signatures, simply select the respective buttons.`,
position: "top"
// style: { backgroundColor: "#abd4d2" },
},
...resArr,
{
selector: '[data-tut="reactourLast"]',
content: `You are good to go`,
content: `You are ready to start using OpenSign! If you need support feel free to contact us.`,
position: "top"
// style: { backgroundColor: "#abd4d2" },
}
@@ -110,7 +116,7 @@ const HomeLayout = () => {
// console.log("closeTour");
setIsTour(false);
const serverUrl = localStorage.getItem("baseUrl");
const appId = localStorage.getItem("AppID12");
const appId = localStorage.getItem("parseAppId");
const extUserClass = localStorage.getItem("extended_class");
const json = JSON.parse(localStorage.getItem("Extand_Class"));
const extUserId = json && json.length > 0 && json[0].objectId;
@@ -218,7 +224,10 @@ const HomeLayout = () => {
<div className="flex md:flex-row flex-col z-50">
<Sidebar isOpen={isOpen} closeSidebar={closeSidebar} />
<div className="relative h-screen flex flex-col justify-between w-full overflow-y-auto">
<div
id="renderList"
className="relative h-screen flex flex-col justify-between w-full overflow-y-auto"
>
<div className="bg-[#eef1f5] p-3">{<Outlet />}</div>
<div className="z-30">
<Footer />
@@ -1,58 +0,0 @@
import React from "react";
import stamp from "./stamp2.png";
import sign from "./sign3.png";
import { themeColor } from "./IconColor.js";
function DragElement({ id }) {
const selectedId = id;
return (
<div>
{selectedId === 3 ? (
<div
style={{
display: "flex",
flexDirection: "column",
alignItems: "center",
userSelect: "none"
}}
>
<img
alt="sign img"
style={{
width: "25px",
height: "23px",
background: themeColor()
}}
src={sign}
/>
<span style={{ color: themeColor(), fontSize: "12px" }}>
Signature
</span>
</div>
) : (
<div
style={{
display: "flex",
flexDirection: "column",
alignItems: "center",
userSelect: "none"
}}
>
<img
alt="stamp img"
style={{
width: "25px",
height: "23px",
background: themeColor()
}}
src={stamp}
/>
<span style={{ color: themeColor(), fontSize: "12px" }}>Stamp</span>
</div>
)}
</div>
);
}
export default DragElement;
@@ -1,3 +0,0 @@
export const themeColor = () => {
return "#47a3ad";
};
Binary file not shown.

Before

Width:  |  Height:  |  Size: 804 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 561 B

@@ -11,8 +11,6 @@ function ChangePassword() {
evt.preventDefault();
try {
if (newpassword === confirmpassword) {
Parse.serverURL = localStorage.getItem("baseUrl");
Parse.initialize(localStorage.getItem("parseAppId"));
Parse.User.logIn(localStorage.getItem("userEmail"), currentpassword)
.then(async (user) => {
if (user) {
@@ -4,16 +4,15 @@ import "../styles/loader.css";
import GetDashboard from "../components/dashboard/GetDashboard";
import { useNavigate, useParams } from "react-router-dom";
import Title from "../components/Title";
import { save_tourSteps } from "../redux/actions";
import { connect } from "react-redux";
const Dashboard = (props) => {
import { useDispatch } from "react-redux";
import { saveTourSteps } from "../redux/reducers/TourStepsReducer";
const Dashboard = () => {
const navigate = useNavigate();
const dispatch = useDispatch();
const { id } = useParams();
const [dashboard, setdashboard] = useState([]);
const [classnameArray, setclassnameArray] = useState([]);
const [loading, setloading] = useState(false);
const [parseBaseUrl] = useState(localStorage.getItem("baseUrl"));
const [parseAppId] = useState(localStorage.getItem("parseAppId"));
const [defaultQuery, setDefaultQuery] = useState("");
useEffect(() => {
@@ -32,8 +31,6 @@ const Dashboard = (props) => {
const getDashboard = async (id) => {
setloading(true);
try {
Parse.serverURL = parseBaseUrl;
Parse.initialize(parseAppId);
var forms = Parse.Object.extend("w_dashboard");
var query = new Parse.Query(forms);
query.equalTo("objectId", id);
@@ -92,7 +89,7 @@ const Dashboard = (props) => {
// style: { backgroundColor: "#abd4d2" },
};
});
props.save_tourSteps(arr);
dispatch(saveTourSteps(arr));
// console.log("arr ", arr);
setclassnameArray(classArray);
if (localStorage.getItem("DashboardDefaultFilter")) {
@@ -137,6 +134,4 @@ const Dashboard = (props) => {
);
};
export default connect(null, {
save_tourSteps
})(Dashboard);
export default Dashboard;
@@ -1,13 +1,13 @@
import React, { useEffect, useState } from "react";
import RenderAllPdfPage from "./component/renderAllPdfPage";
import "../css/./signature.css";
import "../css/AddUser.css";
import Title from "./component/Title";
import ModalUi from "../premitives/ModalUi";
import RenderDebugPdf from "./component/RenderDebugPdf";
import RenderAllPdfPage from "../components/pdf/RenderAllPdfPage";
import "../styles/signature.css";
import "../styles/AddUser.css";
import Title from "../components/Title";
import RenderDebugPdf from "../components/RenderDebugPdf";
import { pdfjs } from "react-pdf";
import Alert from "../premitives/Alert";
import HandleError from "./component/HandleError";
import ModalUi from "../primitives/ModalUi";
import Alert from "../primitives/Alert";
import HandleError from "../primitives/HandleError";
import { useWindowSize } from "../hook/useWindowSize";
function processDimensions(x, y, width, height) {
@@ -28,7 +28,7 @@ function processDimensions(x, y, width, height) {
height: Math.floor(height)
};
}
const DebugUi = () => {
const DebugPdf = () => {
const { width } = useWindowSize();
const [pdf, setPdf] = useState("");
const [isModal, setIsModal] = useState(true);
@@ -426,4 +426,4 @@ const DebugUi = () => {
);
};
export default DebugUi;
export default DebugPdf;
@@ -1,12 +1,15 @@
import React, { useEffect, useState } from "react";
import { connect } from "react-redux";
import { fetchAppInfo, forgetPassword } from "../redux/actions";
import Title from "../components/Title";
import { NavLink } from "react-router-dom";
import login_img from "../assets/images/login_img.svg";
import Parse from "parse";
import Alert from "../primitives/Alert";
function ForgotPassword(props) {
import { appInfo } from "../constant/appinfo";
import { useDispatch } from "react-redux";
import { fetchAppInfo } from "../redux/reducers/infoReducer";
function ForgotPassword() {
const dispatch = useDispatch();
const [state, setState] = useState({
email: "",
password: "",
@@ -27,21 +30,14 @@ function ForgotPassword(props) {
const handleSubmit = async (event) => {
event.preventDefault();
localStorage.setItem("appLogo", props.appInfo.applogo);
localStorage.setItem("appName", props.appInfo.appname);
localStorage.setItem("defaultmenuid", props.appInfo.defaultmenuid);
localStorage.setItem("PageLanding", props.appInfo.LandingPageId);
localStorage.setItem(
"userSettings",
JSON.stringify(props.appInfo.settings)
);
localStorage.setItem("appLogo", appInfo.applogo);
localStorage.setItem("appName", appInfo.appname);
// localStorage.setItem("defaultmenuid", props.appInfo.defaultmenuid);
// localStorage.setItem("PageLanding", props.appInfo.LandingPageId);
localStorage.setItem("userSettings", JSON.stringify(appInfo.settings));
if (state.email) {
const username = state.email;
let baseUrl = localStorage.getItem("BaseUrl12");
let parseAppId = localStorage.getItem("AppID12");
try {
Parse.serverURL = baseUrl;
Parse.initialize(parseAppId);
await Parse.User.requestPasswordReset(username);
setSentStatus("success");
} catch (err) {
@@ -54,14 +50,14 @@ function ForgotPassword(props) {
};
useEffect(() => {
props.fetchAppInfo(localStorage.getItem("domain"));
dispatch(fetchAppInfo());
resize();
window.addEventListener("resize", resize);
return () => window.removeEventListener("resize", resize);
// eslint-disable-next-line
}, []);
let image = props.appInfo.applogo;
let image = appInfo.applogo;
return (
<div className="bg-white">
<Title title="Forgot password page" />
@@ -133,10 +129,4 @@ function ForgotPassword(props) {
);
}
const mapStateToProps = (state) => {
return { appInfo: state.appInfo, forgotPassword: state.forgotPassword };
};
export default connect(mapStateToProps, { fetchAppInfo, forgetPassword })(
ForgotPassword
);
export default ForgotPassword;
@@ -1,16 +1,17 @@
import React, { useState } from "react";
import React, { useEffect, useState } from "react";
import { useNavigate, useParams } from "react-router-dom";
import { formJson } from "../json/FormJson";
import AddUser from "../components/AddUser";
import sanitizeFileName from "../primitives/sanitizeFileName";
import Parse from "parse";
import DropboxChooser from "../components/fields/DropboxChoose";
import DropboxChooser from "../components/shared/fields/DropboxChoose";
import Alert from "../primitives/Alert";
import SelectFolder from "../components/fields/SelectFolder";
import SignersInput from "../components/fields/SignersInput";
import SelectFolder from "../components/shared/fields/SelectFolder";
import SignersInput from "../components/shared/fields/SignersInput";
import Title from "../components/Title";
import PageNotFound from "./PageNotFound";
// `Form` render all type of Form on this basis of their provided in path
function Form() {
const { id } = useParams();
@@ -27,42 +28,47 @@ function Form() {
}
const Forms = (props) => {
const maxFileSize = 20;
const navigate = useNavigate();
const [signers, setSigners] = useState([]);
const [folder, setFolder] = useState({ ObjectId: "", Name: "" });
const [formData, setFormData] = useState({
Name: "",
Description: "",
Note: "Please review and sign this document",
Note: "",
TimeToCompleteDays: 15,
SendinOrder: "false"
});
const [fileupload, setFileUpload] = useState([]);
const [fileload, setfileload] = useState(false);
const [percentage, setpercentage] = useState(0);
const [isReset, setIsReset] = useState(false);
const [isAlert, setIsAlert] = useState(false);
const [isSubmit, setIsSubmit] = useState(false);
const [isErr, setIsErr] = useState("");
const handleStrInput = (e) => {
setFormData({ ...formData, [e.target.name]: e.target.value });
};
useEffect(() => {
handleReset();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [props.title]);
const handleFileInput = (e) => {
setpercentage(0);
try {
let files = e.target.files;
if (typeof files[0] !== "undefined") {
const mb = Math.round(files[0].bytes / Math.pow(1024, 2));
if (mb > 10) {
const mb = Math.round(files[0].size / Math.pow(1024, 2));
if (mb > maxFileSize) {
alert(
`The selected file size is too large. Please select a file less than ${Math.round(
10
)} MB`
`The selected file size is too large. Please select a file less than ${maxFileSize} MB`
);
setFileUpload([]);
e.target.value = "";
return;
} else {
handleFileUpload(files[0]);
}
handleFileUpload(files[0]);
} else {
alert("Please select file.");
return false;
@@ -74,8 +80,6 @@ const Forms = (props) => {
};
const handleFileUpload = async (file) => {
Parse.serverURL = process.env.REACT_APP_SERVERURL;
Parse.initialize(process.env.REACT_APP_APPID);
setfileload(true);
const fileName = file.name;
const name = sanitizeFileName(fileName);
@@ -112,10 +116,10 @@ const Forms = (props) => {
const url = file.link;
const mb = Math.round(file.bytes / Math.pow(1024, 2));
if (mb > 10) {
if (mb > maxFileSize) {
setTimeout(() => {
alert(
`The selected file size is too large. Please select a file less than 10 MB`
`The selected file size is too large. Please select a file less than ${maxFileSize} MB`
);
}, 500);
return;
@@ -162,7 +166,9 @@ const Forms = (props) => {
"TimeToCompleteDays",
parseInt(formData?.TimeToCompleteDays)
);
const isChecked = formData.SendinOrder === "true" ? true : false;
}
if (props.title !== "Sign Yourself") {
const isChecked = formData.SendinOrder === "false" ? false : true;
object.set("SendinOrder", isChecked);
}
object.set("URL", fileupload);
@@ -195,9 +201,7 @@ const Forms = (props) => {
});
setFileUpload([]);
setpercentage(0);
navigate(
`/asmf/remoteUrl=aHR0cHM6Ly9xaWstYWktb3JnLmdpdGh1Yi5pby9TaWduLU1pY3JvYXBwVjIvcmVtb3RlRW50cnkuanM=&moduleToLoad=AppRoutes&remoteName=signmicroapp/${props?.redirectRoute}/${res.id}`
);
navigate(`/${props?.redirectRoute}/${res.id}`);
}
} catch (err) {
console.log("err ", err);
@@ -226,15 +230,22 @@ const Forms = (props) => {
};
const handleReset = () => {
setIsReset(true);
setSigners([]);
setFolder({ ObjectId: "", Name: "" });
setFormData({
Name: "",
Description: "",
Note: ""
Note:
props.title === "Sign Yourself"
? "Note to myself"
: "Please review and sign this document",
TimeToCompleteDays: 15,
SendinOrder: "true"
});
setFileUpload([]);
setpercentage(0);
setTimeout(() => setIsReset(false), 50);
};
return (
<div className="shadow-md rounded my-2 p-3 bg-[#ffffff] md:border-[1px] md:border-gray-600/50">
@@ -280,7 +291,8 @@ const Forms = (props) => {
<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="break-all">
file selected : {fileupload?.split("/")[3]?.split("_")[1]}
file selected :{" "}
{fileupload?.split("/")?.pop()?.split("_")[1]}
</div>
<div
onClick={() => {
@@ -318,7 +330,10 @@ const Forms = (props) => {
</div>
<div className="text-xs mt-2">
<label className="block">
Title<span className="text-red-500 text-[13px]">*</span>
{props.title === "New Template"
? "Template Title"
: "Document Title"}
<span className="text-red-500 text-[13px]">*</span>
</label>
<input
name="Name"
@@ -337,7 +352,9 @@ const Forms = (props) => {
onChange={(e) => handleStrInput(e)}
/>
</div>
{props.signers && <SignersInput onChange={handleSigners} required />}
{props.signers && (
<SignersInput onChange={handleSigners} isReset={isReset} required />
)}
<div className="text-xs mt-2">
<label className="block">
Note<span className="text-red-500 text-[13px]">*</span>
@@ -350,7 +367,11 @@ const Forms = (props) => {
required
/>
</div>
<SelectFolder onSuccess={handleFolder} folderCls={props.Cls} />
<SelectFolder
onSuccess={handleFolder}
folderCls={props.Cls}
isReset={isReset}
/>
{props.title === "Request Signatures" && (
<div className="text-xs mt-2">
@@ -402,10 +423,10 @@ const Forms = (props) => {
type="submit"
disabled={isSubmit}
>
Submit
Next
</button>
<div
className="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="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"
onClick={() => handleReset()}
>
Reset
@@ -5,6 +5,8 @@ import Alert from "../primitives/Alert";
import ModalUi from "../primitives/ModalUi";
import { rejectBtn, submitBtn } from "../constant/const";
import { openInNewTab } from "../constant/Utils";
import PremiumAlertHeader from "../primitives/PremiumAlertHeader";
import Tooltip from "../primitives/Tooltip";
function GenerateToken() {
const [parseBaseUrl] = useState(localStorage.getItem("baseUrl"));
@@ -115,7 +117,13 @@ function GenerateToken() {
</div>
) : (
<div className="bg-white flex flex-col justify-center shadow rounded">
<h1 className="ml-4 mt-3 mb-2 font-semibold">API Token</h1>
<PremiumAlertHeader />
<h1 className="ml-4 mt-3 mb-2 font-semibold">
API Token{" "}
<Tooltip
url={"https://docs.opensignlabs.com/docs/API-docs/opensign-api-v-1"}
/>
</h1>
<ul className="w-full flex flex-col p-2 text-sm">
<li
className={`flex justify-between items-center border-y-[1px] border-gray-300 break-all py-2`}
@@ -1,13 +1,12 @@
import React, { useState } from "react";
import "../css/LoginPage.css";
import loader from "../assests/loader2.gif";
import React, { useState, useEffect } from "react";
import { useNavigate, useParams } from "react-router-dom";
import "../styles/loginPage.css";
import loader from "../assets/images/loader2.gif";
import axios from "axios";
import { useParams } from "react-router-dom";
import { themeColor } from "../utils/ThemeColor/backColor";
import { useEffect } from "react";
import { useNavigate } from "react-router-dom";
import { themeColor } from "../constant/const";
import { contractUsers } from "../constant/Utils";
function Login() {
function GuestLogin() {
const { id, userMail, contactBookId, serverUrl } = useParams();
let navigate = useNavigate();
const [email, setEmail] = useState(userMail);
@@ -18,6 +17,7 @@ function Login() {
useEffect(() => {
handleServerUrl();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
//function generate serverUrl and parseAppId from url and save it in local storage
@@ -104,28 +104,36 @@ function Login() {
} else {
let _user = user.data.result;
const parseId = localStorage.getItem("parseAppId");
const contractUserDetails = await contractUsers(_user.email);
localStorage.setItem("UserInformation", JSON.stringify(_user));
localStorage.setItem(
`Parse/${parseId}/currentUser`,
JSON.stringify(_user)
);
if (contractUserDetails) {
localStorage.setItem(
"Extand_Class",
JSON.stringify(contractUserDetails)
);
}
localStorage.setItem("username", _user.name);
localStorage.setItem("accesstoken", _user.sessionToken);
//save isGuestSigner true in local to handle login flow header in mobile view
localStorage.setItem("isGuestSigner", true);
setLoading(false);
navigate(
`/loadmf/signmicroapp/recipientSignPdf/${id}/${contactBookId}`
);
navigate(`/load/recipientSignPdf/${id}/${contactBookId}`);
}
} catch (error) {}
} catch (error) {
console.log("err ", error);
}
} else {
alert("Please Enter OTP!");
}
};
return (
<div style={{ padding: "2rem" }}>
<div style={{ padding: "2rem", background: "white" }}>
{isLoading ? (
<div
style={{
@@ -189,7 +197,7 @@ function Login() {
<button
type="button"
style={{
background: themeColor(),
background: themeColor,
color: "white"
}}
className="verifyBtn"
@@ -206,7 +214,7 @@ function Login() {
<button
className="verifyBtn"
style={{
background: themeColor(),
background: themeColor,
color: "white",
marginLeft: "0px !important"
}}
@@ -242,7 +250,7 @@ function Login() {
{loading ? (
<button
style={{
background: themeColor(),
background: themeColor,
color: "white"
}}
className="verifyBtn"
@@ -261,7 +269,7 @@ function Login() {
type="button"
onClick={(e) => VerifyOTP(e)}
style={{
background: themeColor(),
background: themeColor,
color: "white"
}}
className="verifyBtn"
@@ -279,4 +287,4 @@ function Login() {
);
}
export default Login;
export default GuestLogin;
@@ -1,9 +1,7 @@
import React, { useEffect, useState } from "react";
import Parse from "parse";
import "../styles/toast.css";
import "../styles/loader.css";
import { connect } from "react-redux";
import { fetchAppInfo, showTenantName } from "../redux/actions";
import { useDispatch } from "react-redux";
import axios from "axios";
import Title from "../components/Title";
import GoogleSignInBtn from "../components/LoginGoogle";
@@ -13,15 +11,19 @@ import login_img from "../assets/images/login_img.svg";
import { useWindowSize } from "../hook/useWindowSize";
import ModalUi from "../primitives/ModalUi";
import { modalCancelBtnColor, modalSubmitBtnColor } from "../constant/const";
function Login(props) {
import Alert from "../primitives/Alert";
import { appInfo } from "../constant/appinfo";
import { fetchAppInfo } from "../redux/reducers/infoReducer";
import { showTenant } from "../redux/reducers/ShowTenant";
function Login() {
const navigate = useNavigate();
const location = useLocation();
const dispatch = useDispatch();
const { width } = useWindowSize();
const [state, setState] = useState({
email: "",
toastColor: "#5cb85c",
toastDescription: "",
alertType: "success",
alertMsg: "",
password: "",
passwordVisible: false,
mobile: "",
@@ -37,18 +39,14 @@ function Login(props) {
Destination: ""
});
const [isModal, setIsModal] = useState(false);
const image = props?.appInfo?.applogo || undefined;
const image = appInfo?.applogo || undefined;
useEffect(() => {
if (localStorage.getItem("accesstoken")) {
setState({ ...state, loading: true });
GetLoginData();
}
props.fetchAppInfo(
localStorage.getItem("domain"),
localStorage.getItem("BaseUrl12"),
localStorage.getItem("AppID12")
);
dispatch(fetchAppInfo());
// eslint-disable-next-line
}, []);
const handleChange = (event) => {
@@ -65,10 +63,8 @@ function Login(props) {
setState({ ...state, loading: true });
let baseUrl = localStorage.getItem("baseUrl");
let parseAppId = localStorage.getItem("parseAppId");
localStorage.setItem("appLogo", props.appInfo.applogo);
localStorage.setItem("appName", props.appInfo.appname);
Parse.serverURL = localStorage.getItem("baseUrl");
Parse.initialize(localStorage.getItem("parseAppId"));
localStorage.setItem("appLogo", appInfo.applogo);
localStorage.setItem("appName", appInfo.appname);
// Pass the username and password to logIn function
await Parse.User.logIn(email, password)
.then(async (user) => {
@@ -87,8 +83,8 @@ function Login(props) {
// Check extended class user role and tenentId
try {
let userRoles = [];
if (props.appInfo.settings) {
let userSettings = props.appInfo.settings;
if (appInfo.settings) {
let userSettings = appInfo.settings;
//Get Current user roles
let url = `${baseUrl}functions/UserGroups`;
@@ -149,11 +145,6 @@ function Login(props) {
"extended_class",
element.extended_class
);
localStorage.setItem(
"userpointer",
element.userpointer
);
const currentUser = Parse.User.current();
await Parse.Cloud.run("getUserDetails", {
email: currentUser.get("email")
@@ -183,8 +174,10 @@ function Login(props) {
}
});
if (tenentInfo.length) {
props.showTenantName(
tenentInfo[0].tenentName || ""
dispatch(
showTenant(
tenentInfo[0].tenentName || ""
)
);
localStorage.setItem(
"TenantName",
@@ -223,8 +216,10 @@ function Login(props) {
}
});
if (tenentInfo.length) {
props.showTenantName(
tenentInfo[0].tenentName || ""
dispatch(
showTenant(
tenentInfo[0].tenentName || ""
)
);
localStorage.setItem(
"TenantName",
@@ -354,13 +349,16 @@ function Login(props) {
setState({
...state,
loading: false,
toastColor: "#d9534f",
toastDescription: `${error.message}`
alertType: "danger",
alertMsg: `${error.message}`
});
const x = document.getElementById("snackbar");
x.className = "show";
setTimeout(function () {
x.className = x.className.replace("show", "");
setState({
...state,
loading: false,
alertType: "danger",
alertMsg: ""
});
}, 2000);
console.log(error);
}
@@ -370,13 +368,16 @@ function Login(props) {
setState({
...state,
loading: false,
toastColor: "#d9534f",
toastDescription: "Login failed: Invalid username or password."
alertType: "danger",
alertMsg: "Invalid username or password!"
});
const x = document.getElementById("snackbar");
x.className = "show";
setTimeout(function () {
x.className = x.className.replace("show", "");
setState({
...state,
loading: false,
alertType: "danger",
alertMsg: ""
});
}, 2000);
console.error("Error while logging in user", error);
});
@@ -391,8 +392,8 @@ function Login(props) {
setState({ ...state, thirdpartyLoader: value });
};
const thirdpartyLoginfn = async (sessionToken, billingDate) => {
const baseUrl = localStorage.getItem("BaseUrl12");
const parseAppId = localStorage.getItem("AppID12");
const baseUrl = localStorage.getItem("baseUrl");
const parseAppId = localStorage.getItem("parseAppId");
const res = await axios.get(baseUrl + "users/me", {
headers: {
"X-Parse-Session-Token": sessionToken,
@@ -417,8 +418,8 @@ function Login(props) {
// Check extended class user role and tenentId
try {
let userRoles = [];
if (props.appInfo.settings) {
let userSettings = props.appInfo.settings;
if (appInfo.settings) {
let userSettings = appInfo.settings;
//Get Current user roles
let url = `${baseUrl}functions/UserGroups`;
@@ -480,7 +481,6 @@ function Login(props) {
"extended_class",
element.extended_class
);
localStorage.setItem("userpointer", element.userpointer);
const currentUser = Parse.User.current();
await Parse.Cloud.run("getUserDetails", {
email: currentUser.get("email")
@@ -509,8 +509,8 @@ function Login(props) {
}
});
if (tenentInfo.length) {
props.showTenantName(
tenentInfo[0].tenentName || ""
dispatch(
showTenant(tenentInfo[0].tenentName || "")
);
localStorage.setItem(
"TenantName",
@@ -549,8 +549,8 @@ function Login(props) {
}
});
if (tenentInfo.length) {
props.showTenantName(
tenentInfo[0].tenentName || ""
dispatch(
showTenant(tenentInfo[0].tenentName || "")
);
localStorage.setItem(
"TenantName",
@@ -647,13 +647,16 @@ function Login(props) {
setState({
...state,
loading: false,
toastColor: "#d9534f",
toastDescription: `${error.message}`
alertType: "danger",
alertMsg: `${error.message}`
});
const x = document.getElementById("snackbar");
x.className = "show";
setTimeout(function () {
x.className = x.className.replace("show", "");
setState({
...state,
loading: false,
alertType: "danger",
alertMsg: ""
});
}, 2000);
console.log(error);
}
@@ -663,8 +666,6 @@ function Login(props) {
const GetLoginData = async () => {
setState({ ...state, loading: true });
try {
Parse.serverURL = localStorage.getItem("baseUrl");
Parse.initialize(localStorage.getItem("parseAppId"));
const user = await Parse.User.become(localStorage.getItem("accesstoken"));
let _usss = user.toJSON();
localStorage.setItem("UserInformation", JSON.stringify(_usss));
@@ -717,13 +718,17 @@ function Login(props) {
setState({
...state,
loading: false,
toastColor: "#d9534f",
toastDescription: `Does not have permissions to access this application.`
alertType: "danger",
alertMsg:
"Does not have permissions to access this application!"
});
const x = document.getElementById("snackbar");
x.className = "show";
setTimeout(function () {
x.className = x.className.replace("show", "");
setState({
...state,
loading: false,
alertType: "danger",
alertMsg: ""
});
}, 2000);
}
// _currentRole = userRoles[0];
@@ -731,92 +736,90 @@ function Login(props) {
} else {
_currentRole = userRoles[0];
}
let SettingsUser = JSON.parse(userSettings);
SettingsUser.forEach(async (element) => {
if (element.role === _currentRole) {
let _role = _currentRole.replace(
`${localStorage.getItem("_appName")}_`,
""
);
localStorage.setItem("_user_role", _role);
// Get TenentID from Extendend Class
localStorage.setItem(
"extended_class",
element.extended_class
);
const currentUser = Parse.User.current();
await Parse.Cloud.run("getUserDetails", {
email: currentUser.get("email")
}).then(
(result) => {
let tenentInfo = [];
const results = [result];
if (results) {
let extendedInfo_stringify = JSON.stringify(results);
let extendedInfo = JSON.parse(extendedInfo_stringify);
if (extendedInfo.length > 1) {
extendedInfo.forEach((x) => {
if (x.TenantId) {
let obj = {
tenentId: x.TenantId.objectId,
tenentName: x.TenantId.TenantName || ""
};
tenentInfo.push(obj);
}
});
localStorage.setItem("showpopup", true);
localStorage.setItem("PageLanding", element.pageId);
localStorage.setItem("defaultmenuid", element.menuId);
localStorage.setItem("pageType", element.pageType);
navigate("/");
if (_currentRole && _currentRole !== "contracts_Guest") {
let SettingsUser = JSON.parse(userSettings);
SettingsUser.forEach(async (item) => {
if (item.role === _currentRole) {
let _role = _currentRole.replace(`${appInfo.appname}_`, "");
localStorage.setItem("_user_role", _role);
// Get TenentID from Extendend Class
localStorage.setItem("extended_class", item.extended_class);
const currentUser = Parse.User.current();
await Parse.Cloud.run("getUserDetails", {
email: currentUser.get("email")
}).then(
(result) => {
let tenentInfo = [];
const results = [result];
if (results) {
let extendedInfo_stringify = JSON.stringify(results);
let extendedInfo = JSON.parse(extendedInfo_stringify);
if (extendedInfo.length > 1) {
extendedInfo.forEach((x) => {
if (x.TenantId) {
let obj = {
tenentId: x.TenantId.objectId,
tenentName: x.TenantId.TenantName || ""
};
tenentInfo.push(obj);
}
});
localStorage.setItem("showpopup", true);
localStorage.setItem("PageLanding", item.pageId);
localStorage.setItem("defaultmenuid", item.menuId);
localStorage.setItem("pageType", item.pageType);
navigate("/");
} else {
extendedInfo.forEach((x) => {
if (x.TenantId) {
let obj = {
tenentId: x.TenantId.objectId,
tenentName: x.TenantId.TenantName || ""
};
localStorage.setItem(
"TenetId",
x.TenantId.objectId
);
tenentInfo.push(obj);
}
});
localStorage.setItem("PageLanding", item.pageId);
localStorage.setItem("defaultmenuid", item.menuId);
localStorage.setItem("pageType", item.pageType);
navigate(`/${item.pageType}/${item.pageId}`);
}
} else {
extendedInfo.forEach((x) => {
if (x.TenantId) {
let obj = {
tenentId: x.TenantId.objectId,
tenentName: x.TenantId.TenantName || ""
};
localStorage.setItem(
"TenetId",
x.TenantId.objectId
);
tenentInfo.push(obj);
}
});
localStorage.setItem("PageLanding", element.pageId);
localStorage.setItem("defaultmenuid", element.menuId);
localStorage.setItem("pageType", element.pageType);
navigate(`/${element.pageType}/${element.pageId}`);
localStorage.setItem("PageLanding", item.pageId);
localStorage.setItem("defaultmenuid", item.menuId);
localStorage.setItem("pageType", item.pageType);
navigate(`/${item.pageType}/${item.pageId}`);
}
} else {
localStorage.setItem("PageLanding", element.pageId);
localStorage.setItem("defaultmenuid", element.menuId);
localStorage.setItem("pageType", element.pageType);
navigate(`/${element.pageType}/${element.pageId}`);
},
(error) => {
setState({
...state,
loading: false,
alertType: "danger",
alertMsg: "You don`t have access to this application!"
});
setTimeout(function () {
setState({
...state,
loading: false,
alertType: "danger",
alertMsg: ""
});
}, 2000);
localStorage.setItem("accesstoken", null);
console.error("Error while fetching Follow", error);
}
},
(error) => {
setState({
...state,
loading: false,
toastColor: "#d9534f",
toastDescription:
"You don`t have access to this application."
});
const x = document.getElementById("snackbar");
x.className = "show";
setTimeout(function () {
x.className = x.className.replace("show", "");
}, 2000);
localStorage.setItem("accesstoken", null);
console.error("Error while fetching Follow", error);
}
);
}
});
);
}
});
} else {
setState({ ...state, loading: false });
handleCloseModal();
}
} else {
console.log("User Role Not Found.");
}
@@ -895,8 +898,8 @@ function Login(props) {
let PageLanding = localStorage.getItem("PageLanding");
let domain = localStorage.getItem("domain");
let _appName = localStorage.getItem("_appName");
let baseUrl = localStorage.getItem("BaseUrl12");
let appid = localStorage.getItem("AppID12");
let baseUrl = localStorage.getItem("baseUrl");
let appid = localStorage.getItem("parseAppId");
localStorage.clear();
@@ -907,8 +910,8 @@ function Login(props) {
localStorage.setItem("PageLanding", PageLanding);
localStorage.setItem("domain", domain);
localStorage.setItem("userSettings", appdata);
localStorage.setItem("BaseUrl12", baseUrl);
localStorage.setItem("AppID12", appid);
localStorage.setItem("baseUrl", baseUrl);
localStorage.setItem("parseAppId", appid);
};
return (
<div className="bg-white">
@@ -942,7 +945,7 @@ function Login(props) {
</div>
</div>
)}
{props.isloginVisible && props.isloginVisible ? (
{appInfo && appInfo.appId ? (
<>
<div aria-labelledby="loginHeading" role="region">
<div className="md:m-10 lg:m-16 md:p-4 lg:p-10 p-4 bg-[#ffffff] md:border-[1px] md:border-gray-400 ">
@@ -1050,7 +1053,7 @@ function Login(props) {
</div>
</form>
<br />
{(props.appInfo.fbAppId || props.appInfo.googleClietId) && (
{(appInfo.fbAppId || appInfo.googleClietId) && (
<div
style={{
display: "flex",
@@ -1081,9 +1084,9 @@ function Login(props) {
justifyContent: "center"
}}
>
{/* {props.appInfo.fbAppId && props.appInfo.fbAppId !== "" ? (
{/* {appInfo.fbAppId && appInfo.fbAppId !== "" ? (
<LoginFacebook
FBCred={props.appInfo.fbAppId}
FBCred={appInfo.fbAppId}
thirdpartyLoginfn={thirdpartyLoginfn}
thirdpartyLoader={state.thirdpartyLoader}
setThirdpartyLoader={setThirdpartyLoader}
@@ -1099,10 +1102,9 @@ function Login(props) {
justifyContent: "center"
}}
>
{props.appInfo.googleClietId &&
props.appInfo.googleClietId !== "" ? (
{appInfo.googleClietId && appInfo.googleClietId !== "" ? (
<GoogleSignInBtn
GoogleCred={props.appInfo.googleClietId}
GoogleCred={appInfo.googleClietId}
thirdpartyLoginfn={thirdpartyLoginfn}
thirdpartyLoader={state.thirdpartyLoader}
setThirdpartyLoader={setThirdpartyLoader}
@@ -1124,14 +1126,7 @@ function Login(props) {
)}
</div>
</div>
<div
id="snackbar"
role="alert"
style={{ backgroundColor: state.toastColor }}
>
{state.toastDescription}
</div>
<Alert type={state.alertType}>{state.alertMsg}</Alert>
</div>
<ModalUi isOpen={isModal} title="Additional Info" showClose={false}>
<form className="px-4 py-3">
@@ -1219,16 +1214,4 @@ function Login(props) {
</div>
);
}
const mapStateToProps = (state) => {
if (Object.keys(state.appInfo).length !== 0) {
return { appInfo: state.appInfo, isloginVisible: true };
} else {
return { appInfo: state.appInfo, isloginVisible: false };
}
};
export default connect(mapStateToProps, {
fetchAppInfo,
showTenantName
})(Login);
export default Login;
@@ -1,25 +1,20 @@
import React, { useState, useRef, useEffect } from "react";
import SignatureCanvas from "react-signature-canvas";
import redPen from "../assests/redPen.png";
import bluePen from "../assests/bluePen.png";
import blackPen from "../assests/blackPen.png";
import "../css/custom.css";
import "../css/signature.css";
import axios from "axios";
import { toDataUrl } from "../utils/toDataUrl";
import "../styles/managesign.css";
import "../styles/signature.css";
import { toDataUrl } from "../constant/Utils";
import Parse from "parse";
import { appInfo } from "../constant/appinfo";
const ManageSign = () => {
let appName;
const appName = appInfo.appname;
const [penColor, setPenColor] = useState("blue");
const [initialPen, setInitialPen] = useState("blue");
const [image, setImage] = useState();
const [signName, setSignName] = useState("");
const [signature, setSignature] = useState("");
const [warning, setWarning] = useState(false);
const [nameWarning, setNameWarning] = useState(false);
const [isvalue, setIsValue] = useState(false);
const allColor = [bluePen, redPen, blackPen];
const allColor = ["blue", "red", "black"];
const [isLoader, setIsLoader] = useState(true);
const [isSuccess, setIsSuccess] = useState(false);
const [Initials, setInitials] = useState("");
@@ -29,59 +24,40 @@ const ManageSign = () => {
const imageRef = useRef(null);
const initailsRef = useRef(null);
useEffect(() => {
getLocalStorageValue();
fetchUserSign();
// eslint-disable-next-line
}, []);
//function for get localstorage value first and than call another function.
const getLocalStorageValue = () => {
let User = JSON.parse(
localStorage.getItem(
"Parse/" + localStorage.getItem("parseAppId") + "/currentUser"
)
);
appName =
localStorage.getItem("_appName") && localStorage.getItem("_appName");
const fetchUserSign = async () => {
const User = Parse.User.current();
if (User) {
fetchUserSign(User);
}
};
const fetchUserSign = async (User) => {
const userId = {
__type: "Pointer",
className: "_User",
objectId: User.objectId,
};
const strObj = JSON.stringify(userId);
const url =
localStorage.getItem("baseUrl") +
`classes/${appName}_Signature?where={"UserId":${strObj}}&limit=1`;
const headers = {
"Content-Type": "application/json",
"X-Parse-Application-Id": localStorage.getItem("parseAppId"),
// "X-Parse-Session-Token": localStorage.getItem("accesstoken"),
};
const res = await axios
.get(url, { headers: headers })
.then((res) => {
if (res.data.results.length > 0) {
setId(res.data.results[0].objectId);
setSignName(res.data.results[0].SignatureName);
setImage(res.data.results[0].ImageURL);
if (res.data.results[0] && res.data.results[0].Initials) {
setInitials(res.data.results[0].Initials);
const userId = {
__type: "Pointer",
className: "_User",
objectId: User.id
};
try {
const signCls = `${appName}_Signature`;
const signQuery = new Parse.Query(signCls);
signQuery.equalTo("UserId", userId);
const signRes = await signQuery.first();
if (signRes) {
const res = signRes.toJSON();
setId(res.objectId);
setSignName(res?.SignatureName);
setImage(res.ImageURL);
if (res && res.Initials) {
setInitials(res.Initials);
setIsInitials(true);
}
} else {
setSignName(User?.get("name") || "");
}
setIsLoader(false);
return res;
})
.catch((error) => {
console.log(error);
alert(`${error.message}`);
});
return res;
} catch (err) {
console.log("Err", err);
alert(`${err.message}`);
}
}
};
const handleSignatureChange = () => {
if (imageRef.current) {
@@ -112,18 +88,6 @@ const ManageSign = () => {
setIsInitials(false);
};
// const handleReset = () => {
// if (canvasRef.current) {
// canvasRef.current.clear();
// }
// if (imageRef.current) {
// imageRef.current.value = "";
// }
// setImage("");
// setSignature("");
// setIsValue(false);
// setSignName("");
// };
const onImageChange = async (event) => {
if (canvasRef.current) {
canvasRef.current.clear();
@@ -140,10 +104,7 @@ const ManageSign = () => {
e.preventDefault();
const isUrl = image.includes("https");
if (!signName) {
setNameWarning(true);
} else if (!isvalue) {
if (!isvalue) {
setWarning(true);
setTimeout(() => setWarning(false), 1000);
} else {
@@ -151,29 +112,32 @@ const ManageSign = () => {
const replaceSpace = signName.replace(/ /g, "_");
let file;
if (signature) {
file = base64StringtoFile(signature, `${replaceSpace}.png`);
file = base64StringtoFile(signature, `${replaceSpace}_sign.png`);
} else {
if (!isUrl) {
file = base64StringtoFile(image, `${replaceSpace}.png`);
file = base64StringtoFile(image, `${replaceSpace}__sign.png`);
}
}
// console.log("isUrl ", isUrl);
let imgUrl;
if (!isUrl) {
imgUrl = await uploadFile(file);
} else {
imgUrl = { data: { imageUrl: image } };
imgUrl = image;
}
let initialsUrl = "";
if (Initials) {
const initialsImg = base64StringtoFile(Initials, `${replaceSpace}.png`);
const isInitialsUrl = Initials.includes("https");
if (!isInitialsUrl && Initials) {
const initialsImg = base64StringtoFile(
Initials,
`${replaceSpace}_initials.png`
);
initialsUrl = await uploadFile(initialsImg);
}
if (imgUrl.data && imgUrl.data.imageUrl) {
if (imgUrl) {
await saveEntry({
name: signName,
url: imgUrl.data.imageUrl,
initialsUrl: initialsUrl,
url: imgUrl,
initialsUrl: initialsUrl
});
}
}
@@ -191,116 +155,54 @@ const ManageSign = () => {
}
const uploadFile = async (file) => {
let parseBaseUrl = localStorage.getItem("baseUrl");
parseBaseUrl = parseBaseUrl.slice(0, -4);
const url = parseBaseUrl + `file_upload`;
const formData = new FormData();
formData.append("file", file);
const config = {
headers: {
"content-type": "multipart/form-data",
"X-Parse-Application-Id": localStorage.getItem("parseAppId"),
},
onUploadProgress: function (progressEvent) {
let percentCompleted = Math.round(
(progressEvent.loaded * 100) / progressEvent.total
);
// setpercentage(percentCompleted);
},
};
const response = await axios
.post(url, formData, config)
.then((res) => {
if (res.data.status === "Error") {
alert(res.data.message);
}
return res;
})
.catch((error) => {
console.log(error);
setIsLoader(false);
alert(`${error.message}`);
});
return response;
try {
const parseFile = new Parse.File(file.name, file);
const response = await parseFile.save();
return response?.url();
} catch (err) {
console.log("sign upload err", err);
setIsLoader(false);
alert(`${err.message}`);
}
};
const saveEntry = async (obj) => {
const signCls = `${appName}_Signature`;
const User = Parse.User.current().id;
const userId = { __type: "Pointer", className: "_User", objectId: User };
if (id) {
const User = JSON.parse(
localStorage.getItem(
"Parse/" + localStorage.getItem("parseAppId") + "/currentUser"
)
);
const url =
localStorage.getItem("baseUrl") +
`classes/${localStorage.getItem("_appName")}_Signature/${id}`;
const body = {
Initials: obj.initialsUrl ? obj.initialsUrl.data.imageUrl : "",
ImageURL: obj.url,
SignatureName: obj.name,
UserId: {
__type: "Pointer",
className: "_User",
objectId: User.objectId,
},
};
const headers = {
"Content-Type": "application/json",
"X-Parse-Application-Id": localStorage.getItem("parseAppId"),
// "X-Parse-Session-Token": localStorage.getItem("accesstoken"),
};
const res = await axios
.put(url, body, { headers: headers })
.then((res) => {
// handleReset();
setIsLoader(false);
setIsSuccess(true);
return res;
})
.catch((error) => {
console.log(error);
setIsLoader(false);
alert(`${error.message}`);
});
return res;
try {
const updateSign = new Parse.Object(signCls);
updateSign.id = id;
updateSign.set("Initials", obj.initialsUrl ? obj.initialsUrl : "");
updateSign.set("ImageURL", obj.url);
updateSign.set("SignatureName", obj.name);
updateSign.set("UserId", userId);
const res = await updateSign.save();
setIsLoader(false);
setIsSuccess(true);
return res;
} catch (err) {
console.log(err);
setIsLoader(false);
alert(`${err.message}`);
}
} else {
const User = JSON.parse(
localStorage.getItem(
"Parse/" + localStorage.getItem("parseAppId") + "/currentUser"
)
);
const url =
localStorage.getItem("baseUrl") +
`classes/${localStorage.getItem("_appName")}_Signature`;
const body = {
Initials: obj.initialsUrl ? obj.initialsUrl.data.imageUrl : "",
ImageURL: obj.url,
SignatureName: obj.name,
UserId: {
__type: "Pointer",
className: "_User",
objectId: User.objectId,
},
};
const headers = {
"Content-Type": "application/json",
"X-Parse-Application-Id": localStorage.getItem("parseAppId"),
// "X-Parse-Session-Token": localStorage.getItem("accesstoken"),
};
const res = await axios
.post(url, body, { headers: headers })
.then((res) => {
// handleReset();
setIsLoader(false);
setIsSuccess(true);
return res;
})
.catch((error) => {
console.log(error);
setIsLoader(false);
alert(`${error.message}`);
});
return res;
try {
const updateSign = new Parse.Object(signCls);
updateSign.set("Initials", obj.initialsUrl ? obj.initialsUrl : "");
updateSign.set("ImageURL", obj.url);
updateSign.set("SignatureName", obj.name);
updateSign.set("UserId", userId);
const res = await updateSign.save();
setIsLoader(false);
setIsSuccess(true);
return res;
} catch (err) {
console.log(err);
setIsLoader(false);
alert(`${err.message}`);
}
}
};
const handleSignatureBtn = () => {
@@ -317,12 +219,15 @@ const ManageSign = () => {
setIsValue(true);
};
return (
<div
style={{
maxHeight: "500px",
overflow: "auto",
}}
>
<div className="relative h-full bg-white flex shadow rounded overflow-auto">
{isLoader && (
<div className="absolute bg-black bg-opacity-75 z-50 w-full h-full flex justify-center items-center">
<div
style={{ color: "#3dd3e0" }}
className="loader-37 text-[45px]"
></div>
</div>
)}
{isSuccess && (
<div
className="alert alert-success successBox"
@@ -332,12 +237,11 @@ const ManageSign = () => {
Signature saved successfully!
</div>
)}
<div
className="mainDiv"
style={{
width: "100%",
paddingRight: "10px",
paddingRight: "10px"
}}
>
<div style={{ margin: 20 }}>
@@ -346,64 +250,12 @@ const ManageSign = () => {
fontWeight: "700",
fontSize: 15,
color: "#000",
paddingBottom: 8,
paddingBottom: 8
}}
>
Manage Signature
My Signature
</div>
<div style={{ display: "flex", flexDirection: "column" }}>
<label
htmlFor="signName"
style={{
fontSize: 12,
position: "relative",
paddingBottom: 5,
}}
>
Signer's Name
{nameWarning && (
<div
className="warning nameWarning"
style={{ fontSize: 12 }}
onAnimationEnd={() => setNameWarning(false)}
>
<i
className="fas fa-exclamation-circle"
style={{ color: "#fab005", fontSize: 15 }}
></i>{" "}
Please fill input field
</div>
)}
</label>
<input
id="signName"
className="signInputManage"
value={signName}
style={{
border: "1px solid #ccc",
borderRadius: 4,
height: 35,
padding: "6px 12px",
marginBottom: 10,
fontSize: 12,
}}
required
onFocus={() => setNameWarning(false)}
onChange={(e) => setSignName(e.target.value)}
/>
<label
htmlFor="imgoverview"
style={{
fontSize: 12,
paddingBottom: 5,
}}
>
Signature/Image
</label>
</div>
<div className="signBlock">
<div className="signBlock mt-4">
<div>
<div style={{ position: "relative" }}>
<div
@@ -412,7 +264,7 @@ const ManageSign = () => {
flexDirection: "row",
justifyContent: "space-between",
width: "50%",
paddingLeft: 10,
paddingLeft: 10
}}
>
<div
@@ -422,7 +274,7 @@ const ManageSign = () => {
justifyContent: "space-around",
alignItems: "center",
gap: 10,
marginBottom: 10,
marginBottom: 10
}}
>
<>
@@ -456,9 +308,7 @@ const ManageSign = () => {
<div
style={{
position: "relative",
border: "2px solid #888",
marginBottom: 6,
border: "2px solid #888"
}}
className="signatureCanvas"
>
@@ -468,7 +318,7 @@ const ManageSign = () => {
style={{
width: "100%",
height: "100%",
objectFit: "contain",
objectFit: "contain"
}}
/>
</div>
@@ -479,7 +329,7 @@ const ManageSign = () => {
canvasProps={{
width: "456px",
height: "180px",
className: "signatureCanvas",
className: "signatureCanvas"
}}
backgroundColor="rgb(255, 255, 255)"
onEnd={() =>
@@ -492,10 +342,9 @@ const ManageSign = () => {
style={{
display: "flex",
flexDirection: "row",
justifyContent: "space-between",
// width: 460,
justifyContent: "space-between"
}}
className="penContainer"
className="penContainerDefault"
>
<div>
{!image && (
@@ -504,11 +353,10 @@ const ManageSign = () => {
>
{allColor.map((data, key) => {
return (
<img
alt="black img"
<i
style={{
border: "none",
margin: "5px",
color: data,
borderBottom:
key === 0 && penColor === "blue"
? "2px solid blue"
@@ -516,7 +364,7 @@ const ManageSign = () => {
? "2px solid red"
: key === 2 && penColor === "black"
? "2px solid black"
: "2px solid white",
: "2px solid white"
}}
onClick={() => {
if (key === 0) {
@@ -528,10 +376,10 @@ const ManageSign = () => {
}
}}
key={key}
src={data}
className="fa solid fa-pen-nib"
width={20}
height={20}
/>
></i>
);
})}
</div>
@@ -540,7 +388,7 @@ const ManageSign = () => {
<div>
<div
type="button"
className="clearbtn"
className="clearbtn cursor-pointer"
onClick={() => handleClear()}
>
Clear
@@ -565,23 +413,16 @@ const ManageSign = () => {
</div>
<div style={{ position: "relative" }}>
<div style={{ margin: "6px 5px 18px" }}>
<span
// onClick={() => handleSignatureBtn()}
className="signature"
>
Initials
</span>
<span className="signature">Initials</span>
</div>
<div>
{isInitials ? (
<div
style={{
position: "relative",
border: "2px solid #888",
marginBottom: 6,
border: "2px solid #888"
}}
className="signatureCanvas"
className="intialSignature"
>
<img
alt="preview image"
@@ -589,7 +430,7 @@ const ManageSign = () => {
style={{
width: "100%",
height: "100%",
objectFit: "contain",
objectFit: "contain"
}}
/>
</div>
@@ -598,9 +439,7 @@ const ManageSign = () => {
ref={initailsRef}
penColor={initialPen}
canvasProps={{
width: "456px",
height: "180px",
className: "signatureCanvas",
className: "intialSignature"
}}
backgroundColor="rgb(255, 255, 255)"
onEnd={() =>
@@ -613,21 +452,19 @@ const ManageSign = () => {
style={{
display: "flex",
flexDirection: "row",
justifyContent: "space-between",
// width: 460,
justifyContent: "space-between"
}}
className="penContainer"
className="penContainerInitial"
>
<div>
{!isInitials && (
<div style={{ display: "flex", flexDirection: "row" }}>
{allColor.map((data, key) => {
return (
<img
alt="pen"
<i
style={{
border: "none",
margin: "5px",
color: data,
borderBottom:
key === 0 && initialPen === "blue"
? "2px solid blue"
@@ -635,7 +472,7 @@ const ManageSign = () => {
? "2px solid red"
: key === 2 && initialPen === "black"
? "2px solid black"
: "2px solid white",
: "2px solid white"
}}
onClick={() => {
if (key === 0) {
@@ -647,10 +484,10 @@ const ManageSign = () => {
}
}}
key={key}
src={data}
className="fa solid fa-pen-nib"
width={20}
height={20}
/>
></i>
);
})}
</div>
@@ -659,7 +496,7 @@ const ManageSign = () => {
<div>
<div
type="button"
className="clearbtn"
className="clearbtn cursor-pointer"
onClick={() => handleClearInitials()}
>
Clear
@@ -687,11 +524,6 @@ const ManageSign = () => {
</button>
</div>
</div>
{isLoader && (
<div className="loaderContainer">
<div className="loader"></div>
</div>
)}
</div>
</div>
);
@@ -1,20 +1,41 @@
import React, { useEffect, useState, useRef } from "react";
import "./LegaDrive.css";
import loader from "../../assests/loader2.gif";
import PdfFileComponent from "./FolderDrive/legaDriveComponent";
import { themeColor, iconColor } from "../../utils/ThemeColor/backColor";
import { getDrive } from "../../utils/Utils";
import "../styles/opensigndrive.css";
import loader from "../assets/images/loader2.gif";
import { themeColor, iconColor } from "../constant/const";
import { getDrive } from "../constant/Utils";
import { useNavigate } from "react-router-dom";
import Title from "../component/Title";
import Title from "../components/Title";
import Parse from "parse";
import ModalUi from "../../premitives/ModalUi";
function PdfFile() {
import ModalUi from "../primitives/ModalUi";
const DriveBody = React.lazy(
() => import("../components/opensigndrive/DriveBody")
);
const Loader = () => {
return (
<div
style={{
height: "100vh",
display: "flex",
alignItems: "center",
justifyContent: "center"
}}
>
<div
style={{
fontSize: "45px",
color: "#3dd3e0"
}}
className="loader-37"
></div>
</div>
);
};
function Opensigndrive() {
const navigate = useNavigate();
const scrollRef = useRef(null);
const [isList, setIsList] = useState(false);
const [selectedSort, setSelectedSort] = useState("Date");
const [sortingOrder, setSortingOrder] = useState("Decending");
const [sortingOrder, setSortingOrder] = useState("Descending");
const [pdfData, setPdfData] = useState([]);
const [isFolder, setIsFolder] = useState(false);
const [newFolderName, setNewFolderName] = useState();
@@ -30,6 +51,17 @@ function PdfFile() {
const [folderName, setFolderName] = useState([]);
const [isAlert, setIsAlert] = useState({ isShow: false, alertMessage: "" });
const [isNewFol, setIsNewFol] = useState(false);
const [skip, setSkip] = useState(0);
const limit = 100;
const [loading, setLoading] = useState(false);
const sortOrder = ["Ascending", "Descending"];
const sortingValue = ["Name", "Date"];
const orderName = {
Ascending: "Ascending",
Descending: "Descending",
Name: "Name",
Date: "Date"
};
const currentUser =
localStorage.getItem(
`Parse/${localStorage.getItem("parseAppId")}/currentUser`
@@ -40,102 +72,83 @@ function PdfFile() {
const jsonCurrentUser = JSON.parse(currentUser);
useEffect(() => {
if (docId) {
getPdfFolderDocumentList();
} else {
getPdfDocumentList();
}
getPdfDocumentList();
// eslint-disable-next-line
}, [docId]);
//function for get all pdf document list
const getPdfDocumentList = async () => {
const load = {
isLoad: true,
message: "This might take some time"
};
let driveDetails;
setIsLoading(load);
const getPdfDocumentList = async (disbaleLoading) => {
setLoading(true);
if (!disbaleLoading) {
setIsLoading({ isLoad: true, message: "This might take some time" });
}
try {
driveDetails = await getDrive();
if (driveDetails) {
if (driveDetails.length > 0) {
setPdfData(driveDetails);
sortApps(null, null, driveDetails);
}
const data = [
{
name: "OpenSign™ Drive",
objectId: ""
}
];
setFolderName(data);
const loadObj = {
isLoad: false
};
setIsLoading(loadObj);
} else if (driveDetails === "Error: Something went wrong!") {
const loadObj = {
isLoad: false
};
const driveDetails = await getDrive(docId, skip, limit);
if (driveDetails && driveDetails === "Error: Something went wrong!") {
setHandleError("Error: Something went wrong!");
setIsLoading(loadObj);
} else if (driveDetails && driveDetails.length > 0) {
setSkip((prevSkip) => prevSkip + limit);
sortingData(null, null, driveDetails, true);
}
if (!docId) {
setFolderName([{ name: "OpenSign™ Drive", objectId: "" }]);
}
} catch (e) {
setIsAlert({
isShow: true,
alertMessage: "something went wrong"
});
}
};
//function for get parent folder document list
const getPdfFolderDocumentList = async () => {
const load = {
isLoad: true,
message: "This might take some time"
};
setIsLoading(load);
let driveDetails;
try {
driveDetails = await getDrive(docId);
if (driveDetails) {
if (driveDetails.length > 0) {
setPdfData(driveDetails);
sortApps(null, null, driveDetails);
} else {
setPdfData([]);
}
const loadObj = {
isLoad: false
};
setIsLoading(loadObj);
} else if (driveDetails === "Error: Something went wrong!") {
const loadObj = {
isLoad: false
};
setHandleError("Error: Something went wrong!");
setIsLoading(loadObj);
}
} catch (e) {
setIsAlert({
isShow: true,
alertMessage: "something went wrong!"
} finally {
setLoading(false);
setIsLoading({
isLoad: false
});
}
};
//function for get all pdf document list
const getParentFolder = async () => {
setIsFolder(true);
//function to fetch drive details list on scroll bottom
const handleScroll = () => {
//get document of render openSign-drive component using id
const documentList = document.getElementById("renderList");
//documentList.clientHeight property returns the height of an element's content area, including padding but not including borders, margins, or scrollbars.
//documentList.scrollHeight property returns the entire height of an element,including the parts that are not visible due to overflow..
// documentList.scrollTop property show height of element, how much the content has been scrolled from the top.
// When the sum of scrollTop and clientHeight is equal to scrollHeight, it means that the user has scrolled to the bottom of the div.
if (
documentList &&
documentList.scrollTop + documentList.clientHeight >=
documentList.scrollHeight
) {
//disableLoading is used disable initial loader
const disableLoading = true;
// If the fetched data length is less than the limit, it means there's no more data to fetch
if (!loading && pdfData.length % 100 === 0) {
getPdfDocumentList(disableLoading);
}
}
};
//useEffect is used to call handleScroll function on scrolling event
useEffect(() => {
const documentList = document.getElementById("renderList");
if (documentList) {
documentList.addEventListener("scroll", handleScroll);
return () => {
documentList.removeEventListener("scroll", handleScroll);
};
}
// eslint-disable-next-line
}, [loading, sortingOrder, selectedSort]); // Add/remove scroll event listener when loading changes
//function for handle folder name path
const handleRoute = (index) => {
setPdfData([]);
setSkip(0);
const updateFolderName = folderName.filter((x, i) => {
if (i <= index) {
return x;
}
});
setFolderName(updateFolderName);
const getLastId = updateFolderName[updateFolderName.length - 1];
setDocId(getLastId.objectId);
@@ -206,34 +219,38 @@ function PdfFile() {
}
};
const sortingApp = (appInfo, type, order) => {
if (type === "Name") {
if (order === "Accending") {
//function to use sorting document list according to type and order
const sortedBy = (appInfo, type, order) => {
if (type === orderName.Name) {
if (order === orderName.Ascending) {
return appInfo.sort((a, b) => (a.Name > b.Name ? 1 : -1));
} else if (order === "Decending") {
} else if (order === orderName.Descending) {
return appInfo.sort((a, b) => (a.Name > b.Name ? -1 : 1));
}
} else if (type === "Date") {
if (order === "Accending") {
} else if (type === orderName.Date) {
if (order === orderName.Ascending) {
return appInfo.sort((a, b) => (a.createdAt > b.createdAt ? 1 : -1));
} else if (order === "Decending") {
} else if (order === orderName.Descending) {
return appInfo.sort((a, b) => (a.createdAt > b.createdAt ? -1 : 1));
}
}
};
const sortApps = (type, order, driveDetails) => {
const selectedSortType = type ? type : selectedSort ? selectedSort : "Date";
const sortOrder = order ? order : sortingOrder ? sortingOrder : "Decending";
//function to use get sorting type, order and document list to sort
const sortingData = (type, order, driveDetails, isInitial) => {
const selectedSortType = type ? type : selectedSort;
const sortOrder = order ? order : sortingOrder;
let sortingData = driveDetails;
if (selectedSortType === "Name") {
sortingApp(sortingData, "Name", sortOrder);
} else if (selectedSortType === "Date") {
sortingApp(sortingData, "Date", sortOrder);
//check isInitial true it means sort previous 20 and get on scrolling 20 = 40 document list
const allPdfData = isInitial ? [...pdfData, ...driveDetails] : driveDetails;
//call sortedBy function according to selected Type and order
if (selectedSortType === orderName.Name) {
sortedBy(allPdfData, orderName.Name, sortOrder);
} else if (selectedSortType === orderName.Date) {
sortedBy(allPdfData, orderName.Date, sortOrder);
}
setPdfData(sortingData);
setPdfData(allPdfData);
};
//function for handle auto scroll on folder path
@@ -300,9 +317,10 @@ function PdfFile() {
// Cleanup the event listener when the component unmounts
document.removeEventListener("click", closeMenuOnOutsideClick);
};
}, [isShowSort || isNewFol]);
// eslint-disable-next-line
}, [isShowSort, isNewFol]);
const handleFolderTab = (folderData, isMove) => {
const handleFolderTab = (folderData) => {
return folderData.map((data, id) => {
return (
<React.Fragment key={id}>
@@ -336,7 +354,7 @@ function PdfFile() {
setError("");
};
return (
<div className="folderComponent ">
<div style={{ backgroundColor: "white" }} className="folderComponent">
<Title title={"OpenSign™ Drive"} drive={true} />
<div>
<ModalUi
@@ -444,9 +462,7 @@ function PdfFile() {
></div>
<div style={{ display: "flex", flexDirection: "row" }}>
<button
style={{
background: themeColor()
}}
style={{ background: themeColor }}
type="submit"
className="finishBtn"
>
@@ -524,7 +540,7 @@ function PdfFile() {
<i
className="fa fa-plus-square"
aria-hidden="true"
style={{ fontSize: "25px", color: `${iconColor()}` }}
style={{ fontSize: "25px", color: `${iconColor}` }}
></i>
</div>
<div
@@ -543,7 +559,7 @@ function PdfFile() {
>
<span
className="dropdown-item itemColor"
onClick={() => getParentFolder()}
onClick={() => setIsFolder(true)}
>
<i
style={{ marginRight: "5px" }}
@@ -588,13 +604,13 @@ function PdfFile() {
style={{
marginRight: "5px",
fontSize: "14px",
color: `${iconColor()}`
color: `${iconColor}`
}}
></i>
<span
style={{
fontSize: "15px",
color: `${iconColor()}`
color: `${iconColor}`
}}
>
{selectedSort}
@@ -607,95 +623,56 @@ function PdfFile() {
aria-labelledby="dropdownMenuButton"
aria-expanded={isShowSort ? "true" : "false"}
>
<span
onClick={() => {
setSelectedSort("Name");
sortApps("Name", null, pdfData);
}}
className="dropdown-item itemColor"
>
{selectedSort !== "Name" ? (
<i
className="fa fa-arrow-up"
aria-hidden="true"
style={{ marginRight: "5px" }}
></i>
) : (
<i
className="fa fa-check"
aria-hidden="true"
style={{ marginRight: "5px" }}
></i>
)}
Name
</span>
<span
onClick={() => {
setSelectedSort("Date");
sortApps("Date", null, pdfData);
}}
className="dropdown-item itemColor"
>
{selectedSort !== "Date" ? (
<i
className="fa fa-arrow-up"
aria-hidden="true"
style={{ marginRight: "5px" }}
></i>
) : (
<i
className="fa fa-check"
aria-hidden="true"
style={{ marginRight: "5px" }}
></i>
)}
Date
</span>
{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" />
<span
onClick={() => {
setSortingOrder("Accending");
sortApps(null, "Accending", pdfData);
}}
className="dropdown-item itemColor"
>
{sortingOrder !== "Accending" ? (
<i
className="fa fa-arrow-up"
aria-hidden="true"
style={{ marginRight: "5px" }}
></i>
) : (
<i
className="fa fa-check"
aria-hidden="true"
style={{ marginRight: "5px" }}
></i>
)}
Accending
</span>
<span
onClick={() => {
setSortingOrder("Decending");
sortApps(null, "Decending", pdfData);
}}
className="dropdown-item itemColor"
>
{sortingOrder !== "Decending" ? (
<i
className="fa fa-arrow-up"
aria-hidden="true"
style={{ marginRight: "5px" }}
></i>
) : (
<i
className="fa fa-check"
aria-hidden="true"
style={{ marginRight: "5px" }}
></i>
)}
Decending
</span>
{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>
@@ -705,7 +682,7 @@ function PdfFile() {
<i
onClick={() => setIsList(!isList)}
className="fa fa-th-large"
style={{ fontSize: "24px", color: `${iconColor()}` }}
style={{ fontSize: "24px", color: `${iconColor}` }}
aria-hidden="true"
></i>
</div>
@@ -714,7 +691,7 @@ function PdfFile() {
<i
className="fa fa-list"
aria-hidden="true"
style={{ fontSize: "23px", color: `${iconColor()}` }}
style={{ fontSize: "23px", color: `${iconColor}` }}
></i>
</div>
)}
@@ -735,18 +712,23 @@ function PdfFile() {
<span style={{ fontWeight: "bold" }}>No Data Found!</span>
</div>
) : (
<PdfFileComponent
pdfData={pdfData}
setFolderName={setFolderName}
setIsLoading={setIsLoading}
setDocId={setDocId}
getPdfFolderDocumentList={getPdfFolderDocumentList}
getPdfDocumentList={getPdfDocumentList}
isDocId={docId}
setPdfData={setPdfData}
isList={isList}
setIsAlert={setIsAlert}
/>
<React.Suspense fallback={<Loader />}>
<DriveBody
pdfData={pdfData}
setFolderName={setFolderName}
setIsLoading={setIsLoading}
setDocId={setDocId}
getPdfDocumentList={getPdfDocumentList}
isDocId={docId}
setPdfData={setPdfData}
isList={isList}
setIsAlert={setIsAlert}
setSkip={setSkip}
/>
{loading && (
<div style={{ textAlign: "center" }}>Loading...</div>
)}
</React.Suspense>
)}
</>
)}
@@ -755,4 +737,4 @@ function PdfFile() {
);
}
export default PdfFile;
export default Opensigndrive;
@@ -1,14 +1,16 @@
import React, { useState, useRef, useEffect } from "react";
import { themeColor } from "../utils/ThemeColor/backColor";
import { themeColor } from "../constant/const";
import { PDFDocument } from "pdf-lib";
import "../css/signature.css";
import "../styles/signature.css";
import axios from "axios";
import loader from "../assests/loader2.gif";
import loader from "../assets/images/loader2.gif";
import { DndProvider } from "react-dnd";
import { HTML5Backend } from "react-dnd-html5-backend";
import { useParams } from "react-router-dom";
import SignPad from "./component/signPad";
import RenderAllPdfPage from "./component/renderAllPdfPage";
import SignPad from "../components/pdf/SignPad";
import RenderAllPdfPage from "../components/pdf/RenderAllPdfPage";
import Tour from "reactour";
import moment from "moment";
import {
contractDocument,
multiSignEmbed,
@@ -18,17 +20,17 @@ import {
onImageSelect,
onSaveSign,
onSaveImage,
addDefaultSignatureImg
} from "../utils/Utils";
import Loader from "./component/loader";
import HandleError from "./component/HandleError";
import Nodata from "./component/Nodata";
import Header from "./component/header";
import RenderPdf from "./component/renderPdf";
import CustomModal from "./component/CustomModal";
import Title from "./component/Title";
import DefaultSignature from "./component/defaultSignature";
import ModalUi from "../premitives/ModalUi";
addDefaultSignatureImg,
radioButtonWidget
} from "../constant/Utils";
import Loader from "../primitives/LoaderWithMsg";
import HandleError from "../primitives/HandleError";
import Header from "../components/pdf/PdfHeader";
import RenderPdf from "../components/pdf/RenderPdf";
import PdfDeclineModal from "../primitives/PdfDeclineModal";
import Title from "../components/Title";
import DefaultSignature from "../components/pdf/DefaultSignature";
import ModalUi from "../primitives/ModalUi";
function PdfRequestFiles() {
const { docId } = useParams();
@@ -48,6 +50,7 @@ function PdfRequestFiles() {
const [imgWH, setImgWH] = useState({});
const imageRef = useRef(null);
const [handleError, setHandleError] = useState();
const [selectWidgetId, setSelectWidgetId] = useState("");
const [isLoading, setIsLoading] = useState({
isLoad: true,
message: "This might take some time"
@@ -57,12 +60,13 @@ function PdfRequestFiles() {
const [pdfNewWidth, setPdfNewWidth] = useState();
const [pdfOriginalWidth, setPdfOriginalWidth] = useState();
const [signerPos, setSignerPos] = useState([]);
const [noData, setNoData] = useState(false);
const [signerObjectId, setSignerObjectId] = useState();
const [isUiLoading, setIsUiLoading] = useState(false);
const [isDecline, setIsDecline] = useState({ isDeclined: false });
const [currentSigner, setCurrentSigner] = useState(false);
const [isAlert, setIsAlert] = useState({ isShow: false, alertMessage: "" });
const [unSignedWidgetId, setUnSignedWidgetId] = useState("");
const [expiredDate, setExpiredDate] = useState("");
const [defaultSignAlert, setDefaultSignAlert] = useState({
isShow: false,
alertMessage: ""
@@ -71,6 +75,8 @@ function PdfRequestFiles() {
isCertificate: false,
isModal: false
});
const [myInitial, setMyInitial] = useState("");
const [isInitial, setIsInitial] = useState(false);
const [pdfLoadFail, setPdfLoadFail] = useState({
status: false,
type: "load"
@@ -79,7 +85,11 @@ function PdfRequestFiles() {
const [isExpired, setIsExpired] = useState(false);
const [alreadySign, setAlreadySign] = useState(false);
const [containerWH, setContainerWH] = useState({});
const [validateAlert, setValidateAlert] = useState(false);
const [widgetsTour, setWidgetsTour] = useState(false);
const [minRequiredCount, setminRequiredCount] = useState();
const [sendInOrder, setSendInOrder] = useState(false);
const [currWidgetsDetails, setCurrWidgetsDetails] = useState({});
const divRef = useRef(null);
const isMobile = window.innerWidth < 767;
const rowLevel =
@@ -105,6 +115,7 @@ function PdfRequestFiles() {
if (documentId) {
getDocumentDetails();
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
useEffect(() => {
if (divRef.current) {
@@ -115,10 +126,12 @@ function PdfRequestFiles() {
height: divRef.current.offsetHeight
});
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [divRef.current]);
//function for get document details for perticular signer with signer'object id
const getDocumentDetails = async () => {
let currUserId;
//getting document details
const documentData = await contractDocument(documentId);
if (documentData && documentData.length > 0) {
@@ -135,9 +148,7 @@ function PdfRequestFiles() {
(data) => data.UserId.objectId === jsonSender.objectId
);
const currUserId = getCurrentSigner[0]
? getCurrentSigner[0].objectId
: "";
currUserId = getCurrentSigner[0] ? getCurrentSigner[0].objectId : "";
setSignerObjectId(currUserId);
if (documentData[0].SignedUrl) {
setPdfUrl(documentData[0].SignedUrl);
@@ -159,7 +170,11 @@ function PdfRequestFiles() {
};
setIsDecline(currentDecline);
} else if (currDate > expireUpdateDate) {
const expireDateFormat = moment(new Date(expireDate)).format(
"MMM DD, YYYY"
);
setIsExpired(true);
setExpiredDate(expireDateFormat);
}
if (documentData.length > 0) {
@@ -287,7 +302,7 @@ function PdfRequestFiles() {
setHandleError("Error: Something went wrong!");
setIsLoading(loadObj);
} else {
setNoData(true);
setHandleError("No Data Found!");
const loadObj = {
isLoad: false
};
@@ -315,7 +330,9 @@ function PdfRequestFiles() {
if (res[0] && res.length > 0) {
setDefaultSignImg(res[0].ImageURL);
setMyInitial(res[0]?.Initials);
}
const loadObj = {
isLoad: false
};
@@ -325,6 +342,7 @@ function PdfRequestFiles() {
const loadObj = {
isLoad: false
};
console.log("Err ", err);
setHandleError("Error: Something went wrong!");
setIsLoading(loadObj);
});
@@ -357,29 +375,135 @@ function PdfRequestFiles() {
}
};
//function for embed signature or image url in pdf
async function embedImages() {
async function embedWidgetsData() {
const validateSigning = checkSendInOrder();
if (validateSigning) {
const checkUser = signerPos.filter(
(data) => data.signerObjId === signerObjectId
);
if (checkUser && checkUser.length > 0) {
let checkSignUrl = [];
const checkSign = checkUser[0].placeHolder.filter(
(data, ind) => data.pos
);
for (let i = 0; i < checkSign.length; i++) {
const posData = checkSign[i].pos.filter((pos) => !pos.SignUrl);
if (posData && posData.length > 0) {
checkSignUrl.push(posData);
let checkboxExist,
requiredRadio,
showAlert = false,
widgetKey,
radioExist,
requiredCheckbox;
for (let i = 0; i < checkUser[0].placeHolder.length; i++) {
for (let j = 0; j < checkUser[0].placeHolder[i].pos.length; j++) {
checkboxExist =
checkUser[0].placeHolder[i].pos[j].type === "checkbox";
radioExist =
checkUser[0].placeHolder[i].pos[j].type === radioButtonWidget;
if (checkboxExist) {
requiredCheckbox = checkUser[0].placeHolder[i].pos.filter(
(position) =>
!position.options?.isReadOnly && position.type === "checkbox"
);
if (requiredCheckbox && requiredCheckbox.length > 0) {
for (let i = 0; i < requiredCheckbox.length; i++) {
const minCount =
requiredCheckbox[i].options?.validation?.minRequiredCount;
const parseMin = minCount && parseInt(minCount);
const maxCount =
requiredCheckbox[i].options?.validation?.maxRequiredCount;
const parseMax = maxCount && parseInt(maxCount);
const response =
requiredCheckbox[i].options?.response?.length;
const defaultValue =
requiredCheckbox[i].options?.defaultValue?.length;
if (parseMin === 0 && parseMax === 0) {
if (!showAlert) {
showAlert = false;
setminRequiredCount(null);
}
} else if (parseMin === 0 && parseMax > 0) {
if (!showAlert) {
showAlert = false;
setminRequiredCount(null);
}
} else if (!response) {
if (!defaultValue) {
if (!showAlert) {
showAlert = true;
widgetKey = requiredCheckbox[i].key;
setminRequiredCount(parseMin);
}
}
} else if (parseMin > 0 && parseMin > response) {
if (!showAlert) {
showAlert = true;
widgetKey = requiredCheckbox[i].key;
setminRequiredCount(parseMin);
}
}
}
}
} else if (radioExist) {
requiredRadio = checkUser[0].placeHolder[i].pos.filter(
(position) =>
!position.options?.isReadOnly &&
position.type === radioButtonWidget
);
if (requiredRadio && requiredRadio?.length > 0) {
let checkSigned;
for (let i = 0; i < requiredRadio?.length; i++) {
checkSigned = requiredRadio[i]?.options.response;
if (!checkSigned) {
let checkDefaultSigned =
requiredRadio[i]?.options.defaultValue;
if (!checkDefaultSigned) {
if (!showAlert) {
showAlert = true;
widgetKey = requiredRadio[i].key;
setminRequiredCount(null);
}
}
}
}
}
} else {
const requiredWidgets = checkUser[0].placeHolder[i].pos.filter(
(position) =>
position.options?.status === "required" &&
position.type !== radioButtonWidget &&
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;
widgetKey = requiredWidgets[i].key;
setminRequiredCount(null);
}
}
}
}
}
}
}
}
}
if (checkSignUrl && checkSignUrl.length > 0) {
setIsAlert({
isShow: true,
alertMessage: "Please complete your signature!"
});
if (checkboxExist && requiredCheckbox && showAlert) {
setUnSignedWidgetId(widgetKey);
setWidgetsTour(true);
} else if (radioExist && showAlert) {
setUnSignedWidgetId(widgetKey);
setWidgetsTour(true);
} else if (showAlert) {
setUnSignedWidgetId(widgetKey);
setWidgetsTour(true);
} else {
setIsUiLoading(true);
const pngUrl = checkUser[0].placeHolder;
@@ -390,97 +514,14 @@ function PdfRequestFiles() {
const pdfDoc = await PDFDocument.load(existingPdfBytes, {
ignoreEncryption: true
});
// let pdfBase64;
//checking if signature is only one then send image url in jpeg formate to server
// if (pngUrl.length === 1 && pngUrl[0].pos.length === 1) {
// if (isDocId) {
// try {
// pdfBase64 = await getBase64FromUrl(pdfUrl);
// } catch (err) {
// console.log(err);
// }
// } else {
// //embed document's object id to all pages in pdf document
// try {
// await embedDocId(pdfDoc, documentId, allPages);
// } catch (err) {
// console.log(err);
// }
// try {
// pdfBase64 = await pdfDoc.saveAsBase64({
// useObjectStreams: false
// });
// } catch (err) {
// console.log(err);
// }
// }
// for (let pngData of pngUrl) {
// const imgUrlList = pngData.pos;
// const pageNo = pngData.pageNumber;
// imgUrlList.map(async (data) => {
// //cheking signUrl is defau;t signature url of custom url
// let ImgUrl = data.SignUrl;
// const checkUrl = urlValidator(ImgUrl);
// //if default signature url then convert it in base 64
// if (checkUrl) {
// ImgUrl = await getBase64FromIMG(ImgUrl + "?get");
// }
// //function for called convert png signatre to jpeg in base 64
// convertPNGtoJPEG(ImgUrl)
// .then((jpegBase64Data) => {
// const removeBase64Fromjpeg = "data:image/jpeg;base64,";
// const newImgUrl = jpegBase64Data.replace(
// removeBase64Fromjpeg,
// ""
// );
// //function for call to embed signature in pdf and get digital signature pdf
// signPdfFun(
// newImgUrl,
// documentId,
// signerObjectId,
// pdfOriginalWidth,
// pngUrl,
// containerWH,
// setIsAlert,
// data,
// pdfBase64,
// pageNo
// )
// .then((res) => {
// if (res && res.status === "success") {
// setPdfUrl(res.data);
// setIsSigned(true);
// setSignedSigners([]);
// setUnSignedSigners([]);
// getDocumentDetails();
// } else {
// setIsAlert({
// isShow: true,
// alertMessage: "something went wrong"
// });
// }
// })
// .catch((err) => {
// setIsAlert({
// isShow: true,
// alertMessage: "something went wrong"
// });
// });
// })
// .catch((error) => {
// console.error("Error:", error);
// });
// });
// }
// }
// //else if signature is more than one then embed all sign with the use of pdf-lib
// else if (pngUrl.length > 0 && pngUrl[0].pos.length > 0) {
const flag = false;
const extUserPtr = pdfDetails[0].ExtUserPtr;
const HeaderDocId = extUserPtr?.HeaderDocId;
//embed document's object id to all pages in pdf document
if (!isDocId) {
await embedDocId(pdfDoc, documentId, allPages);
if (!HeaderDocId) {
if (!isDocId) {
await embedDocId(pdfDoc, documentId, allPages);
}
}
//embed multi signature in pdf
const pdfBytes = await multiSignEmbed(
@@ -490,15 +531,13 @@ function PdfRequestFiles() {
flag,
containerWH
);
//function for call to embed signature in pdf and get digital signature pdf
try {
const res = await signPdfFun(
pdfBytes,
documentId,
signerObjectId,
pdfOriginalWidth,
pngUrl,
containerWH,
setIsAlert
);
if (res && res.status === "success") {
@@ -514,7 +553,6 @@ function PdfRequestFiles() {
const newIndex = index + 1;
const user = pdfDetails?.[0].Signers[newIndex];
if (user) {
let sendMail;
// console.log("pdfDetails", pdfDetails);
const expireDate = pdfDetails?.[0].ExpiryDate.iso;
const newDate = new Date(expireDate);
@@ -543,16 +581,14 @@ function PdfRequestFiles() {
const serverParams = `${newServer}&${localStorage.getItem(
"parseAppId"
)}&${localStorage.getItem("_appName")}`;
const hostUrl =
window.location.origin + "/loadmf/signmicroapp";
const hostUrl = window.location.origin;
let signPdf = `${hostUrl}/login/${pdfDetails?.[0].objectId}/${user.Email}/${objectId}/${serverParams}`;
const openSignUrl =
"https://www.opensignlabs.com/contact-us";
const orgName = pdfDetails[0]?.ExtUserPtr.Company
? pdfDetails[0].ExtUserPtr.Company
: "";
const themeBGcolor = themeColor();
const themeBGcolor = themeColor;
let params = {
recipient: user.Email,
subject: `${pdfDetails?.[0].ExtUserPtr.Name} has requested you to sign ${pdfDetails?.[0].Name}`,
@@ -581,7 +617,7 @@ function PdfRequestFiles() {
openSignUrl +
" target=_blank>here</a>.</p> </div></div></body> </html>"
};
sendMail = await axios.post(url, params, {
await axios.post(url, params, {
headers: headers
});
} catch (error) {
@@ -602,9 +638,7 @@ function PdfRequestFiles() {
});
}
}
setIsSignPad(false);
// }
} else {
setIsAlert({
isShow: true,
@@ -619,6 +653,21 @@ function PdfRequestFiles() {
});
}
}
//function for update TourStatus
const closeTour = async () => {
setWidgetsTour(false);
};
const tourConfig = [
{
selector: '[data-tut="IsSigned"]',
content: minRequiredCount
? `Please confirm that you have selected at least ${minRequiredCount} checkboxes.`
: "Ensure this field is accurately filled and meets all requirements.",
position: "top",
style: { fontSize: "13px" }
}
];
//function for get pdf page details
const pageDetails = async (pdf) => {
@@ -688,9 +737,13 @@ function PdfRequestFiles() {
};
//function for save button to save signature or image url
const saveSign = (isDefaultSign, width, height) => {
const saveSign = (type, isDefaultSign, width, height) => {
const isTypeText = width && height ? true : false;
const signatureImg = isDefaultSign ? defaultSignImg : signature;
const signatureImg = isDefaultSign
? isDefaultSign === "initials"
? myInitial
: defaultSignImg
: signature;
let imgWH = { width: width ? width : "", height: height ? height : "" };
setIsSignPad(false);
setIsImageSelect(false);
@@ -720,6 +773,7 @@ function PdfRequestFiles() {
const placeholderPosition = currentSigner[0].placeHolder;
//function of save signature image and get updated position with signature image url
const getUpdatePosition = onSaveSign(
type,
placeholderPosition,
getIndex,
signKey,
@@ -729,7 +783,7 @@ function PdfRequestFiles() {
isTypeText
);
const updateSignerData = currentSigner.map((obj, ind) => {
const updateSignerData = currentSigner.map((obj) => {
if (obj.signerObjId === signerObjectId) {
return { ...obj, placeHolder: getUpdatePosition };
}
@@ -851,8 +905,6 @@ function PdfRequestFiles() {
<Loader isLoading={isLoading} />
) : handleError ? (
<HandleError handleError={handleError} />
) : noData ? (
<Nodata />
) : (
<div>
{isUiLoading && (
@@ -865,7 +917,7 @@ function PdfRequestFiles() {
justifyContent: "center",
flexDirection: "column",
alignItems: "center",
zIndex: "20",
zIndex: "999",
backgroundColor: "#e6f2f2",
opacity: 0.8
}}
@@ -881,7 +933,17 @@ function PdfRequestFiles() {
</div>
)}
<div className="signatureContainer" ref={divRef}>
<div
className="signatureContainer"
style={{
pointerEvents:
isExpired ||
(isDecline.isDeclined && isDecline.currnt === "another")
? "none"
: "auto"
}}
ref={divRef}
>
<ModalUi
headerColor={"#dc3545"}
isOpen={isAlert.isShow}
@@ -920,40 +982,45 @@ function PdfRequestFiles() {
</button>
</div>
</ModalUi>
<Tour
showNumber={false}
showNavigation={false}
showNavigationNumber={false}
onRequestClose={closeTour}
steps={tourConfig}
isOpen={widgetsTour}
rounded={5}
closeWithMask={false}
/>
{/* this modal is used to show decline alert */}
<CustomModal
<PdfDeclineModal
containerWH={containerWH}
show={isDecline.isDeclined}
headMsg="Document Declined"
bodyMssg={
isDecline.currnt === "Sure" ? (
<p className="pTagBody">
Are you sure want to decline this document ?
</p>
) : isDecline.currnt === "YouDeclined" ? (
<p className="pTagBody">You have declined this document!</p>
) : (
isDecline.currnt === "another" && (
<p className="pTagBody">
You cannot sign this document as it has been declined by
one or more person(s).
</p>
)
)
isDecline.currnt === "Sure"
? "Are you sure want to decline this document ?"
: isDecline.currnt === "YouDeclined"
? "You have declined this document!"
: isDecline.currnt === "another" &&
"You cannot sign this document as it has been declined by one or more recipient(s)."
}
footerMessage={isDecline.currnt === "Sure"}
declineDoc={declineDoc}
setIsDecline={setIsDecline}
/>
{/* this modal is used for show expired alert */}
<CustomModal
<PdfDeclineModal
containerWH={containerWH}
show={isExpired}
headMsg="Document Expired!"
bodyMssg="This Document is no longer available."
bodyMssg={`This document expired on ${expiredDate} and is no longer available to sign.`}
/>
<ModalUi
headerColor={defaultSignImg ? themeColor() : "#dc3545"}
headerColor={defaultSignImg ? themeColor : "#dc3545"}
isOpen={defaultSignAlert.isShow}
title={"Auto sign"}
handleClose={() => {
@@ -980,7 +1047,7 @@ function PdfRequestFiles() {
<button
onClick={() => addDefaultSignature()}
style={{
background: themeColor()
background: themeColor
}}
type="button"
className="finishBtn"
@@ -1079,6 +1146,12 @@ function PdfRequestFiles() {
onSaveImage={saveImage}
onSaveSign={saveSign}
defaultSign={defaultSignImg}
myInitial={myInitial}
isInitial={isInitial}
setIsInitial={setIsInitial}
setIsStamp={setIsStamp}
currWidgetsDetails={currWidgetsDetails}
setCurrWidgetsDetails={setCurrWidgetsDetails}
/>
{/* pdf header which contain funish back button */}
<Header
@@ -1090,7 +1163,7 @@ function PdfRequestFiles() {
signerPos={signerPos}
isSigned={isSigned}
isCompleted={isCompleted}
embedImages={embedImages}
embedWidgetsData={embedWidgetsData}
isShowHeader={true}
setIsDecline={setIsDecline}
decline={true}
@@ -1120,6 +1193,12 @@ function PdfRequestFiles() {
pdfLoadFail={pdfLoadFail}
setSignerPos={setSignerPos}
containerWH={containerWH}
setIsInitial={setIsInitial}
setValidateAlert={setValidateAlert}
unSignedWidgetId={unSignedWidgetId}
setSelectWidgetId={setSelectWidgetId}
selectWidgetId={selectWidgetId}
setCurrWidgetsDetails={setCurrWidgetsDetails}
/>
)}
</div>
@@ -1132,9 +1211,7 @@ function PdfRequestFiles() {
{signedSigners.length > 0 && (
<>
<div
style={{
background: themeColor()
}}
style={{ background: themeColor }}
className="signedStyle"
>
Signed by
@@ -1197,7 +1274,7 @@ function PdfRequestFiles() {
<>
<div
style={{
background: themeColor(),
background: themeColor,
color: "white",
padding: "5px",
fontFamily: "sans-serif",
@@ -1262,7 +1339,6 @@ function PdfRequestFiles() {
)}
{defaultSignImg && !alreadySign && (
<DefaultSignature
themeColor={themeColor}
defaultSignImg={defaultSignImg}
setDefaultSignImg={setDefaultSignImg}
userObjectId={signerObjectId}
@@ -1277,6 +1353,38 @@ function PdfRequestFiles() {
</div>
</div>
)}
<ModalUi
headerColor={"#dc3545"}
isOpen={validateAlert}
title={"Validation alert"}
handleClose={() => {
setValidateAlert(false);
}}
>
<div style={{ height: "100%", padding: 20 }}>
<p>
The input does not meet the criteria set by the regular expression.
</p>
<div
style={{
height: "1px",
backgroundColor: "#9f9f9f",
width: "100%",
marginTop: "15px",
marginBottom: "15px"
}}
></div>
<button
onClick={() => setValidateAlert(false)}
type="button"
className="finishBtn cancelBtn"
>
Close
</button>
</div>
</ModalUi>
</DndProvider>
);
}
@@ -2,20 +2,19 @@ import React, { useState, useEffect } from "react";
import "../styles/pgsignup.css";
import Parse from "parse";
import axios from "axios";
import { fetchAppInfo, showTenantName } from "../redux/actions/index";
import { connect } from "react-redux";
import { useDispatch } from "react-redux";
import Title from "../components/Title";
import { useNavigate, useLocation } from "react-router-dom";
import { appInfo } from "../constant/appinfo";
import { showTenant } from "../redux/reducers/ShowTenant";
import { fetchAppInfo } from "../redux/reducers/infoReducer";
const appId = localStorage.getItem("AppID12");
const server = localStorage.getItem("BaseUrl12");
Parse.serverURL = server;
Parse.initialize(appId);
const PgSignUp = (props) => {
const PgSignUp = () => {
const navigate = useNavigate();
const location = useLocation();
const [parseBaseUrl] = useState(localStorage.getItem("BaseUrl12"));
const [parseAppId] = useState(localStorage.getItem("AppID12"));
const dispatch = useDispatch();
const [parseBaseUrl] = useState(localStorage.getItem("baseUrl"));
const [parseAppId] = useState(localStorage.getItem("parseAppId"));
const [formData, setFormData] = useState({
password: "",
confirmPassword: ""
@@ -28,12 +27,7 @@ const PgSignUp = (props) => {
// below useEffect is used to fetch App data and save to redux state
useEffect(() => {
// Parse.User.logOut()
props.fetchAppInfo(
localStorage.getItem("domain"),
localStorage.getItem("BaseUrl12"),
localStorage.getItem("AppID12")
);
dispatch(fetchAppInfo());
handleSignedUpUser();
// eslint-disable-next-line
}, []);
@@ -224,8 +218,8 @@ const PgSignUp = (props) => {
};
const handleNavigation = async (sessionToken) => {
const baseUrl = localStorage.getItem("BaseUrl12");
const parseAppId = localStorage.getItem("AppID12");
const baseUrl = localStorage.getItem("baseUrl");
const parseAppId = localStorage.getItem("parseAppId");
const res = await axios.get(baseUrl + "users/me", {
headers: {
"X-Parse-Session-Token": sessionToken,
@@ -251,8 +245,8 @@ const PgSignUp = (props) => {
// Check extended class user role and tenentId
try {
let userRoles = [];
if (props.appInfo.settings) {
let userSettings = props.appInfo.settings;
if (appInfo.settings) {
let userSettings = appInfo.settings;
//Get Current user roles
let url = `${baseUrl}functions/UserGroups`;
@@ -299,8 +293,6 @@ const PgSignUp = (props) => {
"extended_class",
element.extended_class
);
localStorage.setItem("userpointer", element.userpointer);
const currentUser = Parse.User.current();
await Parse.Cloud.run("getUserDetails", {
email: currentUser.get("email")
@@ -329,8 +321,8 @@ const PgSignUp = (props) => {
}
});
if (tenentInfo.length) {
props.showTenantName(
tenentInfo[0].tenentName || ""
dispatch(
showTenant(tenentInfo[0].tenentName || "")
);
localStorage.setItem(
"TenantName",
@@ -368,8 +360,8 @@ const PgSignUp = (props) => {
}
});
if (tenentInfo.length) {
props.showTenantName(
tenentInfo[0].tenentName || ""
dispatch(
showTenant(tenentInfo[0].tenentName || "")
);
localStorage.setItem(
"TenantName",
@@ -407,11 +399,11 @@ const PgSignUp = (props) => {
localStorage.setItem("pageType", element.pageType);
setIsLoader(false);
const redirectUrl =
location?.state?.from ||
`/${element.pageType}/${element.pageId}`;
location?.state?.from ||
`/${element.pageType}/${element.pageId}`;
// Redirect to the appropriate URL after successful login
navigate(redirectUrl);
// Redirect to the appropriate URL after successful login
navigate(redirectUrl);
}
},
(error) => {
@@ -547,15 +539,4 @@ const PgSignUp = (props) => {
);
};
const mapStateToProps = (state) => {
if (Object.keys(state.appInfo).length !== 0) {
return { appInfo: state.appInfo, isloginVisible: true };
} else {
return { appInfo: state.appInfo, isloginVisible: false };
}
};
export default connect(mapStateToProps, {
fetchAppInfo,
showTenantName
})(PgSignUp);
export default PgSignUp;
@@ -12,6 +12,7 @@ const Report = () => {
const [List, setList] = useState([]);
const [isLoader, setIsLoader] = useState(true);
const [reportName, setReportName] = useState("");
const [reporthelp, setReportHelp] = useState("");
const [actions, setActions] = useState([]);
const [heading, setHeading] = useState([]);
const [isNextRecord, setIsNextRecord] = useState(false);
@@ -53,18 +54,17 @@ const Report = () => {
setHeading(json.heading);
setReportName(json.reportName);
setForm(json.form);
Parse.serverURL = localStorage.getItem("BaseUrl12");
Parse.initialize(localStorage.getItem("AppID12"));
setReportHelp(json?.helpMsg)
const currentUser = Parse.User.current().id;
const headers = {
"Content-Type": "application/json",
"X-Parse-Application-Id": localStorage.getItem("AppID12"),
"X-Parse-Application-Id": localStorage.getItem("parseAppId"),
sessiontoken: localStorage.getItem("accesstoken")
};
try {
const params = { reportId: id, skip: skipUserRecord, limit: limit };
const url = `${localStorage.getItem("BaseUrl12")}/functions/getReport`;
const url = `${localStorage.getItem("baseUrl")}/functions/getReport`;
const res = await axios.post(url, params, {
headers: headers,
signal: abortController.signal // is used to cancel fetch query
@@ -158,6 +158,7 @@ const Report = () => {
isMoreDocs={isMoreDocs}
docPerPage={docPerPage}
form={form}
report_help={reporthelp}
/>
) : (
<PageNotFound prefix={"Report"} />
@@ -1,28 +1,29 @@
import React, { useState, useEffect } from "react";
import { connect } from "react-redux";
import Parse from "parse";
import axios from "axios";
import Title from "../components/Title";
import { fetchAppInfo, showTenantName } from "../redux/actions";
import { useNavigate, NavLink } from "react-router-dom";
import login_img from "../assets/images/login_img.svg";
import { useWindowSize } from "../hook/useWindowSize";
const Signup = (props) => {
import Alert from "../primitives/Alert";
import { appInfo } from "../constant/appinfo";
import { useDispatch } from "react-redux";
import { fetchAppInfo } from "../redux/reducers/infoReducer";
import { showTenant } from "../redux/reducers/ShowTenant";
const Signup = () => {
const { width } = useWindowSize();
const navigate = useNavigate();
const dispatch = useDispatch();
const [name, setName] = useState("");
const [phone, setPhone] = useState("");
const [password, setPassword] = useState("");
const [email, setEmail] = useState("");
const [parseBaseUrl] = useState(localStorage.getItem("baseUrl"));
const [parseAppId] = useState(localStorage.getItem("parseAppId"));
const [company, setCompany] = useState("");
const [jobTitle, setJobTitle] = useState("");
const [state, setState] = useState({
loading: false,
toastColor: "#5cb85c",
toastDescription: ""
alertType: "success",
alertMsg: ""
});
const [showPassword, setShowPassword] = useState(false);
const [lengthValid, setLengthValid] = useState(false);
@@ -30,14 +31,14 @@ const Signup = (props) => {
const [specialCharValid, setSpecialCharValid] = useState(false);
const togglePasswordVisibility = () => setShowPassword(!showPassword);
const image = props.appInfo.applogo;
const image = appInfo.applogo;
const clearStorage = async () => {
if (Parse.User.current()) {
await Parse.User.logOut();
}
let baseUrl = localStorage.getItem("BaseUrl12");
let appid = localStorage.getItem("AppID12");
let baseUrl = localStorage.getItem("baseUrl");
let appid = localStorage.getItem("parseAppId");
let applogo = localStorage.getItem("appLogo");
let domain = localStorage.getItem("domain");
let appversion = localStorage.getItem("appVersion");
@@ -51,8 +52,8 @@ const Signup = (props) => {
localStorage.clear();
localStorage.setItem("BaseUrl12", baseUrl);
localStorage.setItem("AppID12", appid);
localStorage.setItem("baseUrl", baseUrl);
localStorage.setItem("parseAppId", appid);
localStorage.setItem("appLogo", applogo);
localStorage.setItem("domain", domain);
localStorage.setItem("appversion", appversion);
@@ -80,8 +81,6 @@ const Signup = (props) => {
};
localStorage.setItem("userDetails", JSON.stringify(userDetails));
try {
Parse.serverURL = parseBaseUrl;
Parse.initialize(parseAppId);
event.preventDefault();
var user = new Parse.User();
user.set("name", name);
@@ -93,7 +92,7 @@ const Signup = (props) => {
res
.then(async (r) => {
if (r) {
let roleData = props.appInfo.settings;
let roleData = appInfo.settings;
if (roleData && roleData.length > 0) {
const params = {
userDetails: {
@@ -102,7 +101,7 @@ const Signup = (props) => {
name: name,
email: email,
phone: phone,
role: props.appInfo.defaultRole
role: appInfo.defaultRole
}
};
try {
@@ -129,12 +128,8 @@ const Signup = (props) => {
alert("User already exists with this username!");
setState({ loading: false });
} else {
let baseUrl = localStorage.getItem("BaseUrl12");
let parseAppId = localStorage.getItem("AppID12");
// console.log("state.email ", email);
try {
Parse.serverURL = baseUrl;
Parse.initialize(parseAppId);
await Parse.User.requestPasswordReset(email).then(
async function (res1) {
if (res1.data === undefined) {
@@ -161,8 +156,8 @@ const Signup = (props) => {
};
const handleNavigation = async (sessionToken) => {
const baseUrl = localStorage.getItem("BaseUrl12");
const parseAppId = localStorage.getItem("AppID12");
const baseUrl = localStorage.getItem("baseUrl");
const parseAppId = localStorage.getItem("parseAppId");
const res = await axios.get(baseUrl + "users/me", {
headers: {
"X-Parse-Session-Token": sessionToken,
@@ -188,8 +183,8 @@ const Signup = (props) => {
// Check extended class user role and tenentId
try {
let userRoles = [];
if (props.appInfo.settings) {
let userSettings = props.appInfo.settings;
if (appInfo.settings) {
let userSettings = appInfo.settings;
//Get Current user roles
let url = `${baseUrl}functions/UserGroups`;
@@ -236,8 +231,6 @@ const Signup = (props) => {
"extended_class",
element.extended_class
);
localStorage.setItem("userpointer", element.userpointer);
await Parse.Cloud.run("getUserDetails", {
email: email
}).then(
@@ -265,8 +258,10 @@ const Signup = (props) => {
}
});
if (tenentInfo.length) {
props.showTenantName(
tenentInfo[0].tenentName || ""
dispatch(
showTenant(
tenentInfo[0].tenentName || ""
)
);
localStorage.setItem(
"TenantName",
@@ -309,8 +304,8 @@ const Signup = (props) => {
}
});
if (tenentInfo.length) {
props.showTenantName(
tenentInfo[0].tenentName || ""
dispatch(
showTenant(tenentInfo[0].tenentName || "")
);
localStorage.setItem(
"TenantName",
@@ -358,19 +353,18 @@ const Signup = (props) => {
}
},
(error) => {
/* alert(
"You dont have access to this application."
); */
setState({
loading: false,
toastColor: "#d9534f",
toastDescription:
"You dont have access to this application."
alertType: "danger",
alertMsg:
"You dont have access to this application!"
});
const x = document.getElementById("snackbar");
x.className = "show";
setTimeout(function () {
x.className = x.className.replace("show", "");
setState({
loading: false,
alertType: "danger",
alertMsg: ""
});
}, 2000);
localStorage.setItem("accesstoken", null);
console.error("Error while fetching Follow", error);
@@ -381,25 +375,29 @@ const Signup = (props) => {
} else {
setState({
loading: false,
toastColor: "#d9534f",
toastDescription: "User Role Not Found."
alertType: "danger",
alertMsg: "User Role Not Found!"
});
const x = document.getElementById("snackbar");
x.className = "show";
setTimeout(function () {
x.className = x.className.replace("show", "");
setState({
loading: false,
alertType: "danger",
alertMsg: ""
});
}, 2000);
}
} else {
setState({
loading: false,
toastColor: "#d9534f",
toastDescription: "User Role Not Found."
alertType: "danger",
alertMsg: "User Role Not Found!"
});
const x = document.getElementById("snackbar");
x.className = "show";
setTimeout(function () {
x.className = x.className.replace("show", "");
setState({
loading: false,
alertType: "danger",
alertMsg: ""
});
}, 2000);
}
})
@@ -407,13 +405,16 @@ const Signup = (props) => {
console.log("err", err);
setState({
loading: false,
toastColor: "#d9534f",
toastDescription: `Does not have permissions to access this application.`
alertType: "danger",
alertMsg:
"Does not have permissions to access this application!"
});
const x = document.getElementById("snackbar");
x.className = "show";
setTimeout(function () {
x.className = x.className.replace("show", "");
setState({
loading: false,
alertType: "danger",
alertMsg: ""
});
}, 2000);
});
}
@@ -421,24 +422,22 @@ const Signup = (props) => {
// alert(`${error.message}`);
setState({
loading: false,
toastColor: "#d9534f",
toastDescription: `${error.message}`
alertType: "danger",
alertMsg: `${error.message}`
});
const x = document.getElementById("snackbar");
x.className = "show";
setTimeout(function () {
x.className = x.className.replace("show", "");
setState({
loading: false,
alertType: "danger",
alertMsg: ""
});
}, 2000);
console.log(error);
}
}
};
useEffect(() => {
props.fetchAppInfo(
localStorage.getItem("domain"),
localStorage.getItem("BaseUrl12"),
localStorage.getItem("AppID12")
);
dispatch(fetchAppInfo());
// eslint-disable-next-line
}, []);
@@ -484,7 +483,7 @@ const Signup = (props) => {
<Title title={"Signup page"} />
{props.isloginVisible && props.isloginVisible ? (
{appInfo && appInfo.applogo ? (
<div>
<div className="md:m-10 lg:m-16 md:p-4 lg:p-10 p-5 bg-[#ffffff] md:border-[1px] md:border-gray-400 ">
<div className="w-[250px] h-[66px] inline-block">
@@ -644,10 +643,7 @@ const Signup = (props) => {
)}
</div>
</div>
<div id="snackbar" style={{ backgroundColor: state.toastColor }}>
{state.toastDescription}
</div>
<Alert type={state.alertType}>{state.alertMsg}</Alert>
</div>
) : (
<div
@@ -665,15 +661,4 @@ const Signup = (props) => {
);
};
const mapStateToProps = (state) => {
if (Object.keys(state.appInfo).length !== 0) {
return { appInfo: state.appInfo, isloginVisible: true };
} else {
return { appInfo: state.appInfo, isloginVisible: false };
}
};
export default connect(mapStateToProps, {
fetchAppInfo,
showTenantName
})(Signup);
export default Signup
File diff suppressed because it is too large Load Diff
@@ -1,39 +1,40 @@
import React, { useEffect, useState, useRef } from "react";
import RenderAllPdfPage from "./component/renderAllPdfPage";
import RenderAllPdfPage from "../components/pdf/RenderAllPdfPage";
import { useParams, useNavigate } from "react-router-dom";
import axios from "axios";
import "../css/./signature.css";
import sign from "../assests/sign3.png";
import stamp from "../assests/stamp2.png";
import { themeColor } from "../utils/ThemeColor/backColor";
import "../styles/signature.css";
import { themeColor } from "../constant/const";
import { DndProvider } from "react-dnd";
import { HTML5Backend } from "react-dnd-html5-backend";
import { useDrag, useDrop } from "react-dnd";
import FieldsComponent from "./component/fieldsComponent";
import WidgetComponent from "../components/pdf/WidgetComponent";
import Tour from "reactour";
import Loader from "./component/loader";
import HandleError from "./component/HandleError";
import Nodata from "./component/Nodata";
import SignerListPlace from "./component/signerListPlace";
import Header from "./component/header";
import Loader from "../primitives/LoaderWithMsg";
import HandleError from "../primitives/HandleError";
import SignerListPlace from "../components/pdf/SignerListPlace";
import Header from "../components/pdf/PdfHeader";
import WidgetNameModal from "../components/pdf/WidgetNameModal";
import {
pdfNewWidthFun,
contractUsers,
getHostUrl,
randomId,
addZIndex,
createDocument
} from "../utils/Utils";
import RenderPdf from "./component/renderPdf";
import "../css/AddUser.css";
import Title from "./component/Title";
import LinkUserModal from "./component/LinkUserModal";
import EditTemplate from "./component/EditTemplate";
import ModalUi from "../premitives/ModalUi";
import AddRoleModal from "./component/AddRoleModal";
import PlaceholderCopy from "./component/PlaceholderCopy";
import ModalComponent from "./component/modalComponent";
import TourContentWithBtn from "../premitives/TourContentWithBtn";
createDocument,
defaultWidthHeight,
addWidgetOptions,
textInputWidget,
radioButtonWidget
} from "../constant/Utils";
import RenderPdf from "../components/pdf/RenderPdf";
import "../styles/AddUser.css";
import Title from "../components/Title";
import LinkUserModal from "../primitives/LinkUserModal";
import EditTemplate from "../components/pdf/EditTemplate";
import ModalUi from "../primitives/ModalUi";
import AddRoleModal from "../components/pdf/AddRoleModal";
import PlaceholderCopy from "../components/pdf/PlaceholderCopy";
import TourContentWithBtn from "../primitives/TourContentWithBtn";
import DropdownWidgetOption from "../components/pdf/DropdownWidgetOption";
const TemplatePlaceholder = () => {
const navigate = useNavigate();
const { templateId } = useParams();
@@ -62,7 +63,6 @@ const TemplatePlaceholder = () => {
const [checkTourStatus, setCheckTourStatus] = useState(false);
const [tourStatus, setTourStatus] = useState([]);
const [signerUserId, setSignerUserId] = useState();
const [noData, setNoData] = useState(false);
const [pdfOriginalWidth, setPdfOriginalWidth] = useState();
const [contractName, setContractName] = useState("");
const [containerWH, setContainerWH] = useState();
@@ -74,6 +74,12 @@ const TemplatePlaceholder = () => {
const [isResize, setIsResize] = useState(false);
const [isSigners, setIsSigners] = useState(false);
const [zIndex, setZIndex] = useState(1);
const [showDropdown, setShowDropdown] = useState(false);
const [widgetType, setWidgetType] = useState("");
const [isRadio, setIsRadio] = useState(false);
const [blockColor, setBlockColor] = useState("");
const [selectWidgetId, setSelectWidgetId] = useState("");
const [isNameModal, setIsNameModal] = useState(false);
const [pdfLoadFail, setPdfLoadFail] = useState({
status: false,
type: "load"
@@ -93,7 +99,7 @@ const TemplatePlaceholder = () => {
"#ffffcc"
];
const isMobile = window.innerWidth < 767;
const [{ isOver }, drop] = useDrop({
const [, drop] = useDrop({
accept: "BOX",
drop: (item, monitor) => addPositionOfSignature(item, monitor),
collect: (monitor) => ({
@@ -105,7 +111,7 @@ const TemplatePlaceholder = () => {
item: {
type: "BOX",
id: 1,
text: "drag me"
text: "signature"
},
collect: (monitor) => ({
isDragSign: !!monitor.isDragging()
@@ -117,37 +123,12 @@ const TemplatePlaceholder = () => {
item: {
type: "BOX",
id: 2,
text: "drag me"
text: "stamp"
},
collect: (monitor) => ({
isDragStamp: !!monitor.isDragging()
})
});
const [{ isDragSignatureSS }, dragSignatureSS] = useDrag({
type: "BOX",
item: {
type: "BOX",
id: 3,
text: "drag me"
},
collect: (monitor) => ({
isDragSignatureSS: !!monitor.isDragging()
})
});
const [{ isDragStampSS }, dragStampSS] = useDrag({
type: "BOX",
item: {
type: "BOX",
id: 4,
text: "drag me"
},
collect: (monitor) => ({
isDragStampSS: !!monitor.isDragging()
})
});
const [uniqueId, setUniqueId] = useState("");
const [isModalRole, setIsModalRole] = useState(false);
const [roleName, setRoleName] = useState("");
@@ -159,6 +140,9 @@ const TemplatePlaceholder = () => {
const [IsReceipent, setIsReceipent] = useState(true);
const [isDontShow, setIsDontShow] = useState(false);
const [isDragging, setIsDragging] = useState(false);
const [currWidgetsDetails, setCurrWidgetsDetails] = useState([]);
const [isCheckbox, setIsCheckbox] = useState(false);
const [widgetName, setWidgetName] = useState(false);
const senderUser =
localStorage.getItem(
`Parse/${localStorage.getItem("parseAppId")}/currentUser`
@@ -170,7 +154,7 @@ const TemplatePlaceholder = () => {
useEffect(() => {
fetchTemplate();
// eslint-disable-next-line
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
useEffect(() => {
@@ -182,6 +166,7 @@ const TemplatePlaceholder = () => {
height: divRef.current.offsetHeight
});
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [divRef.current]);
// `fetchTemplate` function in used to get Template from server and setPlaceholder ,setSigner if present
@@ -239,6 +224,7 @@ const TemplatePlaceholder = () => {
});
setSignersData(updatedSigners);
setUniqueId(updatedSigners[0].Id);
setBlockColor(updatedSigners[0].blockColor);
} else {
const updatedSigners = documentData[0].Signers.map((x, index) => ({
...x,
@@ -247,6 +233,7 @@ const TemplatePlaceholder = () => {
}));
setSignersData(updatedSigners);
setUniqueId(updatedSigners[0].Id);
setBlockColor(updatedSigners[0].blockColor);
}
} else {
setRoleName("User 1");
@@ -265,6 +252,7 @@ const TemplatePlaceholder = () => {
setUniqueId(updatedSigners[0].Id);
setSignersData(updatedSigners);
setIsSelectId(0);
setBlockColor(updatedSigners[0].blockColor);
}
}
} else if (
@@ -277,8 +265,7 @@ const TemplatePlaceholder = () => {
setHandleError("Error: Something went wrong!");
setIsLoading(loadObj);
} else {
setNoData(true);
setHandleError("No Data Found!");
const loadObj = {
isLoad: false
};
@@ -317,8 +304,7 @@ const TemplatePlaceholder = () => {
setHandleError("Error: Something went wrong!");
setIsLoading(loadObj);
} else if (res.length === 0) {
setNoData(true);
setHandleError("No Data Found!");
const loadObj = {
isLoad: false
};
@@ -328,6 +314,9 @@ const TemplatePlaceholder = () => {
//function for setting position after drop signature button over pdf
const addPositionOfSignature = (item, monitor) => {
if (item && item.text) {
setWidgetName(item.text);
}
getSignerPos(item, monitor);
};
@@ -345,26 +334,29 @@ const TemplatePlaceholder = () => {
// (data) => data.signerObjId === signerObjId
// );
let filterSignerPos = signerPos.filter((data) => data.Id === uniqueId);
const dragTypeValue = item?.text ? item.text : monitor.type;
let dropData = [];
let placeHolder;
if (item === "onclick") {
const dropObj = {
xPosition: window.innerWidth / 2 - 100,
//onclick put placeholder center on pdf
xPosition: window.innerWidth / 2 - 150,
yPosition: window.innerHeight / 2 - 60,
isStamp: monitor,
isStamp:
(dragTypeValue === "stamp" || dragTypeValue === "image") && true,
key: key,
isDrag: false,
scale: scale,
isMobile: isMobile,
yBottom: window.innerHeight / 2 - 60,
zIndex: posZIndex
zIndex: posZIndex,
type: dragTypeValue,
options: addWidgetOptions(dragTypeValue)
};
dropData.push(dropObj);
placeHolder = {
pageNumber: pageNumber,
pos: dropData
};
} else if (item.type === "BOX") {
} else {
const offset = monitor.getClientOffset();
//adding and updating drop position in array when user drop signature button in div
const containerRect = document
@@ -372,20 +364,17 @@ const TemplatePlaceholder = () => {
.getBoundingClientRect();
const x = offset.x - containerRect.left;
const y = offset.y - containerRect.top;
const ybottom = containerRect.bottom - offset.y;
const dropObj = {
xPosition: signBtnPosition[0] ? x - signBtnPosition[0].xPos : x,
yPosition: signBtnPosition[0] ? y - signBtnPosition[0].yPos : y,
isStamp: isDragStamp || isDragStampSS ? true : false,
isStamp:
(dragTypeValue === "stamp" || dragTypeValue === "image") && true,
key: key,
isDrag: false,
firstXPos: signBtnPosition[0] && signBtnPosition[0].xPos,
firstYPos: signBtnPosition[0] && signBtnPosition[0].yPos,
yBottom: ybottom,
scale: scale,
isMobile: isMobile,
zIndex: posZIndex
zIndex: posZIndex,
type: item.text,
options: addWidgetOptions(dragTypeValue)
};
dropData.push(dropObj);
@@ -454,12 +443,26 @@ const TemplatePlaceholder = () => {
}
setSignerPos((prev) => [...prev, placeHolderPos]);
}
if (dragTypeValue === "dropdown") {
setShowDropdown(true);
} else if (dragTypeValue === "checkbox") {
setIsCheckbox(true);
} else if (dragTypeValue === radioButtonWidget) {
setIsRadio(true);
}
setCurrWidgetsDetails({});
setWidgetType(dragTypeValue);
setSignKey(key);
setSelectWidgetId(key);
setIsMailSend(false);
} else {
setIsReceipent(false);
}
}
};
//function for get pdf page details
const pageDetails = async (pdf) => {
const load = {
@@ -507,7 +510,7 @@ const TemplatePlaceholder = () => {
const getXYdata = getPageNumer[0].pos;
const getPosData = getXYdata;
const addSignPos = getPosData.map((url, ind) => {
const addSignPos = getPosData.map((url) => {
if (url.key === keyValue) {
return {
...url,
@@ -520,13 +523,13 @@ const TemplatePlaceholder = () => {
return url;
});
const newUpdateSignPos = getPlaceHolder.map((obj, ind) => {
const newUpdateSignPos = getPlaceHolder.map((obj) => {
if (obj.pageNumber === pageNumber) {
return { ...obj, pos: addSignPos };
}
return obj;
});
const newUpdateSigner = updateSignPos.map((obj, ind) => {
const newUpdateSigner = updateSignPos.map((obj) => {
if (obj.Id === signId) {
return { ...obj, placeHolder: newUpdateSignPos };
}
@@ -562,19 +565,19 @@ const TemplatePlaceholder = () => {
if (getPageNumer.length > 0) {
const getXYdata = getPageNumer[0].pos.filter(
(data, ind) => data.key !== key
(data) => data.key !== key
);
if (getXYdata.length > 0) {
updateData.push(getXYdata);
const newUpdatePos = getPlaceHolder.map((obj, ind) => {
const newUpdatePos = getPlaceHolder.map((obj) => {
if (obj.pageNumber === pageNumber) {
return { ...obj, pos: updateData[0] };
}
return obj;
});
const newUpdateSigner = signerPos.map((obj, ind) => {
const newUpdateSigner = signerPos.map((obj) => {
if (obj.Id === Id) {
return { ...obj, placeHolder: newUpdatePos };
}
@@ -589,7 +592,7 @@ const TemplatePlaceholder = () => {
);
if (getRemainPage && getRemainPage.length > 0) {
const newUpdatePos = filterSignerPos.map((obj, ind) => {
const newUpdatePos = filterSignerPos.map((obj) => {
if (obj.Id === Id) {
return { ...obj, placeHolder: getRemainPage };
}
@@ -629,7 +632,7 @@ const TemplatePlaceholder = () => {
};
//function for capture position of x and y on hover signature button last position
const handleMouseLeave = (e) => {
const handleMouseLeave = () => {
setSignBtnPosition([xySignature]);
};
@@ -664,7 +667,6 @@ const TemplatePlaceholder = () => {
try {
const data = {
Placeholders: signerPos,
SignedUrl: pdfDetails[0].URL,
Signers: signers,
Name: pdfDetails[0]?.Name || "",
Note: pdfDetails[0]?.Note || "",
@@ -686,7 +688,7 @@ const TemplatePlaceholder = () => {
}
}
)
.then((result) => {
.then(() => {
setIsCreateDocModal(true);
setIsMailSend(true);
const loadObj = {
@@ -727,7 +729,7 @@ const TemplatePlaceholder = () => {
selector: '[data-tut="reactourFirst"]',
content: () => (
<TourContentWithBtn
message={`Select a role from this list to add a place-holder where he is supposed to sign.The placeholder will appear in the same colour as the recipient name once you drop it on the document.`}
message={`Once roles are added, select a role from list to add a place-holder where he is supposed to sign. The placeholder will appear in the same colour as the role name once you drop it on the document.`}
isChecked={handleDontShow}
/>
),
@@ -739,7 +741,7 @@ const TemplatePlaceholder = () => {
selector: '[data-tut="reactourSecond"]',
content: () => (
<TourContentWithBtn
message={`Drag the signature or stamp placeholder onto the PDF to choose your desired signing location.`}
message={`Drag a widget placeholder onto the PDF to choose your desired signing location.`}
isChecked={handleDontShow}
/>
),
@@ -761,7 +763,7 @@ const TemplatePlaceholder = () => {
selector: '[data-tut="reactourFour"]',
content: () => (
<TourContentWithBtn
message={`Clicking "Save" button will save the template and will ask you for creating new document.`}
message={`Clicking "Save" button will save the template and will ask you if you want to create a new document using this template.`}
isChecked={handleDontShow}
/>
),
@@ -805,7 +807,7 @@ const TemplatePlaceholder = () => {
}
}
)
.then((Listdata) => {
.then(() => {
// const json = Listdata.data;
// const res = json.results;
})
@@ -819,11 +821,10 @@ const TemplatePlaceholder = () => {
const handleCreateDocModal = async () => {
setIsCreateDocModal(false);
setIsCreateDoc(true);
const hostUrl = getHostUrl();
// handle create document
const res = await createDocument(pdfDetails, signerPos, signersdata);
if (res.status === "success") {
navigate(`${hostUrl}placeHolderSign/${res.id}`, {
navigate(`/placeHolderSign/${res.id}`, {
state: { title: "Use Template" }
});
setIsCreateDoc(false);
@@ -857,6 +858,7 @@ const TemplatePlaceholder = () => {
setIsModalRole(false);
setRoleName("");
setUniqueId(Id);
setBlockColor(color[index]);
setIsSelectId(index);
setIsMailSend(false);
};
@@ -873,9 +875,11 @@ const TemplatePlaceholder = () => {
if (index === signersdata.length - 1) {
setUniqueId(updateSigner[updateSigner.length - 1]?.Id || "");
setIsSelectId(index - 1 || 0);
setBlockColor(color[index - 1 || 0]);
} else {
setUniqueId(updateSigner[index]?.Id || "");
setIsSelectId(index);
setBlockColor(color[index]);
}
setSignerPos(updatePlaceholderUser);
@@ -964,6 +968,211 @@ const TemplatePlaceholder = () => {
setIsModalRole(false);
};
const handleSaveWidgetsOptions = (
dropdownName,
dropdownOptions,
minCount,
maxCount,
isReadOnly,
addOption,
deleteOption,
status,
defaultValue,
isHideLabel
) => {
const filterSignerPos = signerPos.filter((data) => data.Id === uniqueId);
if (filterSignerPos.length > 0) {
const getPlaceHolder = filterSignerPos[0].placeHolder;
const getPageNumer = getPlaceHolder.filter(
(data) => data.pageNumber === pageNumber
);
if (getPageNumer.length > 0) {
const getXYdata = getPageNumer[0].pos;
const getPosData = getXYdata;
const addSignPos = getPosData.map((position) => {
if (position.key === signKey) {
if (widgetType === radioButtonWidget) {
if (addOption) {
return {
...position,
Height: position.Height
? position.Height + 15
: defaultWidthHeight(widgetType).height + 15
};
} else if (deleteOption) {
return {
...position,
Height: position.Height
? position.Height - 15
: defaultWidthHeight(widgetType).height - 15
};
} else {
return {
...position,
options: {
...position.options,
name: dropdownName,
values: dropdownOptions,
status: status,
defaultValue: defaultValue,
isReadOnly: isReadOnly || false,
isHideLabel: isHideLabel || false
}
};
}
} else if (widgetType === "checkbox") {
if (addOption) {
return {
...position,
Height: position.Height
? position.Height + 15
: defaultWidthHeight(widgetType).height + 15
};
} else if (deleteOption) {
return {
...position,
Height: position.Height
? position.Height - 15
: defaultWidthHeight(widgetType).height - 15
};
} else {
return {
...position,
options: {
...position.options,
name: dropdownName,
values: dropdownOptions,
validation: {
minRequiredCount: minCount,
maxRequiredCount: maxCount
},
isReadOnly: isReadOnly || false,
defaultValue: defaultValue,
isHideLabel: isHideLabel || false
}
};
}
} else {
return {
...position,
options: {
...position.options,
name: dropdownName,
status: status,
values: dropdownOptions,
defaultValue: defaultValue
}
};
}
}
return position;
});
const newUpdateSignPos = getPlaceHolder.map((obj) => {
if (obj.pageNumber === pageNumber) {
return { ...obj, pos: addSignPos };
}
return obj;
});
const newUpdateSigner = signerPos.map((obj) => {
if (obj.Id === uniqueId) {
return { ...obj, placeHolder: newUpdateSignPos };
}
return obj;
});
setSignerPos(newUpdateSigner);
if (!addOption && !deleteOption) {
handleNameModal();
}
}
}
};
const handleWidgetdefaultdata = (defaultdata) => {
const options = ["email", "number", "text"];
let inputype;
if (defaultdata.textvalidate) {
inputype = options.includes(defaultdata.textvalidate)
? defaultdata.textvalidate
: "regex";
} else {
inputype = "text";
}
const filterSignerPos = signerPos.filter((data) => data.Id === uniqueId);
if (filterSignerPos.length > 0) {
const getPlaceHolder = filterSignerPos[0].placeHolder;
const getPageNumer = getPlaceHolder.filter(
(data) => data.pageNumber === pageNumber
);
if (getPageNumer.length > 0) {
const getXYdata = getPageNumer[0].pos;
const getPosData = getXYdata;
const addSignPos = getPosData.map((position) => {
if (position.key === signKey) {
if (position.type === textInputWidget) {
return {
...position,
options: {
...position.options,
name: defaultdata?.name || "text",
status: defaultdata?.status || "required",
hint: defaultdata?.hint || "",
defaultValue: defaultdata?.defaultValue || "",
validation: {
type: inputype,
pattern:
inputype === "regex" ? defaultdata.textvalidate : ""
}
}
};
} else {
return {
...position,
options: {
...position.options,
name: defaultdata.name,
status: defaultdata.status,
defaultValue: defaultdata.defaultValue
}
};
}
}
return position;
});
const newUpdateSignPos = getPlaceHolder.map((obj) => {
if (obj.pageNumber === pageNumber) {
return { ...obj, pos: addSignPos };
}
return obj;
});
const newUpdateSigner = signerPos.map((obj) => {
if (obj.Id === uniqueId) {
return { ...obj, placeHolder: newUpdateSignPos };
}
return obj;
});
setSignerPos(newUpdateSigner);
}
}
setCurrWidgetsDetails({});
handleNameModal();
};
const handleNameModal = () => {
setIsNameModal(false);
setCurrWidgetsDetails({});
setShowDropdown(false);
setIsRadio(false);
setIsCheckbox(false);
};
return (
<div>
<Title title={"Template"} />
@@ -972,8 +1181,6 @@ const TemplatePlaceholder = () => {
<Loader isLoading={isLoading} />
) : handleError ? (
<HandleError handleError={handleError} />
) : noData ? (
<Nodata />
) : (
<div className="signatureContainer" ref={divRef}>
{/* this component used for UI interaction and show their functionality */}
@@ -1055,7 +1262,7 @@ const TemplatePlaceholder = () => {
handleCreateDocModal();
}}
style={{
background: themeColor(),
background: themeColor,
color: "white"
}}
type="button"
@@ -1077,10 +1284,65 @@ const TemplatePlaceholder = () => {
</div>
</ModalUi>
{isCreateDoc && <Loader isLoading={isLoading} />}
<ModalComponent
isShow={isShowEmail}
type={"signersAlert"}
setIsShowEmail={setIsShowEmail}
<ModalUi
headerColor={"#dc3545"}
isOpen={isShowEmail}
title={"signers alert"}
handleClose={() => {
setIsShowEmail(false);
}}
>
<div style={{ height: "100%", padding: 20 }}>
<p>Please select signer for add placeholder!</p>
<div
style={{
height: "1px",
backgroundColor: "#9f9f9f",
width: "100%",
marginTop: "15px",
marginBottom: "15px"
}}
></div>
<button
onClick={() => {
setIsShowEmail(false);
}}
type="button"
className="finishBtn cancelBtn"
>
Ok
</button>
</div>
</ModalUi>
<DropdownWidgetOption
type={radioButtonWidget}
title="Radio group"
showDropdown={isRadio}
setShowDropdown={setIsRadio}
handleSaveWidgetsOptions={handleSaveWidgetsOptions}
currWidgetsDetails={currWidgetsDetails}
setCurrWidgetsDetails={setCurrWidgetsDetails}
handleClose={handleNameModal}
/>
<DropdownWidgetOption
type="checkbox"
title="Checkbox"
showDropdown={isCheckbox}
setShowDropdown={setIsCheckbox}
handleSaveWidgetsOptions={handleSaveWidgetsOptions}
currWidgetsDetails={currWidgetsDetails}
setCurrWidgetsDetails={setCurrWidgetsDetails}
handleClose={handleNameModal}
/>
<DropdownWidgetOption
type="dropdown"
title="Dropdown options"
showDropdown={showDropdown}
setShowDropdown={setShowDropdown}
handleSaveWidgetsOptions={handleSaveWidgetsOptions}
currWidgetsDetails={currWidgetsDetails}
setCurrWidgetsDetails={setCurrWidgetsDetails}
handleClose={handleNameModal}
/>
<PlaceholderCopy
isPageCopy={isPageCopy}
@@ -1139,6 +1401,14 @@ const TemplatePlaceholder = () => {
setSignKey={setSignKey}
setSignerObjId={setSignerObjId}
isDragging={isDragging}
setShowDropdown={setShowDropdown}
setCurrWidgetsDetails={setCurrWidgetsDetails}
setWidgetType={setWidgetType}
setIsRadio={setIsRadio}
setSelectWidgetId={setSelectWidgetId}
selectWidgetId={selectWidgetId}
setIsCheckbox={setIsCheckbox}
handleNameModal={setIsNameModal}
/>
)}
</div>
@@ -1146,25 +1416,19 @@ const TemplatePlaceholder = () => {
{/* signature button */}
{isMobile ? (
<div>
<FieldsComponent
<WidgetComponent
dataTut="reactourFirst"
dataTut2="reactourSecond"
pdfUrl={isMailSend}
sign={sign}
stamp={stamp}
dragSignature={dragSignature}
signRef={signRef}
handleDivClick={handleDivClick}
handleMouseLeave={handleMouseLeave}
isDragSign={isDragSign}
themeColor={themeColor}
dragStamp={dragStamp}
dragRef={dragRef}
isDragStamp={isDragStamp}
isSignYourself={true}
isDragSignatureSS={isDragSignatureSS}
dragSignatureSS={dragSignatureSS}
dragStampSS={dragStampSS}
isSignYourself={false}
addPositionOfSignature={addPositionOfSignature}
signerPos={signerPos}
signersdata={signersdata}
@@ -1184,44 +1448,59 @@ const TemplatePlaceholder = () => {
handleRoleChange={handleRoleChange}
handleOnBlur={handleOnBlur}
title={"Roles"}
initial={true}
isTemplateFlow={true}
sendInOrder={pdfDetails[0].SendinOrder}
setSignersData={setSignersData}
blockColor={blockColor}
setBlockColor={setBlockColor}
/>
</div>
) : (
<div>
<div className="signerComponent">
<SignerListPlace
signerPos={signerPos}
signersdata={signersdata}
isSelectListId={isSelectListId}
setSignerObjId={setSignerObjId}
setRoleName={setRoleName}
setIsSelectId={setIsSelectId}
setContractName={setContractName}
handleAddSigner={handleAddSigner}
setUniqueId={setUniqueId}
handleDeleteUser={handleDeleteUser}
handleRoleChange={handleRoleChange}
handleOnBlur={handleOnBlur}
title={"Roles"}
/>
<div data-tut="reactourSecond">
<FieldsComponent
pdfUrl={isMailSend}
sign={sign}
stamp={stamp}
dragSignature={dragSignature}
signRef={signRef}
handleDivClick={handleDivClick}
handleMouseLeave={handleMouseLeave}
isDragSign={isDragSign}
themeColor={themeColor}
dragStamp={dragStamp}
dragRef={dragRef}
isDragStamp={isDragStamp}
isSignYourself={false}
addPositionOfSignature={addPositionOfSignature}
<div
style={{ maxHeight: window.innerHeight - 70 + "px" }}
className="autoSignScroll"
>
<SignerListPlace
isMailSend={isMailSend}
signerPos={signerPos}
signersdata={signersdata}
isSelectListId={isSelectListId}
setSignerObjId={setSignerObjId}
setRoleName={setRoleName}
setIsSelectId={setIsSelectId}
setContractName={setContractName}
handleAddSigner={handleAddSigner}
setUniqueId={setUniqueId}
handleDeleteUser={handleDeleteUser}
handleRoleChange={handleRoleChange}
handleOnBlur={handleOnBlur}
title={"Roles"}
sendInOrder={pdfDetails[0]?.SendinOrder}
setSignersData={setSignersData}
blockColor={blockColor}
setBlockColor={setBlockColor}
/>
<div data-tut="reactourSecond">
<WidgetComponent
isMailSend={isMailSend}
dragSignature={dragSignature}
signRef={signRef}
handleDivClick={handleDivClick}
handleMouseLeave={handleMouseLeave}
isDragSign={isDragSign}
dragStamp={dragStamp}
dragRef={dragRef}
isDragStamp={isDragStamp}
isSignYourself={false}
addPositionOfSignature={addPositionOfSignature}
title={"Roles"}
initial={true}
isTemplateFlow={true}
/>
</div>
</div>
</div>
</div>
@@ -1257,6 +1536,13 @@ const TemplatePlaceholder = () => {
onSuccess={handleEditTemplateForm}
/>
</ModalUi>
<WidgetNameModal
widgetName={widgetName}
defaultdata={currWidgetsDetails}
isOpen={isNameModal}
handleClose={handleNameModal}
handleData={handleWidgetdefaultdata}
/>
</div>
);
};
@@ -1,4 +1,4 @@
import React, { useState } from "react";
import React, { useState, useEffect } from "react";
import { Navigate, useNavigate } from "react-router-dom";
import Parse from "parse";
import { SaveFileSize } from "../constant/saveFileSize";
@@ -6,6 +6,9 @@ import dp from "../assets/images/dp.png";
import Title from "../components/Title";
import sanitizeFileName from "../primitives/sanitizeFileName";
import axios from "axios";
import PremiumAlertHeader from "../primitives/PremiumAlertHeader";
import Tooltip from "../primitives/Tooltip";
function UserProfile() {
const navigate = useNavigate();
let UserProfile = JSON.parse(localStorage.getItem("UserInformation"));
@@ -17,9 +20,16 @@ function UserProfile() {
const [Image, setImage] = useState(localStorage.getItem("profileImg"));
const [isLoader, setIsLoader] = useState(false);
const [percentage, setpercentage] = useState(0);
const [isDisableDocId, setIsDisableDocId] = useState(false);
Parse.serverURL = parseBaseUrl;
Parse.initialize(parseAppId);
useEffect(() => {
const extClass = localStorage.getItem("Extand_Class");
const jsonSender = JSON.parse(extClass);
const HeaderDocId = jsonSender[0]?.HeaderDocId;
if (HeaderDocId) {
setIsDisableDocId(HeaderDocId);
}
}, []);
const handleSubmit = async (e) => {
e.preventDefault();
setIsLoader(true);
@@ -33,6 +43,7 @@ function UserProfile() {
object.set("name", name);
object.set("ProfilePic", Image);
object.set("phone", phn);
object.save().then(
async (response) => {
if (response) {
@@ -66,8 +77,12 @@ function UserProfile() {
const extClass = localStorage.getItem("extended_class");
const extData = JSON.parse(localStorage.getItem("Extand_Class"));
const ExtUserId = extData[0].objectId;
// console.log("UserId ", ExtUserId);
const body = { Phone: obj.Phone, Name: obj.Name };
const body = {
Phone: obj.Phone,
Name: obj.Name,
HeaderDocId: isDisableDocId
};
await axios.put(
parseBaseUrl + "classes/" + extClass + "/" + ExtUserId,
body,
@@ -137,6 +152,10 @@ function UserProfile() {
return <Navigate to={_redirect} />;
}
const handleDisableDocId = () => {
setIsDisableDocId((prevChecked) => !prevChecked);
};
return (
<React.Fragment>
<Title title={"Profile"} />
@@ -233,7 +252,7 @@ function UserProfile() {
<span className="font-semibold">Email:</span>{" "}
<span>{UserProfile && UserProfile.email}</span>
</li>
<li className="flex justify-between items-center border-y-[1px] border-gray-300 py-2 break-all">
<li className="flex justify-between items-center border-t-[1px] border-gray-300 py-2 break-all">
<span className="font-semibold">Is Email verified:</span>{" "}
<span>
{UserProfile && UserProfile.emailVerified
@@ -241,6 +260,34 @@ function UserProfile() {
: "Not verified"}
</span>
</li>
<li className="border-y-[1px] border-gray-300 break-all">
<div className="flex justify-between items-center py-2">
<span className="font-semibold">
Disable DocumentId :{" "}
<Tooltip url={"https://docs.opensignlabs.com/docs/help/Settings/disabledocumentid"} />{" "}
</span>{" "}
<label
className={`${
editmode ? "cursor-pointer" : ""
} relative inline-flex items-center mb-0`}
>
<input
disabled={editmode ? false : true}
checked={isDisableDocId}
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>
</div>
<PremiumAlertHeader
message={
"Disable documentId is free in beta, this feature will incur a fee later."
}
/>
</li>
</ul>
<div className="flex justify-center pt-2 pb-3 md:pt-3 md:pb-4">
{editmode ? (
@@ -6,6 +6,8 @@ import ModalUi from "../primitives/ModalUi";
import { rejectBtn, submitBtn } from "../constant/const";
import { openInNewTab } from "../constant/Utils";
import Parse from "parse";
import PremiumAlertHeader from "../primitives/PremiumAlertHeader";
import Tooltip from "../primitives/Tooltip";
function Webhook() {
const [parseBaseUrl] = useState(localStorage.getItem("baseUrl"));
@@ -101,7 +103,13 @@ function Webhook() {
</div>
) : (
<div className="bg-white flex flex-col justify-center shadow rounded">
<h1 className="ml-4 mt-3 mb-2 font-semibold">Webhook</h1>
<PremiumAlertHeader />
<h1 className="ml-4 mt-3 mb-2 font-semibold">
Webhook{" "}
<Tooltip
url={"https://docs.opensignlabs.com/docs/API-docs/get-webhook"}
/>
</h1>
<ul className="w-full flex flex-col p-2 text-sm">
<li
className={`flex justify-between items-center border-y-[1px] border-gray-300 break-all py-2`}
@@ -1,7 +1,7 @@
import React, { useState, useEffect } from "react";
import Parse from "parse";
import axios from "axios";
import "../css/AddUser.css";
import "../styles/AddUser.css";
const AddUser = (props) => {
const [name, setName] = useState("");
const [phone, setPhone] = useState("");
@@ -11,9 +11,6 @@ const AddUser = (props) => {
const [isUserExist, setIsUserExist] = useState(false);
const parseBaseUrl = localStorage.getItem("baseUrl");
const parseAppId = localStorage.getItem("parseAppId");
Parse.serverURL = parseBaseUrl;
Parse.initialize(parseAppId);
useEffect(() => {
checkUserExist();
}, []);
@@ -50,8 +47,6 @@ const AddUser = (props) => {
e.preventDefault();
e.stopPropagation();
setIsLoader(true);
Parse.serverURL = parseBaseUrl;
Parse.initialize(parseAppId);
try {
const contactQuery = new Parse.Object("contracts_Contactbook");
contactQuery.set("Name", name);
@@ -158,10 +153,10 @@ const AddUser = (props) => {
const res = await contactQuery.save();
const parseData = JSON.parse(JSON.stringify(res));
if(props.details){
if (props.details) {
props.details(parseData);
}
if (props.closePopup) {
props.closePopup();
}
+1 -1
View File
@@ -18,7 +18,7 @@ const Alert = ({ children, type }) => {
<>
{children && (
<div
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] `}
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`}
>
{children}
</div>
@@ -2,10 +2,11 @@ import React, { useState, useEffect, useMemo } from "react";
import pad from "../assets/images/pad.svg";
import { useNavigate } from "react-router-dom";
import axios from "axios";
import "../styles/report.css";
import ModalUi from "./ModalUi";
import AppendFormInForm from "../components/AppendFormInForm";
import AddSigner from "../components/AddSigner";
import { modalSubmitBtnColor, modalCancelBtnColor } from "../constant/const";
import Alert from "./Alert";
import Tooltip from "./Tooltip";
const ReportTable = ({
ReportName,
List,
@@ -15,7 +16,8 @@ const ReportTable = ({
setIsNextRecord,
isMoreDocs,
docPerPage,
form
form,
report_help
}) => {
const navigate = useNavigate();
const [currentPage, setCurrentPage] = useState(1);
@@ -67,7 +69,7 @@ const ReportTable = ({
const handlemicroapp = async (item, url, btnLabel) => {
if (ReportName === "Templates") {
if (btnLabel === "Edit") {
navigate(`/asmf/${url}/${item.objectId}`);
navigate(`/${url}/${item.objectId}`);
} else {
setActLoader({ [`${item.objectId}_${btnLabel}`]: true });
try {
@@ -149,7 +151,8 @@ const ReportTable = ({
if (res.data && res.data.objectId) {
setActLoader({});
setIsAlert(true);
navigate(`/asmf/${url}/${res.data.objectId}`, {
setTimeout(() => setIsAlert(false), 1500);
navigate(`/${url}/${res.data.objectId}`, {
state: { title: "Use Template" }
});
}
@@ -157,6 +160,7 @@ const ReportTable = ({
console.log("Err", err);
setIsAlert(true);
setIsErr(true);
setTimeout(() => setIsAlert(false), 1500);
setActLoader({});
}
} else {
@@ -166,18 +170,20 @@ const ReportTable = ({
} else {
setIsAlert(true);
setIsErr(true);
setTimeout(() => setIsAlert(false), 1500);
setActLoader({});
}
} catch (err) {
console.log("err", err);
setIsAlert(true);
setIsErr(true);
setTimeout(() => setIsAlert(false), 1500);
setActLoader({});
}
}
} else {
localStorage.removeItem("rowlevel");
navigate("/rpmf/" + url);
navigate(`/${url}`);
localStorage.setItem("rowlevel", JSON.stringify(item));
}
@@ -211,13 +217,15 @@ const ReportTable = ({
setIsDeleteModal({});
setActLoader({ [item.objectId]: true });
try {
const url =
process.env.REACT_APP_SERVERURL + "/classes/contracts_Contactbook/";
const serverUrl = process.env.REACT_APP_SERVERURL
? process.env.REACT_APP_SERVERURL
: window.location.origin + "/api/app";
const url = serverUrl + "/classes/contracts_Contactbook/";
const body = { IsDeleted: true };
const res = await axios.put(url + item.objectId, body, {
headers: {
"Content-Type": "application/json",
"X-Parse-Application-Id": localStorage.getItem("AppID12"),
"X-Parse-Application-Id": localStorage.getItem("parseAppId"),
"X-Parse-Session-Token": localStorage.getItem("accesstoken")
}
});
@@ -225,6 +233,7 @@ const ReportTable = ({
if (res.data && res.data.updatedAt) {
setActLoader({});
setIsAlert(true);
setTimeout(() => setIsAlert(false), 1500);
const upldatedList = List.filter((x) => x.objectId !== item.objectId);
setList(upldatedList);
}
@@ -232,6 +241,7 @@ const ReportTable = ({
console.log("err", err);
setIsAlert(true);
setIsErr(true);
setTimeout(() => setIsAlert(false), 1500);
setActLoader({});
}
};
@@ -240,19 +250,21 @@ const ReportTable = ({
return (
<div className="p-2 overflow-x-scroll w-full bg-white rounded-md">
{isAlert && (
<div
className={`alert alert-${isErr ? "danger" : "success"} alertBox`}
role="alert"
onAnimationEnd={() => setIsAlert(false)}
>
<Alert type={isErr ? "danger" : "success"}>
{isErr
? "Something went wrong, Please try again later!"
: "Record deleted successfully!"}
</div>
</Alert>
)}
<div className="flex flex-row items-center justify-between my-2 mx-3 text-[20px] md:text-[23px]">
<div className="font-light">{ReportName}</div>
<div className="font-light">
{ReportName}{" "}
{report_help && (
<span className="text-xs md:text-[13px] font-normal">
<Tooltip message={report_help} />
</span>
)}
</div>
{ReportName === "Templates" && (
<i
onClick={() => navigate("/form/template")}
@@ -495,7 +507,7 @@ const ReportTable = ({
isOpen={isContactform}
handleClose={handleContactFormModal}
>
<AppendFormInForm
<AddSigner
handleUserData={handleUserData}
closePopup={handleContactFormModal}
/>

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