Compare commits

..
114 Commits
Author SHA1 Message Date
AmolandGitHub b4315b5e0a Merge pull request #163 from OpenSignLabs/staging
v1.0.4
2023-11-10 02:52:04 +05:30
AmolandGitHub c326849b8d Merge pull request #162 from rishabjasrotia/issue/146 2023-11-09 21:18:53 +05:30
prafull-opensignlabsandGitHub a92188d8e2 change variable name 2023-11-09 21:18:36 +05:30
prafull-opensignlabsandGitHub 4055574785 sanitize File Name in upload file 2023-11-09 20:48:53 +05:30
AmolandGitHub 9b295f784a Merge pull request #158 from raktima-opensignlabs/placeholder-mobile-view2 2023-11-09 20:37:49 +05:30
prafull-opensignlabsandGitHub bfae7f236c Merge branch 'staging' into placeholder-mobile-view2 2023-11-09 20:36:33 +05:30
AmolandGitHub fe907116e2 Merge pull request #156 from raktima-opensignlabs/login-header3 2023-11-09 20:27:04 +05:30
rishabjasrotia ade39c2f46 Doc Updated 2023-11-09 18:36:18 +05:30
AndrewandGitHub 31baefcce3 Merge pull request #161 from rishabjasrotia/issue/32 2023-11-09 18:32:23 +05:30
RishabandGitHub 59eb4eb9c7 #32 - Change the title of popup that appears after sending out emails from "Request signatures" flow
#32 - Change the title of popup that appears after sending out emails from "Request signatures" flow
2023-11-09 18:30:37 +05:30
rishabjasrotia 3b93f96479 Fix makefile 2023-11-09 18:05:34 +05:30
rishabjasrotia dbff436bc2 #146 - Fix issue of build & Add local File upload support 2023-11-09 17:53:34 +05:30
AmolandGitHub c3cf9c891e Merge pull request #160 from maoo/patch-1 2023-11-09 17:47:54 +05:30
Maurizio PillituandGitHub 4e7c8c63bb CORS configuration instructions
See https://github.com/OpenSignLabs/OpenSign/issues/159
2023-11-09 12:57:58 +01:00
RaktimaNXG 450a971ca9 remove isSigner exist checking from local storage 2023-11-09 14:30:17 +05:30
RaktimaNXG 5ba1f79f3b replce isSigner variable name to isGuestSigner 2023-11-09 14:23:56 +05:30
AndrewandGitHub d255d5bfb2 Merge pull request #151 from prafull-opensignlabs/mf_header 2023-11-09 12:01:41 +05:30
AndrewandGitHub f5e835cbc4 Merge pull request #148 from prafull-opensignlabs/fix_signup 2023-11-09 12:01:20 +05:30
AmolandGitHub b40eb7119d Merge branch 'issue/119' into staging 2023-11-08 22:36:01 +05:30
RaktimaNXG f56faf3afd handle placeholder block position and size on mobile view 2023-11-08 21:01:09 +05:30
RaktimaNXG 5fa60d8135 solved overflow header on logiin page 2023-11-08 20:42:35 +05:30
AmolandGitHub 695345d911 Merge pull request #144 from raktima-opensignlabs/main
fix: blocking popup on view expired and declined document screens
2023-11-08 20:11:16 +05:30
prafull-opensignlabs 3f60509254 remove header from report microapp 2023-11-08 16:55:30 +05:30
RaktimaandGitHub 6bd9ac0b8f Merge pull request #12 from OpenSignLabs/staging
Update
2023-11-08 16:55:09 +05:30
AmolandGitHub ccecec5e59 Merge pull request #149 from OpenSignLabs/staging
v1.0.3
2023-11-08 14:28:32 +05:30
prafull-opensignlabs 2022df000e fix: user sign up issue for user existing in contact list 2023-11-08 13:56:28 +05:30
prafull-opensignlabsandGitHub ec6e037422 Merge pull request #10 from OpenSignLabs/staging
sync fork
2023-11-07 18:35:15 +05:30
AndrewandGitHub d4be4aec2c Merge pull request #143 from rishabjasrotia/issue/81 2023-11-07 18:09:08 +05:30
prafull-opensignlabsandGitHub 4b11fe77e0 Merge pull request #9 from OpenSignLabs/staging
sync fork
2023-11-07 17:40:34 +05:30
RishabandGitHub 4caf7b8c1a Update header.js 2023-11-07 17:31:50 +05:30
AmolandGitHub c736bbce55 Merge pull request #145 from prafull-opensignlabs/staging
remove hardcoded pfx passphrase
2023-11-07 16:30:35 +05:30
prafull-opensignlabsandGitHub 4bbf0d05d5 Merge pull request #147 from lsprr/accessibility/login
Improve accessibility of the login form
2023-11-07 16:14:40 +05:30
RaktimaNXG d42e11c5c1 fix: blocking screen by warning for expired and decline document 2023-11-07 11:32:25 +05:30
prafull-opensignlabs f227b79316 change prod and dev command 2023-11-07 11:29:08 +05:30
lsprr d4b4e02b62 Improve accessibility of the login form
- Add ARIA labels to input fields for better screen reader support
- Implement keyboard navigation for the login form elements
- Fix semantic HTML issues for assistive technologies
2023-11-06 15:57:49 -05:00
prafull-opensignlabs 1e76cf5253 fix: login url in mail change to current host 2023-11-06 20:48:01 +05:30
prafull-opensignlabs 4b9088b252 docs: update pass_phrase variable in env files 2023-11-06 20:00:10 +05:30
prafull-opensignlabs 820d6378f9 fix: add loadmf route to load login flow of microapp, add pagenotfound microapp 2023-11-06 19:44:06 +05:30
prafull-opensignlabs dfc816bdac Merge branch 'staging' of https://github.com/prafull-opensignlabs/OpenSign into staging 2023-11-06 16:51:17 +05:30
prafull-opensignlabs 0f62419d99 remove confidential passphrase param 2023-11-06 16:48:06 +05:30
prafull-opensignlabsandGitHub 37af995aaa Merge pull request #8 from OpenSignLabs/staging
sync fork
2023-11-06 16:10:54 +05:30
RishabandGitHub 4c69971ba1 Update emailComponent.js 2023-11-06 14:52:23 +05:30
RaktimaNXG fe37f3e021 fix: expired and decline document block whole screeen 2023-11-06 14:51:33 +05:30
RishabandGitHub 9047aa7dc8 Fix Printing for mobile 2023-11-06 14:49:44 +05:30
RishabandGitHub d33df9b934 Fix Print for mobile 2023-11-06 14:49:25 +05:30
RaktimaandGitHub 95558d1407 Merge pull request #11 from OpenSignLabs/staging
update
2023-11-06 14:48:05 +05:30
AndrewandGitHub 3164ee5824 Merge pull request #142 from OpenSignLabs/all-contributors/add-lsprr
docs: add lsprr as a contributor for a11y
2023-11-06 13:56:42 +05:30
allcontributors[bot]andGitHub 6a98adebd2 docs: update .all-contributorsrc 2023-11-06 08:26:13 +00:00
allcontributors[bot]andGitHub 015b752f5b docs: update README.md 2023-11-06 08:26:12 +00:00
AndrewandGitHub 11164a716f Merge pull request #140 from lsprr/lsprr/accessibility/sidebar
Refactor Menu and Social Media Components for Improved Accessibility
2023-11-06 13:55:19 +05:30
AndrewandGitHub 64638acd43 Merge pull request #141 from prafull-opensignlabs/staging 2023-11-06 13:24:20 +05:30
prafull-opensignlabsandGitHub 133769d5fd Merge pull request #7 from OpenSignLabs/staging
Merge pull request #137 from prafull-opensignlabs/staging
2023-11-06 13:19:11 +05:30
prafull-opensignlabs e330285e24 add pagination in reports, fix navigation in signup 2023-11-06 13:17:01 +05:30
lsprr 2acf851852 Refactor: Split Sidebar into Menu and SocialMedia components for modularity
- Created separate Menu and SocialMedia components from the Sidebar.
- Enhanced accessibility features in Menu.js, Sidebar.js, SubMenu.js, and SocialMedia.js.
- Adjusted NavLink components to improve keyboard navigation accessibility.
- Cleaned up and isolated component responsibilities for clarity and maintenance.
2023-11-05 15:55:38 -05:00
rishabjasrotia 73978ebce4 Fix issue 2023-11-05 19:20:34 +05:30
rishabjasrotia 96ae95a97c Fix the generation of remoteentry.js for docker development 2023-11-05 19:13:54 +05:30
rishabjasrotia 356d2e81c5 Update Document & Self Signed Cert added 2023-11-05 19:09:15 +05:30
AndrewandGitHub 66f91d27f5 Merge pull request #138 from OpenSignLabs/staging
v1.0.2
2023-11-05 17:40:37 +05:30
AndrewandGitHub 344d9458ba Merge pull request #137 from prafull-opensignlabs/staging 2023-11-05 11:25:30 +05:30
prafull-opensignlabs 408d84daed fix: file upload issue 2023-11-05 11:24:06 +05:30
prafull-opensignlabsandGitHub f1f4b0f7a2 Merge pull request #6 from OpenSignLabs/staging
sync fork
2023-11-05 10:35:28 +05:30
AndrewandGitHub a7d0b10c95 docs: Update README.md 2023-11-05 03:22:22 +05:30
AmolandGitHub 23a8637539 Merge pull request #130 from raktima-opensignlabs/main 2023-11-03 23:49:05 +05:30
AmolandGitHub ef45221fea Merge pull request #134 from prafull-opensignlabs/staging 2023-11-03 23:28:55 +05:30
prafull-opensignlabs e8350c331d add Public_url in build scripts of microfrontend 2023-11-03 23:27:44 +05:30
AmolandGitHub 8726f06ebf Merge pull request #133 from prafull-opensignlabs/staging 2023-11-03 22:53:46 +05:30
prafull-opensignlabs 184b401582 change homepage url of microfrontend 2023-11-03 22:52:09 +05:30
AmolandGitHub 08ba8b2e47 Merge pull request #132 from prafull-opensignlabs/staging 2023-11-03 22:39:47 +05:30
prafull-opensignlabs 71c5f5923f change homepage param in microfrontend 2023-11-03 22:38:41 +05:30
AmolandGitHub 93daef36cd Merge pull request #131 from prafull-opensignlabs/staging 2023-11-03 22:16:22 +05:30
prafull-opensignlabs 540e5e2997 add homepage param in microfrontend 2023-11-03 22:14:42 +05:30
RaktimaNXG fc2eab7d73 handled placeholder from all devices, remove underline from certificate,login page style,solved reactour issue for document owner from login flow, need your sign reports finish button issue,remove commented code, delete button(cross) on email documents popup issue and solve some minor design issue 2023-11-03 21:46:18 +05:30
RaktimaandGitHub a3ebe95a5e Merge pull request #10 from OpenSignLabs/staging
update
2023-11-03 21:36:04 +05:30
AmolandGitHub ecfad497a2 Merge pull request #128 from prafull-opensignlabs/staging 2023-11-03 20:11:45 +05:30
prafull-opensignlabs 86a4ee7f56 add start-prod to run production build 2023-11-03 19:59:37 +05:30
prafull-opensignlabs a64e4d943a change build scripts to run microfrontend properly 2023-11-03 19:53:12 +05:30
prafull-opensignlabsandGitHub 1a5f1dfa29 Merge pull request #5 from OpenSignLabs/staging
Merge pull request #127 from prafull-opensignlabs/staging
2023-11-03 19:52:23 +05:30
RaktimaandGitHub 4e90ae60a0 Merge pull request #8 from OpenSignLabs/main
Update
2023-11-03 18:06:25 +05:30
AmolandGitHub afe1a2b52e Merge pull request #127 from prafull-opensignlabs/staging 2023-11-03 17:42:27 +05:30
prafull-opensignlabs 2c3b4ec3fe Merge branch 'staging' of https://github.com/prafull-opensignlabs/OpenSign into staging 2023-11-03 17:26:34 +05:30
prafull-opensignlabs b034cfd501 add mfbuild folder to store microapp build 2023-11-03 17:26:20 +05:30
prafull-opensignlabsandGitHub bb04583bca Merge pull request #4 from OpenSignLabs/staging
sync fork
2023-11-03 17:12:43 +05:30
prafull-opensignlabs c684d00bdf integrate microapp code in monorepo 2023-11-03 17:11:09 +05:30
AmolandGitHub 6ac323846f Merge pull request #125 from OpenSignLabs/all-contributors/add-maoo 2023-11-03 16:32:39 +05:30
allcontributors[bot]andGitHub b5830ac792 docs: update .all-contributorsrc 2023-11-03 11:02:11 +00:00
allcontributors[bot]andGitHub 1c81e9e9e8 docs: update README.md 2023-11-03 11:02:10 +00:00
prafull-opensignlabsandGitHub 9ce58dc859 Merge pull request #3 from OpenSignLabs/staging
sync fork
2023-11-03 15:46:37 +05:30
AmolandGitHub a6231dca66 Merge pull request #124 from OpenSignLabs/all-contributors/add-rishabjasrotia 2023-11-03 15:14:03 +05:30
allcontributors[bot]andGitHub 8d62515383 docs: update .all-contributorsrc 2023-11-03 09:43:20 +00:00
allcontributors[bot]andGitHub 826da6cda6 docs: update README.md 2023-11-03 09:43:19 +00:00
AmolandGitHub 17076013fc Merge pull request #103 from rishabjasrotia/main
Fix #100 - Docker Error syntax issue
2023-11-03 15:07:25 +05:30
RishabandGitHub e302d0f1f1 Merge branch 'OpenSignLabs:main' into main 2023-11-03 15:02:34 +05:30
RishabandGitHub 3d744bd476 Update .env.local_dev 2023-11-02 18:23:36 +05:30
Rishab 72af4d979f LocalStack Removed due to DNS issue 2023-11-02 12:49:38 +00:00
RishabandGitHub 5ccd2bc27d Update .env.local_dev 2023-11-02 08:26:05 +05:30
RishabandGitHub 65c277c996 Update docker-compose.yml 2023-11-02 08:03:03 +05:30
Rishab f3a1a0efa9 MongoDB Init DB import logic added 2023-11-02 02:28:00 +00:00
RaktimaandGitHub 39ff162b1c Merge pull request #7 from OpenSignLabs/main
update
2023-11-01 19:12:34 +05:30
RishabandGitHub 4ff36d7c4b Merge branch 'OpenSignLabs:main' into main 2023-11-01 18:49:13 +05:30
rishabjasrotia 0d82c435f9 Fix OpenSignServer start problem 2023-11-01 15:10:06 +05:30
RishabandGitHub aa08a0a290 Merge branch 'OpenSignLabs:main' into main 2023-11-01 15:08:22 +05:30
rishabjasrotia 0a08b742fb Local Environment and localstack added 2023-11-01 14:57:09 +05:30
rishabjasrotia fbe8701f87 Fix local Development problem 2023-11-01 14:56:40 +05:30
RishabandGitHub bcd66b38d0 Merge branch 'OpenSignLabs:main' into main 2023-11-01 08:06:28 +05:30
rishabjasrotia 37ec427ed5 Front End .env 2023-10-31 18:44:52 +05:30
rishabjasrotia 5533cfe831 Update Documentation 2023-10-31 18:41:19 +05:30
rishabjasrotia ef9697b9d6 Usage of MakeFile to build project 2023-10-31 18:40:32 +05:30
RishabandGitHub c4b6a8c99f Merge branch 'OpenSignLabs:main' into main 2023-10-31 18:34:07 +05:30
AndrewandGitHub 22e121d094 fix: change port no to 5001 for Mac compatibility
Apple uses port 5000 for AirPlay Receiver. It will be better if we use port 5001 instead.
2023-10-31 17:24:49 +05:30
RishabandGitHub 91e691630c Removed npm run build
Removed npm run build
2023-10-31 16:53:39 +05:30
RishabandGitHub b58d72c176 Merge branch 'OpenSignLabs:main' into main 2023-10-31 16:53:07 +05:30
RishabandGitHub 4d18aea692 Update Dockerfile 2023-10-31 16:06:06 +05:30
RishabandGitHub f5e164cb3c Update Dockerfile 2023-10-31 16:05:42 +05:30
RishabandGitHub d8d52ab080 Update docker-compose.yml 2023-10-31 16:05:12 +05:30
66 changed files with 4848 additions and 2627 deletions
+27
View File
@@ -151,6 +151,33 @@
"contributions": [
"code"
]
},
{
"login": "rishabjasrotia",
"name": "Rishab",
"avatar_url": "https://avatars.githubusercontent.com/u/33950743?v=4",
"profile": "https://github.com/rishabjasrotia",
"contributions": [
"code"
]
},
{
"login": "maoo",
"name": "Maurizio Pillitu",
"avatar_url": "https://avatars.githubusercontent.com/u/327285?v=4",
"profile": "https://session.it",
"contributions": [
"bug"
]
},
{
"login": "lsprr",
"name": "Luis Parra",
"avatar_url": "https://avatars.githubusercontent.com/u/16653744?v=4",
"profile": "https://luisparra.dev",
"contributions": [
"a11y"
]
}
]
}
+3
View File
@@ -47,3 +47,6 @@ MAILGUN_SENDER=postmaster@mail.yourdomain.com
# Base64 encoded PFX or p12 document signing certificate file *********************************************************************************************************************
PFX_BASE64=
# Provide Pass pharse of above PFX or p12 document
PASS_PHRASE=
+110
View File
@@ -0,0 +1,110 @@
# Clone the repo and rename this file to .env if you want to run the frontend react app locally for some quick contributions to the project.
# When used as it is, this env config will connect to our hosted UAT backend
# Note that any data in staging will get cleared from time to time and you may have to sign up again and again
# Set CI to false while running the app locally
CI=false
# Set it to the URL form where the app home page will be accessed
PUBLIC_URL=http://localhost:3000
# Set it to true if you want to generate the Sourcemap for debugging
GENERATE_SOURCEMAP=false
# Set it to the URL from where APIs will be accessible, for local development it should be localhost:3000/api/app (use your local port number instead)
REACT_APP_SERVERURL=http://localhost:8080/app
# A 12 character long random app identifier. The value of this should be same as APP_ID which is a variable used by backend API.
REACT_APP_APPID=opensignstgn
# Backend ExpressJS config ****************************************************************************************************************************************************************************************
# A 12 character long random app identifier. The value of this should be same as REACT_APP_APPID which is a variable used by Frontend React App.
APP_ID=opensignstgn
# Name of the app. It will be visible in the verification emails sent out.
appName=open_sign_server
# A 12 character long random secret key that allows access to all the data. It is used in Parse dashboard config to view all the data in the database.
MASTER_KEY=XnAadwKxxByMr
# Mongodb URI to connect to
MONGODB_URI=mongodb://host.docker.internal:27017/OpenSignDB
# Path on which APIs should be mounted. Do not change this. This variable shall be removed & value hardcoded in the source code in coming versions.
PARSE_MOUNT=/app
# Set it to the URL from where APIs will be accessible to the NodeJS functions, for local development it should be localhost:3000/api/app (use your local port number instead)
SERVER_URL=http://127.0.0.1:8080/app
# Storage config ************************************************************************************************************************************************************************************************
# Digital ocean space name or AWS S3 bucket name for uploading documents
DO_SPACE=DOSPACENAME
# Digital ocean spaces endpoint or AWS S3 endpoint for uploading documents
DO_ENDPOINT=ams3.digitaloceanspaces.com
# Digital ocean baseurl or AWS S3 base URL
DO_BASEURL=https://DOSPACENAME.ams3.digitaloceanspaces.com
# Digital ocean spaces access key ID or AWS s3 Access key ID for uploading the docs
DO_ACCESS_KEY_ID=
# Digital ocean spaces secret access key or AWS s3 secret access key for uploading the docs
DO_SECRET_ACCESS_KEY=
# Digital ocean spaces region or AWS s3 region
DO_REGION=us-west
# local storage
USE_LOCAL=FALSE
# Email mailgun config (The app will not initialize if any of these 3 variables are not set) *********************************************************************************************************************
MAILGUN_API_KEY=XXXXX
MAILGUN_DOMAIN=mail.yourdomain.com
MAILGUN_SENDER=postmaster@mail.yourdomain.com
# Base64 encoded PFX or p12 document signing certificate file *********************************************************************************************************************
PFX_BASE64='MIIKLwIBAzCCCeUGCSqGSIb3DQEHAaCCCdYEggnSMIIJzjCCBEIGCSqGSIb3DQEH
BqCCBDMwggQvAgEAMIIEKAYJKoZIhvcNAQcBMFcGCSqGSIb3DQEFDTBKMCkGCSqG
SIb3DQEFDDAcBAh6cQqVpHfTzAICCAAwDAYIKoZIhvcNAgkFADAdBglghkgBZQME
ASoEEFKEIGJTTRo3voO/FvsXs7yAggPAI7rMCboTFFBfdMuuV3Y9/xfphAgdGD7P
0xAN10CcmXlMtedc8cRxOaD9n3Q7zJx5iIbqEGDTc0dgp5EtdWsGl7MP76iHkSfB
ZUPc13nbnRU4Nq4hNFcSj1m6NVa0lT9UobbTsG+wUkJn8aLfijzZ1OY82KLlKUoJ
lqLsQ1yZkeLiLKI0aEew/2vzfiLUX9A99qnCRoryo8ZbLiWl0Vu/FEKM5mqIRFEp
BKeSUsRxBfJCMZ2Ks5t4/MTCV+yrcsuhLPF/AJpzKfIinEFDhm7MxP4RXtk2LWNe
+EO2GuFRjZCfsMO0oNWybFmDeNDMCHZj5TeoqL1JwAV5e1lEeqR38v4Wcr4OVefY
DfdrJ2xdvm7XbBZ8Lgx8L4fwugw7oDyTpR2jJqHMlpOsQrxipN6UKkN6EVYeCC5K
4dF5LHdCcIa7L/OI/feD5g/zz8SGCTc91husVN7zi+CVO0lQLRkAj02+VbiXPPDD
eQm/QBieG2yVe5IRfcnIs2aszulbQbgHdguSYSQa/7DEvN/9/uxUIRFbItwrreRI
VAUUNS02L680Zok9xzDed1I/WJoPr2+5n2eV1jc5zoH7mAni0+Z1d5qLoYV6pNaN
P9okvBf75LLNoJKsb/eWlkk73rmlH6/Qz+hudgnlkxUJuU/b79AMQpd0EWEWhcim
ZeB4d9lPLLwyvY/FN4aCGWzsoAW69RK9E1DyGZAZRYRwCKHSWXmCaenR1ilxcPFx
TDavpybObIISPtylv5Z/IGBjE19Lw0UHc6Waln/jx0YXXGGDWs1F/MrdJ/8mkVXf
tHB/5ds4u5md+CmXpaCITO3Cg9GltGSWyDoEJsz1u/Wzq4X4FYmolXiqQvMPQrxu
iThTnPDGbz9VqFSyNKPKswIQ8CUbvZ209A5vjERPzE0Lp1pO39K51fnHD9oD968t
tGbGmNiQ0++Orze79cH0UVwDa6NLGCmnE0oBgke1JDPlaU3kkx7+R9SAS0Zytsmj
aLxW5Z1cOFaqqBLjwgHUxOqRO+cl6P9ORox34wJjiwZKy1L+0ppw22Na/unwi2Rk
a8jvK7+ycOLaiSmI77T0l7VCWgKsRsWLvBA3cjX5XAGtatFXrY/7Imoxl0nWGLjG
n5Sv5XuDek4e4QAPeJmhpURMnzLDsSXAYOSYZvS/kgENYhYSnQLQp50TxrzquA2c
lAeFIEqqAJy9tAMfp5UAqMeOC60Ttn6ySsdOle003F2NrRilhPynNDZ3h1ZQknur
Y9zWUm9qBmXCjhPzdmzHz3Ozj2Bi6kd4MIIFhAYJKoZIhvcNAQcBoIIFdQSCBXEw
ggVtMIIFaQYLKoZIhvcNAQwKAQKgggUxMIIFLTBXBgkqhkiG9w0BBQ0wSjApBgkq
hkiG9w0BBQwwHAQIZenzippqfSQCAggAMAwGCCqGSIb3DQIJBQAwHQYJYIZIAWUD
BAEqBBCddSIj/wfxowZAO1j3W9FwBIIE0C/guzeZtV/vPsaIDAtWEkmepCvhm9Rg
aUgOoR66wjyYx7upeuZJ+pYJdsEqUmTgGYN+ClBpsU0bqCM7PI0mepvIT9kLD6ZL
UkprtNAYP87NBA/e5dpXlGAf9ibDRT0F2Y+lCSF83rCIYKG8n7h5834F6Saf+dU7
6y5bgorbf2Fnxy123XfUSg5qdCraZZM+DwE1gpQdBGrFyq8cwlQ8hJpKHDWup7WA
f2HcT/X0Wjb24L6JWjC1FvTbTNdS/lzTOcqLYUc31iuU9rF6O4qtX9PK/yGWc+YE
qakuV+HrsF4je/YdVZRYHtkbbcYXW9PjtMv+4D1ut5X2SPeHwpj3WmGAb7Zno6SD
SfohMihXvDbIjVSMDBpW97bhgk0h7iS4ISIYoQJUGJv3QQ3XJq91LoIP3zpiO/Cq
ZuuHuGvZmO6lb0PGShRT7mFg3k3rswTfFyKdtY76zAVJIR2bz/6bRf4uQI48SOLR
NX1Z6lavUNiE4nPNlnfBp480C+YANKs/bdev0wkRVmFxPMyb5FFLXwLSqcfdSQag
RayrKd8xPOm6lor3cTvrkO3XH2Hf9TgFHjeIAQ3VZ1Cncb9jfra3V4zvIocek4dC
GREirPbEyL/js5O0aAa0mg9EontMWKRqncomKhUOckheP2dYiQOazDFDFP9OQCYV
MBb0RDwm3+hiMU0lPeO+NAjAv2SfFK7G4maMb2SL7inT7An7ZPPpnDNXLDt+nOgo
IKuaJpy8JX/OKB4ntYsdnQG4E0J3vpHWjYPKif7j1njIYFd76bIgNVlqWuQFArBy
U9BuPyF+eYouJc+TpX9R5ybPvabRR4NUjnrttr2E5AzQfIgNGrSFiewjvYZHQOKd
WyVR9YV0cUv591xyUDdXMoHh+J0v0xK1WCHe/9enY5y/C8YohL8h5tEvInAQconj
lJ2r9qX8iBmIupJij5M5Ebza8HQ4aVMdHu/s05Vj9BC6K0ok3h+DFTj2gUBD24sp
APHic0DmNnciUQuHuuoW/1SVb6I1HJswsgcC8CekvoXF26ygwWhJPyqw+5djip2w
I/l3uOnPPUWZQHKhnBH4noZydrzBBJN1po9dkxb8LKuKZDEcnKo+tQrTnZJaFRXK
pQDsAjQ0HcYi8ZqN/GPezXOqzRgvObevXeDYTJrNejr46B1HqjPw8doai+AEf//1
iiM9EK4y3bGbX837oebTByRi112AOctISHTWbF0zdFMiBO9X9PML4n3i14ToqLH1
EUp0WtCdKLJmrRnO9PKJUMpce3yNu6oRSBzB4EkgUMOTVx9tM66h/gcR3wr+qKJP
1EABMbbCsJeYYLujhQHVh0JluqLBXYuCmr5n6o8qmonj5tEfTn9zs2gi0OvKTliH
wRXWsar004alt8D8o4M/Oqu3qyVV1O8BlVEofUC1CfAMIh/T1NJBeKG/FPfAFoEz
9liLLkoDvGvFVJ4Ezy4BaPtg+G3yU/SeiruwsCB3unHRD7G6VvS4jY2B8vEYl0yM
Z1mLFbKK8CIEvg8+v/vbc0noYUOzd6bkwh6Y6cziR/u78y2nALYZpQK+3XiVVH/v
SaVoDckZgUwAX+dMd1P4U3a487MPXBZZmLVFMHTuv3NvW6NIQCMd4l35ViRd7YcS
V2QDKTnUtPN2MSUwIwYJKoZIhvcNAQkVMRYEFMSz7PlBO5VzTDqC/foidPWrMjkw
MEEwMTANBglghkgBZQMEAgEFAAQgPlLuG+67SxPOEPbgFuEnVgewvY6LUzFmrprx
c6yryFgECIld0S5kDk7JAgIIAA=='
# Provide Pass pharse of above PFX or p12 document
PASS_PHRASE=
+3
View File
@@ -22,3 +22,6 @@
npm-debug.log*
yarn-debug.log*
yarn-error.log*
apps/OpenSign/public/mfbuild/*
microfrontends/SignDocuments/build/*
apps/OpenSignServer/files/files/*
+65
View File
@@ -7,6 +7,7 @@ or follow below instructions to install it on your own infrastructure.
- Localhost(Frontend only)
- Digital Ocean
- Localhost(Docker)
## Localhost(Frontend only)
@@ -83,3 +84,67 @@ You can install all 3 components on digital ocean using the button below -
Visit below link if you face any issues while following the above instructions -
- https://repost.aws/knowledge-center/create-access-key
## Localhost(Docker)
For local Setup we need to need following prerequisite:
Environment Varaibles:
| Environment Varibale | Value | Description |
| ------------- | ------------- | ------------- |
| CI | false | Set CI to false while running the app locally |
| PUBLIC_URL | http://localhost:3000 | Set it to the URL form where the app home page will be accessed |
| GENERATE_SOURCEMAP | false | Set it to true if you want to generate the Sourcemap for debugging |
| REACT_APP_SERVERURL | http://localhost:8080/app | Set it to the URL from where APIs will be accessible, for local development it should be localhost:3000/api/app (use your local port number instead) |
| REACT_APP_APPID | http://localhost:3000 | Set it to the URL form where the app home page will be accessed |
| PUBLIC_URL | 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`
+9
View File
@@ -0,0 +1,9 @@
build:
cp .env.local_dev .env
rm -rf apps/OpenSign/public/mfbuild
cd microfrontends/SignDocuments && npm install && npm run build
docker compose up -d
run:
cp .env.local_dev .env
docker compose up -d
+5 -2
View File
@@ -2,7 +2,7 @@
<div align="center">
The free open source alternative to DocuSign | PandaDoc | SignNow | Adobe Sign | Smartwaiver | SignRequest | HelloSign | Zoho sign.
The free and open source alternative to DocuSign
[![Average time to resolve an issue](http://isitmaintained.com/badge/resolution/opensignlabs/opensign.svg)](http://isitmaintained.com/project/opensignlabs/opensign "Average time to resolve an issue")
[![All Contributors](https://img.shields.io/github/all-contributors/opensignlabs/opensign?color=ee8449&style=flat-square)](#contributors)
@@ -23,7 +23,7 @@ The free open source alternative to DocuSign | PandaDoc | SignNow | Adobe Sign |
<a href="https://www.linkedin.com/company/opensign%E2%84%A2/about/">LinkedIn</a>
## An Open-Source Alternative to DocuSign, PandaDoc, SignNow, Adobe Sign, Smartwaiver, SignRequest, and HelloSign
## An open-source document e-signing solution
---
</div>
@@ -122,6 +122,9 @@ We would like to thank all our contributors and users for their support and feed
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/VishakhaSainani"><img src="https://avatars.githubusercontent.com/u/113436770?v=4?s=100" width="100px;" alt="VishakhaSainani"/><br /><sub><b>VishakhaSainani</b></sub></a><br /><a href="#code-VishakhaSainani" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/andrew-opensignlabs"><img src="https://avatars.githubusercontent.com/u/148278535?v=4?s=100" width="100px;" alt="Andrew"/><br /><sub><b>Andrew</b></sub></a><br /><a href="#code-andrew-opensignlabs" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/rishabjasrotia"><img src="https://avatars.githubusercontent.com/u/33950743?v=4?s=100" width="100px;" alt="Rishab"/><br /><sub><b>Rishab</b></sub></a><br /><a href="#code-rishabjasrotia" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://session.it"><img src="https://avatars.githubusercontent.com/u/327285?v=4?s=100" width="100px;" alt="Maurizio Pillitu"/><br /><sub><b>Maurizio Pillitu</b></sub></a><br /><a href="#bug-maoo" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://luisparra.dev"><img src="https://avatars.githubusercontent.com/u/16653744?v=4?s=100" width="100px;" alt="Luis Parra"/><br /><sub><b>Luis Parra</b></sub></a><br /><a href="#a11y-lsprr" title="Accessibility">️♿️</a></td>
</tr>
</tbody>
</table>
+4 -4
View File
@@ -5,14 +5,14 @@ FROM node:16
WORKDIR /usr/src/app
# Copy package.json and package-lock.json first to leverage Docker cache
COPY apps/OpenSign/package*.json ./
COPY ./package*.json ./
# Install application dependencies
RUN npm install
# Copy the current directory contents into the container
COPY apps/OpenSign/ .
COPY apps/OpenSign/.husky .
COPY ./ .
COPY ./.husky .
# Make port 3000 available to the world outside this container
EXPOSE 3000
@@ -21,5 +21,5 @@ EXPOSE 3000
# ENV NODE_ENV production
# Run the application
CMD ["npm", "start"]
ENTRYPOINT npm run start-dev
+4 -3
View File
@@ -40,8 +40,9 @@
"web-vitals": "^2.1.4"
},
"scripts": {
"start": "mf-cra start",
"build": "npm run micro && CI=false && mf-cra build",
"start": "serve -s build",
"start-dev": "mf-cra start",
"build": "rm -rf public/mfbuild && npm run micro && CI=false && mf-cra build",
"micro": "cd ../../microfrontends/SignDocuments && npm install && npm run build",
"test": "react-scripts test",
"eject": "react-scripts eject",
@@ -84,4 +85,4 @@
"pretty-quick": "^3.1.3",
"tailwindcss": "^3.3.3"
}
}
}
+2
View File
@@ -14,6 +14,7 @@ import PageNotFound from "./routes/PageNotFound";
import ForgetPassword from "./routes/ForgetPassword";
import ChangePassword from "./routes/ChangePassword";
import ReportMicroapp from "./components/ReportMicroapp";
import LoadMf from "./routes/LoadMf";
function App() {
const [isloading, setIsLoading] = useState(true);
@@ -59,6 +60,7 @@ function App() {
<Routes>
<Route exact path="/" element={<Login />} />
<Route exact path="/signup" element={<Signup />} />
<Route exact path="/loadmf/:remoteApp/*" element={<LoadMf />} />
<Route exact path="/forgetpassword" element={<ForgetPassword />} />
{process.env.REACT_APP_ENABLE_SUBSCRIPTION && (
<>
+29 -3
View File
@@ -141,6 +141,32 @@ const GoogleSignInBtn = ({
alert("Please fill required details!");
}
};
const handleCloseModal = () => {
setIsModal(false);
Parse.User.logOut();
let appdata = localStorage.getItem("userSettings");
let applogo = localStorage.getItem("appLogo");
let appName = localStorage.getItem("appName");
let defaultmenuid = localStorage.getItem("defaultmenuid");
let PageLanding = localStorage.getItem("PageLanding");
let domain = localStorage.getItem("domain");
let _appName = localStorage.getItem("_appName");
let baseUrl = localStorage.getItem("BaseUrl12");
let appid = localStorage.getItem("AppID12");
localStorage.clear();
localStorage.setItem("appLogo", applogo);
localStorage.setItem("appName", appName);
localStorage.setItem("_appName", _appName);
localStorage.setItem("defaultmenuid", defaultmenuid);
localStorage.setItem("PageLanding", PageLanding);
localStorage.setItem("domain", domain);
localStorage.setItem("userSettings", appdata);
localStorage.setItem("BaseUrl12", baseUrl);
localStorage.setItem("AppID12", appid);
};
return (
<div style={{ position: "relative" }}>
{thirdpartyLoader && (
@@ -259,16 +285,16 @@ const GoogleSignInBtn = ({
<div>
<button
type="button"
className="btn btn-secondary"
onClick={() => setIsModal(false)}
className="bg-[#6c757d] p-2 text-white rounded"
onClick={handleCloseModal}
style={{ marginRight: 10, width: 90 }}
>
Cancel
</button>
<button
type="button"
className="bg-[#17a2b8] p-2 text-white rounded"
onClick={() => handleSubmitbtn()}
className="btn btn-info"
>
Sign up
</button>
+29 -51
View File
@@ -1,6 +1,6 @@
import useFederatedComponent from "mf-cra";
import React, { Suspense, useEffect } from "react";
import { useNavigate, useParams } from "react-router-dom";
import { useParams } from "react-router-dom";
const MicroappModal = () => {
const { remoteApp } = useParams();
@@ -15,7 +15,9 @@ const MicroappModal = () => {
// console.log("value ", key + ":" + value);
if (key === "remoteUrl") {
obj = { ...obj, [key]: atob(value) };
const url = window.location.origin + "/mfbuild/remoteEntry.js";
// console.log("atob(value) ", atob(value))
obj = { ...obj, [key]: url };
} else {
if (key === "moduleToLoad") {
obj = { ...obj, [key]: "./" + value };
@@ -26,60 +28,36 @@ const MicroappModal = () => {
}
// console.log("app ", remoteApp);
const { Component: RemoteComponent } = useFederatedComponent(obj);
const navigate = useNavigate();
// console.log("RemoteComponent ", RemoteComponent);
return (
<div className="w-full h-full flex items-center justify-center ">
{/* <!-- Modal Container --> */}
<div className="bg-white rounded-lg shadow-lg w-full">
{/* <!-- Modal Header --> */}
<div className="flex w-full items-center border-b-2 mb-2 p-2">
<button
className="focus:outline-none bg-blue-500 text-white text-sm shadow px-2.5 py-1 rounded"
id="closeModal"
onClick={(e) => {
e.preventDefault();
// setIsModal(false);
navigate(-1);
<div className="w-full">
<Suspense
fallback={
<div style={{ height: "300px" }}>
<div
style={{
marginLeft: "45%",
marginTop: "150px",
fontSize: "45px",
color: "#3dd3e0"
}}
className="loader-37"
></div>
</div>
}
>
<div
style={{
backgroundColor: "#ffffff",
width: "100%",
overflow: "hidden",
minHeight: "50vh"
}}
>
Back
</button>
{localStorage.getItem('domain') && (
<p className="flex-1 w-full text-sm md:text-base text-black text-center">
{localStorage.getItem('domain') === "contracts" ? "Document":""}
</p>
)}
</div>
{/* <!-- Modal Body --> */}
<div className="w-full">
<Suspense
fallback={
<div style={{ height: "300px" }}>
<div
style={{
marginLeft: "45%",
marginTop: "150px",
fontSize: "45px",
color: "#3dd3e0"
}}
className="loader-37"
></div>
</div>
}
>
<div
style={{
backgroundColor: "#ffffff",
width: "100%",
overflow: "hidden",
minHeight: "50vh"
}}
>
{RemoteComponent && <RemoteComponent />}
</div>
</Suspense>
</div>
{RemoteComponent && <RemoteComponent />}
</div>
</Suspense>
</div>
</div>
);
@@ -1,8 +1,7 @@
import React, { useState, useEffect } from "react";
import { SaveFileSize } from "../../constant/saveFileSize";
// import Parse from "parse";
// import sanitizeFileName from "../../primitives/sanitizeFileName";
import axios from "axios";
import Parse from "parse";
import sanitizeFileName from "../../primitives/sanitizeFileName";
const FileUpload = (props) => {
const [parseBaseUrl] = useState(localStorage.getItem("baseUrl"));
@@ -69,53 +68,44 @@ const FileUpload = (props) => {
};
const handleFileUpload = async (file) => {
Parse.serverURL = parseBaseUrl;
Parse.initialize(parseAppId);
setfileload(true);
const file_url = parseBaseUrl.slice(0, -4);
const url = `${file_url}file_upload`;
const formData = new FormData();
formData.append("file", file);
const config = {
headers: {
"content-type": "multipart/form-data",
"X-Parse-Application-Id": parseAppId
},
onUploadProgress: function (progressEvent) {
var percentCompleted = Math.round(
(progressEvent.loaded * 100) / progressEvent.total
);
setpercentage(percentCompleted);
}
};
const size = file.size;
const fileName = file.name;
const name = sanitizeFileName(fileName);
const pdfFile = file;
const parseFile = new Parse.File(name, pdfFile);
try {
await axios
.post(url, formData, config)
.then((res) => {
if (res.data.status === "Error") {
alert(res.data.message);
const response = await parseFile.save({
progress: (progressValue, loaded, total, { type }) => {
if (type === "upload" && progressValue !== null) {
const percentCompleted = Math.round((loaded * 100) / total);
// console.log("percentCompleted ", percentCompleted);
setpercentage(percentCompleted);
}
setFileUpload(res.data.imageUrl);
props.onChange(res.data.imageUrl);
setfileload(false);
setpercentage(0);
}
});
if (res.data.imageUrl) {
SaveFileSize(file.size, res.data.imageUrl);
return res.data.imageUrl;
}
})
.catch((err) => {
alert(`${err.message}`);
setfileload(false);
setpercentage(0);
});
setFileUpload(response.url());
props.onChange(response.url());
setfileload(false);
// The response object will contain information about the uploaded file
// console.log("File uploaded:", response);
// You can access the URL of the uploaded file using response.url()
// console.log("File URL:", response.url());
if (response.url()) {
SaveFileSize(size, response.url());
return response.url();
}
} catch (error) {
alert(error.message);
setfileload(false);
setpercentage(0);
console.error("Error uploading file:", error);
}
};
let fileView =
props.formData &&
props.schema.uploadtype === "s3viajw" ? null : props.formData &&
@@ -124,7 +114,7 @@ const FileUpload = (props) => {
<a
href={props.formData}
title={props.formData}
style={{ paddingBottom: "10px", color: "blue"}}
style={{ paddingBottom: "10px", color: "blue" }}
>
Download
</a>
@@ -0,0 +1,21 @@
import React from "react";
import { NavLink } from "react-router-dom";
const Menu = ({ item, isOpen, closeSidebar }) => {
return (
<li key={item.title} role="none">
<NavLink
to={`/${item.pageType}/${item.objectId}`}
className="mx-auto flex items-center hover:bg-[#eef1f5] p-3 lg:p-4"
onClick={closeSidebar}
tabIndex={isOpen ? 0 : -1}
role="menuitem"
>
<i className={`${item.icon} text-[18px]`} aria-hidden="true"></i>
<span className="ml-3 lg:ml-4">{item.title}</span>
</NavLink>
</li>
)
}
export default Menu;
+34 -72
View File
@@ -1,115 +1,77 @@
import React, { useState, useEffect } from "react";
import { Link, NavLink } from "react-router-dom";
import Menu from './Menu';
import Submenu from "./SubMenu";
import dp from "../../assets/images/dp.png";
import SocialMedia from './SocialMedia';
import Parse from "parse";
import dp from "../../assets/images/dp.png";
const Sidebar = ({ isOpen, closeSidebar }) => {
const [menuList, setmenuList] = useState([]);
let username = localStorage.getItem("username");
const image = localStorage.getItem("profileImg") || dp;
const tenantname = localStorage.getItem("TenantName");
const [menuList, setmenuList] = useState([]);
useEffect(() => {
if (localStorage.getItem("accesstoken")) {
menuItem();
}
}, []);
const menuItem = async () => {
const parseBaseUrl = localStorage.getItem("baseUrl");
const parseAppId = localStorage.getItem("parseAppId");
try {
Parse.serverURL = parseBaseUrl;
Parse.initialize(parseAppId);
var sideMenu = Parse.Object.extend("w_menu");
var query = new Parse.Query(sideMenu);
query.equalTo("objectId", localStorage.getItem("defaultmenuid"));
const results = await query.first();
const resultjson = results.toJSON();
// console.log("resultjson ", resultjson);
let result = resultjson;
setmenuList(result.menuItems);
} catch (e) {
console.error("Problem", e);
}
};
return (
<div
className={`${
isOpen ? "block" : "hidden"
} bg-white text-[#444] h-screen w-full md:w-[300px] overflow-y-auto transform transition-transform z-40 ${
isOpen ? "translate-x-0" : "-translate-x-full"
}`}
<aside
className={`${isOpen ? "block" : "hidden"
} bg-white text-[#444] h-screen w-full md:w-[300px] overflow-y-auto transform transition-transform z-40 ${isOpen ? "translate-x-0" : "-translate-x-full"
}`}
>
<div className="flex px-2 py-3 gap-2 items-center shadow-md">
<div className="w-[75px] h-[75px] rounded-full ring-[2px] ring-offset-2 ring-gray-400 overflow-hidden">
<img className="w-full h-full object-contain" src={image} alt="img" />
<img className="w-full h-full object-cover" src={image} alt="Profile" />
</div>
<div>
<p className="text-[14px] font-bold">{username && username}</p>
<p
className={`text-[12px] ${tenantname && tenantname ? "mt-2" : ""}`}
>
{tenantname && tenantname}
<p className="text-[14px] font-bold">{username}</p>
<p className={`text-[12px] ${tenantname ? "mt-2" : ""}`}>
{tenantname}
</p>
</div>
</div>
<ul className="text-sm">
{menuList.length > 0 && (
<>
{menuList.map((item) =>
!item.children ? (
<li key={item.title} onClick={() => closeSidebar()}>
<Link
className={`mx-auto flex items-center hover:bg-[#eef1f5] p-3 lg:p-4 hover:no-underline cursor-pointer`}
to={`/${item.pageType}/${item.objectId}`}
>
<i className={item.icon + " text-[18px]"}></i>
<span title={item.description} className="ml-3 lg:ml-4">
{item.title}
</span>
</Link>
</li>
) : (
<Submenu key={item.title} icon={item.icon} title={item.title}>
{item.children.map((item) => (
<li key={item.title} onClick={() => closeSidebar()} className="pl-6 md:pl-8 hover:bg-[#eef1f5] cursor-pointer">
<Link
className={`mx-auto flex items-center p-2 lg:p-3 hover:no-underline`}
to={`/${item.pageType}/${item.objectId}`}
>
<i className={item.icon + " text-[18px]"}></i>
<span title={item.description} className="ml-3 lg:ml-4">
{item.title}
</span>
</Link>
</li>
))}
</Submenu>
)
)}
</>
)}
</ul>
<div className="mt-4 flex justify-center items-center text-[25px] text-black gap-3">
<NavLink to="https://github.com/opensignlabs/opensign" target="_blank">
<i className="fa-brands fa-github"></i>
</NavLink>
<NavLink
to="https://www.linkedin.com/company/opensign%E2%84%A2/"
target="_blank"
>
<i className="fa-brands fa-linkedin"></i>
</NavLink>
<NavLink to="https://www.twitter.com/opensignlabs" target="_blank">
<i className="fa-brands fa-square-x-twitter"></i>
</NavLink>
<NavLink to="https://discord.com/invite/xe9TDuyAyj" target="_blank">
<i className="fa-brands fa-discord"></i>
</NavLink>
</div>
</div>
<nav aria-label="OpenSign Sidebar Navigation">
<ul className="text-sm" role="menubar" aria-label="OpenSign Sidebar Navigation">
{menuList.map((item) => (
!item.children ? (
<Menu key={item.title} item={item} isOpen={isOpen} closeSidebar={closeSidebar} />
) : (
<Submenu key={item.title} item={item} closeSidebar={closeSidebar} />
)
))}
</ul>
</nav>
<footer className="mt-4 flex justify-center items-center text-[25px] text-black gap-3">
<SocialMedia />
</footer>
</aside>
);
};
@@ -0,0 +1,27 @@
import React from "react";
import { NavLink } from "react-router-dom";
const SocialMedia = () => {
return (
<React.Fragment>
<NavLink to="https://github.com/opensignlabs/opensign" target="_blank" rel="noopener noreferrer">
<i aria-hidden="true" className="fa-brands fa-github"></i>
<span className="fa-sr-only">OpenSign&apos;s Github</span>
</NavLink>
<NavLink to="https://www.linkedin.com/company/opensign%E2%84%A2/" target="_blank" rel="noopener noreferrer">
<i aria-hidden="true" className="fa-brands fa-linkedin"></i>
<span className="fa-sr-only">OpenSign&apos;s LinkedIn</span>
</NavLink>
<NavLink to="https://www.twitter.com/opensignlabs" target="_blank" rel="noopener noreferrer">
<i aria-hidden="true" className="fa-brands fa-square-x-twitter"></i>
<span className="fa-sr-only">OpenSign&apos;s Twitter</span>
</NavLink>
<NavLink to="https://discord.com/invite/xe9TDuyAyj" target="_blank" rel="noopener noreferrer">
<i aria-hidden="true" className="fa-brands fa-discord"></i>
<span className="fa-sr-only">OpenSign&apos;s Discord</span>
</NavLink>
</React.Fragment>
)
}
export default SocialMedia;
+33 -11
View File
@@ -1,30 +1,52 @@
import React, { useState } from "react";
import { NavLink } from "react-router-dom";
const Submenu = ({ icon, title, children }) => {
const [isOpen, setIsOpen] = useState(false);
const Submenu = ({ item, closeSidebar }) => {
const [submenuOpen, setSubmenuOpen] = useState(false);
const { title, icon, children } = item;
const toggleSubmenu = () => {
setIsOpen(!isOpen);
setSubmenuOpen(!submenuOpen);
};
return (
<div>
<li role="none">
<button
onClick={toggleSubmenu}
className="w-full mx-auto flex items-center text-left text-[#444] p-3 lg:p-4 hover:bg-[#eef1f5] focus:outline-none"
className="w-full flex items-center text-left text-[#444] p-3 lg:p-4 hover:bg-[#eef1f5] focus:ring-2 focus:ring-blue-600"
aria-expanded={submenuOpen}
aria-haspopup="true"
aria-controls={`submenu-${title}`}
>
<i className={icon + " text-[18px]"}></i>
<i className={`${icon} text-[18px]`}></i>
<div className="flex justify-between items-center w-full">
<span className="ml-3 lg:ml-4">{title}</span>
<i
className={
isOpen ? "fa-solid fa-angle-down" : "fa-solid fa-angle-right"
}
className={`${submenuOpen ? "fa-solid fa-angle-down" : "fa-solid fa-angle-right"
}`}
aria-hidden="true"
></i>
</div>
</button>
{isOpen && <ul>{children}</ul>}
</div>
{submenuOpen && (
<ul id={`submenu-${title}`} role="menu" aria-label={`${title} submenu`}>
{children.map((childItem) => (
<li key={childItem.title} role="none">
<NavLink
to={`/${childItem.pageType}/${childItem.objectId}`}
className="block pl-6 md:pl-8 py-2 text-sm text-gray-700 hover:bg-blue-500 hover:text-white"
onClick={closeSidebar}
role="menuitem"
tabIndex={submenuOpen ? 0 : -1}
>
<i className={`${childItem.icon} text-[18px]`} aria-hidden="true"></i>
<span className="ml-3 lg:ml-4">{childItem.title}</span>
</NavLink>
</li>
))}
</ul>
)}
</li>
);
};
@@ -1,9 +1,37 @@
import React from "react";
import React, { useState, useEffect, useMemo } from "react";
import pad from "../assets/images/pad.svg";
import { useNavigate } from "react-router-dom";
const ReportTable = ({ ReportName, List, actions }) => {
const ReportTable = ({
ReportName,
List,
actions,
setIsNextRecord,
isMoreDocs
}) => {
const navigate = useNavigate();
const [currentPage, setCurrentPage] = useState(1);
const docPerPage = 10;
// const pageNumbers = [];
// For loop is used to calculate page numbers visible below table
// Initialize pageNumbers using useMemo to avoid unnecessary re-creation
const pageNumbers = useMemo(() => {
const calculatedPageNumbers = [];
for (let i = 1; i <= Math.ceil(List.length / docPerPage); i++) {
calculatedPageNumbers.push(i);
}
return calculatedPageNumbers;
}, [List]);
// below useEffect reset currenpage to 1 if user change route
useEffect(() => {
return () => setCurrentPage(1);
}, []);
// `formatRow` is used to show data in poper manner like
// if data is of array type then it will join array items with ","
// if data is of object type then it Name values will be show in row
// if no data available it will show hyphen "-"
const formatRow = (row) => {
if (Array.isArray(row)) {
let updateArr = row.map((x) => x.Name);
@@ -14,24 +42,17 @@ const ReportTable = ({ ReportName, List, actions }) => {
return "-";
}
};
// below useEffect is used to render next record if IsMoreDoc is true
// second last value of pageNumber array is same as currentPage
useEffect(() => {
if (isMoreDocs && pageNumbers[pageNumbers.length - 1] === currentPage) {
setIsNextRecord(true);
}
}, [isMoreDocs, pageNumbers, currentPage, setIsNextRecord]);
// `handlemicroapp` is used to open microapp
const handlemicroapp = (item, url) => {
localStorage.removeItem("rowlevel");
// const params = new URLSearchParams(url);
// let arr = [];
// for (let [key, value] of params.entries()) {
// if (key === "remoteUrl") {
// arr.push(
// `${key}=${window.btoa(
// window.location.origin + "/mfbuild/remoteEntry.js"
// )}`
// );
// } else {
// arr.push(`${key}=${value}`);
// }
// }
// const remoteUrl = arr.join("&");
// console.log("arr", remoteUrl);
navigate("/rpmf/" + url);
localStorage.setItem("rowlevel", JSON.stringify(item));
// localStorage.setItem("rowlevelMicro");
@@ -39,6 +60,17 @@ const ReportTable = ({ ReportName, List, actions }) => {
const handlebtn = () => {
console.log("clicked");
};
// Get current list
const indexOfLastDoc = currentPage * docPerPage;
const indexOfFirstDoc = indexOfLastDoc - docPerPage;
// `currentLists` is total record render on current page
const currentLists = List.slice(indexOfFirstDoc, indexOfLastDoc);
// Change page
const paginateFront = () => setCurrentPage(currentPage + 1);
const paginateBack = () => setCurrentPage(currentPage - 1);
return (
<div className="p-2 overflow-x-scroll w-full bg-white rounded-md">
<h2 className="text-[23px] font-light my-2">{ReportName}</h2>
@@ -60,8 +92,8 @@ const ReportTable = ({ ReportName, List, actions }) => {
<tbody className="text-[12px]">
{List?.length > 0 ? (
<>
{List.map((item, index) => (
<tr className="border-t-[1px]" key={index}>
{currentLists.map((item, index) => (
<tr className="border-y-[1px]" key={index}>
<td className="px-4 py-2">{index + 1}</td>
<td className="px-4 py-2 font-semibold">{item?.Name} </td>
<td className="px-4 py-2">{item?.Note || "-"}</td>
@@ -121,8 +153,46 @@ const ReportTable = ({ ReportName, List, actions }) => {
)}
</tbody>
</table>
<div className="flex flex-wrap items-center gap-2 p-2 ">
{List.length > 10 && (
<>
{currentPage > 1 && (
<button
onClick={() => paginateBack()}
className="bg-blue-400 text-white rounded px-3 py-2 focus:outline-none"
>
Prev
</button>
)}
</>
)}
{pageNumbers.map((x) => (
<button
key={x}
onClick={() => setCurrentPage(x)}
className=" bg-sky-400 text-white rounded px-3 py-2 focus:outline-none"
>
{x}
</button>
))}
{isMoreDocs && (
<button className="text-black rounded px-1 py-2">...</button>
)}
{List.length > 10 && (
<>
{pageNumbers.includes(currentPage + 1) && (
<button
onClick={() => paginateFront()}
className="bg-blue-400 text-white rounded px-3 py-2 focus:outline-none"
>
Next
</button>
)}
</>
)}
</div>
{List?.length <= 0 && (
<div className="flex flex-col items-center justify-center w-full bg-white roundedm py-4">
<div className="flex flex-col items-center justify-center w-full bg-white rounded py-4">
<div className="w-[60px] h-[60px] overflow-hidden">
<img className="w-full h-full object-contain" src={pad} alt="img" />
</div>
+84
View File
@@ -0,0 +1,84 @@
import { Suspense } from "react";
import { useParams } from "react-router-dom";
import useFederatedComponent from "mf-cra";
import React from "react";
import Title from "../components/Title";
function RemoteApp({ app }) {
// console.log("app ", app);
const { Component: RemoteComponent } = useFederatedComponent(app);
// console.log("RemoteComponent ", RemoteComponent);
return (
<>
<Title title={app.remoteName} />
<Suspense
fallback={
<div style={{ height: "300px" }}>
<div
style={{
marginLeft: "45%",
marginTop: "150px",
fontSize: "45px",
color: "#3dd3e0"
}}
className="loader-37"
></div>
</div>
}
>
<div
style={{
boxShadow: "0 1px 3px 0 rgba(0, 0, 0, 0.33)",
backgroundColor: "#ffffff",
width: "100%",
overflow: "hidden",
borderRadius: 3,
minHeight: "70vh"
}}
>
{RemoteComponent && <RemoteComponent />}
</div>
</Suspense>
</>
);
}
function checkObjectProperties(obj) {
// Check if all three properties exist in the object
if (
obj &&
obj.remoteName !== undefined &&
obj.remoteUrl !== undefined &&
obj.moduleToLoad !== undefined
) {
return true; // All properties are present
} else {
return false; // At least one property is missing
}
}
export default function RemoteAppContainer() {
const { remoteApp } = useParams();
const obj = {
remoteUrl: window.location.origin + "/mfbuild/remoteEntry.js",
moduleToLoad: "./AppRoutes",
remoteName: remoteApp
};
// console.log("obj ", obj);
const isMf = checkObjectProperties(obj);
if (isMf) {
const appToLoad = obj;
return <RemoteApp app={appToLoad} />;
} else {
return (
<div className="flex items-center justify-center h-screen w-full bg-white rounded">
<div className="text-center">
<h1 className="text-[60px] lg:text-[120px] font-semibold text-black">
404
</h1>
<p className="text-[30px] lg:text-[50px] text-black">
Page Not Found
</p>
</div>
</div>
);
}
}
+430 -301
View File
@@ -21,17 +21,18 @@ function Login(props) {
passwordVisible: false,
mobile: "",
phone: "",
OTP: "",
hideNav: "",
scanResult: "",
baseUrl: localStorage.getItem("baseUrl"),
parseAppId: localStorage.getItem("parseAppId"),
loading: false,
thirdpartyLoader: false,
orgModal: false,
ReqOtp: ""
thirdpartyLoader: false
});
const [userDetails, setUserDetails] = useState({
Company: "",
Destination: ""
});
const [isModal, setIsModal] = useState(false);
const image = props?.appInfo?.applogo || undefined;
useEffect(() => {
@@ -94,7 +95,6 @@ function Login(props) {
} else {
localStorage.setItem("profileImg", "");
}
// Check extended class user role and tenentId
try {
let userRoles = [];
@@ -114,44 +114,36 @@ function Login(props) {
};
await axios
.post(url, JSON.stringify(body), { headers: headers })
.then((roles) => {
.then((axiosRes) => {
const roles = axiosRes.data.result;
if (roles) {
userRoles = roles.data.result;
userRoles = roles;
let _currentRole = "";
const valuesToExclude = [
"contracts_Guest",
`${localStorage.getItem("_appName")}_appeditor`
];
if (userRoles.length > 1) {
if (
userRoles[0] ===
`${localStorage.getItem("_appName")}_appeditor`
) {
_currentRole = userRoles[1];
} else {
const rolesfiltered = userRoles.filter(
(x) => x !== "contracts_Guest"
);
if (rolesfiltered.length > 0) {
_currentRole = rolesfiltered[0];
} else {
setThirdpartyLoader(false);
setState({
...state,
loading: false,
toastColor: "#d9534f",
toastDescription: `Does not have permissions to access this application.`
});
const x = document.getElementById("snackbar");
x.className = "show";
setTimeout(function () {
x.className = x.className.replace("show", "");
}, 2000);
}
// _currentRole = userRoles[0];
}
const rolesfiltered = userRoles.filter(
(x) => !valuesToExclude.includes(x)
);
if (rolesfiltered.length > 0) {
_currentRole = rolesfiltered[0];
}
} else {
_currentRole = userRoles[0];
const rolesfiltered = userRoles.filter(
(x) => !valuesToExclude.includes(x)
);
if (rolesfiltered.length > 0) {
_currentRole = userRoles[0];
} else {
_currentRole = "";
}
}
if (
_currentRole &&
_currentRole !==
`${localStorage.getItem("_appName")}_appeditor`
`${localStorage.getItem("_appName")}_appeditor`
) {
userSettings.forEach(async (element) => {
if (element.role === _currentRole) {
@@ -178,7 +170,6 @@ function Login(props) {
query.include("TenantId");
await query.find().then(
(results) => {
// console.log("results ", results);
let tenentInfo = [];
if (results) {
let extendedInfo_stringify =
@@ -339,25 +330,27 @@ function Login(props) {
}
},
(error) => {
/* alert(
"You dont have access to this application."
); */
setState({
...state,
loading: false,
toastColor: "#d9534f",
toastDescription:
"You dont 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);
const payload = {
sessionToken: user.getSessionToken()
};
handleSubmitbtn(payload);
// setState({
// ...state,
// loading: false,
// toastColor: "#d9534f",
// toastDescription:
// "You dont 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
@@ -367,45 +360,18 @@ function Login(props) {
}
});
} else {
setState({
...state,
loading: false,
toastColor: "#d9534f",
toastDescription: "User Role Not Found."
});
const x = document.getElementById("snackbar");
x.className = "show";
setTimeout(function () {
x.className = x.className.replace("show", "");
}, 2000);
setState({ ...state, loading: false });
setIsModal(true);
}
} else {
setState({
...state,
loading: false,
toastColor: "#d9534f",
toastDescription: "User Role Not Found."
});
const x = document.getElementById("snackbar");
x.className = "show";
setTimeout(function () {
x.className = x.className.replace("show", "");
}, 2000);
setState({ ...state, loading: false });
setIsModal(true);
}
})
.catch((err) => {
console.log("err", err);
setState({
...state,
loading: false,
toastColor: "#d9534f",
toastDescription: `Does not have permissions to access this application.`
});
const x = document.getElementById("snackbar");
x.className = "show";
setTimeout(function () {
x.className = x.className.replace("show", "");
}, 2000);
setState({ ...state, loading: false });
setIsModal(true);
});
}
} catch (error) {
@@ -460,7 +426,6 @@ function Login(props) {
await Parse.User.become(sessionToken).then(() => {
window.localStorage.setItem("accesstoken", sessionToken);
});
// console.log("me res ", res);
if (res.data) {
let _user = res.data;
localStorage.setItem("UserInformation", JSON.stringify(_user));
@@ -492,25 +457,36 @@ function Login(props) {
};
await axios
.post(url, JSON.stringify(body), { headers: headers })
.then((roles) => {
.then((axiosRes) => {
const roles = axiosRes.data.result;
if (roles) {
userRoles = roles.data.result;
userRoles = roles;
let _currentRole = "";
const valuesToExclude = [
"contracts_Guest",
`${localStorage.getItem("_appName")}_appeditor`
];
if (userRoles.length > 1) {
if (
userRoles[0] ===
`${localStorage.getItem("_appName")}_appeditor`
) {
_currentRole = userRoles[1];
} else {
_currentRole = userRoles[0];
}
const rolesfiltered = userRoles.filter(
(x) => !valuesToExclude.includes(x)
);
if (rolesfiltered.length > 0) {
_currentRole = rolesfiltered[0];
}
} else {
_currentRole = userRoles[0];
const rolesfiltered = userRoles.filter(
(x) => !valuesToExclude.includes(x)
);
if (rolesfiltered.length > 0) {
_currentRole = userRoles[0];
} else {
_currentRole = "";
}
}
if (
_currentRole &&
_currentRole !==
`${localStorage.getItem("_appName")}_appeditor`
`${localStorage.getItem("_appName")}_appeditor`
) {
userSettings.forEach(async (element) => {
if (element.role === _currentRole) {
@@ -581,7 +557,7 @@ function Login(props) {
);
setThirdpartyLoader(false);
setState({ ...state, loading: false });
navigate(`/`);
navigate("/");
} else {
extendedInfo.forEach((x) => {
if (x.TenantId) {
@@ -619,6 +595,7 @@ function Login(props) {
);
setThirdpartyLoader(false);
setState({ ...state, loading: false });
if (process.env.REACT_APP_ENABLE_SUBSCRIPTION) {
if (billingDate) {
if (billingDate > new Date()) {
localStorage.removeItem("userDetails");
@@ -632,6 +609,7 @@ function Login(props) {
navigate(`/subscription`);
}
}
}
} else {
localStorage.setItem("PageLanding", element.pageId);
localStorage.setItem(
@@ -641,6 +619,7 @@ function Login(props) {
localStorage.setItem("pageType", element.pageType);
setState({ ...state, loading: false });
setThirdpartyLoader(false);
if (process.env.REACT_APP_ENABLE_SUBSCRIPTION) {
if (billingDate) {
if (billingDate > new Date()) {
localStorage.removeItem("userDetails");
@@ -654,27 +633,16 @@ function Login(props) {
navigate(`/subscription`);
}
}
},
}
},
(error) => {
/* alert(
"You dont have access to this application."
); */
const payload = {
sessionToken: sessionToken
};
setThirdpartyLoader(false);
handleSubmitbtn(payload);
setState({
...state,
loading: false,
toastColor: "#d9534f",
toastDescription:
"You dont 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);
// localStorage.setItem("accesstoken", null);
console.error("Error while fetching Follow", error);
}
);
@@ -682,47 +650,18 @@ function Login(props) {
});
} else {
setThirdpartyLoader(false);
setState({
...state,
loading: false,
toastColor: "#d9534f",
toastDescription: "User Role Not Found."
});
const x = document.getElementById("snackbar");
x.className = "show";
setTimeout(function () {
x.className = x.className.replace("show", "");
}, 2000);
setState({ ...state, loading: false });
}
} else {
setThirdpartyLoader(false);
setState({
...state,
loading: false,
toastColor: "#d9534f",
toastDescription: "User Role Not Found."
});
const x = document.getElementById("snackbar");
x.className = "show";
setTimeout(function () {
x.className = x.className.replace("show", "");
}, 2000);
setState({ ...state, loading: false });
}
})
.catch(() => {
.catch((err) => {
console.log("err", err);
setThirdpartyLoader(false);
setState({
...state,
loading: false,
toastColor: "#d9534f",
toastDescription: `Does not have permissions to access this application.`
});
const x = document.getElementById("snackbar");
x.className = "show";
setTimeout(function () {
x.className = x.className.replace("show", "");
}, 2000);
setState({ ...state, loading: false });
});
}
} catch (error) {
@@ -744,7 +683,7 @@ function Login(props) {
};
const GetLoginData = async () => {
setState({...state, loading: true})
setState({ ...state, loading: true });
try {
Parse.serverURL = localStorage.getItem("baseUrl");
Parse.initialize(localStorage.getItem("parseAppId"));
@@ -920,11 +859,86 @@ function Login(props) {
setState({ ...state, passwordVisible: !state.passwordVisible });
};
const handleSubmitbtn = async (e) => {
e.preventDefault();
if (userDetails.Destination && userDetails.Company) {
setThirdpartyLoader(true);
// console.log("handelSubmit", userDetails);
// const payload = await Parse.User.logIn(state.email, state.password);
const payload = { sessionToken: localStorage.getItem("accesstoken") };
const userInformation = JSON.parse(
localStorage.getItem("UserInformation")
);
// console.log("payload ", payload);
if (payload && payload.sessionToken) {
const params = {
userDetails: {
name: userInformation.name,
email: userInformation.email,
phone: userInformation.phone,
role: "contracts_User",
company: userDetails.Company,
jobTitle: userDetails.Destination
}
};
const userSignUp = await Parse.Cloud.run("usersignup", params);
// console.log("userSignUp ", userSignUp);
if (userSignUp && userSignUp.sessionToken) {
const LocalUserDetails = {
name: userInformation.name,
email: userInformation.email,
phone: userInformation.phone,
company: userDetails.Company,
jobTitle: userDetails.JobTitle
};
localStorage.setItem("userDetails", JSON.stringify(LocalUserDetails));
thirdpartyLoginfn(userSignUp.sessionToken);
} else {
alert(userSignUp.message);
}
} else if (
payload &&
payload.message.replace(/ /g, "_") === "Internal_server_err"
) {
alert("Internal server error !");
}
} else {
alert("Please fill required details!");
}
};
const handleCloseModal = () => {
setIsModal(false);
Parse.User.logOut();
let appdata = localStorage.getItem("userSettings");
let applogo = localStorage.getItem("appLogo");
let appName = localStorage.getItem("appName");
let defaultmenuid = localStorage.getItem("defaultmenuid");
let PageLanding = localStorage.getItem("PageLanding");
let domain = localStorage.getItem("domain");
let _appName = localStorage.getItem("_appName");
let baseUrl = localStorage.getItem("BaseUrl12");
let appid = localStorage.getItem("AppID12");
localStorage.clear();
localStorage.setItem("appLogo", applogo);
localStorage.setItem("appName", appName);
localStorage.setItem("_appName", _appName);
localStorage.setItem("defaultmenuid", defaultmenuid);
localStorage.setItem("PageLanding", PageLanding);
localStorage.setItem("domain", domain);
localStorage.setItem("userSettings", appdata);
localStorage.setItem("BaseUrl12", baseUrl);
localStorage.setItem("AppID12", appid);
};
return (
<div className="bg-white">
<Title title={"Login Page"} />
{state.loading && (
<div
aria-live="assertive"
style={{
position: "fixed",
width: "100vw",
@@ -936,145 +950,161 @@ function Login(props) {
}}
>
<div
role="status"
style={{
position: "fixed",
fontSize: "50px",
color: "#3ac9d6",
top: "50%",
left: "45%"
left: "50%",
transform: "translate(-50%, -50%)"
}}
className="loader-37"
></div>
>
<span className="sr-only">Loading...</span>
</div>
</div>
)}
{props.isloginVisible && props.isloginVisible ? (
<div>
<div className="md:m-10 lg:m-16 md:p-4 lg:p-10 p-5 bg-[#ffffff] md:border-[1px] md:border-gray-400 ">
<div className="w-[250px] h-[66px] inline-block">
{state.hideNav ? (
<img src={image} width="100%" alt="" />
) : (
<img src={image} width="100%" alt="" />
)}
</div>
<div className="grid grid-cols-1 md:grid-cols-2 gap-x-2">
<div className="">
<>
<div aria-labelledby="loginHeading" role="region">
<div className="md:m-10 lg:m-16 md:p-4 lg:p-10 p-4 bg-[#ffffff] md:border-[1px] md:border-gray-400 ">
<div className="w-[250px] h-[66px] inline-block">
<img
src={image}
width="100%"
alt="The image displays the OpenSign logo with a stylized blue square with an open corner, accompanied by the tagline Seal the Deal, Openly."
/>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 gap-x-2">
<div>
<form onSubmit={handleSubmit}>
<h2 className="text-[30px] mt-6">Welcome Back !</h2>
<span className="text-[12px] text-[#878787]">
Login to your account
</span>
<div className="shadow-md rounded my-4">
<div className="px-6 py-4">
<label className="block text-xs">Username</label>
<input
type="text"
className="px-3 py-2 w-full border-[1px] border-gray-300 rounded focus:outline-none text-xs"
name="email"
value={state.email}
onChange={handleChange}
required
/>
<hr className="my-2 border-none" />
<label className="block text-xs">Password</label>
<div className="relative">
<div>
<form onSubmit={handleSubmit} aria-label="Login Form">
<h1 className="text-[30px] mt-6">Welcome Back!</h1>
<fieldset>
<legend className="text-[12px] text-[#878787]">
Login to your account
</legend>
<div className="px-6 py-4 outline outline-1 outline-slate-300/50 my-2 rounded shadow-md">
<label className="block text-xs" htmlFor="email">
Username
</label>
<input
type={state.passwordVisible ? "text" : "password"}
className="px-3 py-2 w-full border-[1px] border-gray-300 rounded focus:outline-none text-xs"
name="password"
value={state.password}
id="email"
type="text"
className="px-3 py-2 w-full border-[1px] border-gray-300 rounded text-xs"
name="email"
value={state.email}
onChange={handleChange}
required
/>
<span
className={`absolute top-[50%] right-[10px] -translate-y-[50%] cursor-pointer ${
state.passwordVisible
? "text-[#007bff]"
: "text-black"
}`}
onClick={togglePasswordVisibility}
>
{state.passwordVisible ? (
<i className="fa fa-eye-slash text-xs pb-1" /> // Close eye icon
) : (
<i className="fa fa-eye text-xs pb-1 " /> // Open eye icon
)}
</span>
<hr className="my-2 border-none" />
<label className="block text-xs" htmlFor="password">
Password
</label>
<div className="relative">
<input
id="password"
type={state.passwordVisible ? "text" : "password"}
className="px-3 py-2 w-full border-[1px] border-gray-300 rounded text-xs"
name="password"
value={state.password}
onChange={handleChange}
required
/>
<span
className={`absolute top-[50%] right-[10px] -translate-y-[50%] cursor-pointer ${
state.passwordVisible
? "text-[#007bff]"
: "text-black"
}`}
onClick={togglePasswordVisibility}
>
{state.passwordVisible ? (
<i className="fa fa-eye-slash text-xs pb-1" /> // Close eye icon
) : (
<i className="fa fa-eye text-xs pb-1 " /> // Open eye icon
)}
</span>
</div>
</div>
</div>
</div>
<div className="flex flex-row justify-between items-center text-xs px-4 py-2">
<div>
<label className="form-check-label">
<input
type="checkbox"
className="form-check-input"
value=""
/>
<span className="text-center pl-1">
Remember Password
</span>
</label>
</div>
<div>
<span className="text-[13px]">
<NavLink to={`/forgetpassword`}>
</fieldset>
<div className="flex flex-row justify-between items-center ml-4 py-2">
<div>
<label
className="form-check-label inline-block cursor-pointer"
htmlFor="rememberpassword"
>
<input
type="checkbox"
className="form-check-input mr-1"
value=""
id="rememberpassword"
/>
<span className="text-[13px]">
Remember Password
</span>
</label>
</div>
<div>
<NavLink
to="/forgetpassword"
className="text-[13px] underline focus:outline-none focus:ring-2 focus:ring-blue-600"
>
Forgot Password ?
</NavLink>
</span>
</div>
</div>
</div>
<div className="flex flex-col md:flex-row justify-between items-stretch gap-8 text-center text-xs font-bold mt-2">
<button
type="submit"
className="rounded-sm bg-[#3ac9d6] text-white w-full py-3 shadow uppercase"
disabled={state.loading}
<div className="flex flex-col md:flex-row justify-between items-stretch gap-8 text-center text-xs font-bold mt-2">
<button
type="submit"
className="rounded-sm bg-[#3ac9d6] text-white w-full py-3 shadow outline-none uppercase focus:ring-2 focus:ring-blue-600"
disabled={state.loading}
>
{state.loading ? "Loading..." : "Login"}
</button>
<NavLink
className="rounded-sm cursor-pointer bg-white border-[1px] border-[#15b4e9] text-[#15b4e9] w-full py-3 shadow uppercase"
to="/signup"
style={state.hideNav ? { textAlign: "center" } : {}}
>
Create Account
</NavLink>
</div>
</form>
<br />
{(props.appInfo.fbAppId || props.appInfo.googleClietId) && (
<div
style={{
display: "flex",
alignItems: "center",
justifyContent: "center"
}}
className="text-sm"
>
{state.loading ? "Loading..." : "Login"}
</button>
<NavLink
className="rounded-sm cursor-pointer bg-white border-[1px] border-[#15b4e9] text-[#15b4e9] w-full py-3 shadow uppercase"
to="/signup"
style={state.hideNav ? { textAlign: "center" } : {}}
>
Create Account
</NavLink>
</div>
</form>
<br />
{(props.appInfo.fbAppId || props.appInfo.googleClietId) && (
<hr
className={"border-[1px] border-gray-300 w-full"}
style={{ color: "grey" }}
/>
<span style={{ color: "grey" }} className="px-2 ">
OR
</span>
<hr
className={"border-[1px] border-gray-300 w-full"}
style={{ color: "grey" }}
/>
</div>
)}
<br />
<div
style={{
textAlign: "center",
display: "flex",
alignItems: "center",
justifyContent: "center"
}}
className="text-sm"
>
<hr
className={"border-[1px] border-gray-300 w-full"}
style={{ color: "grey" }}
/>
<span style={{ color: "grey" }} className="px-2 ">
OR
</span>
<hr
className={"border-[1px] border-gray-300 w-full"}
style={{ color: "grey" }}
/>
</div>
)}
<br />
<div
style={{
textAlign: "center",
display: "flex",
alignItems: "center",
justifyContent: "center"
}}
>
{/* {props.appInfo.fbAppId && props.appInfo.fbAppId !== "" ? (
{/* {props.appInfo.fbAppId && props.appInfo.fbAppId !== "" ? (
<LoginFacebook
FBCred={props.appInfo.fbAppId}
thirdpartyLoginfn={thirdpartyLoginfn}
@@ -1082,42 +1112,142 @@ function Login(props) {
setThirdpartyLoader={setThirdpartyLoader}
/>
) : null} */}
</div>
<div style={{ margin: "10px 0" }}></div>
<div
style={{
textAlign: "center",
display: "flex",
alignItems: "center",
justifyContent: "center"
}}
>
{props.appInfo.googleClietId &&
props.appInfo.googleClietId !== "" ? (
<GoogleSignInBtn
GoogleCred={props.appInfo.googleClietId}
thirdpartyLoginfn={thirdpartyLoginfn}
thirdpartyLoader={state.thirdpartyLoader}
setThirdpartyLoader={setThirdpartyLoader}
/>
) : null}
</div>
</div>
<div style={{ margin: "10px 0" }}></div>
<div
style={{
textAlign: "center",
display: "flex",
alignItems: "center",
justifyContent: "center"
}}
>
{props.appInfo.googleClietId &&
props.appInfo.googleClietId !== "" ? (
<GoogleSignInBtn
GoogleCred={props.appInfo.googleClietId}
thirdpartyLoginfn={thirdpartyLoginfn}
thirdpartyLoader={state.thirdpartyLoader}
setThirdpartyLoader={setThirdpartyLoader}
</div>
{!state.hideNav && (
<div className="self-center">
<div className="mx-auto md:w-[300px] lg:w-[400px] xl:w-[500px]">
<img
src={login_img}
alt="The image illustrates a person from behind, seated at a desk with a four-monitor computer setup, in an environment with a light blue and white color scheme, featuring a potted plant to the right."
width="100%"
/>
) : null}
</div>
</div>
)}
</div>
</div>
<div
id="snackbar"
role="alert"
style={{ backgroundColor: state.toastColor }}
>
{state.toastDescription}
</div>
</div>
{isModal && (
<div
className="modal fade show"
id="exampleModal"
tabIndex="-1"
role="dialog"
style={{
display: "block",
zIndex: 1,
backgroundColor: "rgba(0,0,0,0.5)"
}}
>
<div className="modal-dialog" role="document">
<div className="modal-content">
<div className="modal-header">
<h5 className="modal-title">Login form</h5>
<span>
<span></span>
</span>
</div>
<div className="modal-body">
<form className="text-sm">
<div className="form-group">
<label
htmlFor="Company"
style={{ display: "flex" }}
className="col-form-label"
>
Company{" "}
<span style={{ fontSize: 13, color: "red" }}>*</span>
</label>
<input
type="text"
className="form-control"
id="Company"
value={userDetails.Company}
onChange={(e) =>
setUserDetails({
...userDetails,
Company: e.target.value
})
}
required
/>
</div>
<div className="form-group">
<label
htmlFor="Destination"
style={{ display: "flex" }}
className="col-form-label"
>
Destination{" "}
<span style={{ fontSize: 13, color: "red" }}>*</span>
</label>
<input
type="text"
className="form-control"
id="Destination"
value={userDetails.Destination}
onChange={(e) =>
setUserDetails({
...userDetails,
Destination: e.target.value
})
}
required
/>
</div>
<div className="mt-4">
<button
type="button"
className="bg-[#6c757d] text-sm p-2 text-white rounded uppercase"
onClick={handleCloseModal}
style={{ marginRight: 10, width: 90 }}
>
Cancel
</button>
<button
type="button"
className="bg-[#17a2b8] text-sm p-2 text-white rounded uppercase"
onClick={(e) => handleSubmitbtn(e)}
>
Login
</button>
</div>
</form>
</div>
</div>
</div>
{!state.hideNav && (
<div className="self-center">
<div className="mx-auto md:w-[300px] lg:w-[500px]">
<img src={login_img} alt="bisec" width="100%" />
</div>
</div>
)}
</div>
</div>
<div id="snackbar" style={{ backgroundColor: state.toastColor }}>
{state.toastDescription}
</div>
</div>
)}
</>
) : (
<div
style={{
@@ -1132,7 +1262,6 @@ function Login(props) {
)}
</div>
);
// }
}
const mapStateToProps = (state) => {
@@ -64,7 +64,7 @@ const PlanSubscriptions = () => {
style={{
backgroundColor: "white",
overflowY: "auto",
maxHeight: "600px",
maxHeight: "100%",
"--theme-color": "#7952b3",
"--plan-width": 30
}}
+3 -1
View File
@@ -65,7 +65,9 @@ export default function RemoteAppContainer() {
// console.log("value ", key + ":" + value);
if (key === "remoteUrl") {
obj = { ...obj, [key]: atob(value) };
const url = window.location.origin + "/mfbuild/remoteEntry.js";
// console.log("atob(value) ", atob(value))
obj = { ...obj, [key]: url };
} else {
if (key === "moduleToLoad") {
obj = { ...obj, [key]: "./" + value };
+57 -8
View File
@@ -12,14 +12,37 @@ const Report = () => {
const [isLoader, setIsLoader] = useState(true);
const [reportName, setReportName] = useState("");
const [actions, setActions] = useState([]);
const [isNextRecord, setIsNextRecord] = useState(false);
const [isMoreDocs, setIsMoreDocs] = useState(true);
const abortController = new AbortController();
// below useEffect is call when id param change
useEffect(() => {
setReportName("");
setList([]);
getReportData();
// Function returned from useEffect is called on unmount
return () => {
setIsLoader(true);
setList([]);
setIsNextRecord(false);
// Here it'll abort the fetch
abortController.abort();
};
// eslint-disable-next-line
}, [id]);
const getReportData = async () => {
setIsLoader(true);
// below useEffect call when isNextRecord state is true and fetch next record
useEffect(() => {
if (isNextRecord) {
getReportData(List.length, 200);
}
// eslint-disable-next-line
}, [isNextRecord]);
const getReportData = async (skipUserRecord = 0, limit = 200) => {
// setIsLoader(true);
const json = reportJson(id);
if (json) {
setActions(json.actions);
@@ -39,8 +62,11 @@ const Report = () => {
"X-Parse-Session-Token": localStorage.getItem("accesstoken")
};
try {
const url = `${serverURL}?where=${strParams}&keys=${strKeys}&order=${orderBy}&include=AuditTrail.UserPtr`;
const res = await axios.get(url, { headers: headers });
const url = `${serverURL}?where=${strParams}&keys=${strKeys}&order=${orderBy}&skip=${skipUserRecord}&limit=${limit}&include=AuditTrail.UserPtr`;
const res = await axios.get(url, {
headers: headers,
signal: abortController.signal // is used to cancel fetch query
});
if (id === "4Hhwbp482K") {
const listData = res.data?.results.filter(
(x) => x.Signers.length > 0
@@ -66,14 +92,35 @@ const Report = () => {
}
}
}
setList(arr);
if (arr.length === 10) {
setIsMoreDocs(true);
} else {
setIsMoreDocs(false);
}
setList((prevRecord) =>
prevRecord.length > 0 ? [...prevRecord, ...arr] : arr
);
} else {
setList(res.data?.results);
if (res.data.results.length === 10) {
setIsMoreDocs(true);
console.log("here");
} else {
setIsMoreDocs(false);
}
setIsNextRecord(false);
setList((prevRecord) =>
prevRecord.length > 0
? [...prevRecord, ...res.data.results]
: res.data.results
);
}
setIsLoader(false);
} catch (err) {
console.log("err ", err);
setIsLoader(false);
const isCancel = axios.isCancel(err);
if (!isCancel) {
console.log("err ", err);
setIsLoader(false);
}
}
} else {
setIsLoader(false);
@@ -106,6 +153,8 @@ const Report = () => {
ReportName={reportName}
List={List}
actions={actions}
setIsNextRecord={setIsNextRecord}
isMoreDocs={isMoreDocs}
/>
) : (
<div className="flex items-center justify-center h-screen w-full bg-white rounded">
+36 -6
View File
@@ -99,9 +99,38 @@ const Signup = (props) => {
}
}
})
.catch((err) => {
alert(err.message);
setState({ loading: false });
.catch(async (err) => {
if (err.code === 202) {
const userQuery = new Parse.Query("contracts_Users");
userQuery.equalTo("Email", email);
const res = await userQuery.first();
// console.log("Res ", res);
if (res) {
alert("User already exists with this username!");
setState({ loading: false });
} else {
let baseUrl = localStorage.getItem("BaseUrl12");
let parseAppId = localStorage.getItem("AppID12");
// console.log("state.email ", email);
try {
Parse.serverURL = baseUrl;
Parse.initialize(parseAppId);
await Parse.User.requestPasswordReset(email).then(
async function (res1) {
if (res1.data === undefined) {
alert("Email has been sent to your mail!");
}
}
);
} catch (err) {
console.log(err);
}
setState({ loading: false });
}
} else {
alert(err.message);
setState({ loading: false });
}
});
} catch (error) {
console.log("err ", error);
@@ -251,7 +280,7 @@ const Signup = (props) => {
element.pageType
);
setState({ loading: false });
navigate("/login");
navigate("/");
} else {
extendedInfo.forEach((x) => {
if (x.TenantId) {
@@ -453,7 +482,7 @@ const Signup = (props) => {
<div className="">
<form onSubmit={handleSubmit}>
<h2 className="text-[30px] mt-6">Create Account !</h2>
<div className="shadow-md rounded my-4">
<div className="outline outline-1 outline-slate-300/50 shadow-md rounded my-4">
<div className="px-6 py-4 text-xs">
<label className="block ">
Name{" "}
@@ -472,6 +501,7 @@ const Signup = (props) => {
<span style={{ color: "red", fontSize: 13 }}>*</span>
</label>
<input
id="email"
type="text"
className="px-3 py-2 w-full border-[1px] border-gray-300 rounded focus:outline-none text-xs"
value={email}
@@ -563,7 +593,7 @@ const Signup = (props) => {
</div>
{!state.hideNav && (
<div className="self-center">
<div className="mx-auto md:w-[300px] lg:w-[500px]">
<div className="mx-auto md:w-[300px] lg:w-[400px] xl:w-[500px]">
<img src={login_img} alt="bisec" width="100%" />
</div>
</div>
+3 -3
View File
@@ -5,7 +5,7 @@ FROM node:16
WORKDIR /usr/src/app
# Copy package.json and package-lock.json first to leverage Docker cache
COPY apps/OpenSignServer/package*.json ./
COPY ./package*.json ./
# Install application dependencies
RUN npm install
@@ -14,7 +14,7 @@ RUN npm install
# RUN apk add --no-cache make gcc g++ python3
# Copy the current directory contents into the container
COPY apps/OpenSignServer/ .
COPY ./ .
# Make port 8080 available to the world outside this container
EXPOSE 8080
@@ -24,4 +24,4 @@ EXPOSE 8080
# ENV DATABASE_URL mongodb://db:27017
# Run the application
CMD ["npm", "start"]
ENTRYPOINT npm start
@@ -4,6 +4,12 @@ import multerS3 from 'multer-s3';
import aws from 'aws-sdk';
import dotenv from 'dotenv';
dotenv.config();
function sanitizeFileName(fileName) {
// Remove spaces and invalid characters
return fileName.replace(/[^a-zA-Z0-9._-]/g, '');
}
async function uploadFile(req, res) {
try {
//--size extended to 100 mb
@@ -50,16 +56,28 @@ async function uploadFile(req, res) {
region: process.env.DO_REGION,
});
// const s3 = new aws.S3();
const upload = multer({
fileFilter: function (req, file, cb) {
if (accepted_extensions.some(ext => file.originalname.toLowerCase().endsWith('.' + ext))) {
return cb(null, true);
const parseBaseUrl = process.env.SERVER_URL;
const parseAppId = process.env.APP_ID;
if (process.env.USE_LOCAL == "TRUE") {
var fileStorage = multer.diskStorage({
destination: function(req, file, cb) {
cb(null, "files/files");
},
metadata: function (req, file, cb) {
cb(null, { fieldName: 'OPENSIGN_METADATA' });
},
filename: function(req, file, cb) {
let filename = file.originalname;
let newFileName = filename.split('.')[0];
let extension = filename.split('.')[1];
newFileName = sanitizeFileName(newFileName + '_' + new Date().toISOString() + '.' + extension)
console.log(newFileName);
cb(null, newFileName);
}
// otherwise, return error
return cb('Only ' + accepted_extensions.join(', ') + ' files are allowed!');
},
storage: multerS3({
});
} else {
var fileStorage = multerS3({
acl: 'public-read',
s3,
bucket: DO_SPACE,
@@ -69,14 +87,25 @@ async function uploadFile(req, res) {
key: function (req, file, cb) {
//console.log(file);
let filename = file.originalname;
let filenam = filename.split('.')[0];
let newFileName = filename.split('.')[0];
let extension = filename.split('.')[1];
filenam = filenam + '_' + new Date().toISOString() + '.' + extension;
console.log(filenam);
cb(null, filenam);
},
}),
newFileName = sanitizeFileName(newFileName + '_' + new Date().toISOString() + '.' + extension)
console.log(newFileName);
cb(null, newFileName);
}
});
}
// const s3 = new aws.S3();
const upload = multer({
fileFilter: function (req, file, cb) {
if (accepted_extensions.some(ext => file.originalname.toLowerCase().endsWith('.' + ext))) {
return cb(null, true);
}
// otherwise, return error
return cb('Only ' + accepted_extensions.join(', ') + ' files are allowed!');
},
storage: fileStorage,
limits: { fileSize: size },
}).single('file');
@@ -93,7 +122,14 @@ async function uploadFile(req, res) {
const status = 'Success';
//res.header("Access-Control-Allow-Headers", "Content-Type");
//res.setHeader("Access-Control-Allow-Origin", "*");
return res.json({ status, imageUrl: req.file.location });
if (process.env.USE_LOCAL == "TRUE") {
console.log(req.file);
var fileUrl = `${parseBaseUrl}/files/${parseAppId}/${req.file.filename}`;
} else {
var fileUrl = req.file.location;
}
return res.json({ status, imageUrl: fileUrl });
});
} catch (err) {
console.log('Exeption in query ' + err.stack);
@@ -1 +1 @@
const signer=require("node-signpdf").default;class SignPDF{constructor(e,t){this.pdfDoc=e,this.certificate=t}async signPDF(){return signer.sign(this.pdfDoc,this.certificate,{passphrase:"emudhra"})}static unit8ToBuffer(e){var t=Buffer.alloc(e.byteLength),r=new Uint8Array(e);for(let e=0;e<t.length;++e)t[e]=r[e];return t}}module.exports=SignPDF;
const signer=require("node-signpdf").default;class SignPDF{constructor(e,t){this.pdfDoc=e,this.certificate=t}async signPDF(){return signer.sign(this.pdfDoc,this.certificate, process.env.PASS_PHRASE ? {passphrase : process.env.PASS_PHRASE}: null)}static unit8ToBuffer(e){var t=Buffer.alloc(e.byteLength),r=new Uint8Array(e);for(let e=0;e<t.length;++e)t[e]=r[e];return t}}module.exports=SignPDF;
@@ -123,6 +123,9 @@ export default async function (request) {
if (userDetails && userDetails.company) {
newObj.set("Company", userDetails.company);
}
if (userDetails && userDetails.jobTitle) {
newObj.set("JobTitle", userDetails.jobTitle);
}
if (planDetails && planDetails.customer_id) {
newObj.set("Next_billing_date", new Date(planDetails.nextBillingDate));
newObj.set("Plan", planDetails.plan);
+22 -13
View File
@@ -14,23 +14,31 @@ import formData from 'form-data';
import Mailgun from 'mailgun.js';
import { ApiPayloadConverter } from 'parse-server-api-mail-adapter';
import S3Adapter from 'parse-server-s3-adapter';
import FSFilesAdapter from 'parse-server-fs-adapter';
import AWS from 'aws-sdk';
import { app as customRoute } from './cloud/customRoute/customApp.js';
const spacesEndpoint = new AWS.Endpoint(process.env.DO_ENDPOINT);
// console.log("configuration ", configuration);
const s3Options = {
bucket: process.env.DO_SPACE, // globalConfig.S3FilesAdapter.bucket,
baseUrl: process.env.DO_BASEURL,
region: process.env.DO_REGION,
directAccess: true,
preserveFileName: true,
s3overrides: {
accessKeyId: process.env.DO_ACCESS_KEY_ID,
secretAccessKey: process.env.DO_SECRET_ACCESS_KEY,
endpoint: spacesEndpoint,
},
};
if (process.env.USE_LOCAL !== "TRUE") {
const s3Options = {
bucket: process.env.DO_SPACE, // globalConfig.S3FilesAdapter.bucket,
baseUrl: process.env.DO_BASEURL,
region: process.env.DO_REGION,
directAccess: true,
preserveFileName: true,
s3overrides: {
accessKeyId: process.env.DO_ACCESS_KEY_ID,
secretAccessKey: process.env.DO_SECRET_ACCESS_KEY,
endpoint: spacesEndpoint,
},
};
var fsAdapter = new S3Adapter(s3Options);
} else {
var fsAdapter = new FSFilesAdapter({
"filesSubDirectory": "files" // optional, defaults to ./files
});
}
let mailgunClient;
let mailgunDomain;
@@ -55,6 +63,7 @@ export const config = {
publicServerURL: process.env.SERVER_URL || 'http://localhost:8080/app',
// Your apps name. This will appear in the subject and body of the emails that are sent.
appName: 'Open Sign',
allowClientClassCreation: false,
emailAdapter: process.env.MAILGUN_API_KEY
? {
module: 'parse-server-api-mail-adapter',
@@ -85,7 +94,7 @@ export const config = {
},
}
: null,
filesAdapter: new S3Adapter(s3Options),
filesAdapter: fsAdapter,
auth: {
google: {
enabled: true,
+353 -240
View File
@@ -25,8 +25,8 @@
"node-forge": "^1.3.1",
"node-signpdf": "^1.5.1",
"openai": "^4.8.0",
"parse": "4.0.1",
"parse-server": "6.0.0",
"parse": "4.1.0",
"parse-server": "6.3.1",
"parse-server-api-mail-adapter": "^3.0.0",
"parse-server-s3-adapter": "^1.2.0",
"pdf-lib": "^1.16.0",
@@ -301,9 +301,9 @@
}
},
"node_modules/@babel/runtime": {
"version": "7.18.0",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.18.0.tgz",
"integrity": "sha512-YMQvx/6nKEaucl0MY56mwIG483xk8SDNdlUwb2Ts6FUpr7fm85DxEmsY18LXBNhcTz6tO6JwZV8w1W06v8UKeg==",
"version": "7.15.4",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.15.4.tgz",
"integrity": "sha512-99catp6bHCaxr4sJ/DbTGgHS4+Rs2RVd2g7iOap6SLGPDknRK9ztKNsE/Fg6QhSeh1FGE5f6gHGQmvvn3I3xhw==",
"dependencies": {
"regenerator-runtime": "^0.13.4"
},
@@ -312,12 +312,12 @@
}
},
"node_modules/@babel/runtime-corejs3": {
"version": "7.17.8",
"resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.17.8.tgz",
"integrity": "sha512-ZbYSUvoSF6dXZmMl/CYTMOvzIFnbGfv4W3SEHYgMvNsFTeLaF2gkGAF4K2ddmtSK4Emej+0aYcnSC6N5dPCXUQ==",
"version": "7.21.0",
"resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.21.0.tgz",
"integrity": "sha512-TDD4UJzos3JJtM+tHX+w2Uc+KWj7GV+VKKFdMVd2Rx8sdA19hcc3P3AHFYd5LVOw+pYuSd5lICC3gm52B6Rwxw==",
"dependencies": {
"core-js-pure": "^3.20.2",
"regenerator-runtime": "^0.13.4"
"core-js-pure": "^3.25.1",
"regenerator-runtime": "^0.13.11"
},
"engines": {
"node": ">=6.9.0"
@@ -888,65 +888,6 @@
"eslint-scope": "5.1.1"
}
},
"node_modules/@node-redis/bloom": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/@node-redis/bloom/-/bloom-1.0.1.tgz",
"integrity": "sha512-mXEBvEIgF4tUzdIN89LiYsbi6//EdpFA7L8M+DHCvePXg+bfHWi+ct5VI6nHUFQE5+ohm/9wmgihCH3HSkeKsw==",
"peerDependencies": {
"@node-redis/client": "^1.0.0"
}
},
"node_modules/@node-redis/client": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/@node-redis/client/-/client-1.0.5.tgz",
"integrity": "sha512-ESZ3bd1f+od62h4MaBLKum+klVJfA4wAeLHcVQBkoXa1l0viFesOWnakLQqKg+UyrlJhZmXJWtu0Y9v7iTMrig==",
"dependencies": {
"cluster-key-slot": "1.1.0",
"generic-pool": "3.8.2",
"redis-parser": "3.0.0",
"yallist": "4.0.0"
},
"engines": {
"node": ">=12"
}
},
"node_modules/@node-redis/client/node_modules/yallist": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
},
"node_modules/@node-redis/graph": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/@node-redis/graph/-/graph-1.0.0.tgz",
"integrity": "sha512-mRSo8jEGC0cf+Rm7q8mWMKKKqkn6EAnA9IA2S3JvUv/gaWW/73vil7GLNwion2ihTptAm05I9LkepzfIXUKX5g==",
"peerDependencies": {
"@node-redis/client": "^1.0.0"
}
},
"node_modules/@node-redis/json": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/@node-redis/json/-/json-1.0.2.tgz",
"integrity": "sha512-qVRgn8WfG46QQ08CghSbY4VhHFgaTY71WjpwRBGEuqGPfWwfRcIf3OqSpR7Q/45X+v3xd8mvYjywqh0wqJ8T+g==",
"peerDependencies": {
"@node-redis/client": "^1.0.0"
}
},
"node_modules/@node-redis/search": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/@node-redis/search/-/search-1.0.5.tgz",
"integrity": "sha512-MCOL8iCKq4v+3HgEQv8zGlSkZyXSXtERgrAJ4TSryIG/eLFy84b57KmNNa/V7M1Q2Wd2hgn2nPCGNcQtk1R1OQ==",
"peerDependencies": {
"@node-redis/client": "^1.0.0"
}
},
"node_modules/@node-redis/time-series": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/@node-redis/time-series/-/time-series-1.0.2.tgz",
"integrity": "sha512-HGQ8YooJ8Mx7l28tD7XjtB3ImLEjlUxG1wC1PAjxu6hPJqjPshUZxAICzDqDjtIbhDTf48WXXUcx8TQJB1XTKA==",
"peerDependencies": {
"@node-redis/client": "^1.0.0"
}
},
"node_modules/@node-rs/bcrypt": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@node-rs/bcrypt/-/bcrypt-1.1.0.tgz",
@@ -1193,6 +1134,27 @@
}
}
},
"node_modules/@parse/node-apn/node_modules/jsonwebtoken": {
"version": "8.5.1",
"resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz",
"integrity": "sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w==",
"dependencies": {
"jws": "^3.2.2",
"lodash.includes": "^4.3.0",
"lodash.isboolean": "^3.0.3",
"lodash.isinteger": "^4.0.4",
"lodash.isnumber": "^3.0.3",
"lodash.isplainobject": "^4.0.6",
"lodash.isstring": "^4.0.1",
"lodash.once": "^4.0.0",
"ms": "^2.1.1",
"semver": "^5.6.0"
},
"engines": {
"node": ">=4",
"npm": ">=1.4.28"
}
},
"node_modules/@parse/node-apn/node_modules/node-forge": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.0.tgz",
@@ -1201,6 +1163,14 @@
"node": ">= 6.13.0"
}
},
"node_modules/@parse/node-apn/node_modules/semver": {
"version": "5.7.2",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz",
"integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==",
"bin": {
"semver": "bin/semver"
}
},
"node_modules/@parse/node-gcm": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/@parse/node-gcm/-/node-gcm-1.0.2.tgz",
@@ -1301,9 +1271,9 @@
}
},
"node_modules/@parse/push-adapter": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/@parse/push-adapter/-/push-adapter-4.1.2.tgz",
"integrity": "sha512-034vZTlAzgdfefIY4+Q4j8DHS/VwUAIVoh1JeRkHNfyQmUQ++uKbQbUQdJ/nf11HHS69kwLENs13BmhlHMpyHQ==",
"version": "4.1.3",
"resolved": "https://registry.npmjs.org/@parse/push-adapter/-/push-adapter-4.1.3.tgz",
"integrity": "sha512-Oy53ag7DpUva5dUWwP6tNEsrxv2xU9QIk+rb84q1DIm1qVgo2yl4oXcZ3FPG2Ks/NYURbv4w+z9oaSgVfyBRfQ==",
"dependencies": {
"@parse/node-apn": "5.1.3",
"@parse/node-gcm": "1.0.2",
@@ -1314,17 +1284,6 @@
"node": ">= 12"
}
},
"node_modules/@parse/push-adapter/node_modules/@babel/runtime": {
"version": "7.15.4",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.15.4.tgz",
"integrity": "sha512-99catp6bHCaxr4sJ/DbTGgHS4+Rs2RVd2g7iOap6SLGPDknRK9ztKNsE/Fg6QhSeh1FGE5f6gHGQmvvn3I3xhw==",
"dependencies": {
"regenerator-runtime": "^0.13.4"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@parse/push-adapter/node_modules/@babel/runtime-corejs3": {
"version": "7.14.7",
"resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.14.7.tgz",
@@ -1473,6 +1432,64 @@
"pako": "^1.0.10"
}
},
"node_modules/@redis/bloom": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/@redis/bloom/-/bloom-1.2.0.tgz",
"integrity": "sha512-HG2DFjYKbpNmVXsa0keLHp/3leGJz1mjh09f2RLGGLQZzSHpkmZWuwJbAvo3QcRY8p80m5+ZdXZdYOSBLlp7Cg==",
"peerDependencies": {
"@redis/client": "^1.0.0"
}
},
"node_modules/@redis/client": {
"version": "1.5.7",
"resolved": "https://registry.npmjs.org/@redis/client/-/client-1.5.7.tgz",
"integrity": "sha512-gaOBOuJPjK5fGtxSseaKgSvjiZXQCdLlGg9WYQst+/GRUjmXaiB5kVkeQMRtPc7Q2t93XZcJfBMSwzs/XS9UZw==",
"dependencies": {
"cluster-key-slot": "1.1.2",
"generic-pool": "3.9.0",
"yallist": "4.0.0"
},
"engines": {
"node": ">=14"
}
},
"node_modules/@redis/client/node_modules/yallist": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
},
"node_modules/@redis/graph": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@redis/graph/-/graph-1.1.0.tgz",
"integrity": "sha512-16yZWngxyXPd+MJxeSr0dqh2AIOi8j9yXKcKCwVaKDbH3HTuETpDVPcLujhFYVPtYrngSco31BUcSa9TH31Gqg==",
"peerDependencies": {
"@redis/client": "^1.0.0"
}
},
"node_modules/@redis/json": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/@redis/json/-/json-1.0.4.tgz",
"integrity": "sha512-LUZE2Gdrhg0Rx7AN+cZkb1e6HjoSKaeeW8rYnt89Tly13GBI5eP4CwDVr+MY8BAYfCg4/N15OUrtLoona9uSgw==",
"peerDependencies": {
"@redis/client": "^1.0.0"
}
},
"node_modules/@redis/search": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/@redis/search/-/search-1.1.2.tgz",
"integrity": "sha512-/cMfstG/fOh/SsE+4/BQGeuH/JJloeWuH+qJzM8dbxuWvdWibWAOAHHCZTMPhV3xIlH4/cUEIA8OV5QnYpaVoA==",
"peerDependencies": {
"@redis/client": "^1.0.0"
}
},
"node_modules/@redis/time-series": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/@redis/time-series/-/time-series-1.0.4.tgz",
"integrity": "sha512-ThUIgo2U/g7cCuZavucQTQzA9g9JbDDY2f64u3AbAoz/8vE2lt2U37LamDUVChhaDA3IRT9R6VvJwqnUfTJzng==",
"peerDependencies": {
"@redis/client": "^1.0.0"
}
},
"node_modules/@repeaterjs/repeater": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/@repeaterjs/repeater/-/repeater-3.0.4.tgz",
@@ -1889,11 +1906,11 @@
}
},
"node_modules/assert-options": {
"version": "0.7.0",
"resolved": "https://registry.npmjs.org/assert-options/-/assert-options-0.7.0.tgz",
"integrity": "sha512-7q9uNH/Dh8gFgpIIb9ja8PJEWA5AQy3xnBC8jtKs8K/gNVCr1K6kIvlm59HUyYgvM7oEDoLzGgPcGd9FqhtXEQ==",
"version": "0.8.1",
"resolved": "https://registry.npmjs.org/assert-options/-/assert-options-0.8.1.tgz",
"integrity": "sha512-5lNGRB5g5i2bGIzb+J1QQE1iKU/WEMVBReFIc5pPDWjcPj23otPL0eI6PB2v7QPi0qU6Mhym5D3y0ZiSIOf3GA==",
"engines": {
"node": ">=8.0.0"
"node": ">=10.0.0"
}
},
"node_modules/assert-plus": {
@@ -2506,9 +2523,9 @@
}
},
"node_modules/cluster-key-slot": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.1.0.tgz",
"integrity": "sha512-2Nii8p3RwAPiFwsnZvukotvow2rIHM+yQ6ZcBXGHdniadkYGZYiGmkHJIbZPIV9nfv7m/U1IPMVVcAhoWFeklw==",
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.1.2.tgz",
"integrity": "sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA==",
"engines": {
"node": ">=0.10.0"
}
@@ -2573,11 +2590,11 @@
}
},
"node_modules/commander": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz",
"integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==",
"version": "10.0.1",
"resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz",
"integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==",
"engines": {
"node": ">= 6"
"node": ">=14"
}
},
"node_modules/commondir": {
@@ -2664,9 +2681,9 @@
"integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ=="
},
"node_modules/core-js-pure": {
"version": "3.30.2",
"resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.30.2.tgz",
"integrity": "sha512-p/npFUJXXBkCCTIlEGBdghofn00jWG6ZOtdoIXSJmAu2QBvN0IqpZXWweOytcwE6cfx8ZvVUy1vw8zxhe4Y2vg==",
"version": "3.33.2",
"resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.33.2.tgz",
"integrity": "sha512-a8zeCdyVk7uF2elKIGz67AjcXOxjRbwOLz8SbklEso1V+2DoW4OkAMZN9S9GBgvZIaqQi/OemFX4OiSoQEmg1Q==",
"hasInstallScript": true,
"funding": {
"type": "opencollective",
@@ -3804,9 +3821,9 @@
}
},
"node_modules/express-rate-limit": {
"version": "6.6.0",
"resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-6.6.0.tgz",
"integrity": "sha512-HFN2+4ZGdkQOS8Qli4z6knmJFnw6lZed67o6b7RGplWeb1Z0s8VXaj3dUgPIdm9hrhZXTRpCTHXA0/2Eqex0vA==",
"version": "6.7.0",
"resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-6.7.0.tgz",
"integrity": "sha512-vhwIdRoqcYB/72TK3tRZI+0ttS8Ytrk24GfmsxDXK9o9IhHNO5bXRiXQSExPQ4GbaE5tvIS7j1SGrxsuWs+sGA==",
"engines": {
"node": ">= 12.9.0"
},
@@ -4299,9 +4316,9 @@
}
},
"node_modules/generic-pool": {
"version": "3.8.2",
"resolved": "https://registry.npmjs.org/generic-pool/-/generic-pool-3.8.2.tgz",
"integrity": "sha512-nGToKy6p3PAbYQ7p1UlWl6vSPwfwU6TMSWK7TTu+WUY4ZjyZQGniGGt2oNVvyNSpyZYSB43zMXVLcBm08MTMkg==",
"version": "3.9.0",
"resolved": "https://registry.npmjs.org/generic-pool/-/generic-pool-3.9.0.tgz",
"integrity": "sha512-hymDOu5B53XvN4QT9dBmZxPX4CWhBPPLguTZ9MMFeFa/Kg0xWVfylOVNlJji/E7yTZWFd/q9GO5TxDLq156D7g==",
"engines": {
"node": ">= 4"
}
@@ -4764,9 +4781,9 @@
}
},
"node_modules/idb-keyval": {
"version": "6.0.3",
"resolved": "https://registry.npmjs.org/idb-keyval/-/idb-keyval-6.0.3.tgz",
"integrity": "sha512-yh8V7CnE6EQMu9YDwQXhRxwZh4nv+8xm/HV4ZqK4IiYFJBWYGjJuykADJbSP+F/GDXUBwCSSNn/14IpGL81TuA==",
"version": "6.2.0",
"resolved": "https://registry.npmjs.org/idb-keyval/-/idb-keyval-6.2.0.tgz",
"integrity": "sha512-uw+MIyQn2jl3+hroD7hF8J7PUviBU7BPKWw4f/ISf32D4LoGu98yHjrzWWJDASu9QNrX10tCJqk9YY0ClWm8Ng==",
"dependencies": {
"safari-14-idb-fix": "^3.0.0"
}
@@ -5559,34 +5576,50 @@
}
},
"node_modules/jsonwebtoken": {
"version": "8.5.1",
"resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz",
"integrity": "sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w==",
"version": "9.0.0",
"resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.0.tgz",
"integrity": "sha512-tuGfYXxkQGDPnLJ7SibiQgVgeDgfbPq2k2ICcbgqW8WxWLBAxKQM/ZCu/IT8SOSwmaYl4dpTFCW5xZv7YbbWUw==",
"dependencies": {
"jws": "^3.2.2",
"lodash.includes": "^4.3.0",
"lodash.isboolean": "^3.0.3",
"lodash.isinteger": "^4.0.4",
"lodash.isnumber": "^3.0.3",
"lodash.isplainobject": "^4.0.6",
"lodash.isstring": "^4.0.1",
"lodash.once": "^4.0.0",
"lodash": "^4.17.21",
"ms": "^2.1.1",
"semver": "^5.6.0"
"semver": "^7.3.8"
},
"engines": {
"node": ">=4",
"npm": ">=1.4.28"
"node": ">=12",
"npm": ">=6"
}
},
"node_modules/jsonwebtoken/node_modules/lru-cache": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
"dependencies": {
"yallist": "^4.0.0"
},
"engines": {
"node": ">=10"
}
},
"node_modules/jsonwebtoken/node_modules/semver": {
"version": "5.7.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
"integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
"version": "7.5.4",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz",
"integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==",
"dependencies": {
"lru-cache": "^6.0.0"
},
"bin": {
"semver": "bin/semver"
"semver": "bin/semver.js"
},
"engines": {
"node": ">=10"
}
},
"node_modules/jsonwebtoken/node_modules/yallist": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
},
"node_modules/jsprim": {
"version": "1.4.2",
"resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz",
@@ -7277,45 +7310,44 @@
}
},
"node_modules/parse": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/parse/-/parse-4.0.1.tgz",
"integrity": "sha512-ctv7zaVKlQIBSbarorB7TH3yacDzCvgWBP4ccpLKxlpe21QlaY88kv9V7ca7JdG/Txb3qWug4MwepQoPogXB6Q==",
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/parse/-/parse-4.1.0.tgz",
"integrity": "sha512-s0Ti+nWrKWj9DlFcmkEE05fGwa/K5ycZSdqCz01F8YL7Hevqv4WLXAmYGOwzq5UJSZ005seKgb20KwVwLdy/Zg==",
"dependencies": {
"@babel/runtime": "7.18.0",
"@babel/runtime-corejs3": "7.17.8",
"idb-keyval": "6.0.3",
"@babel/runtime-corejs3": "7.21.0",
"idb-keyval": "6.2.0",
"react-native-crypto-js": "1.0.0",
"uuid": "3.4.0",
"ws": "8.6.0",
"uuid": "9.0.0",
"ws": "8.12.0",
"xmlhttprequest": "1.8.0"
},
"engines": {
"node": ">=14.21.0 <17 || >=18 <19"
"node": ">=14.21.0 <17 || >=18 <20"
},
"optionalDependencies": {
"crypto-js": "4.1.1"
}
},
"node_modules/parse-server": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/parse-server/-/parse-server-6.0.0.tgz",
"integrity": "sha512-Ma7TP3ONqd4ja3KcEO4tnO55YiZ5w5ihtucQoAbeJwbKXqwZ3A0E9t4o4ilPqDKO+qxo+cA9yoNKej2cGVVVTg==",
"version": "6.3.1",
"resolved": "https://registry.npmjs.org/parse-server/-/parse-server-6.3.1.tgz",
"integrity": "sha512-Dhf6mCqRlvPNbeuGl71d+FpBakXFSIEw2ayhnDee8L99WYZTCiP8x4RDs/xIdXVsUIgRWR1xvkEtRHuyll75OA==",
"hasInstallScript": true,
"dependencies": {
"@babel/eslint-parser": "7.19.1",
"@graphql-tools/merge": "8.3.6",
"@babel/eslint-parser": "7.21.8",
"@graphql-tools/merge": "8.4.1",
"@graphql-tools/schema": "9.0.4",
"@graphql-tools/utils": "8.12.0",
"@graphql-yoga/node": "2.6.0",
"@parse/fs-files-adapter": "1.2.2",
"@parse/push-adapter": "4.1.2",
"@parse/push-adapter": "4.1.3",
"bcryptjs": "2.4.3",
"body-parser": "1.20.1",
"commander": "5.1.0",
"body-parser": "1.20.2",
"commander": "10.0.1",
"cors": "2.8.5",
"deepcopy": "2.1.0",
"express": "4.18.2",
"express-rate-limit": "6.6.0",
"express-rate-limit": "6.7.0",
"follow-redirects": "1.15.2",
"graphql": "16.6.0",
"graphql-list-fields": "2.0.2",
@@ -7323,27 +7355,28 @@
"graphql-tag": "2.12.6",
"intersect": "1.0.1",
"ip-range-check": "0.2.0",
"jsonwebtoken": "8.5.1",
"jsonwebtoken": "9.0.0",
"jwks-rsa": "2.1.5",
"ldapjs": "2.3.3",
"lodash": "4.17.21",
"lru-cache": "7.12.0",
"lru-cache": "9.1.1",
"mime": "3.0.0",
"mongodb": "4.10.0",
"mustache": "4.2.0",
"parse": "4.0.1",
"path-to-regexp": "0.1.7",
"pg-monitor": "1.5.0",
"pg-promise": "10.12.1",
"parse": "4.1.0",
"path-to-regexp": "6.2.1",
"pg-monitor": "2.0.0",
"pg-promise": "11.5.0",
"pluralize": "8.0.0",
"redis": "4.0.6",
"semver": "7.3.8",
"rate-limit-redis": "3.0.2",
"redis": "4.6.6",
"semver": "7.5.2",
"subscriptions-transport-ws": "0.11.0",
"tv4": "1.3.0",
"uuid": "9.0.0",
"winston": "3.8.1",
"winston": "3.8.2",
"winston-daily-rotate-file": "4.7.1",
"ws": "8.9.0"
"ws": "8.13.0"
},
"bin": {
"parse-server": "bin/parse-server"
@@ -7380,9 +7413,9 @@
}
},
"node_modules/parse-server/node_modules/@babel/eslint-parser": {
"version": "7.19.1",
"resolved": "https://registry.npmjs.org/@babel/eslint-parser/-/eslint-parser-7.19.1.tgz",
"integrity": "sha512-AqNf2QWt1rtu2/1rLswy6CDP7H9Oh3mMhk177Y67Rg8d7RD9WfOLLv8CGn6tisFvS2htm86yIe1yLF6I1UDaGQ==",
"version": "7.21.8",
"resolved": "https://registry.npmjs.org/@babel/eslint-parser/-/eslint-parser-7.21.8.tgz",
"integrity": "sha512-HLhI+2q+BP3sf78mFUZNCGc10KEmoUqtUT1OCdMZsN+qr4qFeLUod62/zAnF3jNQstwyasDkZnVXwfK2Bml7MQ==",
"dependencies": {
"@nicolo-ribaudo/eslint-scope-5-internals": "5.1.1-v1",
"eslint-visitor-keys": "^2.1.0",
@@ -7397,13 +7430,60 @@
}
},
"node_modules/parse-server/node_modules/@babel/eslint-parser/node_modules/semver": {
"version": "6.3.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
"version": "6.3.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
"integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
"bin": {
"semver": "bin/semver.js"
}
},
"node_modules/parse-server/node_modules/@graphql-tools/merge": {
"version": "8.4.1",
"resolved": "https://registry.npmjs.org/@graphql-tools/merge/-/merge-8.4.1.tgz",
"integrity": "sha512-hssnPpZ818mxgl5+GfyOOSnnflAxiaTn1A1AojZcIbh4J52sS1Q0gSuBR5VrnUDjuxiqoCotpXdAQl+K+U6KLQ==",
"dependencies": {
"@graphql-tools/utils": "^9.2.1",
"tslib": "^2.4.0"
},
"peerDependencies": {
"graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0"
}
},
"node_modules/parse-server/node_modules/@graphql-tools/merge/node_modules/@graphql-tools/utils": {
"version": "9.2.1",
"resolved": "https://registry.npmjs.org/@graphql-tools/utils/-/utils-9.2.1.tgz",
"integrity": "sha512-WUw506Ql6xzmOORlriNrD6Ugx+HjVgYxt9KCXD9mHAak+eaXSwuGGPyE60hy9xaDEoXKBsG7SkG69ybitaVl6A==",
"dependencies": {
"@graphql-typed-document-node/core": "^3.1.1",
"tslib": "^2.4.0"
},
"peerDependencies": {
"graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0"
}
},
"node_modules/parse-server/node_modules/body-parser": {
"version": "1.20.2",
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz",
"integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==",
"dependencies": {
"bytes": "3.1.2",
"content-type": "~1.0.5",
"debug": "2.6.9",
"depd": "2.0.0",
"destroy": "1.2.0",
"http-errors": "2.0.0",
"iconv-lite": "0.4.24",
"on-finished": "2.4.1",
"qs": "6.11.0",
"raw-body": "2.5.2",
"type-is": "~1.6.18",
"unpipe": "1.0.0"
},
"engines": {
"node": ">= 0.8",
"npm": "1.2.8000 || >= 1.4.16"
}
},
"node_modules/parse-server/node_modules/bson": {
"version": "4.7.2",
"resolved": "https://registry.npmjs.org/bson/-/bson-4.7.2.tgz",
@@ -7415,6 +7495,14 @@
"node": ">=6.9.0"
}
},
"node_modules/parse-server/node_modules/debug": {
"version": "2.6.9",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
"dependencies": {
"ms": "2.0.0"
}
},
"node_modules/parse-server/node_modules/denque": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz",
@@ -7424,11 +7512,11 @@
}
},
"node_modules/parse-server/node_modules/lru-cache": {
"version": "7.12.0",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.12.0.tgz",
"integrity": "sha512-OIP3DwzRZDfLg9B9VP/huWBlpvbkmbfiBy8xmsXp4RPmE4A3MhwNozc5ZJ3fWnSg8fDcdlE/neRTPG2ycEKliw==",
"version": "9.1.1",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-9.1.1.tgz",
"integrity": "sha512-65/Jky17UwSb0BuB9V+MyDpsOtXKmYwzhyl+cOa9XUiI4uV2Ouy/2voFP3+al0BjZbJgMBD8FojMpAf+Z+qn4A==",
"engines": {
"node": ">=12"
"node": "14 || >=16.14"
}
},
"node_modules/parse-server/node_modules/mongodb": {
@@ -7448,10 +7536,34 @@
"saslprep": "^1.0.3"
}
},
"node_modules/parse-server/node_modules/ms": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
},
"node_modules/parse-server/node_modules/path-to-regexp": {
"version": "6.2.1",
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.2.1.tgz",
"integrity": "sha512-JLyh7xT1kizaEvcaXOQwOc2/Yhw6KZOvPf1S8401UyLk86CU79LN3vl7ztXGm/pZ+YjoyAJ4rxmHwbkBXJX+yw=="
},
"node_modules/parse-server/node_modules/raw-body": {
"version": "2.5.2",
"resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz",
"integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==",
"dependencies": {
"bytes": "3.1.2",
"http-errors": "2.0.0",
"iconv-lite": "0.4.24",
"unpipe": "1.0.0"
},
"engines": {
"node": ">= 0.8"
}
},
"node_modules/parse-server/node_modules/semver": {
"version": "7.3.8",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz",
"integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==",
"version": "7.5.2",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.5.2.tgz",
"integrity": "sha512-SoftuTROv/cRjCze/scjGyiDtcUyxw1rgYQSZY7XTmtR5hX+dm76iDbTH8TkLPHCQmlbQVSSbNZCPM2hb0knnQ==",
"dependencies": {
"lru-cache": "^6.0.0"
},
@@ -7482,15 +7594,15 @@
}
},
"node_modules/parse-server/node_modules/ws": {
"version": "8.9.0",
"resolved": "https://registry.npmjs.org/ws/-/ws-8.9.0.tgz",
"integrity": "sha512-Ja7nszREasGaYUYCI2k4lCKIRTt+y7XuqVoHR44YpI49TtryyqbqvDMn5eqfW7e6HzTukDRIsXqzVHScqRcafg==",
"version": "8.13.0",
"resolved": "https://registry.npmjs.org/ws/-/ws-8.13.0.tgz",
"integrity": "sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==",
"engines": {
"node": ">=10.0.0"
},
"peerDependencies": {
"bufferutil": "^4.0.1",
"utf-8-validate": "^5.0.2"
"utf-8-validate": ">=5.0.2"
},
"peerDependenciesMeta": {
"bufferutil": {
@@ -7507,12 +7619,11 @@
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
},
"node_modules/parse/node_modules/uuid": {
"version": "3.4.0",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
"integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==",
"deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.",
"version": "9.0.0",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.0.tgz",
"integrity": "sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==",
"bin": {
"uuid": "bin/uuid"
"uuid": "dist/bin/uuid"
}
},
"node_modules/parseurl": {
@@ -7591,21 +7702,24 @@
"integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow=="
},
"node_modules/pg": {
"version": "8.8.0",
"resolved": "https://registry.npmjs.org/pg/-/pg-8.8.0.tgz",
"integrity": "sha512-UXYN0ziKj+AeNNP7VDMwrehpACThH7LUl/p8TDFpEUuSejCUIwGSfxpHsPvtM6/WXFy6SU4E5RG4IJV/TZAGjw==",
"version": "8.11.0",
"resolved": "https://registry.npmjs.org/pg/-/pg-8.11.0.tgz",
"integrity": "sha512-meLUVPn2TWgJyLmy7el3fQQVwft4gU5NGyvV0XbD41iU9Jbg8lCH4zexhIkihDzVHJStlt6r088G6/fWeNjhXA==",
"dependencies": {
"buffer-writer": "2.0.0",
"packet-reader": "1.0.0",
"pg-connection-string": "^2.5.0",
"pg-pool": "^3.5.2",
"pg-protocol": "^1.5.0",
"pg-connection-string": "^2.6.0",
"pg-pool": "^3.6.0",
"pg-protocol": "^1.6.0",
"pg-types": "^2.1.0",
"pgpass": "1.x"
},
"engines": {
"node": ">= 8.0.0"
},
"optionalDependencies": {
"pg-cloudflare": "^1.1.0"
},
"peerDependencies": {
"pg-native": ">=3.0.1"
},
@@ -7615,10 +7729,16 @@
}
}
},
"node_modules/pg-cloudflare": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/pg-cloudflare/-/pg-cloudflare-1.1.1.tgz",
"integrity": "sha512-xWPagP/4B6BgFO+EKz3JONXv3YDgvkbVrGw2mTo3D6tVDQRh1e7cqVGvyR3BE+eQgAvx1XhW/iEASj4/jCWl3Q==",
"optional": true
},
"node_modules/pg-connection-string": {
"version": "2.6.0",
"resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.6.0.tgz",
"integrity": "sha512-x14ibktcwlHKoHxx9X3uTVW9zIGR41ZB6QNhHb21OPNdCCO3NaRnpJuwKIQSR4u+Yqjx4HCvy7Hh7VSy1U4dGg=="
"version": "2.6.2",
"resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.6.2.tgz",
"integrity": "sha512-ch6OwaeaPYcova4kKZ15sbJ2hKb/VP48ZD2gE7i1J+L4MspCtBMAx8nMgz7bksc7IojCIIWuEhHibSMFH8m8oA=="
},
"node_modules/pg-int8": {
"version": "1.0.1",
@@ -7629,22 +7749,22 @@
}
},
"node_modules/pg-minify": {
"version": "1.6.2",
"resolved": "https://registry.npmjs.org/pg-minify/-/pg-minify-1.6.2.tgz",
"integrity": "sha512-1KdmFGGTP6jplJoI8MfvRlfvMiyBivMRP7/ffh4a11RUFJ7kC2J0ZHlipoKiH/1hz+DVgceon9U2qbaHpPeyPg==",
"version": "1.6.3",
"resolved": "https://registry.npmjs.org/pg-minify/-/pg-minify-1.6.3.tgz",
"integrity": "sha512-NoSsPqXxbkD8RIe+peQCqiea4QzXgosdTKY8p7PsbbGsh2F8TifDj/vJxfuR8qJwNYrijdSs7uf0tAe6WOyCsQ==",
"engines": {
"node": ">=8.0"
"node": ">=12.0.0"
}
},
"node_modules/pg-monitor": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/pg-monitor/-/pg-monitor-1.5.0.tgz",
"integrity": "sha512-Zg5RpoYaz0zyRwAQWKrRxUZgzZ+/r4McMP4vEvg+qE8765SHAB1wHZL58uAjocG4WSK/NLP/zZhUuoyurw4l6Q==",
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/pg-monitor/-/pg-monitor-2.0.0.tgz",
"integrity": "sha512-UqjhroM701sRrJHhXeF1OwNBGxkN9R0YgkVU8A46wWn3RwK/K7QDylChMoDxo8TmGp86CBP4ZSf+RK9vD8XyVA==",
"dependencies": {
"cli-color": "2.0.3"
},
"engines": {
"node": ">=7.6"
"node": ">=14"
}
},
"node_modules/pg-monitor/node_modules/cli-color": {
@@ -7703,25 +7823,25 @@
"integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg=="
},
"node_modules/pg-pool": {
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.6.0.tgz",
"integrity": "sha512-clFRf2ksqd+F497kWFyM21tMjeikn60oGDmqMT8UBrynEwVEX/5R5xd2sdvdo1cZCFlguORNpVuqxIj+aK4cfQ==",
"version": "3.6.1",
"resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.6.1.tgz",
"integrity": "sha512-jizsIzhkIitxCGfPRzJn1ZdcosIt3pz9Sh3V01fm1vZnbnCMgmGl5wvGGdNN2EL9Rmb0EcFoCkixH4Pu+sP9Og==",
"peerDependencies": {
"pg": ">=8.0"
}
},
"node_modules/pg-promise": {
"version": "10.12.1",
"resolved": "https://registry.npmjs.org/pg-promise/-/pg-promise-10.12.1.tgz",
"integrity": "sha512-SiJkBUDGq7PNfJFJbWferodsSH+vLrhte0Q0kVgQbwlNYeKmp9Hhkr+357+5DWEuBGOHhSu1UQffSSf5HVqRtA==",
"version": "11.5.0",
"resolved": "https://registry.npmjs.org/pg-promise/-/pg-promise-11.5.0.tgz",
"integrity": "sha512-ZfhntV6Yoc3S0hQWOlEodk5fEmF9ADxKl0vNvBnZgzvLt73uY29wVaNBz2AZK2J0gVmm/zhO51RXPtI4MgKkSQ==",
"dependencies": {
"assert-options": "0.7.0",
"pg": "8.8.0",
"pg-minify": "1.6.2",
"spex": "3.2.0"
"assert-options": "0.8.1",
"pg": "8.11.0",
"pg-minify": "1.6.3",
"spex": "3.3.0"
},
"engines": {
"node": ">=12.0"
"node": ">=14.0"
}
},
"node_modules/pg-protocol": {
@@ -8082,6 +8202,17 @@
"node": ">= 0.6"
}
},
"node_modules/rate-limit-redis": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/rate-limit-redis/-/rate-limit-redis-3.0.2.tgz",
"integrity": "sha512-4SBK6AzIr9PKkCF4HmSDcJH2O2KKMF3fZEcsbNMXyaL5I9d6X71uOreUldFRiyrRyP+qkQrTxzJ38ZKKN+sScw==",
"engines": {
"node": ">= 14.5.0"
},
"peerDependencies": {
"express-rate-limit": "^6"
}
},
"node_modules/raw-body": {
"version": "2.5.1",
"resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz",
@@ -8145,35 +8276,16 @@
}
},
"node_modules/redis": {
"version": "4.0.6",
"resolved": "https://registry.npmjs.org/redis/-/redis-4.0.6.tgz",
"integrity": "sha512-IaPAxgF5dV0jx+A9l6yd6R9/PAChZIoAskDVRzUODeLDNhsMlq7OLLTmu0AwAr0xjrJ1bibW5xdpRwqIQ8Q0Xg==",
"version": "4.6.6",
"resolved": "https://registry.npmjs.org/redis/-/redis-4.6.6.tgz",
"integrity": "sha512-aLs2fuBFV/VJ28oLBqYykfnhGGkFxvx0HdCEBYdJ99FFbSEMZ7c1nVKwR6ZRv+7bb7JnC0mmCzaqu8frgOYhpA==",
"dependencies": {
"@node-redis/bloom": "1.0.1",
"@node-redis/client": "1.0.5",
"@node-redis/graph": "1.0.0",
"@node-redis/json": "1.0.2",
"@node-redis/search": "1.0.5",
"@node-redis/time-series": "1.0.2"
}
},
"node_modules/redis-errors": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/redis-errors/-/redis-errors-1.2.0.tgz",
"integrity": "sha512-1qny3OExCf0UvUV/5wpYKf2YwPcOqXzkwKKSmKHiE6ZMQs5heeE/c8eXK+PNllPvmjgAbfnsbpkGZWy8cBpn9w==",
"engines": {
"node": ">=4"
}
},
"node_modules/redis-parser": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/redis-parser/-/redis-parser-3.0.0.tgz",
"integrity": "sha512-DJnGAeenTdpMEH6uAJRK/uiyEIH9WVsUmoLwzudwGJUwZPp80PDBWPHXSAGNPwNvIXAbe7MSUB1zQFugFml66A==",
"dependencies": {
"redis-errors": "^1.0.0"
},
"engines": {
"node": ">=4"
"@redis/bloom": "1.2.0",
"@redis/client": "1.5.7",
"@redis/graph": "1.1.0",
"@redis/json": "1.0.4",
"@redis/search": "1.1.2",
"@redis/time-series": "1.0.4"
}
},
"node_modules/regenerator-runtime": {
@@ -8737,11 +8849,11 @@
}
},
"node_modules/spex": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/spex/-/spex-3.2.0.tgz",
"integrity": "sha512-9srjJM7NaymrpwMHvSmpDeIK5GoRMX/Tq0E8aOlDPS54dDnDUIp30DrP9SphMPEETDLzEM9+4qo+KipmbtPecg==",
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/spex/-/spex-3.3.0.tgz",
"integrity": "sha512-VNiXjFp6R4ldPbVRYbpxlD35yRHceecVXlct1J4/X80KuuPnW2AXMq3sGwhnJOhKkUsOxAT6nRGfGE5pocVw5w==",
"engines": {
"node": ">=4.5"
"node": ">=10.0.0"
}
},
"node_modules/split2": {
@@ -9629,10 +9741,11 @@
}
},
"node_modules/winston": {
"version": "3.8.1",
"resolved": "https://registry.npmjs.org/winston/-/winston-3.8.1.tgz",
"integrity": "sha512-r+6YAiCR4uI3N8eQNOg8k3P3PqwAm20cLKlzVD9E66Ch39+LZC+VH1UKf9JemQj2B3QoUHfKD7Poewn0Pr3Y1w==",
"version": "3.8.2",
"resolved": "https://registry.npmjs.org/winston/-/winston-3.8.2.tgz",
"integrity": "sha512-MsE1gRx1m5jdTTO9Ld/vND4krP2To+lgDoMEHGGa4HIlAUyXJtfc7CxQcGXVyz2IBpw5hbFkj2b/AtUdQwyRew==",
"dependencies": {
"@colors/colors": "1.5.0",
"@dabh/diagnostics": "^2.0.2",
"async": "^3.2.3",
"is-stream": "^2.0.0",
@@ -9788,15 +9901,15 @@
}
},
"node_modules/ws": {
"version": "8.6.0",
"resolved": "https://registry.npmjs.org/ws/-/ws-8.6.0.tgz",
"integrity": "sha512-AzmM3aH3gk0aX7/rZLYvjdvZooofDu3fFOzGqcSnQ1tOcTWwhM/o+q++E8mAyVVIyUdajrkzWUGftaVSDLn1bw==",
"version": "8.12.0",
"resolved": "https://registry.npmjs.org/ws/-/ws-8.12.0.tgz",
"integrity": "sha512-kU62emKIdKVeEIOIKVegvqpXMSTAMLJozpHZaJNDYqBjzlSYXQGviYwN1osDLJ9av68qHd4a2oSjd7yD4pacig==",
"engines": {
"node": ">=10.0.0"
},
"peerDependencies": {
"bufferutil": "^4.0.1",
"utf-8-validate": "^5.0.2"
"utf-8-validate": ">=5.0.2"
},
"peerDependenciesMeta": {
"bufferutil": {
+3 -2
View File
@@ -34,10 +34,11 @@
"node-forge": "^1.3.1",
"node-signpdf": "^1.5.1",
"openai": "^4.8.0",
"parse": "4.0.1",
"parse-server": "6.0.0",
"parse": "4.1.0",
"parse-server": "6.3.1",
"parse-server-api-mail-adapter": "^3.0.0",
"parse-server-s3-adapter": "^1.2.0",
"parse-server-fs-adapter": "1.0.1",
"pdf-lib": "^1.16.0",
"pdfkit": "^0.13.0",
"razorpay": "^2.8.6",
+6
View File
@@ -0,0 +1,6 @@
#!/bin/bash
awslocal s3api \
create-bucket --bucket my-bucket \
--create-bucket-configuration LocationConstraint=eu-central-1 \
--region eu-central-1
+11
View File
@@ -0,0 +1,11 @@
# Use the official MongoDB imagee
FROM mongo:latest
# Create a directory to host initialization scripts
RUN mkdir -p /docker-entrypoint-initdb.d
# Copy default data JSON files to the initialization directory
COPY ./default-data/*.json /docker-entrypoint-initdb.d/
# Execute the initialization script during container startup
CMD ["mongod"]
@@ -0,0 +1,70 @@
[{
"_id": "lpm8ijrwod",
"name": "contracts_Admin",
"_wperm": [
"*"
],
"_rperm": [
"*"
],
"_acl": {
"*": {
"r": true,
"w": true
}
},
"_created_at": {
"$date": "2023-09-19T09:25:20.205Z"
},
"_updated_at": {
"$date": "2023-09-28T09:47:03.968Z"
}
},
{
"_id": "Bz90QJSYMw",
"name": "contracts_Guest",
"_wperm": [
"ZhOmhqvw7S"
],
"_rperm": [
"*",
"ZhOmhqvw7S"
],
"_acl": {
"ZhOmhqvw7S": {
"w": true,
"r": true
},
"*": {
"r": true
}
},
"_created_at": {
"$date": "2023-10-20T07:56:10.094Z"
},
"_updated_at": {
"$date": "2023-10-20T10:50:36.229Z"
}
},
{
"_id": "Tb14x04JK2",
"name": "contracts_User",
"_wperm": [
"*"
],
"_rperm": [
"*"
],
"_acl": {
"*": {
"r": true,
"w": true
}
},
"_created_at": {
"$date": "2023-09-19T09:25:20.205Z"
},
"_updated_at": {
"$date": "2023-10-20T06:54:09.836Z"
}
}]
@@ -0,0 +1,657 @@
[{
"_id": "_Role",
"objectId": "string",
"updatedAt": "date",
"createdAt": "date",
"name": "string",
"users": "relation<_User>",
"roles": "relation<_Role>",
"_metadata": {
"indexes": {
"name_1": {
"name": 1
},
"_id_": {
"_id": 1
}
},
"class_permissions": {
"get": {
"*": true
},
"find": {
"*": true
},
"count": {
"*": true
},
"create": {
"*": true
},
"update": {
"*": true
},
"delete": {
"*": true
},
"addField": {},
"protectedFields": {
"*": []
}
}
}
},
{
"_id": "_Session",
"objectId": "string",
"updatedAt": "date",
"createdAt": "date",
"user": "*_User",
"installationId": "string",
"sessionToken": "string",
"expiresAt": "date",
"createdWith": "object",
"_metadata": {
"indexes": {
"_id_": {
"_id": 1
}
}
}
},
{
"_id": "_User",
"objectId": "string",
"updatedAt": "date",
"createdAt": "date",
"username": "string",
"email": "string",
"emailVerified": "boolean",
"authData": "object",
"_metadata": {
"indexes": {
"phone_1": {
"phone": 1
},
"username_1": {
"username": 1
},
"case_insensitive_username": {
"username": 1
},
"email_1": {
"email": 1
},
"case_insensitive_email": {
"email": 1
},
"_id_": {
"_id": 1
}
},
"class_permissions": {
"get": {
"*": true
},
"find": {
"*": true
},
"count": {
"*": true
},
"create": {
"*": true
},
"update": {
"*": true
},
"delete": {
"*": true
},
"addField": {},
"protectedFields": {
"*": [
"email"
]
}
}
},
"name": "string",
"phone": "string",
"ProfilePic": "string"
},
{
"_id": "contracts_Contactbook",
"objectId": "string",
"updatedAt": "date",
"createdAt": "date",
"Phone": "string",
"Email": "string",
"Name": "string",
"UserRole": "string",
"UserId": "*_User",
"CreatedBy": "*_User",
"_metadata": {
"indexes": {
"_id_": {
"_id": 1
}
}
},
"TenantId": "*partners_Tenant",
"TourStatus": "array"
},
{
"_id": "contracts_Document",
"objectId": "string",
"updatedAt": "date",
"createdAt": "date",
"_metadata": {
"fields_options": {
"EnablePhoneOTP": {
"required": "false"
},
"IsCompleted": {
"required": "false",
"defaultValue": false
},
"IsDeclined": {
"required": "false",
"defaultValue": false
},
"SendinOrder": {
"required": "false",
"defaultValue": false
},
"ExpiryDate": {
"required": "false"
},
"Signers": {
"required": "false"
},
"Name": {
"required": "false"
},
"AgreementValidUntil": {
"required": "false"
},
"URL": {
"required": "false"
},
"RemindOnceInEvery": {
"required": "false",
"defaultValue": 5
},
"EnableEmailOTP": {
"required": "false"
},
"AutomaticReminders": {
"required": "false",
"defaultValue": false
},
"SentToOthers": {
"required": "false",
"defaultValue": false
},
"TimeToCompleteDays": {
"required": "false",
"defaultValue": 15
},
"Recipients": {
"required": "false"
},
"Type": {
"required": "false"
},
"Description": {
"required": "false"
},
"ExtUserPtr": {
"required": "false"
},
"SignedUrl": {
"required": "false"
},
"AuditTrail": {
"required": "false"
},
"Placeholders": {
"required": "false"
},
"Folder": {
"required": "false"
},
"Note": {
"required": false
},
"Clauses": {
"required": false
},
"AgreementDelta": {
"required": false
}
},
"indexes": {
"_id_": {
"_id": 1
}
},
"class_permissions": {
"get": {
"*": true
},
"find": {
"*": true
},
"count": {
"*": true
},
"create": {
"*": true
},
"update": {
"*": true
},
"delete": {
"*": true
},
"addField": {},
"protectedFields": {
"*": []
}
}
},
"EnablePhoneOTP": "boolean",
"IsCompleted": "boolean",
"IsDeclined": "boolean",
"SendinOrder": "boolean",
"ExpiryDate": "date",
"Signers": "array",
"Name": "string",
"AgreementValidUntil": "date",
"URL": "string",
"RemindOnceInEvery": "number",
"EnableEmailOTP": "boolean",
"AutomaticReminders": "boolean",
"SentToOthers": "boolean",
"TimeToCompleteDays": "number",
"Recipients": "array",
"Type": "string",
"Description": "string",
"ExtUserPtr": "*contracts_Users",
"SignedUrl": "string",
"AuditTrail": "array",
"Placeholders": "array",
"Folder": "*contracts_Document",
"Note": "string",
"CreatedBy": "*_User",
"Clauses": "array",
"AgreementDelta": "array"
},
{
"_id": "contracts_Signature",
"objectId": "string",
"updatedAt": "date",
"createdAt": "date",
"_metadata": {
"fields_options": {
"SignatureName": {
"required": "false"
},
"SignText": {
"required": "false"
},
"ImageURL": {
"required": "false"
},
"SignTextFont": {
"required": "false"
},
"InitialsText": {
"required": "false"
},
"InitialsFont": {
"required": "false"
},
"UserId": {
"required": false
}
},
"indexes": {
"_id_": {
"_id": 1
}
},
"class_permissions": {
"get": {
"*": true
},
"find": {
"*": true
},
"count": {
"*": true
},
"create": {
"*": true
},
"update": {
"*": true
},
"delete": {
"*": true
},
"addField": {},
"protectedFields": {
"*": []
}
}
},
"SignatureName": "string",
"SignText": "string",
"ImageURL": "string",
"SignTextFont": "string",
"InitialsText": "string",
"InitialsFont": "string",
"Initials": "string",
"UserId": "*_User"
},
{
"_id": "contracts_Users",
"objectId": "string",
"updatedAt": "date",
"createdAt": "date",
"_metadata": {
"fields_options": {
"Name": {
"required": "false"
},
"Phone": {
"required": "false"
},
"JobTitle": {
"required": "false"
},
"Email": {
"required": "false"
},
"Company": {
"required": "false"
},
"UserId": {
"required": "false"
},
"TenantId": {
"required": "false"
},
"TourStatus": {
"required": false
},
"IsContactEntry": {
"required": false,
"defaultValue": false
},
"ShareWithTeam": {
"required": false
}
},
"indexes": {
"_id_": {
"_id": 1
}
},
"class_permissions": {
"get": {
"*": true
},
"find": {
"*": true
},
"count": {
"*": true
},
"create": {
"*": true
},
"update": {
"*": true
},
"delete": {
"*": true
},
"addField": {},
"protectedFields": {
"*": []
}
}
},
"Name": "string",
"Phone": "string",
"JobTitle": "string",
"Email": "string",
"Company": "string",
"UserId": "*_User",
"TenantId": "*partners_Tenant",
"TourStatus": "array",
"Plan": "object",
"UserRole": "string",
"Next_billing_date": "date",
"Customer_id": "string",
"Subscription_id": "string",
"CreatedBy": "*_User",
"IsContactEntry": "boolean",
"ShareWithTeam": "boolean"
},
{
"_id": "partners_DataFiles",
"objectId": "string",
"updatedAt": "date",
"createdAt": "date",
"FileSize": "number",
"FileUrl": "string",
"_metadata": {
"indexes": {
"_id_": {
"_id": 1
}
}
}
},
{
"_id": "partners_Subscriptions",
"objectId": "string",
"updatedAt": "date",
"createdAt": "date"
},
{
"_id": "partners_Tenant",
"objectId": "string",
"updatedAt": "date",
"createdAt": "date",
"EmailAddress": "string",
"TenantName": "string",
"IsActive": "boolean",
"CreatedBy": "*_User",
"ContactNumber": "string",
"UserId": "*_User",
"_metadata": {
"indexes": {
"_id_": {
"_id": 1
}
}
}
},
{
"_id": "partners_TenantCredits",
"objectId": "string",
"updatedAt": "date",
"createdAt": "date",
"usedStorage": "number",
"PartnersTenant": "*partners_Tenant",
"_metadata": {
"indexes": {
"_id_": {
"_id": 1
}
}
}
},
{
"_id": "w_appinfo",
"objectId": "string",
"updatedAt": "date",
"createdAt": "date",
"orgId": "string",
"forgetpassFormId": "string",
"mainformObjId": "string",
"applogo": "string",
"fbAppId": "string",
"appname": "string",
"loginFormId": "string",
"baseurl": "string",
"org_name": "string",
"signUpFormId": "string",
"defaultmenuid": "string",
"version": "string",
"formTitle": "string",
"googleClietId": "string",
"_metadata": {
"indexes": {
"_id_": {
"_id": 1
}
},
"class_permissions": {
"get": {
"*": true
},
"find": {
"*": true
},
"count": {
"*": true
},
"create": {
"*": true
},
"update": {
"*": true
},
"delete": {
"*": true
},
"addField": {
"*": true
}
},
"fields_options": {
"uploadUrl": {
"required": false
}
}
},
"class": "string",
"LandingPageId": "string",
"accessType": "string",
"settings": "array",
"appTitle": "string",
"metaDescription": "string",
"branding_image": "string",
"fev_Icon": "string",
"defaultRole": "string",
"results": "array",
"loginType": "string",
"createdBy": "*_User",
"domain": "string",
"enableWebNotification": "boolean",
"allowWhiteLabel": "boolean",
"uploadUrl": "string"
},
{
"_id": "w_dashboard",
"objectId": "string",
"updatedAt": "date",
"createdAt": "date",
"dbDescription": "string",
"dbTitle": "string",
"bgColor": "string",
"rows": "array",
"_metadata": {
"indexes": {
"_id_": {
"_id": 1
}
}
},
"appId": "*w_appinfo"
},
{
"_id": "w_formV3",
"objectId": "string",
"updatedAt": "date",
"createdAt": "date",
"description": "string",
"uiSchema": "object",
"jsonSchema": "object",
"_metadata": {
"indexes": {
"_id_": {
"_id": 1
}
}
},
"class": "string",
"success_message": "string",
"restrict_form_entry": "object",
"send_email": "boolean",
"restrict_form_access": "object",
"email_template": "object",
"form_permission": "string",
"success_redirect": "string",
"form_buttons": "object",
"buttons": "object",
"appId": "*w_appinfo",
"rpTitle": "string",
"rpDescription": "string",
"rpType": "string",
"bgColor": "string",
"rows": "array",
"redirect_id": "string",
"formACL": "object",
"userSchema": "object",
"isRegisterForm": "boolean",
"liveValidate": "boolean",
"noValidate": "boolean",
"validFunction": "string",
"help": "object",
"name": "string",
"phone": "string",
"email": "string",
"password": "string",
"username": "string",
"role": "string",
"helpText": "object",
"helpTextForm": "object",
"hideActionsAfter": "number",
"rules": "array",
"extraActions": "object",
"persistentFields": "array"
},
{
"_id": "w_menu",
"objectId": "string",
"updatedAt": "date",
"createdAt": "date",
"menuTitle": "string",
"menuType": "string",
"menuItems": "array",
"_metadata": {
"indexes": {
"_id_": {
"_id": 1
}
}
},
"appId": "*w_appinfo"
}]
File diff suppressed because one or more lines are too long
@@ -0,0 +1,104 @@
[{
"_id": "35KBoSgoAK",
"rows": [
{
"columns": [
{
"colxs": "12",
"colmd": "6",
"collg": "6",
"widget": {
"type": "Card",
"icon": "fas fa-signature",
"bgColor": "#f0058e",
"label": "Need your Signature",
"description": null,
"data": {
"id": "e04ee9dc-932d-6b80-0202-703fd154eb74",
"queryType": "",
"class": "contracts_Document",
"query": "where={\"$and\":[{\"AuditTrail.UserPtr\":{\"$ne\":{\"__type\":\"Pointer\",\"className\": \"contracts_Users\",\"objectId\":\"#objectId#\"}}},{\"AuditTrail.Activity\":{\"$ne\":\"Signed\"}}],\"Signers\":{\"$in\":[{\"__type\":\"Pointer\",\"className\":\"contracts_Users\",\"objectId\":\"#objectId#\"}]},\"IsDeclined\":{\"$ne\":true},\"IsCompleted\":{\"$ne\":true},\"Type\":{\"$ne\":\"Folder\"},\"Placeholders\":{\"$ne\":null},\"ExpiryDate\":{\"#*gt\":{\"__type\":\"#Date#\",\"iso\":\"#today#\"}}}&count=1",
"key": "count",
"Redirect_type": "Report",
"Redirect_id": "4Hhwbp482K",
"tourSection": "tourcard1",
"tourMessage": "This card shows the aggregate count of documents that are awaiting your signature. Clicking on this card will seamlessly take you to the detailed list of such documents for your review and action."
}
}
},
{
"colxs": "12",
"colmd": "6",
"collg": "6",
"widget": {
"type": "Card",
"icon": "fas fa-sign-out-alt",
"bgColor": "#g0058e",
"label": "Out for signatures",
"description": null,
"data": {
"id": "c1935cc0-28d4-3d73-b72a-8c1e3d18a17f",
"queryType": "",
"class": "contracts_Document",
"query": "where={\"CreatedBy\":{\"__type\":\"Pointer\",\"className\":\"_User\",\"objectId\":\"#UserId.objectId#\"},\"IsCompleted\":{\"$ne\":true},\"IsDeclined\":{\"$ne\":true},\"Type\":{\"$ne\":\"Folder\"},\"Placeholders\":{\"$ne\":null},\"ExpiryDate\":{\"#*gt\":{\"__type\":\"#Date#\",\"iso\":\"#today#\"}}}&count=1",
"key": "count",
"Redirect_type": "Report",
"Redirect_id": "1MwEuxLEkF",
"tourSection": "tourcard2",
"tourMessage": "This card indicates the total number of documents you've sent out for signatures. A single click on this card will navigate you to a comprehensive list of these documents, allowing you to monitor their status."
}
}
},
{
"colxs": "12",
"colmd": "6",
"collg": "6",
"widget": {
"type": "report",
"reportId": "5Go51Q7T8r",
"data": {
"tourSection": "tourreport1",
"tourMessage": "Here lies a curated list of documents that are pending your signature. These are requests from other users that require your immediate attention for completion."
}
}
},
{
"colxs": "12",
"colmd": "6",
"collg": "6",
"widget": {
"type": "report",
"reportId": "d9k3UfYHBc",
"data": {
"tourSection": "tourreport2",
"tourMessage": "This area displays all the documents you've dispatched for signatures from other parties. It serves as a real-time tracker for documents pending external approval."
}
}
},
{
"colxs": "12",
"colmd": "12",
"collg": "12",
"widget": {
"type": "report",
"reportId": "kC5mfynCi4",
"data": {
"tourSection": "tourreport3",
"tourMessage": "In this section, you'll find your draft documents awaiting completion. These are the documents you've initiated but haven't yet finalized for sending."
}
}
}
]
}
],
"_p_appId": "w_appinfo$aIPmIvMzGM",
"dbTitle": "Dashboard",
"dbDescription": null,
"bgColor": "#ffffff",
"_created_at": {
"$date": "2023-09-04T13:17:26.707Z"
},
"_updated_at": {
"$date": "2023-09-27T04:53:20.395Z"
}
}]
@@ -0,0 +1,272 @@
[{
"_id": "H9vRfEYKhT",
"_created_at": {
"$date": "2023-09-04T14:04:00.669Z"
},
"_updated_at": {
"$date": "2023-10-20T06:27:02.314Z"
},
"_p_appId": "w_appinfo$aIPmIvMzGM",
"menuItems": [
{
"icon": "fas fa-tachometer-alt",
"title": "Dashboard",
"target": "",
"pageType": "dashboard",
"description": "",
"objectId": "35KBoSgoAK"
},
{
"icon": "far fa-newspaper",
"title": "New Document",
"target": "_self",
"pageType": null,
"description": null,
"objectId": null,
"children": [
{
"icon": "fas fa-pen-nib",
"title": "Sign yourself",
"target": "_self",
"pageType": "form",
"description": "",
"objectId": "sHAnZphf69"
},
{
"icon": "fas fa-file-signature",
"title": "Request signatures",
"target": "_self",
"pageType": "form",
"description": "",
"objectId": "8mZzFxbG1z"
}
]
},
{
"icon": "fas fa-folder",
"title": "OpenSignDrive™",
"target": "_self",
"pageType": "mf",
"description": "",
"objectId": "remoteUrl=aHR0cHM6Ly9xaWstYWktb3JnLmdpdGh1Yi5pby9TaWduLU1pY3JvYXBwVjIvcmVtb3RlRW50cnkuanM=&moduleToLoad=AppRoutes&remoteName=signmicroapp/legadrive"
},
{
"icon": "fas fa-address-card",
"title": "Reports",
"target": "_self",
"pageType": null,
"description": "",
"objectId": null,
"children": [
{
"icon": "fas fa-signature",
"title": "Need your sign",
"target": "_self",
"pageType": "report",
"description": "",
"objectId": "4Hhwbp482K"
},
{
"icon": "fas fa-tasks",
"title": "In Progress",
"target": "_self",
"pageType": "report",
"description": "",
"objectId": "1MwEuxLEkF"
},
{
"icon": "fas fa-check-circle",
"title": "Completed",
"target": "_self",
"pageType": "report",
"description": "",
"objectId": "kQUoW4hUXz"
},
{
"icon": "fas fa-edit",
"title": "Drafts",
"target": "_self",
"pageType": "report",
"description": "",
"objectId": "ByHuevtCFY"
},
{
"icon": "fas fa-times-circle",
"title": "Declined",
"target": "_self",
"pageType": "report",
"description": "",
"objectId": "UPr2Fm5WY3"
},
{
"icon": "fas fa-hourglass-end",
"title": "Expired",
"target": "_self",
"pageType": "report",
"description": "",
"objectId": "zNqBHXHsYH"
}
]
},
{
"icon": "fas fa-cog",
"title": "Settings",
"target": "_self",
"pageType": null,
"description": "",
"objectId": null,
"children": [
{
"icon": "fas fa-pen-fancy",
"title": "My Signature",
"target": "_self",
"pageType": "mf",
"description": "",
"objectId": "remoteUrl=aHR0cHM6Ly9xaWstYWktb3JnLmdpdGh1Yi5pby9TaWduLU1pY3JvYXBwVjIvcmVtb3RlRW50cnkuanM=&moduleToLoad=AppRoutes&remoteName=signmicroapp/managesign"
}
]
}
],
"menuTitle": "Default Menu",
"menuType": "Side Menu"
},
{
"_id": "VPh91h0ZHk",
"_created_at": {
"$date": "2023-09-04T14:16:15.424Z"
},
"_updated_at": {
"$date": "2023-10-20T06:25:59.660Z"
},
"_p_appId": "w_appinfo$aIPmIvMzGM",
"menuItems": [
{
"icon": "fas fa-tachometer-alt",
"title": "Dashboard",
"target": "",
"pageType": "dashboard",
"description": "",
"objectId": "35KBoSgoAK"
},
{
"icon": "far fa-newspaper",
"title": "New Document",
"target": "_self",
"pageType": null,
"description": null,
"objectId": null,
"children": [
{
"icon": "fas fa-pen-nib",
"title": "Sign yourself",
"target": "_self",
"pageType": "form",
"description": "",
"objectId": "sHAnZphf69"
},
{
"icon": "fas fa-file-signature",
"title": "Request signatures",
"target": "_self",
"pageType": "form",
"description": "",
"objectId": "8mZzFxbG1z"
}
]
},
{
"icon": "fas fa-folder",
"title": "OpenSignDrive™",
"target": "_self",
"pageType": "mf",
"description": "",
"objectId": "remoteUrl=aHR0cHM6Ly9xaWstYWktb3JnLmdpdGh1Yi5pby9TaWduLU1pY3JvYXBwVjIvcmVtb3RlRW50cnkuanM=&moduleToLoad=AppRoutes&remoteName=signmicroapp/legadrive"
},
{
"icon": "fas fa-address-card",
"title": "Reports",
"target": "_self",
"pageType": null,
"description": "",
"objectId": null,
"children": [
{
"icon": "fas fa-signature",
"title": "Need your sign",
"target": "_self",
"pageType": "report",
"description": "",
"objectId": "4Hhwbp482K"
},
{
"icon": "fas fa-tasks",
"title": "In Progress",
"target": "_self",
"pageType": "report",
"description": "",
"objectId": "1MwEuxLEkF"
},
{
"icon": "fas fa-check-circle",
"title": "Completed",
"target": "_self",
"pageType": "report",
"description": "",
"objectId": "kQUoW4hUXz"
},
{
"icon": "fas fa-edit",
"title": "Drafts",
"target": "_self",
"pageType": "report",
"description": "",
"objectId": "ByHuevtCFY"
},
{
"icon": "fas fa-times-circle",
"title": "Declined",
"target": "_self",
"pageType": "report",
"description": "",
"objectId": "UPr2Fm5WY3"
},
{
"icon": "fas fa-hourglass-end",
"title": "Expired",
"target": "_self",
"pageType": "report",
"description": "",
"objectId": "zNqBHXHsYH"
}
]
},
{
"icon": "fas fa-cog",
"title": "Settings",
"target": "_self",
"pageType": null,
"description": "",
"objectId": null,
"children": [
{
"icon": "fas fa-pen-fancy",
"title": "My Signature",
"target": "_self",
"pageType": "mf",
"description": "",
"objectId": "remoteUrl=aHR0cHM6Ly9xaWstYWktb3JnLmdpdGh1Yi5pby9TaWduLU1pY3JvYXBwVjIvcmVtb3RlRW50cnkuanM=&moduleToLoad=AppRoutes&remoteName=signmicroapp/managesign"
},
{
"icon": "far fa-user",
"title": "Add User",
"target": "_self",
"pageType": "form",
"description": "",
"objectId": "lM0xRnM3iE"
}
]
}
],
"menuTitle": "Admin Menu",
"menuType": "Side Menu"
}]
+17
View File
@@ -0,0 +1,17 @@
#!/bin/bash
echo "Starting MongoDB initial data import..."
# Wait for MongoDB to fully start
sleep 10
# Import the data
mongoimport --host localhost --db OpenSignDB --collection _Role --type json --file /docker-entrypoint-initdb.d/legadraGCva._Role.json --jsonArray
mongoimport --host localhost --db OpenSignDB --collection _SCHEMA --type json --file /docker-entrypoint-initdb.d/legadraGCva._SCHEMA.json --jsonArray
mongoimport --host localhost --db OpenSignDB --collection w_appinfo --type json --file /docker-entrypoint-initdb.d/legadraGCva.w_appinfo.json --jsonArray
mongoimport --host localhost --db OpenSignDB --collection w_dashboard --type json --file /docker-entrypoint-initdb.d/legadraGCva.w_dashboard.json --jsonArray
mongoimport --host localhost --db OpenSignDB --collection w_menu --type json --file /docker-entrypoint-initdb.d/legadraGCva.w_menu.json --jsonArray
echo "MongoDB initial data import done."
+55
View File
@@ -0,0 +1,55 @@
MIIKLwIBAzCCCeUGCSqGSIb3DQEHAaCCCdYEggnSMIIJzjCCBEIGCSqGSIb3DQEH
BqCCBDMwggQvAgEAMIIEKAYJKoZIhvcNAQcBMFcGCSqGSIb3DQEFDTBKMCkGCSqG
SIb3DQEFDDAcBAh6cQqVpHfTzAICCAAwDAYIKoZIhvcNAgkFADAdBglghkgBZQME
ASoEEFKEIGJTTRo3voO/FvsXs7yAggPAI7rMCboTFFBfdMuuV3Y9/xfphAgdGD7P
0xAN10CcmXlMtedc8cRxOaD9n3Q7zJx5iIbqEGDTc0dgp5EtdWsGl7MP76iHkSfB
ZUPc13nbnRU4Nq4hNFcSj1m6NVa0lT9UobbTsG+wUkJn8aLfijzZ1OY82KLlKUoJ
lqLsQ1yZkeLiLKI0aEew/2vzfiLUX9A99qnCRoryo8ZbLiWl0Vu/FEKM5mqIRFEp
BKeSUsRxBfJCMZ2Ks5t4/MTCV+yrcsuhLPF/AJpzKfIinEFDhm7MxP4RXtk2LWNe
+EO2GuFRjZCfsMO0oNWybFmDeNDMCHZj5TeoqL1JwAV5e1lEeqR38v4Wcr4OVefY
DfdrJ2xdvm7XbBZ8Lgx8L4fwugw7oDyTpR2jJqHMlpOsQrxipN6UKkN6EVYeCC5K
4dF5LHdCcIa7L/OI/feD5g/zz8SGCTc91husVN7zi+CVO0lQLRkAj02+VbiXPPDD
eQm/QBieG2yVe5IRfcnIs2aszulbQbgHdguSYSQa/7DEvN/9/uxUIRFbItwrreRI
VAUUNS02L680Zok9xzDed1I/WJoPr2+5n2eV1jc5zoH7mAni0+Z1d5qLoYV6pNaN
P9okvBf75LLNoJKsb/eWlkk73rmlH6/Qz+hudgnlkxUJuU/b79AMQpd0EWEWhcim
ZeB4d9lPLLwyvY/FN4aCGWzsoAW69RK9E1DyGZAZRYRwCKHSWXmCaenR1ilxcPFx
TDavpybObIISPtylv5Z/IGBjE19Lw0UHc6Waln/jx0YXXGGDWs1F/MrdJ/8mkVXf
tHB/5ds4u5md+CmXpaCITO3Cg9GltGSWyDoEJsz1u/Wzq4X4FYmolXiqQvMPQrxu
iThTnPDGbz9VqFSyNKPKswIQ8CUbvZ209A5vjERPzE0Lp1pO39K51fnHD9oD968t
tGbGmNiQ0++Orze79cH0UVwDa6NLGCmnE0oBgke1JDPlaU3kkx7+R9SAS0Zytsmj
aLxW5Z1cOFaqqBLjwgHUxOqRO+cl6P9ORox34wJjiwZKy1L+0ppw22Na/unwi2Rk
a8jvK7+ycOLaiSmI77T0l7VCWgKsRsWLvBA3cjX5XAGtatFXrY/7Imoxl0nWGLjG
n5Sv5XuDek4e4QAPeJmhpURMnzLDsSXAYOSYZvS/kgENYhYSnQLQp50TxrzquA2c
lAeFIEqqAJy9tAMfp5UAqMeOC60Ttn6ySsdOle003F2NrRilhPynNDZ3h1ZQknur
Y9zWUm9qBmXCjhPzdmzHz3Ozj2Bi6kd4MIIFhAYJKoZIhvcNAQcBoIIFdQSCBXEw
ggVtMIIFaQYLKoZIhvcNAQwKAQKgggUxMIIFLTBXBgkqhkiG9w0BBQ0wSjApBgkq
hkiG9w0BBQwwHAQIZenzippqfSQCAggAMAwGCCqGSIb3DQIJBQAwHQYJYIZIAWUD
BAEqBBCddSIj/wfxowZAO1j3W9FwBIIE0C/guzeZtV/vPsaIDAtWEkmepCvhm9Rg
aUgOoR66wjyYx7upeuZJ+pYJdsEqUmTgGYN+ClBpsU0bqCM7PI0mepvIT9kLD6ZL
UkprtNAYP87NBA/e5dpXlGAf9ibDRT0F2Y+lCSF83rCIYKG8n7h5834F6Saf+dU7
6y5bgorbf2Fnxy123XfUSg5qdCraZZM+DwE1gpQdBGrFyq8cwlQ8hJpKHDWup7WA
f2HcT/X0Wjb24L6JWjC1FvTbTNdS/lzTOcqLYUc31iuU9rF6O4qtX9PK/yGWc+YE
qakuV+HrsF4je/YdVZRYHtkbbcYXW9PjtMv+4D1ut5X2SPeHwpj3WmGAb7Zno6SD
SfohMihXvDbIjVSMDBpW97bhgk0h7iS4ISIYoQJUGJv3QQ3XJq91LoIP3zpiO/Cq
ZuuHuGvZmO6lb0PGShRT7mFg3k3rswTfFyKdtY76zAVJIR2bz/6bRf4uQI48SOLR
NX1Z6lavUNiE4nPNlnfBp480C+YANKs/bdev0wkRVmFxPMyb5FFLXwLSqcfdSQag
RayrKd8xPOm6lor3cTvrkO3XH2Hf9TgFHjeIAQ3VZ1Cncb9jfra3V4zvIocek4dC
GREirPbEyL/js5O0aAa0mg9EontMWKRqncomKhUOckheP2dYiQOazDFDFP9OQCYV
MBb0RDwm3+hiMU0lPeO+NAjAv2SfFK7G4maMb2SL7inT7An7ZPPpnDNXLDt+nOgo
IKuaJpy8JX/OKB4ntYsdnQG4E0J3vpHWjYPKif7j1njIYFd76bIgNVlqWuQFArBy
U9BuPyF+eYouJc+TpX9R5ybPvabRR4NUjnrttr2E5AzQfIgNGrSFiewjvYZHQOKd
WyVR9YV0cUv591xyUDdXMoHh+J0v0xK1WCHe/9enY5y/C8YohL8h5tEvInAQconj
lJ2r9qX8iBmIupJij5M5Ebza8HQ4aVMdHu/s05Vj9BC6K0ok3h+DFTj2gUBD24sp
APHic0DmNnciUQuHuuoW/1SVb6I1HJswsgcC8CekvoXF26ygwWhJPyqw+5djip2w
I/l3uOnPPUWZQHKhnBH4noZydrzBBJN1po9dkxb8LKuKZDEcnKo+tQrTnZJaFRXK
pQDsAjQ0HcYi8ZqN/GPezXOqzRgvObevXeDYTJrNejr46B1HqjPw8doai+AEf//1
iiM9EK4y3bGbX837oebTByRi112AOctISHTWbF0zdFMiBO9X9PML4n3i14ToqLH1
EUp0WtCdKLJmrRnO9PKJUMpce3yNu6oRSBzB4EkgUMOTVx9tM66h/gcR3wr+qKJP
1EABMbbCsJeYYLujhQHVh0JluqLBXYuCmr5n6o8qmonj5tEfTn9zs2gi0OvKTliH
wRXWsar004alt8D8o4M/Oqu3qyVV1O8BlVEofUC1CfAMIh/T1NJBeKG/FPfAFoEz
9liLLkoDvGvFVJ4Ezy4BaPtg+G3yU/SeiruwsCB3unHRD7G6VvS4jY2B8vEYl0yM
Z1mLFbKK8CIEvg8+v/vbc0noYUOzd6bkwh6Y6cziR/u78y2nALYZpQK+3XiVVH/v
SaVoDckZgUwAX+dMd1P4U3a487MPXBZZmLVFMHTuv3NvW6NIQCMd4l35ViRd7YcS
V2QDKTnUtPN2MSUwIwYJKoZIhvcNAQkVMRYEFMSz7PlBO5VzTDqC/foidPWrMjkw
MEEwMTANBglghkgBZQMEAgEFAAQgPlLuG+67SxPOEPbgFuEnVgewvY6LUzFmrprx
c6yryFgECIld0S5kDk7JAgIIAA==
+21
View File
@@ -0,0 +1,21 @@
-----BEGIN CERTIFICATE-----
MIIDXTCCAkWgAwIBAgIUdpdDPiNqilWn26oMvcpT9qmMtoswDQYJKoZIhvcNAQEL
BQAwPjELMAkGA1UEBhMCSU4xCzAJBgNVBAgMAk5JMQowCAYDVQQHDAFOMQowCAYD
VQQKDAFTMQowCAYDVQQLDAFTMB4XDTIzMTEwNTEzMDg1OFoXDTI0MTEwNDEzMDg1
OFowPjELMAkGA1UEBhMCSU4xCzAJBgNVBAgMAk5JMQowCAYDVQQHDAFOMQowCAYD
VQQKDAFTMQowCAYDVQQLDAFTMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC
AQEAzT30t7Adb6XdXWywzC4RF03r3piTt5MF4MZClvorsl8bySNKrYkl7i5+igpz
36SfLp090Dal0cUZ7it9QCxaxrWv3m8OFAwfwK5ePuzUryF6/QJcoF560Sq4k3Pb
640PJ5UlFwvUqsXQN8A/pAA6S96MqpwCrPQE0u5OcRQuVIsZxBL2s17lv5eROjX+
Ufx/6qtmuZscn9xKDP6GNO8aa6X0YZMoVXlll14iEn4bg0yagiY7QhvVCzK8q7nB
9yKCLvw/28eSoD08yJnHnUZnIOoNrn+cZKTkl8VcyKW55IeOiUilb5h3a07JD6bj
Q/VroPQE5UtveajB9CBa3eUCiwIDAQABo1MwUTAdBgNVHQ4EFgQUIQGrIwhvSNkG
L3ATZra96d4cDE4wHwYDVR0jBBgwFoAUIQGrIwhvSNkGL3ATZra96d4cDE4wDwYD
VR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAp2mCfhRf6Jft6lSgL4hi
I8xHfqcUjG+XnDM1Pi7gKVxxclwVQ67vVtfO0rU1SBPWUO3nIaaLN9Wyzcx+LXPV
4e3pyHlq2T6Z6ENuozOsMhHeY9+ows6wPBcxq57KLLHnBpx3lJiKHKOp0ueiAbkz
LaI+Mm+VQo0MbzhCw7KXs8VPFt8YO+S3XircVMWaa007VgGY/NjYF62hlG35fD/v
CTHccRj5Y3coQ2MjosTUQTd4u3N5VhgxdRbyMdpjpwDxu0u9BE7ISXKMBhnBLV/w
+/mxoF2bqExBuPiZS8vT6yW9rehdi/KR9c26GUreTsKLtjXyveeP6VLoTJ60T3D9
Jg==
-----END CERTIFICATE-----
+30
View File
@@ -0,0 +1,30 @@
-----BEGIN ENCRYPTED PRIVATE KEY-----
MIIFHDBOBgkqhkiG9w0BBQ0wQTApBgkqhkiG9w0BBQwwHAQIJvntFBuTIWACAggA
MAwGCCqGSIb3DQIJBQAwFAYIKoZIhvcNAwcECEE+1CDDu5XvBIIEyEwR/61HhjJ0
P6oGr1E+uDTKVcUqK++fbsrhqxYq+oEoj+w5C1KOgUxQYQTm2he6PhfGkPh56V9w
OaArJ+QrGrSFRUdTtLZG+qBbfyWKQyah9VxwYhmG9Ptf6RyQXDJnup4WtgJWI2sw
fAcJ6QqPQkSFUq/0cn0s/RLNCy6P8qKfUjdVugEv0K9dsc7dFNWZQEQlpyKeZdbY
rJfKjf85qSmDpFfRnP1B0n//vzlPWK03fNH2be4EnBTFW7l1sDnju6iwasLSP7P+
EuGq8Bw9YGlf3I/STWGgfxWWLZACCjgVDiRjLakstkodLqC1tZAWawOKcDQGPyKG
nRrF/yF4H0ChmcMBA9Ur4zxBd4uayWujwqIPehfWU+ODYYaVDluSVrxiTaSHGAP2
XnT6vrOnR5sg/uzgsbuApHTbHCW+lplof/R0swvwyt15fKaD8HsngNMN6R75e0ar
6+ltI/BLgcSbu0f7Fe8qMumBNrJiU5j09EdvDKaIEe3+Ko2HWCV/zLgxvL8BwGyB
K9RSMw1YzivO/CahWE3cQcS4GQSX84+y8VXF43CxpmTRf3Hmdpj4JBGB0fOvGHzA
hv+st5E+hhSOOv2ZZ00XtEaUi3d2uQFYApxEoXubz2QG481M7ulNXaVd74DZf/Fr
J+R7BmCa633rEw34sXFKUcfdfVOzUfMnMGvO5danSrov6k/cFfLPH56ORb9Ep30a
U1fXHP+pcFQohR/kjAk5gjDUr8pjkOJ0/JHv106rptT4SNCznvJa8BvWtP9wDXDv
UZDA/UCLlnl20mJUjLtb0iM5vtqhi7XOxDoS8AauOimSEh+M0uLEZ7HOQvtGchLl
tDLd/DVew/WzPBhL4eNTmhwwno9JL21nPBEaFAa58djoiZXgzUdLQbBDbo/7nsRA
UJ9imt0HmhDU+xrimnMZJD051KcbohHjPvTnTb4qvd0Rt7u/dpL9NT07rQlVIe3u
qGl4sEe+1vEueRdHt5QCSGbxnwPPHdE9XMsK8et3M/DOYN+ToB9QmDm72lLsJNkm
0nxdYVpfXHUiPmMorkJgb9YXfY+j0UEWuT0l4bl7a5+mzGm/Zy9FCoLaW7MTWNJd
fyDSYsVotOhRdCBi0Osho21GldKmfX6XoqHYENVqsh7x9bgvjNwvLNgpCWXYh7/Q
K6N3iDQ3G3A6x9nOgeKpXYREd8fx8byM6u7FAttVTtcV71QaWU3TSn7Oice1Bklg
osIhUJydHny856D/WCD6EmnPBuukx9Tht8NKtJVS0XoXqbz69mx4xfq987HGkJJa
nvCgkZOr/LhcVylmRjg9ZVfiUrwim4Gp42gV3JtsZpOGE1m+1twSXShtr/PQ2FdF
jD41LOEG1OGdZ5XIDLxAI4085jwVD/WIRo/AZELENog1XKtjeXSqJ/H7njauB30w
MeNv0VRTIItVA0eXRDwoqjpqyGSdn9YF2SQ/qDR6WU+Y2bVD38m6ZJlsy/zHx9uc
sH1DK7hbbRRSuZ9Sx/TjD19DWJ4qNPTpUZTd0+dxsG/HGQKpkbpXI5f3aQ6nTWWM
MjlWF6mUI06iLIRhLyNwBrtEjJHL1k8fIOvO/MUKtj72VBGt/fnoutS0WifZLvfn
mFXB4iaMX0hGcgzpK4iNcg==
-----END ENCRYPTED PRIVATE KEY-----
Binary file not shown.
+12 -6
View File
@@ -5,25 +5,30 @@ services:
build:
context: ./apps/OpenSignServer
dockerfile: Dockerfile
image: OpenSignServer-image
image: opensignserver-image
container_name: OpenSignServer-container
command: /usr/src/app/node_modules/.bin/nodemon server.js
volumes:
- ./apps/OpenSignServer/:/usr/src/app
- /usr/src/app/node_modules
ports:
- "5000:5000"
- "8080:8080"
depends_on:
- mongo
env_file: ./OpenSignServer/.env
env_file: .env
environment:
- NODE_ENV=development
networks:
- app-network
mongo:
image: mongo
build:
context: ./apps/mongo
dockerfile: Dockerfile
container_name: mongo-container
image: opensign-mongo
volumes:
- data-volume:/data/db
- ./apps/mongo/mongo-init.sh:/docker-entrypoint-initdb.d/mongo-init.sh:ro
ports:
- "27017:27017"
networks:
@@ -32,9 +37,10 @@ services:
build:
context: ./apps/OpenSign
dockerfile: Dockerfile
image: OpenSign-image
image: opensign-image
container_name: OpenSign-container
command: npm start
env_file: .env
volumes:
- ./apps/OpenSign/:/usr/app
- /usr/app/node_modules
@@ -53,4 +59,4 @@ volumes:
data-volume:
node_modules:
web-root:
      driver: local
driver: local
+1 -1
View File
@@ -9,7 +9,7 @@
/coverage
# production
/build
/mfbuild
# misc
.DS_Store
+2 -1
View File
@@ -2,6 +2,7 @@
"name": "signmicroapp",
"version": "0.1.0",
"private": true,
"homepage": "./mfbuild",
"dependencies": {
"@radix-ui/themes": "^1.1.2",
"@react-pdf/renderer": "^3.1.9",
@@ -35,7 +36,7 @@
},
"scripts": {
"start": "mf-cra start",
"build": "CI=false && mf-cra build && mv build ../../apps/OpenSign/public/mfbuild",
"build": "CI=false && PUBLIC_URL=./mfbuild BUILD_PATH='./mfbuild' mf-cra build && mv mfbuild ../../apps/OpenSign/public",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
@@ -33,23 +33,23 @@ function Certificate({ pdfData }) {
page: {
borderRadius: "5px",
padding: "10px",
backgroundColor: "white",
backgroundColor: "white"
},
section1: {
border: "1px solid rgb(177, 174, 174)",
padding: "20px",
padding: "20px"
},
textStyle: {
fontWeight: "bold",
fontSize: "11px",
marginBottom: "10px",
marginBottom: "10px"
},
textStyle2: {
fontWeight: "600",
fontSize: "11px",
marginBottom: "10px",
color: "gray",
},
color: "gray"
}
});
const generatedDate = () => {
@@ -57,7 +57,7 @@ function Certificate({ pdfData }) {
const localExpireDate = newDate.toLocaleDateString("en-US", {
day: "numeric",
month: "long",
year: "numeric",
year: "numeric"
});
var currentOffset = newDate.getTimezoneOffset();
@@ -79,7 +79,7 @@ function Certificate({ pdfData }) {
textAlign: "right",
color: "gray",
fontSize: "10px",
marginBottom: "30px",
marginBottom: "30px"
}}
>
Generated On {localExpireDate} {hoursIST}:{minutesIST} IST
@@ -92,7 +92,7 @@ function Certificate({ pdfData }) {
const localExpireDate = newDate.toLocaleDateString("en-US", {
day: "numeric",
month: "long",
year: "numeric",
year: "numeric"
});
var currentOffset = newDate.getTimezoneOffset();
@@ -136,7 +136,7 @@ function Certificate({ pdfData }) {
)
);
};
return (
isLoad && (
<Document>
@@ -151,7 +151,7 @@ function Certificate({ pdfData }) {
fontSize: "20px",
fontWeight: "bold",
color: "#31bceb",
marginBottom: "10px",
marginBottom: "10px"
}}
>
{" "}
@@ -165,7 +165,7 @@ function Certificate({ pdfData }) {
fontSize: "16px",
fontWeight: "bold",
color: "#31bceb",
margin: "10px 0px 10px 0px",
margin: "10px 0px 10px 0px"
}}
>
Summary
@@ -203,36 +203,40 @@ function Certificate({ pdfData }) {
fontSize: "16px",
fontWeight: "bold",
color: "#31bceb",
margin: "10px 0px 10px 0px",
margin: "10px 0px 10px 0px"
}}
>
Recipients
</Text>
<View>
{multiSigner && multiSigner.map((data, ind) => {
return (
<View
key={ind}
style={{ display: "flex", flexDirection: "column" }}
>
{multiSigner &&
multiSigner.map((data, ind) => {
return (
<View
key={ind}
style={{
border: "0.4px solid #bdbbbb",
marginBottom: "10px",
display: "flex",
flexDirection: "column"
}}
></View>
{signerName(data)}
>
<View
style={{
border: "0.4px solid #bdbbbb",
marginBottom: "10px"
}}
></View>
{signerName(data)}
<Text style={styles.textStyle}>
Accessed from : &nbsp;
<Text style={styles.textStyle2}>
{data.ipAddress}
<Text style={styles.textStyle}>
Accessed from : &nbsp;
<Text style={styles.textStyle2}>
{data.ipAddress}
</Text>
</Text>
</Text>
</View>
);
})}
</View>
);
})}
</View>
</View>
) : (
@@ -242,7 +246,7 @@ function Certificate({ pdfData }) {
fontSize: "16px",
fontWeight: "bold",
color: "#31bceb",
margin: "10px 0px 10px 0px",
margin: "10px 0px 10px 0px"
}}
>
Recipients
@@ -259,7 +263,8 @@ function Certificate({ pdfData }) {
<Text style={styles.textStyle}>
Accessed from : &nbsp;
<Text style={styles.textStyle2}>
{pdfData[0].AuditTrail && pdfData[0].AuditTrail[0].ipAddress}
{pdfData[0].AuditTrail &&
pdfData[0].AuditTrail[0].ipAddress}
</Text>
</Text>
@@ -42,7 +42,7 @@ function DraftDocument() {
.then((Listdata) => {
const json = Listdata.data;
const res = json.results;
// console.log("res", res);
if (res[0] && res.length > 0) {
setPdfDetails(res);
const loadObj = {
@@ -74,20 +74,16 @@ function DraftDocument() {
//checking document is completed and signer exist then navigate to pdfRequestFiles file
if (data.IsCompleted && checkSignerExist) {
// window.location.hash = `/pdfRequestFiles`;
navigate(`${hostUrl}pdfRequestFiles`);
navigate(`${hostUrl}pdfRequestFiles`);
}
//checking document is completed and signer does not exist then navigate to recipientSignPdf file
else if (data.IsCompleted && !checkSignerExist) {
// window.location.hash = `/recipientSignPdf/${data.objectId}/${data.ExtUserPtr.Phone}`;
navigate(
`${hostUrl}signaturePdf`
);
}
//checking document is declined by someone then navigate to pdfRequestFiles file
else if (isDecline) {
// window.location.hash = `/pdfRequestFiles`;
navigate(`${hostUrl}pdfRequestFiles`);
}
//checking document has expired and signers exist and placeholder does not set yet then navigate to pdfRequestFiles file
@@ -97,7 +93,6 @@ function DraftDocument() {
checkSignerExist &&
!isPlaceholder
) {
// window.location.hash = `/placeHolderSign`;
navigate(`${hostUrl}placeHolderSign`);
}
//checking document has expired and signers does not exist and document not signed yet then navigate to pdfRequestFiles file
@@ -8,7 +8,7 @@ import "../css/signature.css";
import axios from "axios";
import { toDataUrl } from "../utils/toDataUrl";
// console.log("appName ", appName)
const ManageSign = () => {
let appName;
const [penColor, setPenColor] = useState("blue");
@@ -68,7 +68,6 @@ const ManageSign = () => {
if (res.data.results.length > 0) {
setId(res.data.results[0].objectId);
setSignName(res.data.results[0].SignatureName);
// console.log(res.data.results[0].ImageURL);
setImage(res.data.results[0].ImageURL);
if (res.data.results[0] && res.data.results[0].Initials) {
setInitials(res.data.results[0].Initials);
@@ -143,7 +142,7 @@ const ManageSign = () => {
if (!signName) {
setNameWarning(true);
// setTimeout(() => setNameWarning(false), 1000);
} else if (!isvalue) {
setWarning(true);
setTimeout(() => setWarning(false), 1000);
@@ -337,12 +336,8 @@ const ManageSign = () => {
<div
className="mainDiv"
style={{
// height: "100%",
width: "100%",
paddingRight: "10px",
// maxHeight:"500px",
}}
>
<div style={{ margin: 20 }}>
@@ -0,0 +1,16 @@
import React from "react";
const PageNotFound = () => {
return (
<div className="flex items-center justify-center h-screen w-full bg-white rounded">
<div className="text-center">
<h1 className="text-[60px] lg:text-[120px] font-semibold text-black">
404
</h1>
<p className="text-[30px] lg:text-[50px] text-black">Page Not Found</p>
</div>
</div>
);
};
export default PageNotFound;
@@ -11,17 +11,13 @@ import { HTML5Backend } from "react-dnd-html5-backend";
import { useParams } from "react-router-dom";
import SignPad from "./component/signPad";
import RenderAllPdfPage from "./component/renderAllPdfPage";
import {
contactBook,
contractUsers,
getBase64FromIMG,
getBase64FromUrl
} from "../utils/Utils";
import { getBase64FromIMG, getBase64FromUrl } 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";
function PdfRequestFiles() {
const { docId } = useParams();
@@ -65,7 +61,9 @@ function PdfRequestFiles() {
});
const [isSigned, setIsSigned] = useState(false);
const [isExpired, setIsExpired] = useState(false);
const [alreadySign, setAlreadySign] = useState(false);
const [containerWH, setContainerWH] = useState({});
const divRef = useRef(null);
const rowLevel =
localStorage.getItem("rowlevel") &&
JSON.parse(localStorage.getItem("rowlevel"));
@@ -89,6 +87,7 @@ function PdfRequestFiles() {
const clientWidth = window.innerWidth;
const value = docId ? 80 : 30;
const pdfWidth = clientWidth - 160 - 200 - value;
//160 is width of left side, 200 is width of right side component and 50 is space of middle compoent
//pdf from left and right component
setPdfNewWidth(pdfWidth);
@@ -96,30 +95,17 @@ function PdfRequestFiles() {
getDocumentDetails();
}
}, []);
useEffect(() => {
if (divRef.current) {
setContainerWH({
width: divRef.current.offsetWidth,
height: divRef.current.offsetHeight
});
}
}, [divRef.current]);
//function for get document details for perticular signer with signer'object id
const getDocumentDetails = async () => {
const contractUsersRes = await contractUsers(jsonSender.objectId);
if (contractUsersRes && contractUsersRes[0]) {
const objId = contractUsersRes[0].objectId;
setSignerObjectId(objId);
} else if (contractUsersRes === "Error: Something went wrong!") {
const loadObj = {
isLoad: false
};
setHandleError("Error: Something went wrong!");
setIsLoading(loadObj);
} else if (contractUsersRes.length === 0) {
const contractContactBook = await contactBook(jsonSender.objectId);
if (contractContactBook && contractContactBook[0]) {
const objId = contractUsersRes[0].objectId;
setSignerObjectId(objId);
}
}
await axios
.get(
`${localStorage.getItem("baseUrl")}classes/${localStorage.getItem(
@@ -136,13 +122,24 @@ function PdfRequestFiles() {
.then((Listdata) => {
const json = Listdata.data;
const res = json.results;
// console.log("res", res);
if (res[0] && res.length > 0) {
const isCompleted = res[0].IsCompleted && res[0].IsCompleted;
const expireDate = res[0].ExpiryDate.iso;
const declined = res[0].IsDeclined && res[0].IsDeclined;
const expireUpdateDate = new Date(expireDate).getTime();
const currDate = new Date().getTime();
const getSigners = res[0].Signers;
const getCurrentSigner =
getSigners &&
getSigners.filter(
(data) => data.UserId.objectId === jsonSender.objectId
);
const currUserId = getCurrentSigner[0]
? getCurrentSigner[0].objectId
: "";
setSignerObjectId(currUserId);
if (res[0].SignedUrl) {
setPdfUrl(res[0].SignedUrl);
} else {
@@ -154,6 +151,7 @@ function PdfRequestFiles() {
isCertificate: true,
isModal: true
};
setAlreadySign(true);
setIsCompleted(data);
} else if (declined) {
const currentDecline = {
@@ -173,17 +171,34 @@ function PdfRequestFiles() {
(data) => data.Activity === "Signed"
);
const checkAlreadySign =
json.results[0].AuditTrail &&
json.results[0].AuditTrail.length > 0 &&
json.results[0].AuditTrail.filter(
(data) =>
data.UserPtr.objectId === currUserId &&
data.Activity === "Signed"
);
if (
checkAlreadySign &&
checkAlreadySign[0] &&
checkAlreadySign.length > 0
) {
setAlreadySign(true);
}
let signers = [];
let unSignedSigner = [];
//check document is signed or not
if (checkDocIdExist && checkDocIdExist.length > 0) {
setAlreadySign(true);
setIsDocId(true);
const signerRes = res[0].Signers;
//comparison auditTrail user details with signers user details
for (let i = 0; i < signerRes.length; i++) {
const signerId = signerRes[i].objectId;
// console.log("getSigner", getSigner);
let isSigned = false;
for (let j = 0; j < checkDocIdExist.length; j++) {
const signedExist =
@@ -192,7 +207,6 @@ function PdfRequestFiles() {
// if match then add signed data in signer array and break loop
if (signerId === signedExist) {
// console.log("signedExist", signedExist);
signers.push({ ...signerRes[i], ...signerRes[i] });
isSigned = true;
break;
@@ -202,8 +216,6 @@ function PdfRequestFiles() {
if (!isSigned) {
unSignedSigner.push({ ...signerRes[i], ...signerRes[i] });
}
// console.log("check Signers status",signers,unSignedSigner)
}
setSignedSigners(signers);
setUnSignedSigners(unSignedSigner);
@@ -211,7 +223,6 @@ function PdfRequestFiles() {
setSignerPos(res[0].Placeholders);
} else {
let unsigned = [];
// console.log("else condition");
for (let i = 0; i < res.length; i++) {
unsigned.push(res[i].Signers);
}
@@ -226,7 +237,6 @@ function PdfRequestFiles() {
alert("No data found!");
}
} else {
// alert("No data found!");
setNoData(true);
const loadObj = {
isLoad: false
@@ -279,7 +289,6 @@ function PdfRequestFiles() {
});
};
// console.log("signer", signerPos, unsignedSigners, isCompleted);
//function for embed signature or image url in pdf
async function embedImages() {
const checkUser = signerPos.filter(
@@ -320,7 +329,6 @@ function PdfRequestFiles() {
//checking if signature is only one then send image url in jpeg formate to server
if (pngUrl.length === 1 && pngUrl[0].pos.length === 1) {
// console.log("else condition");
if (isDocId) {
pdfBase64 = await getBase64FromUrl(url);
} else {
@@ -330,7 +338,7 @@ function PdfRequestFiles() {
const fontSize = 10;
const textContent =
documentId && `OpenSign™ DocumentId: ${documentId}`;
// console.log("textcontent", documentId);
const pages = pdfDoc.getPages();
const page = pages[i];
@@ -472,10 +480,54 @@ function PdfRequestFiles() {
const imgWidth = imgUrlList[id].Width
? imgUrlList[id].Width
: 150;
const isMobile = window.innerWidth < 767;
const newWidth = window.innerWidth;
const scale = isMobile ? pdfOriginalWidth / newWidth : 1;
const xPos = (pos) => {
//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) {
const x = pos.xPosition * (pos.scale / scale);
return x * scale + 50;
} else {
const x = pos.xPosition / scale;
return x * 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) {
const x = pos.xPosition * pos.scale + 50;
return x;
} else {
return pos.xPosition;
}
}
};
const yPos = (pos) => {
//checking both condition mobile and desktop view
const y = pos.yPosition / scale;
if (isMobile) {
//if pos.isMobile false -- placeholder saved from desktop view then handle position in mobile view divided by scale
if (pos.isMobile) {
const y = pos.yPosition * (pos.scale / scale);
return page.getHeight() - y * scale - imgHeight;
} else {
return page.getHeight() - y * scale - imgHeight;
}
} 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) {
const y = pos.yPosition * pos.scale;
return page.getHeight() - y - imgHeight;
} else {
return page.getHeight() - pos.yPosition - imgHeight;
}
}
};
page.drawImage(img, {
x: imgUrlList[id].xPosition,
y: page.getHeight() - imgUrlList[id].yPosition - imgHeight,
x: xPos(imgUrlList[id]),
y: yPos(imgUrlList[id]),
width: imgWidth,
height: imgHeight
});
@@ -506,24 +558,91 @@ function PdfRequestFiles() {
signerData
) => {
let signgleSign;
const isMobile = window.innerWidth < 767;
const newWidth = window.innerWidth;
const scale = isMobile ? pdfOriginalWidth / newWidth : 1;
if (
signerData &&
signerData.length === 1 &&
signerData[0].pos.length === 1
) {
const height = xyPosData.Height ? xyPosData.Height : 60;
const bottomY = xyPosData.isDrag
? xyPosData.yBottom - height
: xyPosData.yBottom - height + xyPosData.firstYPos;
const xPos = (pos) => {
//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) {
const x = pos.xPosition * (pos.scale / scale);
return x * scale + 50;
} else {
const x = pos.xPosition / scale;
return x * 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) {
const x = pos.xPosition * pos.scale + 50;
return x;
} else {
return pos.xPosition;
}
}
};
const yBottom = (pos) => {
let yPosition;
//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) {
const y = pos.yPosition * (pos.scale / scale);
yPosition = pos.isDrag
? y * scale - height
: pos.firstYPos
? y * scale - height + pos.firstYPos
: y * scale - height;
return yPosition;
} else {
const y = pos.yBottom / scale;
yPosition = pos.isDrag
? y * scale - height
: pos.firstYPos
? y * scale - height + pos.firstYPos
: y * scale - height;
return yPosition;
}
} 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) {
const y = pos.yBottom * pos.scale;
yPosition = pos.isDrag
? y - height
: pos.firstYPos
? y - height + pos.firstYPos
: y - height;
return yPosition;
} else {
yPosition = pos.isDrag
? pos.yBottom - height
: pos.firstYPos
? pos.yBottom - height + pos.firstYPos
: pos.yBottom - height;
return yPosition;
}
}
};
const bottomY = yBottom(xyPosData);
signgleSign = {
pdfFile: pdfBase64Url,
docId: documentId,
userId: signerObjectId,
sign: {
Base64: base64Url,
Left: xyPosData.resizeXPos
? xyPosData.resizeXPos
: xyPosData.xPosition,
Left: xPos(xyPosData),
Bottom: bottomY,
Width: xyPosData.Width ? xyPosData.Width : 150,
Height: height,
@@ -537,7 +656,8 @@ function PdfRequestFiles() {
) {
signgleSign = {
pdfFile: base64Url,
docId: documentId
docId: documentId,
userId: signerObjectId
};
}
@@ -565,7 +685,6 @@ function PdfRequestFiles() {
}
})
.catch((err) => {
// this.setState({ loading: false });
console.log("axois err ", err);
alert("something went wrong");
});
@@ -595,17 +714,12 @@ function PdfRequestFiles() {
//function for image upload or update
const onImageChange = (event) => {
if (event.target.files && event.target.files[0]) {
// setIsSignPad(false);
const imageType = event.target.files[0].type;
const reader = new FileReader();
reader.readAsDataURL(event.target.files[0]);
reader.onloadend = function (e) {
let width, height;
const image = new Image();
image.src = e.target.result;
image.onload = function () {
width = image.width;
@@ -783,8 +897,6 @@ function PdfRequestFiles() {
return obj;
});
// currentSigner[0].placeHolder.splice(i, 1, newUpdateUrl[0]);
// console.log("currentSigner sign", currentSigner);
const newUpdatePos = currentSigner.map((obj, ind) => {
if (obj.signerObjId === signerObjectId) {
return { ...obj, placeHolder: newUpdateUrl };
@@ -807,6 +919,7 @@ function PdfRequestFiles() {
//function for set decline true on press decline button
const declineDoc = async () => {
setIsDecline({ isDeclined: false });
const data = {
IsDeclined: true
};
@@ -842,8 +955,6 @@ function PdfRequestFiles() {
});
};
// console.log("unsigned", unsignedSigners, signerObjectId,isExpired);
return (
<DndProvider backend={HTML5Backend}>
{isLoading.isLoad ? (
@@ -859,7 +970,7 @@ function PdfRequestFiles() {
style={{
position: "absolute",
height: "100vh",
width: window.innerWidth,
width: "100%",
display: "flex",
justifyContent: "center",
flexDirection: "column",
@@ -880,7 +991,39 @@ function PdfRequestFiles() {
</div>
)}
<div className="signatureContainer">
<div className="signatureContainer" ref={divRef}>
{/* this modal is used to show decline alert */}
<CustomModal
containerWH={containerWH}
show={isDecline.isDeclined}
headMsg="Document Declined Alert!"
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>
)
)
}
footerMessage={isDecline.currnt === "Sure"}
declineDoc={declineDoc}
setIsDecline={setIsDecline}
/>
{/* this modal is used for show expired alert */}
<CustomModal
containerWH={containerWH}
show={isExpired}
headMsg="Document Expired!"
bodyMssg="This Document is no longer available."
/>
{/* this component used to render all pdf pages in left side */}
<RenderAllPdfPage
signPdfUrl={pdfDetails[0].URL}
@@ -896,66 +1039,6 @@ function PdfRequestFiles() {
marginRight: pdfOriginalWidth > 500 && "20px"
}}
>
<Modal show={isExpired}>
<ModalHeader className="bg-danger">
<span className="spanTagHead">Document Expired!</span>
</ModalHeader>
<Modal.Body>
<p className="pTagBody">
This Document is no longer available.
</p>
</Modal.Body>
</Modal>
{/* this modal is used for show decline alert */}
<Modal show={isDecline.isDeclined}>
<ModalHeader className="bg-danger">
<span className="spanTagHead">Document Declined Alert!</span>
</ModalHeader>
<Modal.Body>
{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>
)
)}
</Modal.Body>
<Modal.Footer>
{isDecline.currnt === "Sure" && (
<>
<button
style={{
color: "black"
}}
type="button"
className="finishBtn"
onClick={() => setIsDecline({ isDeclined: false })}
>
Close
</button>
<button
style={{
background: "#de4337"
}}
type="button"
className="finishBtn"
onClick={() => declineDoc()}
>
Yes
</button>
</>
)}
</Modal.Footer>
</Modal>
{/* this modal is used show this document is already sign */}
<Modal show={isCompleted.isModal}>
@@ -1015,6 +1098,8 @@ function PdfRequestFiles() {
setIsDecline={setIsDecline}
decline={true}
currentSigner={currentSigner}
pdfUrl={pdfUrl}
alreadySign={alreadySign}
/>
<RenderPdf
@@ -1045,7 +1130,6 @@ function PdfRequestFiles() {
<div
style={{
background: themeColor()
// color:"white"
}}
className="signedStyle"
>
@@ -27,8 +27,6 @@ import RenderPdf from "./component/renderPdf";
import { contractUsers, contactBook } from "../utils/Utils";
//For signYourself inProgress section signer can add sign and complete doc sign.
function SignYourSelf() {
// pdfjs.GlobalWorkerOptions.workerSrc = `//cdnjs.cloudflare.com/ajax/libs/pdf.js/${pdfjs.version}/pdf.worker.js`;
const [pdfDetails, setPdfDetails] = useState([]);
const [isSignPad, setIsSignPad] = useState(false);
const [allPages, setAllPages] = useState(null);
@@ -310,52 +308,6 @@ function SignYourSelf() {
};
setIsLoading(loadObj);
}
// await axios
// .get(
// `${localStorage.getItem("baseUrl")}classes/${localStorage.getItem(
// "_appName"
// )}_Contactbook?where={"UserId": {"__type": "Pointer","className": "_User", "objectId":"${
// jsonSender.objectId
// }"}}`,
// {
// headers: {
// "Content-Type": "application/json",
// "X-Parse-Application-Id": localStorage.getItem("parseAppId"),
// "X-Parse-Session-Token": localStorage.getItem("accesstoken"),
// },
// }
// )
// .then((Listdata) => {
// const json = Listdata.data;
// const res = json.results;
// if (res[0]) {
// setSignerUserId(res[0].objectId);
// const tourstatuss = res[0].TourStatus && res[0].TourStatus;
// if (tourstatuss && tourstatuss.length > 0) {
// setTourStatus(tourstatuss);
// const checkTourRecipients = tourstatuss.filter(
// (data) => data.signyourself
// );
// if (checkTourRecipients && checkTourRecipients.length > 0) {
// setCheckTourStatus(checkTourRecipients[0].signyourself);
// }
// }
// }
// const loadObj = {
// isLoad: false,
// };
// setIsLoading(loadObj);
// })
// .catch((err) => {
// const loadObj = {
// isLoad: false,
// };
// setHandleError("Error: Something went wrong!");
// setIsLoading(loadObj);
// });
};
//function for setting position after drop signature button over pdf
@@ -618,22 +570,33 @@ function SignYourSelf() {
? imgUrlList[id].Height
: 60;
const imgWidth = imgUrlList[id].Width ? imgUrlList[id].Width : 150;
const isMobile = window.innerWidth < 712;
const isMobile = window.innerWidth < 767;
const newWidth = window.innerWidth;
const scale = isMobile ? pdfOriginalWidth / newWidth : 1;
const posY = () => {
if (id === 0) {
return (
page.getHeight() -
imgUrlList[id].yPosition * scale -
imgHeight
);
} else if (id > 0) {
return page.getHeight() - imgUrlList[id].yPosition * scale;
}
};
page.drawImage(img, {
x: isMobile
? imgUrlList[id].xPosition * scale + 50
? imgUrlList[id].xPosition * scale + imgWidth / 2
: imgUrlList[id].xPosition,
y:
page.getHeight() - imgUrlList[id].yPosition * scale - imgHeight,
y: posY(),
width: imgWidth,
height: imgHeight
});
});
}
const pdfBytes = await pdfDoc.saveAsBase64({ useObjectStreams: false });
// console.log("pdfbyte", pdfBytes);
signPdfFun(pdfBytes, documentId);
}
setIsSignPad(false);
@@ -652,10 +615,10 @@ function SignYourSelf() {
pageNo
) => {
let singleSign;
const isMobile = window.innerWidth < 712;
const isMobile = window.innerWidth < 767;
const newWidth = window.innerWidth;
const scale = isMobile ? pdfOriginalWidth / newWidth : 1;
const imgWidth = xyPosData.Width.Width ? xyPosData.Width.Width : 150;
if (xyPostion.length === 1 && xyPostion[0].pos.length === 1) {
const height = xyPosData.Height ? xyPosData.Height : 60;
const bottomY = xyPosData.isDrag
@@ -670,7 +633,7 @@ function SignYourSelf() {
sign: {
Base64: base64Url,
Left: isMobile
? xyPosData.xPosition * scale + 80
? xyPosData.xPosition * scale + imgWidth / 2
: xyPosData.xPosition,
Bottom: bottomY,
Width: xyPosData.Width ? xyPosData.Width : 150,
@@ -684,14 +647,13 @@ function SignYourSelf() {
docId: documentId
};
}
// console.log("data",singleSign)
await axios
.post(`${localStorage.getItem("baseUrl")}functions/signPdf`, singleSign, {
headers: {
"Content-Type": "application/json",
"X-Parse-Application-Id": localStorage.getItem("parseAppId"),
sessionToken: localStorage.getItem("accesstoken")
// sessiontoken,
}
})
.then((Listdata) => {
@@ -718,7 +680,6 @@ function SignYourSelf() {
//function for save x and y position and show signature tab on that position
const handleTabDrag = (key, e) => {
// console.log("key", key);
setDragKey(key);
setIsDragging(true);
};
@@ -791,8 +752,6 @@ function SignYourSelf() {
//function for image upload or update
const onImageChange = (event) => {
if (event.target.files && event.target.files[0]) {
// setIsSignPad(false);
const imageType = event.target.files[0].type;
const reader = new FileReader();
@@ -825,16 +784,11 @@ function SignYourSelf() {
setImage({ src: image.src, imgType: imageType });
};
//const imgUrl = URL.createObjectURL(event.target.files[0]);
// const imgData = { width: newWidth, height: newHeight, src: imgUrl };
}
};
//function for save button to save signature or image url
const saveSign = (isDefaultSign) => {
// console.log("isDefault sign", isDefaultSign);
const signatureImg = isDefaultSign ? defaultSignImg : signature;
setIsSignPad(false);
@@ -878,9 +832,6 @@ function SignYourSelf() {
if (updateFilter.length > 0) {
const getXYdata = xyPostion[index].pos;
// const updateWidth = getXYdata[key].Width;
// const updateHeight = getXYdata[key].Height;
const getPosData = getXYdata;
const addSign = getPosData.map((url, ind) => {
if (url.key === key) {
@@ -937,7 +888,7 @@ function SignYourSelf() {
let filterData = xyPostion[index].pos.filter((data) => data.key !== key);
// //delete and update block position
//delete and update block position
if (filterData.length > 0) {
updateResizeData.push(filterData);
const newUpdatePos = xyPostion.map((obj, ind) => {
@@ -949,12 +900,10 @@ function SignYourSelf() {
setXyPostion(newUpdatePos);
} else {
// setXyPostion([]);
const getRemainPage = xyPostion.filter(
(data) => data.pageNumber !== pageNumber
);
// console.log("remainPage",getRemainPage)
if (getRemainPage && getRemainPage.length > 0) {
setXyPostion(getRemainPage);
} else {
@@ -996,7 +945,6 @@ function SignYourSelf() {
};
const tourConfig = [
{
// updateDelay: 1500,
selector: '[data-tut="reactourFirst"]',
content: `Drag the signature or stamp placeholder onto the PDF to choose your desired signing location.`,
position: "top",
@@ -1046,8 +994,6 @@ function SignYourSelf() {
)
.then((Listdata) => {
// const json = Listdata.data;
// const res = json.results;
// console.log("res", json);
})
.catch((err) => {
console.log("axois err ", err);
@@ -0,0 +1,59 @@
import React from "react";
import "../../css/customModal.css";
import "../../css/signature.css";
function CustomModal({
show,
headMsg,
bodyMssg,
footerMessage,
declineDoc,
setIsDecline,
containerWH
}) {
const isMobile = window.innerWidth < 767;
return (
show && (
<div
className="parentDiv"
style={{
width: containerWH && containerWH.width,
height: isMobile ? "100%" : containerWH && containerWH.height
}}
>
<div className="childDiv">
<div className="modalHeadDiv bg-danger">{headMsg && headMsg}</div>
<div className="modalBodyDIv">
<p className="pTagBody">{bodyMssg && bodyMssg}</p>
</div>
{footerMessage && (
<div className="modalFooterDiv">
<button
style={{
color: "black"
}}
type="button"
className="finishBtn"
onClick={() => setIsDecline({ isDeclined: false })}
>
Close
</button>
<button
style={{
background: "#de4337"
}}
type="button"
className="finishBtn"
onClick={() => declineDoc()}
>
Yes
</button>
</div>
)}
</div>
</div>
)
);
}
export default CustomModal;
@@ -1,58 +1,18 @@
import React, { useEffect } from "react";
import axios from "axios";
import React from "react";
function DefaultSignature({
themeColor,
defaultSignImg,
setShowAlreadySignDoc,
setDefaultSignImg,
userObjectId,
setIsLoading,
xyPostion,
xyPostion
}) {
useEffect(() => {
getDefaultSignature(userObjectId);
}, []);
//function for fetch default sigature added bu users
const getDefaultSignature = async (userObjectId) => {
await axios
.get(
`${localStorage.getItem("baseUrl")}classes/${localStorage.getItem(
"_appName"
)}_Signature?where={"UserId": {"__type": "Pointer","className": "_User", "objectId":"${userObjectId}"}}`,
{
headers: {
"Content-Type": "application/json",
"X-Parse-Application-Id": localStorage.getItem("parseAppId"),
"X-Parse-Session-Token": localStorage.getItem("accesstoken"),
},
}
)
.then((Listdata) => {
const json = Listdata.data;
const res = json.results;
if (res[0] && res.length > 0) {
setDefaultSignImg(res[0].ImageURL);
}
const loadObj = {
isLoad: false,
};
setIsLoading(loadObj);
})
.catch((err) => {
// this.setState({ loading: false });
console.log("axois err ", err);
});
};
const confirmToaddDefaultSign = () => {
if (xyPostion.length > 0) {
const alreadySign = {
status: true,
mssg: "Are you sure you want to sign at requested locations?",
sure: true,
sure: true
};
setShowAlreadySignDoc(alreadySign);
} else {
@@ -67,7 +27,7 @@ function DefaultSignature({
background: themeColor(),
color: "white",
padding: "5px",
fontFamily: "sans-serif",
fontFamily: "sans-serif"
}}
>
Signature
@@ -78,7 +38,7 @@ function DefaultSignature({
flexDirection: "column",
alignItems: "center",
marginTop: "10px",
fontWeight: "600",
fontWeight: "600"
}}
>
{defaultSignImg ? (
@@ -90,7 +50,7 @@ function DefaultSignature({
style={{
width: "100%",
height: "100%",
objectFit: "contain",
objectFit: "contain"
}}
src={defaultSignImg}
/>
@@ -100,7 +60,7 @@ function DefaultSignature({
background: themeColor(),
color: "white",
marginTop: "20px",
cursor: "pointer",
cursor: "pointer"
}}
type="button"
className="finishBtn finishnHover"
@@ -111,7 +71,9 @@ function DefaultSignature({
</>
) : (
<div style={{ margin: "10px" }}>
<span>Click a signature placeholder to start signing the document!</span>
<span>
Click a signature placeholder to start signing the document!
</span>
</div>
)}
</div>
@@ -18,7 +18,7 @@ function EmailComponent({
setSuccessEmail,
signObjId,
pdfName,
sender,
sender
}) {
const [emailCount, setEmailCount] = useState([]);
const [emailValue, setEmailValue] = useState();
@@ -26,30 +26,11 @@ function EmailComponent({
//function for send email
const sendEmail = async () => {
setIsLoading(true);
let sendMail, recipent;
let sendMail;
for (let i = 0; i < emailCount.length; i++) {
// await axios
// .get(
// `${localStorage.getItem("baseUrl")}classes/${localStorage.getItem("_appName")}_Contactbook?where={"Email":"${emailCount[i]}"}`,
// {
// headers: {
// "Content-Type": "application/json",
// "X-Parse-Application-Id": localStorage.getItem("parseAppId"),
// sessionToken: localStorage.getItem("accesstoken"),
// },
// }
// )
// .then((Listdata) => {
// const json = Listdata.data;
// if (json.results[0]) {
// recipent = json.results[0];
// }
// })
// .catch((err) => {
// console.log("axois err ", err);
// });
try {
console.log("recipients", recipent);
const imgPng =
"https://qikinnovation.ams3.digitaloceanspaces.com/logo.png";
// "https://qikinnovation.ams3.digitaloceanspaces.com/mailLogo_2023-08-18T12%3A51%3A31.573Z.png";
@@ -58,15 +39,9 @@ function EmailComponent({
const headers = {
"Content-Type": "application/json",
"X-Parse-Application-Id": localStorage.getItem("parseAppId"),
sessionToken: localStorage.getItem("accesstoken"),
sessionToken: localStorage.getItem("accesstoken")
};
// const serverUrl = localStorage.getItem("baseUrl");
// const newServer = serverUrl.replaceAll("/", "%2F");
// const serverParams = `${newServer}&${localStorage.getItem(
// "parseAppId"
// )}&${localStorage.getItem("_appName")}`;
// let pdfUrlWeb = `<span><a href=https://qik-ai-org.github.io/Sign-MicroappV2/#/login/${signObjId}/${recipent.Email}/${serverParams} style='cursor: pointer;'> ${pdfName}</a><span>`;
const themeBGcolor = themeColor();
let params = {
pdfName: pdfName,
@@ -83,8 +58,7 @@ function EmailComponent({
pdfName +
" Standard is attached to this email. Kindly download the document from the attachment.</p></div> </div><div><p>This is an automated email from Open Sign. For any queries regarding this email, please contact the sender " +
sender.email +
" directly. If you think this email is inappropriate or spam, you may file a complaint with Open Sign here.</p></div></div></body></html>",
//"html":"<html><head><meta http-equiv='Content-Type' content='text/html; charset=UTF-8' /> </head> <body> <div style='background-color: #f5f5f5; padding: 20px'> <div style=' box-shadow: rgba(0, 0, 0, 0.1) 0px 4px 12px;background-color: white;padding-bottom: 20px;'> <div><img src="+imgPng +" height='50' style='padding: 20px' /></div> <div style=' padding: 2px;font-family: system-ui;background-color: #47a3ad;'><p style='font-size: 20px;font-weight: 400;color: white;padding-left: 20px;' > Digital Signature Request</p></div><div><p style='padding: 20px;font-family: system-ui;font-size: 14px; margin-bottom: 10px;'> " + recipent.Name + " has requested you to review and sign" +pdfName+"</p><div style='padding: 5px 0px 5px 25px;display: flex;flex-direction: row;justify-content: space-around;'><span>Sender</span><span>" + recipent.Email + " </span></div><div style='display: flex; justify-content: center;margin-top: 10px;'><button style='padding: 8px 15px 8px 15px;background-color: #d46b0f;color: white; border: 0px;box-shadow: rgba(0, 0, 0, 0.05) 0px 6px 24px 0px,rgba(0, 0, 0, 0.08) 0px 0px 0px 1px;'>Sign here</button></div></div></div><div><p> This is an automated email from Open Sign. For any queries regarding this email, please contact the sender " + recipent.Email + " directly.If you think this email is inappropriate or spam, you may file a complaint with Open Sign here.</p> </div></div></body> </html>"
" directly. If you think this email is inappropriate or spam, you may file a complaint with Open Sign here.</p></div></div></body></html>"
};
sendMail = await axios.post(url, params, { headers: headers });
} catch (error) {
@@ -135,10 +109,18 @@ function EmailComponent({
const handleToPrint = async (event) => {
event.preventDefault();
const base64 = await getBase64FromUrl(pdfUrl);
printModule({ printable: base64, type: "pdf", base64: true });
const pdf = await getBase64FromUrl(pdfUrl);
const isAndroidDevice = navigator.userAgent.match(/Android/i);
const isAppleDevice = (/iPad|iPhone|iPod/.test(navigator.platform) || (navigator.platform === 'MacIntel' && navigator.maxTouchPoints > 1)) && !window.MSStream
if (isAndroidDevice || isAppleDevice) {
const byteArray = Uint8Array.from(atob(pdf).split('').map(char => char.charCodeAt(0)));
const blob = new Blob([byteArray], { type: 'application/pdf' });
const blobUrl = URL.createObjectURL(blob);
window.open(blobUrl, '_blank');
} else {
printModule({ printable: pdf, type: "pdf", base64: true });
}
// window.print('https://nxgcreator.s3.ap-south-1.amazonaws.com/exported_file_32_2023-08-22T04%3A59%3A13.432Z.pdf',);
};
//handle download signed pdf
@@ -146,6 +128,9 @@ function EmailComponent({
saveAs(pdfUrl, `${pdfName}_signed_by_OpenSign™.pdf`);
};
const isAndroid = /Android/i.test(navigator.userAgent);
return (
<div>
{/* isEmail */}
@@ -162,7 +147,7 @@ function EmailComponent({
alignItems: "center",
zIndex: "20",
backgroundColor: "#e6f2f2",
opacity: 0.8,
opacity: 0.8
}}
>
<img
@@ -181,26 +166,28 @@ function EmailComponent({
<div style={{ display: "flex", flexDirection: "row" }}>
<div></div>
<button
onClick={handleToPrint}
style={{
display: "flex",
flexDirection: "row",
alignItems: "center",
}}
className="btn btn-primary btn-sm"
>
<i
className="fa fa-print"
{!isAndroid && (
<button
onClick={handleToPrint}
style={{
fontSize: "15px",
marginRight: "3px",
color: "white",
display: "flex",
flexDirection: "row",
alignItems: "center"
}}
aria-hidden="true"
></i>
Print
</button>
className="btn btn-primary btn-sm"
>
<i
className="fa fa-print"
style={{
fontSize: "15px",
marginRight: "3px",
color: "white"
}}
aria-hidden="true"
></i>
Print
</button>
)}
<button
className="btn btn-danger btn-sm"
@@ -209,7 +196,7 @@ function EmailComponent({
display: "flex",
flexDirection: "row",
alignItems: "center",
marginLeft: "10px",
marginLeft: "10px"
}}
>
<i
@@ -217,7 +204,7 @@ function EmailComponent({
style={{
color: "white",
fontSize: "15px",
marginRight: "3px",
marginRight: "3px"
}}
aria-hidden="true"
></i>
@@ -231,7 +218,7 @@ function EmailComponent({
<div
style={{
position: "absolute",
marginLeft: "50px",
marginLeft: "50px"
}}
>
<img
@@ -249,7 +236,7 @@ function EmailComponent({
verticalAlign: "baseline",
fontWeight: "500",
color: "#403f3e",
fontSize: "15px",
fontSize: "15px"
}}
>
Recipients added here will get a copy of the signed document.
@@ -261,18 +248,20 @@ function EmailComponent({
style={{
display: "flex",
flexDirection: "row",
width: "450px",
flexWrap: "wrap",
flexWrap: "wrap"
}}
>
{emailCount.map((data, ind) => {
return (
<div className="emailChip" key={ind}>
<div className="emailChip"
style={{display:"flex", flexDirection:"row", alignItems:"center"}}
key={ind}>
<span
style={{
color: "white",
fontSize: "13px",
marginRight: "20px",
marginRight: "20px"
}}
>
{data}
@@ -317,7 +306,7 @@ function EmailComponent({
)}
<span
style={{
cursor: emailValue && "pointer",
cursor: emailValue && "pointer"
}}
onClick={() => {
if (emailValue) {
@@ -330,7 +319,7 @@ function EmailComponent({
backgroundColor: themeColor(),
padding: "2px 10px",
marginTop: "10px",
color: "white",
color: "white"
}}
className="fa fa-plus"
aria-hidden="true"
@@ -342,7 +331,7 @@ function EmailComponent({
background: "#e3e2e1",
marginTop: "30px",
padding: "5px",
borderRadius: "3px",
borderRadius: "3px"
}}
>
<span style={{ fontWeight: "700" }}>Note:</span>
@@ -356,7 +345,7 @@ function EmailComponent({
<Modal.Footer>
<button
style={{
color: "black",
color: "black"
}}
type="button"
className="finishBtn"
@@ -368,7 +357,7 @@ function EmailComponent({
disabled={emailCount.length === 0 && true}
style={{
background: themeColor(),
color: "white",
color: "white"
}}
type="button"
className={emailCount.length === 0 ? "defaultBtn" : "finishBtn"}
@@ -36,8 +36,8 @@ function FieldsComponent({
}) {
const signStyle = pdfUrl ? "disableSign" : "signatureBtn";
const isMobile = window.innerWidth < 712;
const isMobile = window.innerWidth <767;
const SelectItem = React.forwardRef(
({ children, className, ...props }, forwardedRef) => {
return (
@@ -107,7 +107,7 @@ function FieldsComponent({
}}
>
<Select.Trigger
className="SelectTrigger"
className={selectedEmail ? "selectEmail": "SelectTrigger"}
style={{
background: isSelectListId
? color[isSelectListId % color.length]
@@ -115,7 +115,10 @@ function FieldsComponent({
}}
aria-label="Food"
>
<Select.Value placeholder="Select signer.." />
<Select.Value
placeholder="Select signer.." />
{!selectedEmail &&
<Select.Icon className="SelectIcon">
<i
style={{
@@ -127,7 +130,7 @@ function FieldsComponent({
className="fa fa-angle-down"
aria-hidden="true"
></i>
</Select.Icon>
</Select.Icon>}
</Select.Trigger>
<Select.Portal>
<Select.Content
@@ -33,10 +33,11 @@ function Header({
decline,
currentSigner,
dataTut4,
alreadySign
}) {
const isMobile = window.innerWidth < 712;
const isMobile = window.innerWidth < 767;
const navigate = useNavigate();
const isGuestSigner = localStorage.getItem("isGuestSigner");
//for go to previous page
function previousPage() {
changePage(-1);
@@ -49,7 +50,7 @@ function Header({
const handleDeclinePdfAlert = async () => {
const currentDecline = {
currnt: "Sure",
isDeclined: true,
isDeclined: true
};
setIsDecline(currentDecline);
};
@@ -59,8 +60,16 @@ function Header({
event.preventDefault();
const pdf = await getBase64FromUrl(pdfUrl);
printModule({ printable: pdf, type: "pdf", base64: true });
const isAndroidDevice = navigator.userAgent.match(/Android/i);
const isAppleDevice = (/iPad|iPhone|iPod/.test(navigator.platform) || (navigator.platform === 'MacIntel' && navigator.maxTouchPoints > 1)) && !window.MSStream
if (isAndroidDevice || isAppleDevice) {
const byteArray = Uint8Array.from(atob(pdf).split('').map(char => char.charCodeAt(0)));
const blob = new Blob([byteArray], { type: 'application/pdf' });
const blobUrl = URL.createObjectURL(blob);
window.open(blobUrl, '_blank');
} else {
printModule({ printable: pdf, type: "pdf", base64: true });
}
};
//handle download signed pdf
@@ -72,14 +81,16 @@ function Header({
return (
<div
style={{ paddingBottom: "5px", paddingTop: "5px" }}
style={{ padding: !isGuestSigner && "5px 0px 5px 0px" }}
className="mobileHead"
>
{isMobile && isShowHeader ? (
<div
id="navbar"
className="stickyHead"
style={{ width: window.innerWidth - 30 + "px" }}
className={isGuestSigner ? "stickySignerHead" : "stickyHead"}
style={{
width: isGuestSigner ? window.innerWidth : window.innerWidth - 30 + "px"
}}
>
<div className="preBtn2">
<div
@@ -108,7 +119,7 @@ function Header({
fontSize: "13px",
fontWeight: "600",
marginLeft: "10px",
marginRight: "10px",
marginRight: "10px"
}}
>
{pageNumber || (allPages ? 1 : "--")} of {allPages || "--"}
@@ -132,7 +143,7 @@ function Header({
color: themeColor(),
border: "none",
fontWeight: "650",
fontSize: "16px",
fontSize: "16px"
}}
>
<i className="fa fa-ellipsis-v" aria-hidden="true"></i>
@@ -151,7 +162,7 @@ function Header({
<div
style={{
display: "flex",
flexDirection: "row",
flexDirection: "row"
}}
>
<i
@@ -164,6 +175,7 @@ function Header({
</DropdownMenu.Item>
<DropdownMenu.Item className="DropdownMenuItem">
<PDFDownloadLink
style={{ textDecoration: "none" }}
document={<Certificate pdfData={pdfDetails} />}
fileName={`completion certificate-${
pdfDetails[0] && pdfDetails[0].Name
@@ -175,22 +187,26 @@ function Header({
{loading ? (
"Loading document..."
) : (
<div
<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",
marginRight: "3px"
}}
aria-hidden="true"
></i>
Certificate
</div>
</button>
)}
</>
)}
@@ -216,7 +232,7 @@ function Header({
border: "none",
fontWeight: "650",
fontSize: "16px",
marginRight: "10px",
marginRight: "10px"
}}
>
Decline
@@ -224,18 +240,16 @@ function Header({
)}
{isPlaceholder ? (
<div
onClick={() => {
if (!isMailSend) {
alertSendEmail();
}
}}
style={{
color: isMailSend ? "gray" : themeColor(),
border: "none",
fontWeight: "650",
fontSize: "16px",
fontSize: "16px"
}}
data-tut={dataTut4}
>
@@ -243,7 +257,7 @@ function Header({
</div>
) : (
<div
data-tut="reactourThird"
data-tut="reactourThird"
onClick={() => {
if (!pdfUrl) {
embedImages();
@@ -253,7 +267,7 @@ function Header({
color: themeColor(),
border: "none",
fontWeight: "650",
fontSize: "16px",
fontSize: "16px"
}}
>
Finish
@@ -277,10 +291,8 @@ function Header({
pdfUrl || isAlreadySign.mssg ? (
<div style={{ display: "flex", flexDirection: "row" }}>
{pdfDetails[0] && pdfDetails.length > 0 && (
// <Certificate
// pdfData={completePdfData}
// />
<PDFDownloadLink
style={{ textDecoration: "none" }}
document={<Certificate pdfData={pdfDetails} />}
fileName={`completion certificate-${
pdfDetails[0] && pdfDetails[0].Name
@@ -296,7 +308,7 @@ function Header({
style={{
display: "flex",
flexDirection: "row",
alignItems: "center",
alignItems: "center"
}}
>
<i
@@ -304,7 +316,7 @@ function Header({
style={{
color: "white",
fontSize: "15px",
marginRight: "3px",
marginRight: "3px"
}}
aria-hidden="true"
></i>
@@ -319,7 +331,7 @@ function Header({
style={{
display: "flex",
flexDirection: "row",
alignItems: "center",
alignItems: "center"
}}
className="defaultBtn printBtn"
>
@@ -328,7 +340,7 @@ function Header({
style={{
fontSize: "15px",
marginRight: "3px",
color: "white",
color: "white"
}}
aria-hidden="true"
></i>
@@ -340,7 +352,7 @@ function Header({
style={{
display: "flex",
flexDirection: "row",
alignItems: "center",
alignItems: "center"
}}
className="defaultBtn downloadBtn"
onClick={() => handleDownloadPdf()}
@@ -350,7 +362,7 @@ function Header({
style={{
color: "white",
fontSize: "15px",
marginRight: "3px",
marginRight: "3px"
}}
aria-hidden="true"
></i>
@@ -361,7 +373,7 @@ function Header({
<div style={{ display: "flex", flexDirection: "row" }}>
<button
style={{
background: "#de4337",
background: "#de4337"
}}
className="finishBtn hoverCss"
onClick={() => {
@@ -374,7 +386,7 @@ function Header({
<button
data-tut="reactourThird"
style={{
background: !pdfUrl ? "#188ae2" : "#d3edeb",
background: !pdfUrl ? "#188ae2" : "#d3edeb"
}}
className="finishBtn sendHover"
onClick={() => {
@@ -387,85 +399,6 @@ function Header({
</button>
</div>
)
) : pdfUrl || (documentStatus && documentStatus.isCompleted) ? (
<div style={{ display: "flex", flexDirection: "row" }}>
<PDFDownloadLink
document={<Certificate pdfData={pdfDetails} />}
fileName={`completion certificate-${
pdfDetails[0] && pdfDetails[0].Name
}.pdf`}
>
{({ blob, url, loading, error }) =>
loading ? (
"Loading document..."
) : (
<button
type="button"
style={{
display: "flex",
flexDirection: "row",
alignItems: "center",
}}
className="defaultBtn certificateBtn"
>
<i
className="fa fa-certificate"
style={{
color: "white",
fontSize: "15px",
marginRight: "3px",
}}
aria-hidden="true"
></i>
Certificate
</button>
)
}
</PDFDownloadLink>
<button
onClick={handleToPrint}
type="button"
style={{
display: "flex",
flexDirection: "row",
alignItems: "center",
}}
className="defaultBtn printBtn"
>
<i
className="fa fa-print"
style={{
fontSize: "15px",
marginRight: "3px",
color: "white",
}}
aria-hidden="true"
></i>
Print
</button>
<button
type="button"
className="defaultBtn downloadBtn"
style={{
display: "flex",
flexDirection: "row",
alignItems: "center",
marginLeft: "10px",
}}
onClick={() => handleDownloadPdf()}
>
<i
className="fa fa-download"
style={{
color: "white",
fontSize: "15px",
marginRight: "3px",
}}
aria-hidden="true"
></i>
Download
</button>
</div>
) : isPlaceholder ? (
<>
{!isMailSend &&
@@ -502,7 +435,7 @@ function Header({
data-tut="reactourFour"
style={{
background: isMailSend ? "rgb(203, 203, 203)" : "#188ae2",
color: isMailSend && "rgb(77, 75, 75)",
color: isMailSend && "rgb(77, 75, 75)"
}}
onClick={() => {
alertSendEmail();
@@ -514,10 +447,11 @@ function Header({
</div>
</>
) : isPdfRequestFiles ? (
isSigned ? (
alreadySign ? (
<div style={{ display: "flex", flexDirection: "row" }}>
{isCompleted.isCertificate && (
<PDFDownloadLink
style={{ textDecoration: "none" }}
document={<Certificate pdfData={pdfDetails} />}
fileName={`completion certificate-${
pdfDetails[0] && pdfDetails[0].Name
@@ -533,7 +467,7 @@ function Header({
style={{
display: "flex",
flexDirection: "row",
alignItems: "center",
alignItems: "center"
}}
>
<i
@@ -541,7 +475,7 @@ function Header({
style={{
color: "white",
fontSize: "15px",
marginRight: "3px",
marginRight: "3px"
}}
aria-hidden="true"
></i>
@@ -558,7 +492,7 @@ function Header({
style={{
display: "flex",
flexDirection: "row",
alignItems: "center",
alignItems: "center"
}}
>
<i
@@ -566,7 +500,7 @@ function Header({
style={{
fontSize: "15px",
marginRight: "3px",
color: "white",
color: "white"
}}
aria-hidden="true"
></i>
@@ -579,7 +513,7 @@ function Header({
style={{
display: "flex",
flexDirection: "row",
alignItems: "center",
alignItems: "center"
}}
onClick={() => handleDownloadPdf()}
>
@@ -588,7 +522,7 @@ function Header({
style={{
color: "white",
fontSize: "15px",
marginRight: "3px",
marginRight: "3px"
}}
aria-hidden="true"
></i>
@@ -610,7 +544,7 @@ function Header({
<>
<button
style={{
background: "#de4337",
background: "#de4337"
}}
className="finishBtn hoverCss"
onClick={() => {
@@ -621,7 +555,7 @@ function Header({
</button>
<button
style={{
background: "#188ae2",
background: "#188ae2"
}}
type="button"
className="finishBtn sendHover"
@@ -635,6 +569,86 @@ function Header({
)}
</div>
)
) : pdfUrl || (documentStatus && documentStatus.isCompleted) ? (
<div style={{ display: "flex", flexDirection: "row" }}>
<PDFDownloadLink
style={{ textDecoration: "none" }}
document={<Certificate pdfData={pdfDetails} />}
fileName={`completion certificate-${
pdfDetails[0] && pdfDetails[0].Name
}.pdf`}
>
{({ blob, url, loading, error }) =>
loading ? (
"Loading document..."
) : (
<button
type="button"
style={{
display: "flex",
flexDirection: "row",
alignItems: "center"
}}
className="defaultBtn certificateBtn"
>
<i
className="fa fa-certificate"
style={{
color: "white",
fontSize: "15px",
marginRight: "3px"
}}
aria-hidden="true"
></i>
Certificate
</button>
)
}
</PDFDownloadLink>
<button
onClick={handleToPrint}
type="button"
style={{
display: "flex",
flexDirection: "row",
alignItems: "center"
}}
className="defaultBtn printBtn"
>
<i
className="fa fa-print"
style={{
fontSize: "15px",
marginRight: "3px",
color: "white"
}}
aria-hidden="true"
></i>
Print
</button>
<button
type="button"
className="defaultBtn downloadBtn"
style={{
display: "flex",
flexDirection: "row",
alignItems: "center",
marginLeft: "10px"
}}
onClick={() => handleDownloadPdf()}
>
<i
className="fa fa-download"
style={{
color: "white",
fontSize: "15px",
marginRight: "3px"
}}
aria-hidden="true"
></i>
Download
</button>
</div>
) : (
<div>
<button
@@ -649,7 +663,7 @@ function Header({
<button
style={{
background: "#188ae2",
background: "#188ae2"
}}
type="button"
className="finishBtn sendHover"
@@ -5,8 +5,6 @@ import { Rnd } from "react-rnd";
import { themeColor } from "../../utils/ThemeColor/backColor";
import { Document, Page, pdfjs } from "react-pdf";
// import Draggable from "react-draggable";
pdfjs.GlobalWorkerOptions.workerSrc = `//cdnjs.cloudflare.com/ajax/libs/pdf.js/${pdfjs.version}/pdf.worker.js`;
function RenderPdf({
@@ -41,19 +39,98 @@ function RenderPdf({
placeholder,
pdfLoadFail
}) {
const isMobile = window.innerWidth < 712;
const isMobile = window.innerWidth < 767;
const newWidth = window.innerWidth;
const scale = isMobile ? pdfOriginalWidth / newWidth : 1;
// handle signature block width and height according to screen
const posWidth = (pos) => {
let width;
if (isMobile) {
if (!pos.isMobile) {
width = pos.Width / scale ? pos.Width / scale : 150 / scale;
return width;
} else {
width = pos.Width ? pos.Width : 150;
return width;
}
} else {
width = pos.Width ? pos.Width : 150;
return width;
}
};
const posHeight = (pos) => {
let width;
if (isMobile) {
if (!pos.isMobile) {
width = pos.Height / scale ? pos.Height / scale : 60 / scale;
return width;
} else {
width = pos.Height ? pos.Height : 60;
return width;
}
} else {
width = pos.Height ? pos.Height : 60;
return width;
}
};
//check isGuestSigner is present in local if yes than handle login flow header in mobile view
const isGuestSigner = localStorage.getItem("isGuestSigner");
//function for render placeholder block over pdf document
const checkSignedSignes = (data) => {
// console.log("data",data)
const checkSign = signedSigners.filter(
(sign) => sign.objectId === data.signerObjId
);
if (data.signerObjId === signerObjectId) {
setCurrentSigner(true);
}
const xPos = (pos) => {
//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 pos.xPosition / scale - 20;
}
//pos.isMobile true -- placeholder save from mobile view(small device) handle position in mobile view(small screen) view divided by scale
else {
return pos.xPosition * (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 && pos.xPosition * pos.scale + 50;
}
//else placeholder save from desktop(bigscreen) and show in desktop(bigscreen)
else {
return pos.xPosition;
}
}
};
const yPos = (pos) => {
//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 pos.yPosition / scale;
}
//pos.isMobile true -- placeholder save from mobile view(small device) handle position in mobile view(small screen) view divided by scale
else {
return pos.yPosition * (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 && pos.yPosition * pos.scale + 50;
}
//else placeholder save from desktop(bigscreen) and show in desktop(bigscreen)
else {
return pos.yPosition;
}
}
};
return (
checkSign.length === 0 &&
data.placeHolder.map((placeData, key) => {
@@ -91,15 +168,13 @@ function RenderPdf({
borderWidth: "0.2px"
}}
size={{
width: pos.Width ? pos.Width : 150,
height: pos.Height ? pos.Height : 60
width: posWidth(pos),
height: posHeight(pos)
}}
lockAspectRatio={pos.Width && 2.5}
default={{
x: pos.scale
? pos.xPosition * pos.scale
: pos.xPosition,
y: pos.scale ? pos.yPosition * pos.scale : pos.yPosition
x: xPos(pos),
y: yPos(pos)
}}
onClick={() => {
setIsSignPad(true);
@@ -160,12 +235,12 @@ function RenderPdf({
borderWidth: "0.2px"
}}
default={{
x: pos.scale ? pos.xPosition * pos.scale : pos.xPosition,
y: pos.scale ? pos.yPosition * pos.scale : pos.yPosition
x: xPos(pos),
y: yPos(pos)
}}
size={{
width: pos.Width ? pos.Width : 150,
height: pos.Height ? pos.Height : 60
width: posWidth(pos),
height: posHeight(pos)
}}
lockAspectRatio={pos.Width ? pos.Width / pos.Height : 2.5}
>
@@ -174,7 +249,7 @@ function RenderPdf({
fontSize: "12px",
color: "black",
fontWeight: "600",
// justifyContent: "center",
marginTop: "0px"
}}
>
@@ -191,26 +266,11 @@ function RenderPdf({
return (
<>
{isMobile ? (
// <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",
// marginTop: "50px",
// }}
// noScrollY={false}
// noScrollX={pdfNewWidth < pdfOriginalWidth ? false : true}
// >
{isMobile && scale ? (
<div
style={{
border: "0.1px solid #ebe8e8"
// marginTop: "50px",
// height:window.innerHeight-100+'px',
// width:window.innerWidth
border: "0.1px solid #ebe8e8",
marginTop: isGuestSigner && "30px"
}}
ref={drop}
id="container"
@@ -269,13 +329,20 @@ function RenderPdf({
borderWidth: "0.2px"
}}
size={{
width: pos.Width ? pos.Width : 150,
height: pos.Height ? pos.Height : 60
width: posWidth(pos),
height: posHeight(pos)
}}
lockAspectRatio={pos.Width && 2.5}
//if pos.isMobile false -- placeholder saved from desktop view then handle position in mobile view divide by scale
//else if pos.isMobile true -- placeholder saved from mobile or tablet view then handle position in desktop view divide by scale
default={{
x: pos.xPosition,
y: pos.yPosition
x: !pos.isMobile
? pos.xPosition / scale
: pos.xPosition * (pos.scale / scale) - 50,
y: !pos.isMobile
? pos.yPosition / scale
: pos.yPosition * (pos.scale / scale)
}}
onClick={() => {
setIsSignPad(true);
@@ -328,13 +395,20 @@ function RenderPdf({
borderWidth: "0.2px"
}}
size={{
width: pos.Width ? pos.Width : 150,
height: pos.Height ? pos.Height : 60
width: posWidth(pos),
height: posHeight(pos)
}}
disableDragging={true}
default={{
x: pos.xPosition,
y: pos.yPosition
//if pos.isMobile false -- placeholder saved from desktop view then handle position in mobile view divide by scale
//else if pos.isMobile true -- placeholder saved from mobile or tablet view then handle position in desktop view divide by scale
x: !pos.isMobile
? pos.xPosition / scale
: pos.xPosition * (pos.scale / scale) - 50,
y: !pos.isMobile
? pos.yPosition / scale
: pos.yPosition * (pos.scale / scale)
}}
onClick={() => {
setIsSignPad(true);
@@ -409,7 +483,14 @@ function RenderPdf({
right: { display: "none" },
bottomRight: { display: "block" }
}}
onDragStop={handleStop}
onDragStop={(event, dragElement) =>
handleStop(
event,
dragElement,
data.signerObjId,
pos.key
)
}
default={{
x: pos.xPosition,
y: pos.yPosition
@@ -437,13 +518,6 @@ function RenderPdf({
data.signerObjId
);
}}
// onClick={(e) => {
// e.stopPropagation();
// handleDeleteSign(
// pos.key,
// data.signerObjId
// );
// }}
style={{
position: "absolute",
right: 0,
@@ -461,7 +535,7 @@ function RenderPdf({
fontSize: "12px",
color: "black",
fontWeight: "600",
// justifyContent: "center",
marginTop: "0px"
}}
>
@@ -532,7 +606,6 @@ function RenderPdf({
>
{" "}
<div
// className="dragElm"
onTouchStart={(e) => {
if (!isDragging) {
setTimeout(() => {
@@ -545,18 +618,12 @@ function RenderPdf({
}}
>
<div
// className="dragElm"
ref={nodeRef}
onTouchStart={(e) => {
e.stopPropagation();
handleDeleteSign(pos.key);
setIsStamp(false);
}}
// onClick={(e) => {
// e.stopPropagation();
// handleDeleteSign(pos.key);
// setIsStamp(false);
// }}
style={{
position: "absolute",
right: 0,
@@ -590,10 +657,8 @@ function RenderPdf({
<>
<Rnd
allowAnyClick
// cancel=".dragElm"
ref={nodeRef}
key={pos.key}
// lockAspectRatio={2.5}
lockAspectRatio={
pos.Width ? pos.Width / pos.Height : 2.5
}
@@ -616,53 +681,22 @@ function RenderPdf({
onDrag={(e) => {
handleTabDrag(pos.key, e);
}}
// onMouseUp={(e) => handleTabDrag(pos.key, e)}
onDragStop={handleStop}
size={{
width: pos.Width ? pos.Width : 150,
height: pos.Height ? pos.Height : 60
}}
// onMouseDown={(e) => {
// if (!isDragging) {
// console.log("child m=event",isDragging);
// setTimeout(() => {
// if(isDeleted){
// setIsSignPad(true);
// // setIsSignPad(false)
// setSignKey(pos.key);
// setIsStamp(pos.isStamp);
// }else{
// setIsSignPad(true);
// // setIsSignPad(false)
// setSignKey(pos.key);
// setIsStamp(pos.isStamp);
// }
// }, 500);
// }
// }}
default={{
x: pos.xPosition,
y: pos.yPosition
}}
// onClick={(e) => {
// if (!isDragging) {
// e.stopPropagation();
// setIsSignPad(true);
// setSignKey(pos.key);
// setIsStamp(pos.isStamp);
// }
// }}
>
<div
onTouchStart={(e) => {
if (!isDragging) {
setTimeout(() => {
setIsSignPad(true);
//setIsSignPad(false)
setSignKey(pos.key);
setIsStamp(pos.isStamp);
}, 500);
@@ -686,21 +720,9 @@ function RenderPdf({
}}
>
<div
// onMouseDown={(e) => {
// console.log("child m=event")
// e.preventDefault();
// setIsDragging(true)
// handleDeleteSign(pos.key);
// setIsStamp(false);
// setTimeout(()=>{
// setIsDragging(false)
// },2000)
// }}
onTouchStart={(e) => {
e.stopPropagation();
e.preventDefault();
// setIsDragging(true);
handleDeleteSign(pos.key);
setIsStamp(false);
@@ -756,7 +778,6 @@ function RenderPdf({
onLoadSuccess={pageDetails}
ref={pdfRef}
file={pdfUrl ? pdfUrl : pdfDetails[0] && pdfDetails[0].URL}
// file="https://qikinnovation.ams3.digitaloceanspaces.com/exported_file_2068_2023-08-30T05%3A04%3A26.334Z.pdf" // "https://api.printnode.com/static/test/pdf/multipage.pdf" // {pdfUrl ? pdfUrl : signPdfUrl}
>
{Array.from(new Array(numPages), (el, index) => (
<Page
@@ -764,7 +785,6 @@ function RenderPdf({
pageNumber={pageNumber}
width={window.innerWidth}
height={window.innerHeight}
// scale={1}
renderAnnotationLayer={false}
renderTextLayer={false}
onGetAnnotationsError={(error) => {
@@ -776,7 +796,6 @@ function RenderPdf({
</div>
</div>
) : (
// </RSC>
<RSC
style={{
position: "relative",
@@ -854,12 +873,15 @@ function RenderPdf({
height: pos.Height ? pos.Height : 60
}}
lockAspectRatio={pos.Width && 2.5}
//if pos.isMobile false -- placeholder saved from mobile view then handle position in desktop view to multiply by scale
default={{
x: pos.scale
? pos.xPosition * pos.scale
x: pos.isMobile
? pos.scale &&
pos.xPosition * pos.scale + 20
: pos.xPosition,
y: pos.scale
? pos.yPosition * pos.scale
y: pos.isMobile
? pos.scale && pos.yPosition * pos.scale
: pos.yPosition
}}
onClick={() => {
@@ -917,12 +939,15 @@ function RenderPdf({
height: pos.Height ? pos.Height : 60
}}
disableDragging={true}
//if pos.isMobile false -- placeholder saved from mobile view then handle position in desktop view to multiply by scale
default={{
x: pos.scale
? pos.xPosition * pos.scale
x: pos.isMobile
? pos.scale &&
pos.xPosition * pos.scale + 20
: pos.xPosition,
y: pos.scale
? pos.yPosition * pos.scale
y: pos.isMobile
? pos.scale && pos.yPosition * pos.scale
: pos.yPosition
}}
onClick={() => {
@@ -998,7 +1023,14 @@ function RenderPdf({
right: { display: "none" },
bottomRight: { display: "block" }
}}
onDragStop={handleStop}
onDragStop={(event, dragElement) =>
handleStop(
event,
dragElement,
data.signerObjId,
pos.key
)
}
default={{
x: pos.xPosition,
y: pos.yPosition
@@ -1043,7 +1075,7 @@ function RenderPdf({
fontSize: "12px",
color: "black",
fontWeight: "600",
// justifyContent: "center",
marginTop: "0px"
}}
>
@@ -1067,7 +1099,6 @@ function RenderPdf({
<Rnd
ref={nodeRef}
key={pos.key}
// lockAspectRatio={2.5}
lockAspectRatio={
pos.Width ? pos.Width / pos.Height : 2.5
}
@@ -1158,7 +1189,6 @@ function RenderPdf({
<Rnd
ref={nodeRef}
key={pos.key}
// lockAspectRatio={2.5}
lockAspectRatio={
pos.Width ? pos.Width / pos.Height : 2.5
}
@@ -1264,13 +1294,11 @@ function RenderPdf({
onLoadSuccess={pageDetails}
ref={pdfRef}
file={pdfUrl ? pdfUrl : pdfDetails[0] && pdfDetails[0].URL}
// file="https://qikinnovation.ams3.digitaloceanspaces.com/exported_file_2068_2023-08-30T05%3A04%3A26.334Z.pdf" // "https://api.printnode.com/static/test/pdf/multipage.pdf" // {pdfUrl ? pdfUrl : signPdfUrl}
>
{Array.from(new Array(numPages), (el, index) => (
<Page
key={index}
pageNumber={pageNumber}
// width={pdfNewWidth}
renderAnnotationLayer={false}
renderTextLayer={false}
onGetAnnotationsError={(error) => {
@@ -1286,4 +1314,4 @@ function RenderPdf({
);
}
export default RenderPdf;
export default RenderPdf;
@@ -6,77 +6,60 @@ import { useParams } from "react-router-dom";
import { themeColor } from "../utils/ThemeColor/backColor";
import { useEffect } from "react";
import { useNavigate } from "react-router-dom";
// import { useHistory } from "react-router-dom/cjs/react-router-dom.min";
function Login() {
const { id, userMail,contactBookId, serverUrl } = useParams();
let navigate = useNavigate();
// const history = useHistory();
function Login() {
const { id, userMail, contactBookId, serverUrl } = useParams();
let navigate = useNavigate();
const [email, setEmail] = useState(userMail);
const [OTP, setOTP] = useState("");
const [EnterOTP, setEnterOtp] = useState(false);
const [loading, setLoading] = useState(false);
const [isLoading, setIsLoading] = useState(true);
useEffect(() => {
handleServerUrl();
}, []);
//https://qik-ai-org.github.io/Sign-MicroappV2/#/login/LqgGeZHd17/raktima.c@qik.ai/https:%2F%2Fserver3.qik.ai%2Fdefaultssty%2F&defaultssty&contracts
// login/LqgGeZHd17/raktima.c@qik.ai/https:%2F%2Fserver3.qik.ai%2Fdefaultssty&defaultssty&contracts
//function generate serverUrl and parseAppId from url and save it in local storage
const handleServerUrl = () => {
// console.log("params", serverUrl);
//split url in array from '&'
localStorage.clear();
const checkSplit = serverUrl.split("&");
const server = checkSplit[0];
const parseId = checkSplit[1];
const appName = checkSplit[2];
// console.log("appName", appName);
const newServer = server.replaceAll("%2F", "/");
localStorage.setItem("baseUrl", newServer);
localStorage.setItem("parseAppId", parseId);
localStorage.setItem("_appName", appName);
setIsLoading(false);
// console.log("checkSPlit", newServer, parseId, appName);
};
const handleChange = (event) => {
const { value } = event.target;
setOTP(value);
};
//send email OTP function
const SendOtp = async (e) => {
const serverUrl =
localStorage.getItem("baseUrl") && localStorage.getItem("baseUrl");
const parseId =
localStorage.getItem("parseAppId") && localStorage.getItem("parseAppId");
// console.log("server",serverUrl)
if (serverUrl && localStorage) {
setLoading(true);
e.preventDefault();
setEmail(email);
try {
// const { baseUrl, parseAppId, mobile } = this.state;
let url = `${serverUrl}functions/SendOTPMailV1/`;
const headers = {
"Content-Type": "application/json",
"X-Parse-Application-Id": parseId,
"X-Parse-Application-Id": parseId
};
let body = {
email: email.toString(),
// appId: {
// __type: "Pointer",
// className: "w_appinfo",
// objectId: localStorage.getItem("_app_objectId"),
// },
email: email.toString()
};
let Otp = await axios.post(url, body, { headers: headers });
@@ -85,7 +68,7 @@ function Login() {
setEnterOtp(true);
}
} catch (error) {
// this.setState({ loading: false });
alert("something went wrong!");
}
} else {
alert("something went wrong!");
@@ -97,47 +80,38 @@ function Login() {
e.preventDefault();
const serverUrl =
localStorage.getItem("baseUrl") && localStorage.getItem("baseUrl");
const parseId =
localStorage.getItem("parseAppId") && localStorage.getItem("parseAppId");
if (OTP) {
setLoading(true);
try {
// AuthLoginAs
let url = `${serverUrl}functions/AuthLoginAsMail/`;
const headers = {
"Content-Type": "application/json",
"X-Parse-Application-Id": parseId,
"X-Parse-Application-Id": parseId
};
let body = {
email: email,
// email,
otp: OTP,
otp: OTP
};
let user = await axios.post(url, body, { headers: headers });
// console.log("user", user.data.result);
if (user.data.result === "Invalid Otp") {
alert("Invalid Otp");
setLoading(false);
}else if(user.data.result === "user not found!"){
} else if (user.data.result === "user not found!") {
alert("User not found!");
setLoading(false);
}
else {
} else {
let _user = user.data.result;
localStorage.setItem("UserInformation", JSON.stringify(_user));
// localStorage.setItem("userEmail", email);
localStorage.setItem("username", _user.name);
// console.log("session token", _user.sessionToken);
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 user to on signature page
// history.push(`/recipientSignPdf/${id}/${_user.phone}`);
navigate(`/recipientSignPdf/${id}/${contactBookId}`);
navigate(
`/loadmf/signmicroapp/recipientSignPdf/${id}/${contactBookId}`
);
}
} catch (error) {}
} else {
@@ -146,7 +120,7 @@ function Login() {
};
return (
<React.Fragment>
<div style={{ padding: "2rem" }}>
{isLoading ? (
<div
style={{
@@ -154,7 +128,7 @@ function Login() {
justifyContent: "center",
alignItems: "center",
height: "100vh",
flexDirection: "column",
flexDirection: "column"
}}
>
<img
@@ -172,137 +146,131 @@ function Login() {
margin: "10px",
border: "0.5px solid #c5c7c9",
padding: "30px",
boxShadow: "rgba(99, 99, 99, 0.2) 0px 2px 8px 0px",
// box-shadow: rgba(99, 99, 99, 0.2) 0px 2px 8px 0px;
boxShadow: "rgba(99, 99, 99, 0.2) 0px 2px 8px 0px"
}}
>
<div className="main_head">
<div className="main-logo">
<img alt="sign img" src="https://qikinnovation.ams3.digitaloceanspaces.com/logo.png" width="100%" />
<img
alt="sign img"
src="https://qikinnovation.ams3.digitaloceanspaces.com/logo.png"
width="100%"
/>
</div>
</div>
{!EnterOTP ? (
<form>
<div className="row">
<div className="col-sm-6 KLO">
<h2>Welcome Back !</h2>
<span className="KNLO">
Verification code is sent to your email
</span>
<div className="card card-box">
<div className="card-body">
<input
type="email"
className="form-control"
name="mobile"
value={email}
disabled
height={30}
style={{ fontSize: "20px", fontWeight: "600" }}
/>
<br />
</div>
</div>
<div
className="col-md-4 col-sm-4"
style={{
textAlign: "center",
display: "flex",
alignItems: "center",
justifyContent: "center",
}}
>
{loading ? (
<button
className="btn btn-info loadinBtn "
type="button"
style={{ marginBottom: "4px", width: "210px" }}
disabled
>
<span
className="spinner-border spinner-border-sm "
role="status"
aria-hidden="true"
></span>
Loading...
</button>
) : (
<button
className="btn btn-sm otpButton"
onClick={(e) => SendOtp(e)}
style={{
marginBottom: "4px",
width: "210px",
background: themeColor(),
color: "white",
fontWeight: "600",
}}
>
Send OTP
</button>
)}
<div className="row">
<div className="col-sm-6 KLO">
<span className="welcomeText">Welcome Back !</span>
<br />
<span className="KNLO">
Verification code is sent to your email
</span>
<div className="card card-box" style={{ borderRadius: "0px" }}>
<div className="card-body">
<input
type="email"
name="mobile"
value={email}
disabled
className="loginInput"
/>
<br />
</div>
</div>
<div className="btnContainer">
{loading ? (
<button
type="button"
style={{
background: themeColor(),
color: "white"
}}
className="verifyBtn"
disabled
>
<span
className="spinner-border spinner-border-sm "
role="status"
aria-hidden="true"
></span>
Loading...
</button>
) : (
<button
className="verifyBtn"
style={{
background: themeColor(),
color: "white",
marginLeft: "0px !important"
}}
onClick={(e) => SendOtp(e)}
>
Send OTP
</button>
)}
</div>
</div>
</form>
</div>
) : (
<form>
<div className="row">
<div className="col-sm-6 KLO">
<h2>Welcome Back !</h2>
<span className="KNLO">You will get a OTP via Email</span>
<div className="card card-box">
<div className="card-body">
<label>Enter Verification Code</label>
<input
type="number"
className="form-control"
name="OTP"
value={OTP}
min="4"
max="4"
onChange={handleChange}
/>
<div className="row">
<div className="col-sm-6 KLO">
<span className="welcomeText">Welcome Back !</span>
<br />
<span className="KNLO">You will get a OTP via Email</span>
<div className="card card-box">
<div className="card-body">
<label>Enter Verification Code</label>
<input
type="number"
className="loginInput"
name="OTP"
value={OTP}
onChange={handleChange}
/>
<br />
</div>
</div>
<div
className="col-md-4 col-sm-4"
style={{ textAlign: "center" }}
>
{loading ? (
<button
className="btn btn-info "
type="button"
style={{ marginBottom: "4px", width: "210px" }}
disabled
>
<span
className="spinner-border spinner-border-sm "
role="status"
aria-hidden="true"
></span>
Loading...
</button>
) : (
<button
type="button"
onClick={(e) => VerifyOTP(e)}
className="btn btn-info login-btn"
>
Verify
</button>
)}
<br />
</div>
</div>
<div>
{loading ? (
<button
style={{
background: themeColor(),
color: "white"
}}
className="verifyBtn"
type="button"
disabled
>
<span
className="spinner-border spinner-border-sm "
role="status"
aria-hidden="true"
></span>
Loading...
</button>
) : (
<button
type="button"
onClick={(e) => VerifyOTP(e)}
style={{
background: themeColor(),
color: "white"
}}
className="verifyBtn"
>
Verify
</button>
)}
</div>
</div>
</form>
</div>
)}
</div>
)}
</React.Fragment>
</div>
);
}
@@ -17,11 +17,13 @@ import HandleError from "./component/HandleError";
import Nodata from "./component/Nodata";
import SignerListPlace from "./component/signerListPlace";
import Header from "./component/header";
import { contactBook, contractUsers } from "../utils/Utils";
import { contactBook, contractUsers, getHostUrl } from "../utils/Utils";
import RenderPdf from "./component/renderPdf";
import ModalComponent from "./component/modalComponent";
import { useNavigate } from "react-router-dom";
function PlaceHolderSign() {
const navigate = useNavigate();
const [pdfDetails, setPdfDetails] = useState([]);
const [isMailSend, setIsMailSend] = useState(false);
const [allPages, setAllPages] = useState(null);
@@ -74,7 +76,9 @@ function PlaceHolderSign() {
"#66ccff",
"#ffffcc"
];
const isMobile = window.innerWidth < 767;
const newWidth = window.innerWidth;
const scale = pdfOriginalWidth / newWidth;
const [{ isOver }, drop] = useDrop({
accept: "BOX",
drop: (item, monitor) => addPositionOfSignature(item, monitor),
@@ -119,7 +123,7 @@ function PlaceHolderSign() {
isDragSignatureSS: !!monitor.isDragging()
})
});
const isMobile = window.innerWidth < 712;
const [{ isDragStampSS }, dragStampSS] = useDrag({
type: "BOX",
@@ -257,56 +261,10 @@ function PlaceHolderSign() {
setIsLoading(loadObj);
}
}
// await axios
// .get(
// `${localStorage.getItem("baseUrl")}classes/${localStorage.getItem(
// "_appName"
// )}_Contactbook?where={"UserId": {"__type": "Pointer","className": "_User", "objectId":"${
// jsonSender.objectId
// }"}}`,
// {
// headers: {
// "Content-Type": "application/json",
// "X-Parse-Application-Id": localStorage.getItem("parseAppId"),
// "X-Parse-Session-Token": localStorage.getItem("accesstoken"),
// },
// }
// )
// .then((Listdata) => {
// const json = Listdata.data;
// const res = json.results;
// if (res[0] && res.length) {
// setSignerUserId(res[0].objectId);
// const tourstatus = res[0].TourStatus && res[0].TourStatus;
// if (tourstatus && tourstatus.length > 0) {
// setTourStatus(tourstatus);
// const checkTourRecipients = tourstatus.filter(
// (data) => data.placeholder
// );
// if (checkTourRecipients && checkTourRecipients.length > 0) {
// setCheckTourStatus(checkTourRecipients[0].placeholder);
// }
// }
// const loadObj = {
// isLoad: false,
// };
// setIsLoading(loadObj);
// }
// })
// .catch((err) => {
// const loadObj = {
// isLoad: false,
// };
// setHandleError("Error: Something went wrong!");
// setIsLoading(loadObj);
// });
};
//function for setting position after drop signature button over pdf
const addPositionOfSignature = (item, monitor) => {
const isMobile = window.innerWidth < 712;
if (isMobile) {
if (selectedEmail) {
getSignerPos(item, monitor);
@@ -319,9 +277,6 @@ function PlaceHolderSign() {
};
const getSignerPos = (item, monitor) => {
const isMobile = window.innerWidth < 712;
const newWidth = window.innerWidth;
const scale = pdfOriginalWidth / newWidth;
const key = Math.floor(1000 + Math.random() * 9000);
let filterSignerPos = signerPos.filter(
(data) => data.signerObjId === signerObjId
@@ -336,7 +291,8 @@ function PlaceHolderSign() {
isStamp: monitor,
key: key,
isDrag: false,
scale: isMobile && scale,
scale: scale,
isMobile: isMobile,
yBottom: window.innerHeight / 2 - 60
};
dropData.push(dropObj);
@@ -365,7 +321,8 @@ function PlaceHolderSign() {
firstXPos: signBtnPosition[0] && signBtnPosition[0].xPos,
firstYPos: signBtnPosition[0] && signBtnPosition[0].yPos,
yBottom: ybottom,
scale: isMobile && scale
scale: scale,
isMobile: isMobile
};
dropData.push(dropObj);
@@ -394,16 +351,12 @@ function PlaceHolderSign() {
//add entry of position for same signer on multiple page
if (getPageNumer.length > 0) {
const getPos = getPageNumer[0].pos;
//if (updateData.length > dropData.length) {
const newSignPos = getPos.concat(dropData);
let xyPos = {
pageNumber: pageNumber,
pos: newSignPos
};
updatePlace.push(xyPos);
let placeHolderPos = {
blockColor: color[isSelectListId],
signerObjId: signerObjId,
@@ -417,7 +370,6 @@ function PlaceHolderSign() {
signerPos.splice(colorIndex, 1, placeHolderPos);
} else {
// const newSignPos = getPlaceHolder.push(xyPosArr[0]);
const newSignPoss = getPlaceHolder.concat(xyPosArr[0]);
let placeHolderPos = {
@@ -467,17 +419,19 @@ function PlaceHolderSign() {
};
//function for set and update x and y postion after drag and drop signature tab
const handleStop = (event, dragElement) => {
const handleStop = (event, dragElement, signerId, key) => {
const containerRect = document
.getElementById("container")
.getBoundingClientRect();
const signId = signerId ? signerId : signerObjId;
const keyValue = key ? key : dragKey;
const ybottom = containerRect.height - dragElement.y;
if (dragKey >= 0) {
if (keyValue >= 0) {
const filterSignerPos = signerPos.filter(
(data) => data.signerObjId === signerObjId
(data) => data.signerObjId === signId
);
if (filterSignerPos.length > 0) {
const getPlaceHolder = filterSignerPos[0].placeHolder;
@@ -490,7 +444,7 @@ function PlaceHolderSign() {
const getPosData = getXYdata;
const addSignPos = getPosData.map((url, ind) => {
if (url.key === dragKey) {
if (url.key === keyValue) {
return {
...url,
xPosition: dragElement.x,
@@ -509,16 +463,15 @@ function PlaceHolderSign() {
return obj;
});
const newUpdateSigner = signerPos.map((obj, ind) => {
if (obj.signerObjId === signerObjId) {
if (obj.signerObjId === signId) {
return { ...obj, placeHolder: newUpdateSignPos };
}
return obj;
});
setSignerPos(newUpdateSigner);
}
}
// }
}
};
@@ -556,6 +509,7 @@ function PlaceHolderSign() {
}
return obj;
});
setSignerPos(newUpdateSigner);
} else {
const updateFilter = signerPos.filter(
@@ -577,6 +531,7 @@ function PlaceHolderSign() {
(data) => data.signerObjId !== signerId
);
signerupdate.push(newUpdatePos[0]);
setSignerPos(signerupdate);
} else {
setSignerPos(updateFilter);
@@ -621,12 +576,14 @@ function PlaceHolderSign() {
}
return obj;
});
const newUpdateSigner = signerPos.map((obj, ind) => {
if (obj.signerObjId === signerId) {
return { ...obj, placeHolder: newUpdateSignPos };
}
return obj;
});
setSignerPos(newUpdateSigner);
} else {
const getXYdata = getPageNumer[0].pos;
@@ -650,12 +607,14 @@ function PlaceHolderSign() {
}
return obj;
});
const newUpdateSigner = signerPos.map((obj, ind) => {
if (obj.signerObjId === signerId) {
return { ...obj, placeHolder: newUpdateSignPos };
}
return obj;
});
setSignerPos(newUpdateSigner);
}
}
@@ -670,8 +629,6 @@ function PlaceHolderSign() {
//function for capture position on hover signature button
const handleDivClick = (e) => {
// if (signBtnPosition.length == 0) {
const divRect = e.currentTarget.getBoundingClientRect();
const mouseX = e.clientX - divRect.left;
const mouseY = e.clientY - divRect.top;
@@ -721,17 +678,13 @@ function PlaceHolderSign() {
month: "long",
year: "numeric"
});
let sender = signersdata.ExtUserPtr.Email;
// let sender ="raktima.c@qik.ai"
const signerMail = signersdata.Signers;
for (let i = 0; i < signerMail.length; i++) {
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 = {
"Content-Type": "application/json",
@@ -745,7 +698,8 @@ function PlaceHolderSign() {
"parseAppId"
)}&${localStorage.getItem("_appName")}`;
let signPdf = `https://qik-ai-org.github.io/Sign-MicroappV2/#/login/${signersdata.objectId}/${signerMail[i].Email}/${objectId}/${serverParams}`;
const hostUrl = window.location.origin + "/loadmf/signmicroapp";
let signPdf = `${hostUrl}/login/${signersdata.objectId}/${signerMail[i].Email}/${objectId}/${serverParams}`;
const themeBGcolor = themeColor();
let params = {
@@ -800,14 +754,12 @@ function PlaceHolderSign() {
}
)
.then((result) => {
// const res = result.data;
setIsSend(true);
setIsMailSend(true);
const loadObj = {
isLoad: false
};
setIsLoading(loadObj);
// console.log("save res", res);
})
.catch((err) => {
console.log("axois err ", err);
@@ -889,6 +841,12 @@ function PlaceHolderSign() {
console.log("axois err ", err);
});
};
const handleRecipientSign = () => {
const hostUrl = getHostUrl();
navigate(
`${hostUrl}recipientSignPdf/${documentId}/${currentEmail[0].objectId}`
);
};
return (
<DndProvider backend={HTML5Backend}>
{isLoading.isLoad ? (
@@ -993,9 +951,8 @@ function PlaceHolderSign() {
style={{
background: themeColor()
}}
// className="bg-danger"
>
<span style={{ color: "white" }}>Send Mail </span>
<span style={{ color: "white" }}>Mails Sent</span>
</Modal.Header>
{/* signature modal */}
@@ -1023,21 +980,19 @@ function PlaceHolderSign() {
No
</button>
<a
style={{ color: "white" }}
href={`https://qik-ai-org.github.io/Sign-MicroappV2/#/recipientSignPdf/${documentId}/${currentEmail[0].objectId}`}
<button
onClick={() => {
handleRecipientSign();
}}
style={{
background: themeColor(),
color: "white"
}}
type="button"
className="finishBtn"
>
<button
style={{
background: themeColor(),
color: "white"
}}
type="button"
className="finishBtn"
>
Yes
</button>
</a>
Yes
</button>
</>
) : (
<button
@@ -1160,8 +1115,6 @@ function PlaceHolderSign() {
dragRef={dragRef}
isDragStamp={isDragStamp}
isSignYourself={false}
// xyPostion={xyPostion}
// isSigners={false}
addPositionOfSignature={addPositionOfSignature}
/>
</div>
@@ -23,8 +23,8 @@ import Loader from "./component/loader";
import HandleError from "./component/HandleError";
import Nodata from "./component/Nodata";
import Header from "./component/header";
import ModalComponent from "./component/modalComponent";
import RenderPdf from "./component/renderPdf";
import CustomModal from "./component/CustomModal";
function EmbedPdfImage() {
const { id, contactBookId } = useParams();
const [isSignPad, setIsSignPad] = useState(false);
@@ -67,13 +67,15 @@ function EmbedPdfImage() {
status: false,
type: "load"
});
const [containerWH, setContainerWH] = useState({});
const docId = id && id;
//"F0hg0twSJH";
const isMobile = window.innerWidth < 767;
const index = xyPostion.findIndex((object) => {
return object.pageNumber === pageNumber;
});
const divRef = useRef(null);
//check isGuestSigner is present in local if yes than handle login flow header in mobile view
const isGuestSigner = localStorage.getItem("isGuestSigner");
useEffect(() => {
const clientWidth = window.innerWidth;
const pdfWidth = clientWidth - 160 - 220 - 30;
@@ -82,15 +84,21 @@ function EmbedPdfImage() {
setPdfNewWidth(pdfWidth);
getDocumentDetails();
}, []);
useEffect(() => {
if (divRef.current) {
setContainerWH({
width: divRef.current.offsetWidth,
height: divRef.current.offsetHeight
});
}
}, [divRef.current]);
//function for get document details for perticular signer with signer'object id
const getDocumentDetails = async () => {
//aspfUo7wRl
let currUserId, userObjectId;
const json = await contactBookName(contactBookId, "_Users");
const json = await contactBookName(contactBookId, "_Contactbook");
if (json !== "Error: Something went wrong!" && json && json.results[0]) {
setContractName("_Users");
setContractName("_Contactbook");
if (json.results[0]) {
userObjectId = json.results[0].UserId.objectId;
setUserObjectID(userObjectId);
@@ -123,9 +131,10 @@ function EmbedPdfImage() {
setHandleError("Error: Something went wrong!");
setIsLoading(loadObj);
} else {
const json = await contactBookName(contactBookId, "_Contactbook");
if (json && json.results[0]) {
setContractName("_Contactbook");
const json = await contactBookName(contactBookId, "_Users");
if (json !== "Error: Something went wrong!" && json && json.results[0]) {
setContractName("_Users");
if (json.results[0]) {
userObjectId = json.results[0].UserId.objectId;
setUserObjectID(userObjectId);
@@ -151,57 +160,14 @@ function EmbedPdfImage() {
};
setIsLoading(loadObj);
}
} else if (json === "Error: Something went wrong!") {
const loadObj = {
isLoad: false
};
setHandleError("Error: Something went wrong!");
setIsLoading(loadObj);
}
}
// await axios
// .get(//m4GJ12tm87
// `${localStorage.getItem("baseUrl")}classes/${localStorage.getItem(
// "_appName"
// )}_Contactbook?where={"Phone":"${userPhone}"}`,
// {
// headers: {
// "Content-Type": "application/json",
// "X-Parse-Application-Id": localStorage.getItem("parseAppId"),
// sessionToken: localStorage.getItem("accesstoken"),
// },
// }
// )
// .then((Listdata) => {
// const json = Listdata.data;
// if (json.results[0]) {
// userObjectId = json.results[0].UserId.objectId;
// setUserObjectID(userObjectId);
// currUserId = json.results[0].objectId;
// setSignerUserId(currUserId);
// const tourstatus =
// json.results[0].TourStatus && json.results[0].TourStatus;
// if (tourstatus && tourstatus.length > 0) {
// setTourStatus(tourstatus);
// const checkTourRecipients = tourstatus.filter(
// (data) => data.recipientssign
// );
// if (checkTourRecipients && checkTourRecipients.length > 0) {
// setCheckTourStatus(checkTourRecipients[0].recipientssign);
// }
// }
// } else {
// setNoData(true);
// const loadObj = {
// isLoad: false,
// };
// setIsLoading(loadObj);
// }
// })
// .catch((err) => {
// const loadObj = {
// isLoad: false,
// };
// setHandleError("Error: Something went wrong!");
// setIsLoading(loadObj);
// });
await axios
.get(
@@ -220,7 +186,6 @@ function EmbedPdfImage() {
.then((Listdata) => {
const json = Listdata.data;
const res = json.results;
// console.log("res",res)
if (res[0] && res.length > 0) {
const declined = res[0].IsDeclined && res[0].IsDeclined;
const isCompleted = res[0].IsCompleted && res[0].IsCompleted;
@@ -233,16 +198,12 @@ function EmbedPdfImage() {
//then show alert with completed message
const alreadySign = {
status: true,
mssg: "This document has already been signed!"
mssg: "This document has been successfully signed!"
};
setIsAlreadySign(alreadySign);
setPdfUrl(res[0].SignedUrl);
setSignedPdfData(json.results);
setCompletePdfData(res);
const loadObj = {
isLoad: false
};
setIsLoading(loadObj);
} else if (declined) {
const currentDecline = {
currnt: "another",
@@ -251,11 +212,6 @@ function EmbedPdfImage() {
setIsDecline(currentDecline);
setSignedPdfData(json.results);
const loadObj = {
isLoad: false
};
setIsLoading(loadObj);
} else if (currDate > expireUpdateDate) {
setIsExpired(true);
const checkDocIdExist =
@@ -282,11 +238,6 @@ function EmbedPdfImage() {
const key = currUser[0].placeHolder[0].pos[0].key;
setSignKey(key);
const loadObj = {
isLoad: false
};
setIsLoading(loadObj);
}
//for show current requested signer's placeholder
else {
@@ -302,17 +253,7 @@ function EmbedPdfImage() {
const key = currUser[0].placeHolder[0].pos[0].key;
setSignKey(key);
const loadObj = {
isLoad: false
};
setIsLoading(loadObj);
}
const loadObj = {
isLoad: false
};
setIsLoading(loadObj);
} else {
//checking document has signed by someone or not
@@ -326,6 +267,7 @@ function EmbedPdfImage() {
//if signed by someone than go to in if condition
// and second signer could not be add documentId
//for that setIsDocId true
if (checkDocIdExist && checkDocIdExist.length > 0) {
setIsDocId(true);
@@ -336,7 +278,7 @@ function EmbedPdfImage() {
data.Activity === "Signed"
);
// if checkAlreadyBySigner has some data that current user alredy sign this document
// if checkAlreadyBySigner has some data that current user already sign this document
// then show alert with message
if (checkAlreadyBySigner && checkAlreadyBySigner.length > 0) {
const alreadySign = {
@@ -345,10 +287,7 @@ function EmbedPdfImage() {
};
setIsAlreadySign(alreadySign);
setPdfUrl(res[0].SignedUrl);
const loadObj = {
isLoad: false
};
setIsLoading(loadObj);
setSignedPdfData(json.results);
}
//else show placeholder of current requested signer
else {
@@ -364,11 +303,6 @@ function EmbedPdfImage() {
const key = currUser[0].placeHolder[0].pos[0].key;
setSignKey(key);
const loadObj = {
isLoad: false
};
setIsLoading(loadObj);
}
}
//for show current requested signer's placeholder
@@ -385,19 +319,8 @@ function EmbedPdfImage() {
const key = currUser[0].placeHolder[0].pos[0].key;
setSignKey(key);
const loadObj = {
isLoad: false
};
setIsLoading(loadObj);
}
}
} else {
setNoData(true);
const loadObj = {
isLoad: false
};
setIsLoading(loadObj);
}
})
.catch((err) => {
@@ -434,8 +357,12 @@ function EmbedPdfImage() {
setIsLoading(loadObj);
})
.catch((err) => {
// this.setState({ loading: false });
console.log("axois err ", err);
const loadObj = {
isLoad: false
};
setHandleError("Error: Something went wrong!");
setIsLoading(loadObj);
});
};
@@ -624,23 +551,62 @@ function EmbedPdfImage() {
? imgUrlList[id].Height
: 60;
const imgWidth = imgUrlList[id].Width ? imgUrlList[id].Width : 150;
const isMobile = window.innerWidth < 712;
const isMobile = window.innerWidth < 767;
const newWidth = window.innerWidth;
const scale = isMobile ? pdfOriginalWidth / newWidth : 1;
page.drawImage(img, {
x: isMobile
? imgUrlList[id].xPosition * scale + 50
: imgUrlList[id].xPosition,
const xPos = (pos) => {
//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) {
const x = pos.xPosition * (pos.scale / scale);
return x * scale + 50;
} else {
const x = pos.xPosition / scale;
return x * 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) {
const x = pos.xPosition * pos.scale + 50;
return x;
} else {
return pos.xPosition;
}
}
};
const yPos = (pos) => {
//checking both condition mobile and desktop view
y:
page.getHeight() - imgUrlList[id].yPosition * scale - imgHeight,
if (isMobile) {
//if pos.isMobile false -- placeholder saved from desktop view then handle position in mobile view divided by scale
if (pos.isMobile) {
const y = pos.yPosition * (pos.scale / scale);
return page.getHeight() - y * scale - imgHeight;
} else {
const y = pos.yPosition / scale;
return page.getHeight() - y * scale - imgHeight;
}
} 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) {
const y = pos.yPosition * pos.scale;
return page.getHeight() - y - imgHeight;
} else {
return page.getHeight() - pos.yPosition - imgHeight;
}
}
};
page.drawImage(img, {
x: xPos(imgUrlList[id]),
y: yPos(imgUrlList[id]),
width: imgWidth,
height: imgHeight
});
});
}
const pdfBytes = await pdfDoc.saveAsBase64({ useObjectStreams: false });
//console.log("pdfbyte", pdfBytes);
signPdfFun(pdfBytes, docId);
}
@@ -658,29 +624,87 @@ function EmbedPdfImage() {
pdfBase64Url,
pageNo
) => {
let signgleSign;
const isMobile = window.innerWidth < 712;
let singleSign;
const isMobile = window.innerWidth < 767;
const newWidth = window.innerWidth;
const scale = isMobile ? pdfOriginalWidth / newWidth : 1;
const height = xyPosData ? xyPosData.Height : 60;
const xPos = (pos) => {
//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) {
const x = pos.xPosition * (pos.scale / scale);
return x * scale + 50;
} else {
const x = pos.xPosition / scale;
return x * 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) {
const x = pos.xPosition * pos.scale + 50;
return x;
} else {
return pos.xPosition;
}
}
};
const yBottom = (pos) => {
let yPosition;
//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) {
const y = pos.yPosition * (pos.scale / scale);
yPosition = pos.isDrag
? y * scale - height
: pos.firstYPos
? y * scale - height + pos.firstYPos
: y * scale - height;
return yPosition;
} else {
const y = pos.yBottom / scale;
yPosition = pos.isDrag
? y * scale - height
: pos.firstYPos
? y * scale - height + pos.firstYPos
: y * scale - height;
return yPosition;
}
} 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) {
const y = pos.yBottom * pos.scale;
yPosition = pos.isDrag
? y - height
: pos.firstYPos
? y - height + pos.firstYPos
: y - height;
return yPosition;
} else {
yPosition = pos.isDrag
? pos.yBottom - height
: pos.firstYPos
? pos.yBottom - height + pos.firstYPos
: pos.yBottom - height;
return yPosition;
}
}
};
if (xyPostion.length === 1 && xyPostion[0].pos.length === 1) {
const height = xyPosData.Height ? xyPosData.Height : 60;
const bottomY = xyPosData.isDrag
? xyPosData.yBottom * scale - height
: xyPosData.firstYPos
? xyPosData.yBottom * scale - height + xyPosData.firstYPos
: xyPosData.yBottom * scale - height;
signgleSign = {
const bottomY = yBottom(xyPosData);
singleSign = {
pdfFile: pdfBase64Url,
docId: docId,
userId: signerUserId,
sign: {
Base64: base64Url,
Left: isMobile
? xyPosData.resizeXPos
? xyPosData.resizeXPos * scale + 80
: xyPosData.xPosition * scale + 80
: xyPosData.resizeXPos
? xyPosData.resizeXPos
: xyPosData.xPosition,
Left: xPos(xyPosData),
Bottom: bottomY,
Width: xyPosData.Width ? xyPosData.Width : 150,
Height: height,
@@ -688,33 +712,25 @@ function EmbedPdfImage() {
}
};
} else if (xyPostion.length > 0 && xyPostion[0].pos.length > 0) {
signgleSign = {
singleSign = {
pdfFile: base64Url,
docId: docId
docId: docId,
userId: signerUserId
};
}
await axios
.post(
`${localStorage.getItem("baseUrl")}functions/signPdf`,
signgleSign,
{
headers: {
"Content-Type": "application/json",
"X-Parse-Application-Id": localStorage.getItem("parseAppId"),
sessionToken: localStorage.getItem("accesstoken")
}
.post(`${localStorage.getItem("baseUrl")}functions/signPdf`, singleSign, {
headers: {
"Content-Type": "application/json",
"X-Parse-Application-Id": localStorage.getItem("parseAppId"),
sessionToken: localStorage.getItem("accesstoken")
}
)
})
.then((Listdata) => {
const json = Listdata.data;
if (json.result.data) {
// setPdfUrl(json.result.data);
// const loadObj = {
// isLoad: false,
// };
// setIsLoading(loadObj);
getDocumentDetails();
}
})
@@ -731,8 +747,6 @@ function EmbedPdfImage() {
//function for image upload or update
const onImageChange = (event) => {
if (event.target.files && event.target.files[0]) {
// setIsSignPad(false);
const imageType = event.target.files[0].type;
const reader = new FileReader();
@@ -872,7 +886,7 @@ function EmbedPdfImage() {
} else {
updatedTourStatus = [{ recipientssign: true }];
}
// console.log("updatedTourStatus", updatedTourStatus);
await axios
.put(
`${localStorage.getItem("baseUrl")}classes/${localStorage.getItem(
@@ -899,7 +913,6 @@ function EmbedPdfImage() {
});
};
// console.log("is sign",isAlreadySign.status)
const tourFunction = () => {
const tourConfig = [
{
@@ -922,16 +935,17 @@ function EmbedPdfImage() {
}
];
const stepsToShow =
!defaultSignImg &&
tourConfig.filter(
(step, index) => step.selector !== '[data-tut="reactourFirst"]'
let stepsToShow = [];
if (!defaultSignImg || isMobile) {
stepsToShow = tourConfig.filter(
(step) => step.selector !== '[data-tut="reactourFirst"]'
);
}
return (
<Tour
onRequestClose={closeTour}
steps={stepsToShow}
steps={stepsToShow && stepsToShow.length > 0 ? stepsToShow : tourConfig}
isOpen={signTour}
closeWithMask={false}
rounded={5}
@@ -948,7 +962,37 @@ function EmbedPdfImage() {
) : noData ? (
<Nodata />
) : (
<div className="signatureContainer">
<div className="signatureContainer" ref={divRef}>
{/* this modal is used to show decline alert */}
<CustomModal
containerWH={containerWH}
show={isDecline.isDeclined}
headMsg="Document Declined Alert!"
bodyMssg={
isDecline.currnt === "Sure" ? (
<p>Are you sure want to decline this document ?</p>
) : isDecline.currnt === "YouDeclined" ? (
<p>You have declined this document!</p>
) : (
isDecline.currnt === "another" && (
<p>
You cannot sign this document as it has been declined by one
or more person(s).
</p>
)
)
}
footerMessage={isDecline.currnt === "Sure"}
declineDoc={declineDoc}
setIsDecline={setIsDecline}
/>
{/* this modal is used for show expired alert */}
<CustomModal
containerWH={containerWH}
show={isExpired}
headMsg="Document Expired!"
bodyMssg="This Document is no longer available."
/>
{/* this component used for UI interaction and show their functionality */}
{pdfLoadFail.status &&
!isExpired &&
@@ -967,61 +1011,10 @@ function EmbedPdfImage() {
{/* pdf render view */}
<div
style={{
marginLeft: pdfOriginalWidth > 500 && "20px",
marginRight: pdfOriginalWidth > 500 && "20px"
marginLeft: !isGuestSigner && pdfOriginalWidth > 500 && "20px",
marginRight: !isGuestSigner && pdfOriginalWidth > 500 && "20px"
}}
>
{/* this modal is used for show decline alert */}
<Modal show={isDecline.isDeclined}>
<ModalHeader className="bg-danger" style={{ color: "white" }}>
Document Declined Alert!
</ModalHeader>
<Modal.Body>
{isDecline.currnt === "Sure" ? (
<p>Are you sure want to decline this document ?</p>
) : isDecline.currnt === "YouDeclined" ? (
<p>You have declined this document!</p>
) : (
isDecline.currnt === "another" && (
<p>
You cannot sign this document as it has been declined by
one or more person(s).
</p>
)
)}
</Modal.Body>
<Modal.Footer>
{isDecline.currnt === "Sure" && (
<>
<button
style={{
color: "black"
}}
type="button"
className="finishBtn"
onClick={() => setIsDecline({ isDeclined: false })}
>
Close
</button>
<button
style={{
background: "#de4337"
}}
type="button"
className="finishBtn"
onClick={() => declineDoc()}
>
Yes
</button>
</>
)}
</Modal.Footer>
</Modal>
{/* this modal component is used for show expired document */}
<ModalComponent isShow={isExpired} type={"expire"} />
{/* this modal is used show this document is already sign */}
<Modal show={isAlreadySign.status}>
<ModalHeader style={{ background: themeColor() }}>
@@ -1112,7 +1105,7 @@ function EmbedPdfImage() {
/>
</div>
{!pdfUrl && !isAlreadySign.status ? (
{!pdfUrl ? (
<div data-tut="reactourFirst">
{/* this component is used to render default signature of user in the right side of the component */}
@@ -1134,9 +1127,9 @@ function EmbedPdfImage() {
)}
</div>
)}
{/* ndD5gdaxqw */}
</DndProvider>
);
}
export default EmbedPdfImage;
export default EmbedPdfImage;
+7 -1
View File
@@ -8,6 +8,7 @@ import Login from "./Component/login";
import DraftDocument from "./Component/DraftDocument";
import PdfRequestFiles from "./Component/PdfRequestFiles";
import LegaDrive from "./Component/LegaDrive/LegaDrive";
import PageNotFound from "./Component/PageNotFound";
// `AppRoutes` is used to define route path of app and
// it expose to host app, check moduleFederation.config.js for more
@@ -33,7 +34,10 @@ function AppRoutes() {
{/*Add default signature of user route */}
<Route path="/managesign" element={<ManageSign />} />
{/* login page route */}
<Route path="/login/:id/:userMail/:contactBookId/:serverUrl" element={<Login />} />
<Route
path="/login/:id/:userMail/:contactBookId/:serverUrl"
element={<Login />}
/>
{/* draft document route to handle and navigate route page accordiing to document status */}
<Route path="/draftDocument" element={<DraftDocument />} />
{/* for user signature (need your sign route) with row level data */}
@@ -42,6 +46,8 @@ function AppRoutes() {
<Route path="/pdfRequestFiles/:docId" element={<PdfRequestFiles />} />
{/* lega drive route */}
<Route path="/legadrive" element={<LegaDrive />} />
{/* Page Not Found */}
<Route path="*" element={<PageNotFound />} />
</Routes>
</div>
);
@@ -1,9 +1,46 @@
.react-tel-input .form-control {
.loginInput{
padding: 10px;
border-radius: 4px;
width: 100%;
height: 45px;
margin-top: 4px;
font-size: 0.75rem;
border: 1px solid #e2dddd;;
background-color: #e0e5f5;
color: black;
padding-left: 1rem!important;
padding-right: 1rem!important;
padding-top: 0.5rem!important;
font-family: inherit;
font-feature-settings: inherit;
font-variation-settings: inherit;
font-weight: inherit;
overflow: visible;
}
.loginInput:focus{
outline: none;
border: none;
}
.verifyBtn{
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1), 0 1px 2px rgba(0, 0, 0, 0.18);
padding: 3px 30px;
color: white;
font-weight: 500 !important;
font-size: 14px !important;
border: none;
}
.verifyBtn:focus {
border: none;
outline: none;
}
.verifyBtn:hover {
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1), 0 2px 4px rgba(0, 0, 0, 0.18);
color: white;
}
.fakeimg {
height: 200px;
background: #aaa;
@@ -110,16 +147,17 @@
.KNLO {
color: #878787;
font-size: 13px;
}
.form-check-label {
margin-left: 17px;
margin-bottom: 12px;
}
input:focus {
border-color: #ccc !important;
.welcomeText{
font-size: 30px;
}
@media only screen and (max-width: 600px) {
.KLO1 {
@@ -148,4 +186,25 @@ input:focus {
}
@media screen and (max-width:366px) {
.main-logo {
width: 150px;
height: 46px;
display: inline-block;
}
.welcomeText{
font-size: 20px;
}
.KNLO {
color: #878787;
font-size: 10px;
}
.btnContainer{
display: flex;
justify-content: center;
align-items: center;
}
}
@@ -0,0 +1,59 @@
.parentDiv {
background: gray;
position: absolute;
z-index: 20;
background-color: rgba(0, 0, 0, 0.75);
display: flex;
flex-direction: column;
align-items: center;
}
.childDiv {
width: 50%;
display: flex;
flex-direction: column;
justify-content: center;
align-content: center;
background-color: #fff;
margin: 30px 20px;
border: 0px 1px 1px 1px solid rgba(0, 0, 0, .2);
border-radius: 0.3rem;
outline: 0;
}
.modalHeadDiv {
padding: 10px;
color: #fff;
border-top-left-radius: 0.3rem;
border-top-right-radius: 0.3rem;
font-size: 17px;
font-weight: 500;
}
.modalBodyDIv {
padding: 20px;
}
.spanTagHead {
color: white !important;
font-size: 17px;
font-weight: 500;
}
.pTagBody {
font-size: 15px !important;
}
.modalFooterDiv {
margin: 10px;
display: flex;
justify-content: flex-end;
}
@media screen and (max-width:500px) {
.childDiv {
margin: 50px 7px;
width: 90%;
}
}
File diff suppressed because it is too large Load Diff
+27 -47
View File
@@ -57,34 +57,41 @@ export function onSaveImage(xyPostion, index, signKey, imgWH, image) {
(data, ind) =>
data.key === signKey && data.Width && data.Height && data.SignUrl
);
if (updateFilter.length > 0) {
let newWidth, nweHeight;
let newWidth, newHeight;
const aspectRatio = imgWH.width / imgWH.height;
const getXYdata = xyPostion[index].pos;
if (aspectRatio === 1) {
newWidth = aspectRatio * 100;
nweHeight = aspectRatio * 100;
newHeight = aspectRatio * 100;
} else if (aspectRatio < 2) {
newWidth = aspectRatio * 100;
nweHeight = 100;
newHeight = 100;
} else if (aspectRatio > 2 && aspectRatio < 4) {
newWidth = aspectRatio * 70;
nweHeight = 70;
newHeight = 70;
} else if (aspectRatio > 4) {
newWidth = aspectRatio * 40;
nweHeight = 40;
newHeight = 40;
} else if (aspectRatio > 5) {
newWidth = aspectRatio * 10;
nweHeight = 10;
newHeight = 10;
}
const getPosData = getXYdata;
const addSign = getPosData.map((url, ind) => {
let getPosData = xyPostion[index].pos.filter(
(data) => data.key === signKey
);
const addSign = getXYdata.map((url, ind) => {
if (url.key === signKey) {
return {
...url,
Width: newWidth,
Height: nweHeight,
Width: getPosData[0].Width ? getPosData[0].Width : newWidth,
Height: getPosData[0].Height ? getPosData[0].Height : newHeight,
SignUrl: image.src,
ImageType: image.imgType
};
@@ -103,8 +110,9 @@ export function onSaveImage(xyPostion, index, signKey, imgWH, image) {
} else {
const getXYdata = xyPostion[index].pos;
const getPosData = getXYdata;
let getPosData = xyPostion[index].pos.filter(
(data) => data.key === signKey
);
const aspectRatio = imgWH.width / imgWH.height;
let newWidth, newHeight;
@@ -125,13 +133,13 @@ export function onSaveImage(xyPostion, index, signKey, imgWH, image) {
newHeight = 10;
}
const addSign = getPosData.map((url, ind) => {
const addSign = getXYdata.map((url, ind) => {
if (url.key === signKey) {
return {
...url,
Width: newWidth,
Height: newHeight,
SignUrl: image.src,
Width: getPosData[0].Width ? getPosData[0].Width : newWidth,
Height: getPosData[0].Height ? getPosData[0].Height : newHeight,
SignUrl: image.src,
ImageType: image.imgType
};
}
@@ -151,15 +159,10 @@ export function onSaveImage(xyPostion, index, signKey, imgWH, image) {
//function for save button to save signature or image url
export function onSaveSign(xyPostion, index, signKey, signatureImg) {
// const updateFilter = xyPostion[index].pos.filter(
// (data) => data.key === signKey && data.SignUrl
// );
let getXYdata = xyPostion[index].pos;
let getPosData = getXYdata;
// if (updateFilter.length > 0) {
// updateFilter[0].SignUrl = signatureImg;
const addSign = getPosData.map((url, ind) => {
let getPosData = xyPostion[index].pos.filter((data) => data.key === signKey);
const addSign = getXYdata.map((url, ind) => {
if (url.key === signKey) {
return {
...url,
@@ -178,27 +181,6 @@ export function onSaveSign(xyPostion, index, signKey, signatureImg) {
return obj;
});
return newUpdateUrl;
// } else {
// const addSign = getPosData.map((url, ind) => {
// if (url.key === signKey) {
// return {
// ...url,
// SignUrl: signatureImg,
// Width: getPosData[0].Width ? getPosData[0].Width : 150,
// Height: getPosData[0].Height ? getPosData[0].Height : 60
// };
// }
// return url;
// });
// const newUpdateUrl = xyPostion.map((obj, ind) => {
// if (ind === index) {
// return { ...obj, pos: addSign };
// }
// return obj;
// });
// return newUpdateUrl;
// }
}
//function for getting contract_User details
@@ -278,5 +260,3 @@ export const contactBookName = async (objectId, className) => {
});
return result;
};