mirror of
https://github.com/OpenSignLabs/OpenSign.git
synced 2026-09-05 01:07:39 +02:00
Compare commits
90
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e71924a264 | ||
|
|
4ae9748004 | ||
|
|
eda6113792 | ||
|
|
4f1509c836 | ||
|
|
dfcf32ef3e | ||
|
|
4a95257ee2 | ||
|
|
ee1e13ef61 | ||
|
|
c9c099ffc5 | ||
|
|
a80f4fb3c9 | ||
|
|
941f3ac47f | ||
|
|
80d3200d57 | ||
|
|
55926e25d2 | ||
|
|
a31f3ebad7 | ||
|
|
dc9c32c6ee | ||
|
|
dac3aac2a1 | ||
|
|
40196e823c | ||
|
|
7708b7e938 | ||
|
|
8bbc5a9bc6 | ||
|
|
4dbdfb1b77 | ||
|
|
05c51edce3 | ||
|
|
379e8cd95e | ||
|
|
9fd00d4427 | ||
|
|
ca114cf124 | ||
|
|
75128784db | ||
|
|
722f0e277e | ||
|
|
7089998966 | ||
|
|
52211ddfa4 | ||
|
|
2b8b762d35 | ||
|
|
04c228cd36 | ||
|
|
915f8e7700 | ||
|
|
218cea00b5 | ||
|
|
f38f5ea670 | ||
|
|
a9c08c8a9f | ||
|
|
9406c4f718 | ||
|
|
791d8beb06 | ||
|
|
57a9f3aca0 | ||
|
|
ae8bf187c8 | ||
|
|
88f2ab1f8e | ||
|
|
76f5136073 | ||
|
|
0f84cd8949 | ||
|
|
adfdf7606f | ||
|
|
ce671d4294 | ||
|
|
2e7cf7a9df | ||
|
|
f699d93e44 | ||
|
|
531ef4d0b2 | ||
|
|
4c6dbb6690 | ||
|
|
0beb60d1b5 | ||
|
|
893c9d7c42 | ||
|
|
b7a22d94db | ||
|
|
3d854756d1 | ||
|
|
251e7058f1 | ||
|
|
368eb24217 | ||
|
|
f89ef54b82 | ||
|
|
b9d9f8772b | ||
|
|
f2ee03e850 | ||
|
|
92e59a0072 | ||
|
|
5394c0b520 | ||
|
|
e4a9c6f8c2 | ||
|
|
e559d037c3 | ||
|
|
c9909a0869 | ||
|
|
988fc1bbfd | ||
|
|
1831bbcd70 | ||
|
|
ced9bbdbd5 | ||
|
|
15d57d937b | ||
|
|
555979869d | ||
|
|
4e6477297e | ||
|
|
e9e06fc53b | ||
|
|
ecb2818589 | ||
|
|
c442689573 | ||
|
|
88919f2634 | ||
|
|
1a1bc41283 | ||
|
|
4188caed33 | ||
|
|
50557d8bc5 | ||
|
|
0f1ef0406e | ||
|
|
ffc742b460 | ||
|
|
0c04cc6ce6 | ||
|
|
4e6dfed838 | ||
|
|
fdc0524ad2 | ||
|
|
9852c87be7 | ||
|
|
1268f65516 | ||
|
|
6551b2537a | ||
|
|
b138ccf625 | ||
|
|
27ff7baa6d | ||
|
|
3fc41f4255 | ||
|
|
b20aa33a04 | ||
|
|
a64da4cd85 | ||
|
|
e80bcfc586 | ||
|
|
de5b8160a2 | ||
|
|
83df969751 | ||
|
|
f04fd16c9e |
Generated
+1269
-793
File diff suppressed because it is too large
Load Diff
+21
-19
@@ -4,16 +4,17 @@
|
|||||||
"private": true,
|
"private": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@formkit/auto-animate": "^0.8.2",
|
"@formkit/auto-animate": "^0.8.2",
|
||||||
"@lottiefiles/dotlottie-react": "^0.8.9",
|
"@lottiefiles/dotlottie-react": "^0.9.0",
|
||||||
"@pdf-lib/fontkit": "^1.1.1",
|
"@pdf-lib/fontkit": "^1.1.1",
|
||||||
"@radix-ui/themes": "^3.1.3",
|
"@radix-ui/themes": "^3.1.3",
|
||||||
"@react-pdf/renderer": "^3.4.4",
|
"@react-pdf/renderer": "^4.0.0",
|
||||||
"@reduxjs/toolkit": "^2.2.7",
|
"@reduxjs/toolkit": "^2.2.7",
|
||||||
"axios": "^1.7.5",
|
"axios": "^1.7.7",
|
||||||
"file-saver": "^2.0.5",
|
"file-saver": "^2.0.5",
|
||||||
"i18next": "^23.14.0",
|
"i18next": "^23.15.1",
|
||||||
"i18next-browser-languagedetector": "^8.0.0",
|
"i18next-browser-languagedetector": "^8.0.0",
|
||||||
"i18next-http-backend": "^2.6.1",
|
"i18next-http-backend": "^2.6.1",
|
||||||
|
"jszip": "^3.10.1",
|
||||||
"jwt-decode": "^4.0.0",
|
"jwt-decode": "^4.0.0",
|
||||||
"moment": "^2.30.1",
|
"moment": "^2.30.1",
|
||||||
"nth-check": "^2.1.1",
|
"nth-check": "^2.1.1",
|
||||||
@@ -25,7 +26,7 @@
|
|||||||
"react-bootstrap": "^2.10.4",
|
"react-bootstrap": "^2.10.4",
|
||||||
"react-confetti": "^6.1.0",
|
"react-confetti": "^6.1.0",
|
||||||
"react-cookie": "^7.2.0",
|
"react-cookie": "^7.2.0",
|
||||||
"react-datepicker": "^7.3.0",
|
"react-datepicker": "^7.4.0",
|
||||||
"react-dnd": "^16.0.1",
|
"react-dnd": "^16.0.1",
|
||||||
"react-dnd-html5-backend": "^16.0.1",
|
"react-dnd-html5-backend": "^16.0.1",
|
||||||
"react-dnd-multi-backend": "^8.0.3",
|
"react-dnd-multi-backend": "^8.0.3",
|
||||||
@@ -33,17 +34,18 @@
|
|||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
"react-gtm-module": "^2.0.11",
|
"react-gtm-module": "^2.0.11",
|
||||||
"react-helmet": "^6.1.0",
|
"react-helmet": "^6.1.0",
|
||||||
"react-i18next": "^15.0.1",
|
"react-i18next": "^15.0.2",
|
||||||
"react-konva": "^18.2.10",
|
"react-konva": "^18.2.10",
|
||||||
"react-pdf": "^9.1.0",
|
"react-pdf": "^9.1.1",
|
||||||
"react-quill-new": "^3.3.0",
|
"react-quill-new": "^3.3.2",
|
||||||
"react-redux": "^9.1.2",
|
"react-redux": "^9.1.2",
|
||||||
"react-rnd": "^10.4.11",
|
"react-rnd": "^10.4.13",
|
||||||
"react-router-dom": "^6.26.1",
|
"react-router-dom": "^6.26.2",
|
||||||
"react-scripts": "5.0.1",
|
"react-scripts": "5.0.1",
|
||||||
"react-scrollbars-custom": "^4.1.1",
|
"react-scrollbars-custom": "^4.1.1",
|
||||||
"react-select": "^5.8.0",
|
"react-select": "^5.8.1",
|
||||||
"react-signature-canvas": "^1.0.6",
|
"react-signature-canvas": "^1.0.6",
|
||||||
|
"react-syntax-highlighter": "^15.5.0",
|
||||||
"react-tooltip": "^5.28.0",
|
"react-tooltip": "^5.28.0",
|
||||||
"react-web-share": "^2.0.2",
|
"react-web-share": "^2.0.2",
|
||||||
"reactour": "^1.19.4",
|
"reactour": "^1.19.4",
|
||||||
@@ -59,7 +61,7 @@
|
|||||||
"build-webpack": "webpack --config webpack.config.js",
|
"build-webpack": "webpack --config webpack.config.js",
|
||||||
"build": "npm run version && npm run build-webpack && react-scripts build",
|
"build": "npm run version && npm run build-webpack && react-scripts build",
|
||||||
"build-watch": "webpack --config webpack.config.js --watch",
|
"build-watch": "webpack --config webpack.config.js --watch",
|
||||||
"start-dev": "concurrently \"npm run build-watch\" \"react-scripts start\"",
|
"start-dev": "react-scripts start",
|
||||||
"start": "serve -s build",
|
"start": "serve -s build",
|
||||||
"version": "curl -s https://api.github.com/repos/opensignlabs/opensign/releases/latest | grep '\"tag_name\":' | awk -F '\"' '{print $4}' > ./public/version.txt",
|
"version": "curl -s https://api.github.com/repos/opensignlabs/opensign/releases/latest | grep '\"tag_name\":' | awk -F '\"' '{print $4}' > ./public/version.txt",
|
||||||
"version-win": "powershell -Command \"Invoke-RestMethod -Uri 'https://api.github.com/repos/opensignlabs/opensign/releases/latest' | Select-Object -ExpandProperty tag_name | Out-File -FilePath ./public/version.txt\"",
|
"version-win": "powershell -Command \"Invoke-RestMethod -Uri 'https://api.github.com/repos/opensignlabs/opensign/releases/latest' | Select-Object -ExpandProperty tag_name | Out-File -FilePath ./public/version.txt\"",
|
||||||
@@ -96,25 +98,25 @@
|
|||||||
"@babel/core": "^7.25.2",
|
"@babel/core": "^7.25.2",
|
||||||
"@babel/preset-env": "^7.25.4",
|
"@babel/preset-env": "^7.25.4",
|
||||||
"@babel/preset-react": "^7.24.7",
|
"@babel/preset-react": "^7.24.7",
|
||||||
"@babel/runtime-corejs2": "^7.25.4",
|
"@babel/runtime-corejs2": "^7.25.6",
|
||||||
"autoprefixer": "^10.4.20",
|
"autoprefixer": "^10.4.20",
|
||||||
"babel-loader": "^9.1.3",
|
"babel-loader": "^9.2.1",
|
||||||
"clean-webpack-plugin": "^4.0.0",
|
"clean-webpack-plugin": "^4.0.0",
|
||||||
"commitizen": "^4.3.0",
|
"commitizen": "^4.3.0",
|
||||||
"concurrently": "^8.2.2",
|
"concurrently": "^9.0.1",
|
||||||
"css-loader": "^7.1.2",
|
"css-loader": "^7.1.2",
|
||||||
"daisyui": "^4.12.10",
|
"daisyui": "^4.12.10",
|
||||||
"dotenv": "^16.4.5",
|
"dotenv": "^16.4.5",
|
||||||
"dotenv-webpack": "^8.1.0",
|
"dotenv-webpack": "^8.1.0",
|
||||||
"eslint": "^8.57.0",
|
"eslint": "^9.11.1",
|
||||||
"eslint-plugin-prettier": "^5.2.1",
|
"eslint-plugin-prettier": "^5.2.1",
|
||||||
"eslint-plugin-react": "^7.34.3",
|
"eslint-plugin-react": "^7.36.1",
|
||||||
"lint-staged": "^15.2.10",
|
"lint-staged": "^15.2.10",
|
||||||
"mini-css-extract-plugin": "^2.9.1",
|
"mini-css-extract-plugin": "^2.9.1",
|
||||||
"postcss": "^8.4.45",
|
"postcss": "^8.4.47",
|
||||||
"prettier": "^3.3.3",
|
"prettier": "^3.3.3",
|
||||||
"pretty-quick": "^4.0.0",
|
"pretty-quick": "^4.0.0",
|
||||||
"tailwindcss": "^3.4.10",
|
"tailwindcss": "^3.4.13",
|
||||||
"terser-webpack-plugin": "^5.3.10",
|
"terser-webpack-plugin": "^5.3.10",
|
||||||
"webpack-cli": "^5.1.4"
|
"webpack-cli": "^5.1.4"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -131,7 +131,8 @@
|
|||||||
"Share": "Share",
|
"Share": "Share",
|
||||||
"View": "View",
|
"View": "View",
|
||||||
"option": "Option",
|
"option": "Option",
|
||||||
"Embed": "Embed"
|
"Embed": "Embed",
|
||||||
|
"Copy TemplateId":"Copy TemplateId"
|
||||||
},
|
},
|
||||||
"report-heading": {
|
"report-heading": {
|
||||||
"Sr.No": "Sr.No",
|
"Sr.No": "Sr.No",
|
||||||
@@ -151,7 +152,8 @@
|
|||||||
"Name": "Name",
|
"Name": "Name",
|
||||||
"Status": "Status",
|
"Status": "Status",
|
||||||
"created-date": "Created Date",
|
"created-date": "Created Date",
|
||||||
"Type": "Type"
|
"Type": "Type",
|
||||||
|
"Logs": "Logs"
|
||||||
},
|
},
|
||||||
"report-help": {
|
"report-help": {
|
||||||
"Draft Documents": "These are documents you have started but have not finalized for sending.",
|
"Draft Documents": "These are documents you have started but have not finalized for sending.",
|
||||||
@@ -263,7 +265,8 @@
|
|||||||
"make-template-private-alert": "Are you sure you want to make this template private? This will remove it from your public profile.",
|
"make-template-private-alert": "Are you sure you want to make this template private? This will remove it from your public profile.",
|
||||||
"public-role": "Public role",
|
"public-role": "Public role",
|
||||||
"public-url": "Public URL",
|
"public-url": "Public URL",
|
||||||
"public-url-copy-mssg": " Here’s your public URL: Copy it or share it with the signer, and you will be able to see all your publicly set templates.",
|
"public-url-copy": "Here’s your public URL: ",
|
||||||
|
"public-url-copy-mssg":"Copy it or share it with the signer, and you will be able to see all your publicly set templates.",
|
||||||
"add-public-url-alert": "Please add your public URL, and you will be able to make a public template.",
|
"add-public-url-alert": "Please add your public URL, and you will be able to make a public template.",
|
||||||
"share-with-alert": "You cannot share a template if any roles already have contacts assigned. Please remove all contact assignments from the roles before sharing the template.",
|
"share-with-alert": "You cannot share a template if any roles already have contacts assigned. Please remove all contact assignments from the roles before sharing the template.",
|
||||||
"share-with": "Share with",
|
"share-with": "Share with",
|
||||||
@@ -572,9 +575,10 @@
|
|||||||
"pdf-request-file-5": "You can click 'Auto Sign All' to automatically sign at all the locations meant to be signed by you. Make sure that you review the document properly before you click this button .",
|
"pdf-request-file-5": "You can click 'Auto Sign All' to automatically sign at all the locations meant to be signed by you. Make sure that you review the document properly before you click this button .",
|
||||||
"placeholder-sign-1": "Select a recipient from this list to add a place-holder where he is supposed to sign.The placeholder will appear in the same colour as the recipient name once you drop it on the document.",
|
"placeholder-sign-1": "Select a recipient from this list to add a place-holder where he is supposed to sign.The placeholder will appear in the same colour as the recipient name once you drop it on the document.",
|
||||||
"placeholder-sign-2": "Clicking 'Add recipients' button will allow you to add more signers.",
|
"placeholder-sign-2": "Clicking 'Add recipients' button will allow you to add more signers.",
|
||||||
"placeholder-sign-3": "Drag or click on a field to add it to the document.",
|
"placeholder-sign-3": "Click this button to add more recipients/signers to the document.",
|
||||||
"placeholder-sign-4": "The PDF content area already displays the template's existing placeholders. For your convenience, these placeholders will match the color of the recipient's name, making them easily identifiable.",
|
"placeholder-sign-4": "Drag or click on a field to add it to the document.",
|
||||||
"placeholder-sign-5": "Clicking 'Send' will save the document. In the next step you can customize the emails to be sent out to the recipients or copy the signing links and share those with the recipients yourself.",
|
"placeholder-sign-5": "The PDF content area already displays the template's existing placeholders. For your convenience, these placeholders will match the color of the recipient's name, making them easily identifiable.",
|
||||||
|
"placeholder-sign-6": "Clicking 'Send' will save the document. In the next step you can customize the emails to be sent out to the recipients or copy the signing links and share those with the recipients yourself.",
|
||||||
"report-1": "Click the 'Add' button to create a new template. Templates are reusable documents designed to quickly generate new documents with the same structure and varying signers. For example, an HR template for onboarding could have predefined roles like ‘HR Manager’ and ‘New Employee’. Each time you use the template, you can assign the ‘New Employee’ role to different incoming staff members, while the ‘HR Manager’ role remains constant, facilitating a seamless onboarding process for each recruit. ",
|
"report-1": "Click the 'Add' button to create a new template. Templates are reusable documents designed to quickly generate new documents with the same structure and varying signers. For example, an HR template for onboarding could have predefined roles like ‘HR Manager’ and ‘New Employee’. Each time you use the template, you can assign the ‘New Employee’ role to different incoming staff members, while the ‘HR Manager’ role remains constant, facilitating a seamless onboarding process for each recruit. ",
|
||||||
"redirect": "Click the 'Use' button to create a new document from an existing template.",
|
"redirect": "Click the 'Use' button to create a new document from an existing template.",
|
||||||
"bulksend": "To quickly create and send multiple documents using an existing template, click the 'Quick Send' button.",
|
"bulksend": "To quickly create and send multiple documents using an existing template, click the 'Quick Send' button.",
|
||||||
@@ -630,6 +634,19 @@
|
|||||||
"reason":"Reason",
|
"reason":"Reason",
|
||||||
"decline-by":"Declined/revoked by",
|
"decline-by":"Declined/revoked by",
|
||||||
"document-declined": "Document declined",
|
"document-declined": "Document declined",
|
||||||
|
"public-template-mssg-1":"To integrate OpenSign into your React or Next.js project, simply run the following command:",
|
||||||
|
"public-template-mssg-2" :"Ensure you have npm or yarn set up in your project. If you’re using Yarn, you can replace npm install with yarn add @opensign/react.",
|
||||||
|
"public-template-mssg-3" :"Need more details or examples?",
|
||||||
|
"public-template-mssg-4": "Visit the",
|
||||||
|
"public-template-mssg-5": " npm for the latest updates, detailed documentation, and version history.",
|
||||||
|
"public-template-mssg-6" :"You need to set this template as public before you can utilize this code snippet.",
|
||||||
|
"copy-code":"COPY",
|
||||||
|
"copied-code":"COPIED",
|
||||||
|
"Installation":"Installation",
|
||||||
|
"Usage" :"Usage",
|
||||||
|
"insufficient-credits":"Insufficient Signing Credits",
|
||||||
|
"insufficient-credits-mssg":"The owner of this document currently lacks the necessary OpenSign credits for you to sign. Please reach out to the owner if you require further details.",
|
||||||
|
"angular-npm-mssg-1": "To integrate OpenSign into your Angular project, simply run the following command:",
|
||||||
"quota-mail-info-head":"Monthly request signatures email limit",
|
"quota-mail-info-head":"Monthly request signatures email limit",
|
||||||
"quota-mail-info": "You can send upto 15 signature request emails every month. Upgrade now to send unlimited signing requests directly.",
|
"quota-mail-info": "You can send upto 15 signature request emails every month. Upgrade now to send unlimited signing requests directly.",
|
||||||
"quota-mail": "You've reached your limit of 15 signature request emails for this month. Upgrade now to continue sending emails directly.",
|
"quota-mail": "You've reached your limit of 15 signature request emails for this month. Upgrade now to continue sending emails directly.",
|
||||||
@@ -647,5 +664,10 @@
|
|||||||
"p4": "Please choose the option that best suits your document signing requirements."
|
"p4": "Please choose the option that best suits your document signing requirements."
|
||||||
},
|
},
|
||||||
"advanced-options":"Advanced options",
|
"advanced-options":"Advanced options",
|
||||||
"hide-advanced-options":"Hide Advanced options"
|
"hide-advanced-options":"Hide Advanced options",
|
||||||
|
"download-files":"Download files",
|
||||||
|
"download-pdf":"Download Pdf",
|
||||||
|
"pdf-certificate":"Download Pdf + Certificate",
|
||||||
|
"document-logs":"Document logs"
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -136,7 +136,8 @@
|
|||||||
"Name": "Nom",
|
"Name": "Nom",
|
||||||
"Status": "Statut",
|
"Status": "Statut",
|
||||||
"created-date": "Date de création",
|
"created-date": "Date de création",
|
||||||
"Type": "Saisir"
|
"Type": "Saisir",
|
||||||
|
"Logs": "Journaux"
|
||||||
},
|
},
|
||||||
"btnLabel": {
|
"btnLabel": {
|
||||||
"sign": "Signer",
|
"sign": "Signer",
|
||||||
@@ -150,7 +151,8 @@
|
|||||||
"Share": "Partager",
|
"Share": "Partager",
|
||||||
"View": "Voir",
|
"View": "Voir",
|
||||||
"option": "Option",
|
"option": "Option",
|
||||||
"Embed": "Intégrer"
|
"Embed": "Intégrer",
|
||||||
|
"Copy TemplateId": "Copier l'ID du modèle"
|
||||||
},
|
},
|
||||||
"report-help": {
|
"report-help": {
|
||||||
"Draft Documents": "Il s'agit de documents que vous avez commencés mais que vous n'avez pas finalisés pour envoi.",
|
"Draft Documents": "Il s'agit de documents que vous avez commencés mais que vous n'avez pas finalisés pour envoi.",
|
||||||
@@ -262,7 +264,8 @@
|
|||||||
"make-template-private-alert": "Êtes-vous sûr de vouloir rendre ce modèle privé ? Cela le supprimera de votre profil public.",
|
"make-template-private-alert": "Êtes-vous sûr de vouloir rendre ce modèle privé ? Cela le supprimera de votre profil public.",
|
||||||
"public-role": "Rôle public",
|
"public-role": "Rôle public",
|
||||||
"public-url": "URL publique",
|
"public-url": "URL publique",
|
||||||
"public-url-copy-mssg": "Voici votre URL publique : copiez-la ou partagez-le avec le signataire et vous pouvoir voir tous vos paramètres publics modèles.",
|
"public-url-copy": "Voici votre URL publique : ",
|
||||||
|
"public-url-copy-mssg": "copiez-la ou partagez-le avec le signataire et vous pouvoir voir tous vos paramètres publics modèles.",
|
||||||
"add-public-url-alert": "Veuillez ajouter votre URL publique et vous pourra rendre public modèle.",
|
"add-public-url-alert": "Veuillez ajouter votre URL publique et vous pourra rendre public modèle.",
|
||||||
"share-with-alert": "Vous ne pouvez pas partager un modèle si des contacts sont déjà attribués à des rôles. Veuillez supprimer toutes les attributions de contacts des rôles avant de partager le modèle.",
|
"share-with-alert": "Vous ne pouvez pas partager un modèle si des contacts sont déjà attribués à des rôles. Veuillez supprimer toutes les attributions de contacts des rôles avant de partager le modèle.",
|
||||||
"share-with": "Partager avec",
|
"share-with": "Partager avec",
|
||||||
@@ -571,9 +574,10 @@
|
|||||||
"pdf-request-file-5": "Vous pouvez cliquer sur 'Signer automatiquement tout' pour signer automatiquement à tous les emplacements que vous êtes censé signer. Assurez-vous de lire correctement le document avant de cliquer sur ce bouton.",
|
"pdf-request-file-5": "Vous pouvez cliquer sur 'Signer automatiquement tout' pour signer automatiquement à tous les emplacements que vous êtes censé signer. Assurez-vous de lire correctement le document avant de cliquer sur ce bouton.",
|
||||||
"placeholder-sign-1": "Sélectionnez un destinataire dans cette liste pour ajouter un espace réservé à l'endroit où il est censé signer. L'espace réservé apparaîtra de la même couleur que le nom du destinataire une fois que vous le déposerez sur le document.",
|
"placeholder-sign-1": "Sélectionnez un destinataire dans cette liste pour ajouter un espace réservé à l'endroit où il est censé signer. L'espace réservé apparaîtra de la même couleur que le nom du destinataire une fois que vous le déposerez sur le document.",
|
||||||
"placeholder-sign-2": "Cliquer sur le bouton 'Ajouter des destinataires' vous permettra d'ajouter plus de signataires.",
|
"placeholder-sign-2": "Cliquer sur le bouton 'Ajouter des destinataires' vous permettra d'ajouter plus de signataires.",
|
||||||
"placeholder-sign-3": "Faites glisser ou cliquez sur un champ pour l'ajouter au document.",
|
"placeholder-sign-3": "Cliquez sur ce bouton pour ajouter plus de destinataires/signataires au document",
|
||||||
"placeholder-sign-4": "La zone de contenu PDF affiche déjà les espaces réservés existants du modèle. Pour votre commodité, ces espaces réservés correspondront à la couleur du nom du destinataire, ce qui les rendra facilement identifiables.",
|
"placeholder-sign-4": "Faites glisser ou cliquez sur un champ pour l'ajouter au document.",
|
||||||
"placeholder-sign-5": "Cliquer sur 'Envoyer' enregistrera le document. À l'étape suivante, vous pourrez personnaliser les e-mails à envoyer aux destinataires ou copier les liens de signature et les partager vous-même avec les destinataires.",
|
"placeholder-sign-5": "La zone de contenu PDF affiche déjà les espaces réservés existants du modèle. Pour votre commodité, ces espaces réservés correspondront à la couleur du nom du destinataire, ce qui les rendra facilement identifiables.",
|
||||||
|
"placeholder-sign-6": "Cliquer sur 'Envoyer' enregistrera le document. À l'étape suivante, vous pourrez personnaliser les e-mails à envoyer aux destinataires ou copier les liens de signature et les partager vous-même avec les destinataires.",
|
||||||
"report-1": "Cliquez sur le bouton 'Ajouter' pour créer un nouveau modèle. Les modèles sont des documents réutilisables conçus pour générer rapidement de nouveaux documents avec la même structure et différents signataires. Par exemple, un modèle RH pour l'intégration peut avoir des rôles prédéfinis tels que 'Responsable RH' et ' Nouvel employé'. Chaque fois que vous utilisez le modèle, vous pouvez attribuer le rôle 'Nouvel employé' à différents membres du personnel entrants, tandis que le rôle 'Responsable RH' reste constant, facilitant ainsi un processus d'intégration fluide pour chaque recrue",
|
"report-1": "Cliquez sur le bouton 'Ajouter' pour créer un nouveau modèle. Les modèles sont des documents réutilisables conçus pour générer rapidement de nouveaux documents avec la même structure et différents signataires. Par exemple, un modèle RH pour l'intégration peut avoir des rôles prédéfinis tels que 'Responsable RH' et ' Nouvel employé'. Chaque fois que vous utilisez le modèle, vous pouvez attribuer le rôle 'Nouvel employé' à différents membres du personnel entrants, tandis que le rôle 'Responsable RH' reste constant, facilitant ainsi un processus d'intégration fluide pour chaque recrue",
|
||||||
"redirect": "Cliquez sur le bouton 'Utiliser' pour créer un nouveau document à partir d'un modèle existant.",
|
"redirect": "Cliquez sur le bouton 'Utiliser' pour créer un nouveau document à partir d'un modèle existant.",
|
||||||
"bulksend": "Pour créer et envoyer rapidement plusieurs documents à l'aide d'un modèle existant, cliquez sur le bouton 'Envoi rapide'.",
|
"bulksend": "Pour créer et envoyer rapidement plusieurs documents à l'aide d'un modèle existant, cliquez sur le bouton 'Envoi rapide'.",
|
||||||
@@ -629,6 +633,19 @@
|
|||||||
"reason" :"Raison",
|
"reason" :"Raison",
|
||||||
"decline-by" :"Refusé/révoqué par",
|
"decline-by" :"Refusé/révoqué par",
|
||||||
"document-declined":"document refusé",
|
"document-declined":"document refusé",
|
||||||
|
"public-template-mssg-1" :"Pour intégrer OpenSign dans votre projet React ou Next.js, exécutez simplement la commande suivante :",
|
||||||
|
"public-template-mssg-2" :"Assurez-vous que npm ou Yarn est configuré dans votre projet. Si vous utilisez Yarn, vous pouvez remplacer npm install par Yarn Add @opensign/react.",
|
||||||
|
"public-template-mssg-3" :"Besoin de plus de détails ou d'exemples ?",
|
||||||
|
"public-template-mssg-4": "Visitez le",
|
||||||
|
"public-template-mssg-5": "npm pour les dernières mises à jour, une documentation détaillée et l'historique des versions.",
|
||||||
|
"public-template-mssg-6":"Vous devez définir ce modèle comme public avant de pouvoir utiliser cet extrait de code.",
|
||||||
|
"copy-code":"COPIE",
|
||||||
|
"copied-code":"COPIÉ",
|
||||||
|
"Installation":"Installation",
|
||||||
|
"Usage" :"Usage",
|
||||||
|
"insufficient-credits":"Crédits de signature insuffisants",
|
||||||
|
"insufficient-credits-mssg" :"Le propriétaire de ce document ne dispose actuellement pas des crédits OpenSign nécessaires pour que vous puissiez le signer. Veuillez contacter le propriétaire si vous avez besoin de plus de détails.",
|
||||||
|
"angular-npm-mssg-1" :"Pour intégrer OpenSign dans votre projet Angular, exécutez simplement la commande suivante :",
|
||||||
"quota-mail-info-head":"Limite mensuelle d'e-mails de signatures de demandes",
|
"quota-mail-info-head":"Limite mensuelle d'e-mails de signatures de demandes",
|
||||||
"quota-mail-info": "Vous pouvez envoyer jusqu'à 15 e-mails de demande de signature chaque mois. Mettez à niveau maintenant pour envoyer directement des demandes de signature illimitées.",
|
"quota-mail-info": "Vous pouvez envoyer jusqu'à 15 e-mails de demande de signature chaque mois. Mettez à niveau maintenant pour envoyer directement des demandes de signature illimitées.",
|
||||||
"quota-mail": "Vous avez atteint votre limite de 15 e-mails de demande de signature pour ce mois. Mettez à niveau maintenant pour continuer à envoyer des e-mails directement.",
|
"quota-mail": "Vous avez atteint votre limite de 15 e-mails de demande de signature pour ce mois. Mettez à niveau maintenant pour continuer à envoyer des e-mails directement.",
|
||||||
@@ -646,6 +663,10 @@
|
|||||||
"p4": "Veuillez choisir l'option qui correspond le mieux à vos exigences en matière de signature de documents."
|
"p4": "Veuillez choisir l'option qui correspond le mieux à vos exigences en matière de signature de documents."
|
||||||
},
|
},
|
||||||
"advanced-options":"Options avancées",
|
"advanced-options":"Options avancées",
|
||||||
"hide-advanced-options": "Masquer les options avancées"
|
"hide-advanced-options": "Masquer les options avancées",
|
||||||
|
"download-files" :"Télécharger des fichiers",
|
||||||
|
"download-pdf" :"Télécharger le PDF",
|
||||||
|
"pdf-certificate" :"Télécharger Pdf + Certificat",
|
||||||
|
"document-logs":"Journaux de documents"
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -20,6 +20,9 @@ const Header = ({ showSidebar }) => {
|
|||||||
const { t, i18n } = useTranslation();
|
const { t, i18n } = useTranslation();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const { width } = useWindowSize();
|
const { width } = useWindowSize();
|
||||||
|
const current_notification_version = "1"; // Update this with each new feature release
|
||||||
|
// Get the dismissed version from local storage
|
||||||
|
const dismissedVersion = localStorage.getItem("notificationDismissedVersion");
|
||||||
const username = localStorage.getItem("username") || "";
|
const username = localStorage.getItem("username") || "";
|
||||||
const image = localStorage.getItem("profileImg") || dp;
|
const image = localStorage.getItem("profileImg") || dp;
|
||||||
const [isOpen, setIsOpen] = useState(false);
|
const [isOpen, setIsOpen] = useState(false);
|
||||||
@@ -30,9 +33,15 @@ const Header = ({ showSidebar }) => {
|
|||||||
);
|
);
|
||||||
const [emailUsed, setEmailUsed] = useState(0);
|
const [emailUsed, setEmailUsed] = useState(0);
|
||||||
const [isModal, setIsModal] = useState(false);
|
const [isModal, setIsModal] = useState(false);
|
||||||
|
const [showNotification, setShowNotification] = useState(
|
||||||
|
(!dismissedVersion || dismissedVersion !== current_notification_version) &&
|
||||||
|
true
|
||||||
|
);
|
||||||
const toggleDropdown = () => {
|
const toggleDropdown = () => {
|
||||||
setIsOpen(!isOpen);
|
setIsOpen(!isOpen);
|
||||||
|
if (width <= 768) {
|
||||||
|
showSidebar();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
checkSubscription();
|
checkSubscription();
|
||||||
@@ -58,6 +67,13 @@ const Header = ({ showSidebar }) => {
|
|||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.log("err in while fetching monthlyfreeEmails", err);
|
console.log("err in while fetching monthlyfreeEmails", err);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
const applogo = await getAppLogo();
|
||||||
|
if (applogo?.logo) {
|
||||||
|
setAppLogo(applogo?.logo);
|
||||||
|
} else {
|
||||||
|
setAppLogo(localStorage.getItem("appLogo") || "");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -115,17 +131,34 @@ const Header = ({ showSidebar }) => {
|
|||||||
const handleMailUsed = () => {
|
const handleMailUsed = () => {
|
||||||
setIsModal(!isModal);
|
setIsModal(!isModal);
|
||||||
};
|
};
|
||||||
|
// Handle dismissing the notification
|
||||||
|
const dismissNotification = () => {
|
||||||
|
// Store the current version as dismissed in local storage
|
||||||
|
localStorage.setItem(
|
||||||
|
"notificationDismissedVersion",
|
||||||
|
current_notification_version
|
||||||
|
);
|
||||||
|
setShowNotification(false);
|
||||||
|
};
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
{isEnableSubscription && (
|
{isEnableSubscription && showNotification && (
|
||||||
<div className="shadow py-1 text-center bg-[#CAE4FA] text-[14px] p-1">
|
<div className="flex justify-between items-center shadow py-1 bg-[#CAE4FA] p-1">
|
||||||
{t("header-news")} —
|
<div className="text-center text-[14px] ml-auto">
|
||||||
<span
|
{t("header-news")} —
|
||||||
className="cursor-pointer font-medium underline text-blue-800"
|
<span
|
||||||
onClick={() => navigate("/profile")}
|
className="cursor-pointer font-medium underline text-blue-800"
|
||||||
|
onClick={() => navigate("/profile")}
|
||||||
|
>
|
||||||
|
{" " + t("header-news-btn") + "."}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
className="ml-auto mr-1 cursor-pointer"
|
||||||
|
onClick={() => dismissNotification()}
|
||||||
>
|
>
|
||||||
{" " + t("header-news-btn") + "."}
|
<i className="fa-light fa-xmark"></i>
|
||||||
</span>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<div className="op-navbar bg-base-100 shadow">
|
<div className="op-navbar bg-base-100 shadow">
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import * as HoverCard from "@radix-ui/react-hover-card";
|
|||||||
import ModalUi from "../../primitives/ModalUi";
|
import ModalUi from "../../primitives/ModalUi";
|
||||||
import FolderModal from "../shared/fields/FolderModal";
|
import FolderModal from "../shared/fields/FolderModal";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
|
import { handleDownloadPdf } from "../../constant/Utils";
|
||||||
|
|
||||||
function DriveBody(props) {
|
function DriveBody(props) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
@@ -100,16 +101,17 @@ function DriveBody(props) {
|
|||||||
|
|
||||||
//function for navigate user to microapp-signature component
|
//function for navigate user to microapp-signature component
|
||||||
const checkPdfStatus = async (data) => {
|
const checkPdfStatus = async (data) => {
|
||||||
const signerExist = data.Signers && data.Signers;
|
const signerExist = data?.Signers;
|
||||||
const isDecline = data.IsDeclined && data.IsDeclined;
|
const isDecline = data?.IsDeclined;
|
||||||
const isPlaceholder = data.Placeholders && data.Placeholders;
|
const isPlaceholder = data?.Placeholders;
|
||||||
const signedUrl = data.SignedUrl;
|
const signedUrl = data?.SignedUrl;
|
||||||
|
const isSignYourself = data?.IsSignyourself;
|
||||||
//checking if document has completed and request signature flow
|
//checking if document has completed and request signature flow
|
||||||
if (data?.IsCompleted && signerExist?.length > 0) {
|
if (data?.IsCompleted && signerExist?.length > 0) {
|
||||||
navigate(`/recipientSignPdf/${data.objectId}`);
|
navigate(`/recipientSignPdf/${data.objectId}`);
|
||||||
}
|
}
|
||||||
//checking if document has completed and signyour-self flow
|
//checking if document has completed and signyour-self flow
|
||||||
else if (!signerExist && !isPlaceholder) {
|
else if ((!signerExist && !isPlaceholder) || isSignYourself) {
|
||||||
navigate(`/signaturePdf/${data.objectId}`);
|
navigate(`/signaturePdf/${data.objectId}`);
|
||||||
}
|
}
|
||||||
//checking if document has declined by someone
|
//checking if document has declined by someone
|
||||||
@@ -136,12 +138,10 @@ function DriveBody(props) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleMenuItemClick = (selectType, data) => {
|
const handleMenuItemClick = async (selectType, data) => {
|
||||||
switch (selectType) {
|
switch (selectType) {
|
||||||
case "Download": {
|
case "Download": {
|
||||||
const pdfName = data && data.Name;
|
await handleDownloadPdf([data]);
|
||||||
const pdfUrl = data && data.SignedUrl ? data.SignedUrl : data.URL;
|
|
||||||
saveAs(pdfUrl, `${sanitizeFileName(pdfName)}_signed_by_OpenSign™.pdf`);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "Rename": {
|
case "Rename": {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import { handleDownloadPdf, handleToPrint } from "../../constant/Utils";
|
import { handleToPrint } from "../../constant/Utils";
|
||||||
import { themeColor, emailRegex } from "../../constant/const";
|
import { themeColor, emailRegex } from "../../constant/const";
|
||||||
import Loader from "../../primitives/Loader";
|
import Loader from "../../primitives/Loader";
|
||||||
import ModalUi from "../../primitives/ModalUi";
|
import ModalUi from "../../primitives/ModalUi";
|
||||||
@@ -15,7 +15,8 @@ function EmailComponent({
|
|||||||
sender,
|
sender,
|
||||||
setIsAlert,
|
setIsAlert,
|
||||||
extUserId,
|
extUserId,
|
||||||
activeMailAdapter
|
activeMailAdapter,
|
||||||
|
setIsDownloadModal
|
||||||
}) {
|
}) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const [emailList, setEmailList] = useState([]);
|
const [emailList, setEmailList] = useState([]);
|
||||||
@@ -29,6 +30,28 @@ function EmailComponent({
|
|||||||
const pdfName = pdfDetails[0]?.Name;
|
const pdfName = pdfDetails[0]?.Name;
|
||||||
setIsLoading(true);
|
setIsLoading(true);
|
||||||
let sendMail;
|
let sendMail;
|
||||||
|
|
||||||
|
const docId = !pdfDetails?.[0]?.IsEnableOTP
|
||||||
|
? pdfDetails?.[0]?.objectId
|
||||||
|
: "";
|
||||||
|
let presignedUrl = pdfUrl;
|
||||||
|
try {
|
||||||
|
// const url = await Parse.Cloud.run("getsignedurl", { url: pdfUrl });
|
||||||
|
const axiosRes = await axios.post(
|
||||||
|
`${localStorage.getItem("baseUrl")}/functions/getsignedurl`,
|
||||||
|
{ url: pdfUrl, docId: docId },
|
||||||
|
{
|
||||||
|
headers: {
|
||||||
|
"content-type": "Application/json",
|
||||||
|
"X-Parse-Application-Id": localStorage.getItem("parseAppId"),
|
||||||
|
"X-Parse-Session-Token": localStorage.getItem("accesstoken")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
presignedUrl = axiosRes.data.result;
|
||||||
|
} catch (err) {
|
||||||
|
console.log("err in getsignedurl", err);
|
||||||
|
}
|
||||||
for (let i = 0; i < emailList.length; i++) {
|
for (let i = 0; i < emailList.length; i++) {
|
||||||
try {
|
try {
|
||||||
const imgPng =
|
const imgPng =
|
||||||
@@ -46,7 +69,7 @@ function EmailComponent({
|
|||||||
mailProvider: activeMailAdapter,
|
mailProvider: activeMailAdapter,
|
||||||
extUserId: extUserId,
|
extUserId: extUserId,
|
||||||
pdfName: pdfName,
|
pdfName: pdfName,
|
||||||
url: pdfUrl,
|
url: presignedUrl,
|
||||||
recipient: emailList[i],
|
recipient: emailList[i],
|
||||||
subject: `${sender.name} has signed the doc - ${pdfName}`,
|
subject: `${sender.name} has signed the doc - ${pdfName}`,
|
||||||
from: sender.email,
|
from: sender.email,
|
||||||
@@ -129,6 +152,11 @@ function EmailComponent({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
const handleClose = () => {
|
||||||
|
setIsEmail(false);
|
||||||
|
setEmailValue("");
|
||||||
|
setEmailList([]);
|
||||||
|
};
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
{/* isEmail */}
|
{/* isEmail */}
|
||||||
@@ -165,9 +193,10 @@ function EmailComponent({
|
|||||||
)}
|
)}
|
||||||
<button
|
<button
|
||||||
className="op-btn op-btn-primary op-btn-sm text-[15px] ml-2"
|
className="op-btn op-btn-primary op-btn-sm text-[15px] ml-2"
|
||||||
onClick={() =>
|
onClick={() => {
|
||||||
handleDownloadPdf(pdfDetails, pdfUrl, setIsDownloading)
|
handleClose();
|
||||||
}
|
setIsDownloadModal(true);
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<i className="fa-light fa-download" aria-hidden="true"></i>
|
<i className="fa-light fa-download" aria-hidden="true"></i>
|
||||||
{t("download")}
|
{t("download")}
|
||||||
@@ -263,11 +292,7 @@ function EmailComponent({
|
|||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className="op-btn op-btn-ghost ml-2"
|
className="op-btn op-btn-ghost ml-2"
|
||||||
onClick={() => {
|
onClick={() => handleClose()}
|
||||||
setIsEmail(false);
|
|
||||||
setEmailValue("");
|
|
||||||
setEmailList([]);
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
{t("close")}
|
{t("close")}
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
@@ -0,0 +1,267 @@
|
|||||||
|
import React, { useState } from "react";
|
||||||
|
import { Prism as SyntaxHighlighter } from "react-syntax-highlighter";
|
||||||
|
import { tomorrow } from "react-syntax-highlighter/dist/esm/styles/prism";
|
||||||
|
import { copytoData } from "../../constant/Utils";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
|
||||||
|
function EmbedTab(props) {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const tabName = [
|
||||||
|
{ title: "React/Next.js", icon: "fa-brands fa-react", color: "#61dafb" },
|
||||||
|
{ title: "JavaScript", icon: "fa-brands fa-js", color: "#ffd43b" },
|
||||||
|
{ title: "Angular", icon: "fa-brands fa-angular", color: "#ff5733" }
|
||||||
|
];
|
||||||
|
const [activeTab, setActiveTab] = useState(0);
|
||||||
|
// State to track if the code has been copied
|
||||||
|
const [isCopied, setIsCopied] = useState(false);
|
||||||
|
const reactCode = [
|
||||||
|
{
|
||||||
|
id: 0,
|
||||||
|
title: "Installation",
|
||||||
|
codeString: `
|
||||||
|
npm install @opensign/react`
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
title: "Usage",
|
||||||
|
codeString: `
|
||||||
|
import React from "react";
|
||||||
|
import Opensign from "@opensign/react";
|
||||||
|
|
||||||
|
export function App() {
|
||||||
|
return (
|
||||||
|
<div className="app">
|
||||||
|
<Opensign
|
||||||
|
onLoad={() => console.log("success")}
|
||||||
|
onLoadError={(error) => console.log(error)}
|
||||||
|
templateId= {"${props.templateId}"}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
`
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
const angularCode = [
|
||||||
|
{
|
||||||
|
id: 0,
|
||||||
|
title: "Installation",
|
||||||
|
codeString: `
|
||||||
|
npm install @opensign/angular`
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
title: "Usage",
|
||||||
|
codeString: `
|
||||||
|
import { Component } from '@angular/core';
|
||||||
|
import {OpensignComponent} from "@opensign/angular"
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector:'app-root',
|
||||||
|
standalone: true,
|
||||||
|
imports: [OpensignComponent],
|
||||||
|
template: '<opensign templateId={"${props.templateId}"}
|
||||||
|
(onLoad)="handleLoad()"
|
||||||
|
(onLoadError)="handleError($event)"
|
||||||
|
></opensign>',
|
||||||
|
})
|
||||||
|
export class AppComponent{
|
||||||
|
handleLoad() {
|
||||||
|
console.log("success");
|
||||||
|
}
|
||||||
|
handleError(error: string) {
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
`
|
||||||
|
}
|
||||||
|
];
|
||||||
|
const jsCodeString = `
|
||||||
|
<script
|
||||||
|
src= "https://app.opensignlabs.com/static/js/public-template.bundle.js"
|
||||||
|
id="opensign-script"
|
||||||
|
templateId=${props.templateId}
|
||||||
|
></script>
|
||||||
|
`;
|
||||||
|
|
||||||
|
const handleCopy = (code, ind) => {
|
||||||
|
copytoData(code);
|
||||||
|
setIsCopied({ ...isCopied, [ind]: true });
|
||||||
|
setTimeout(() => setIsCopied(false), 3000);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="mt-4 border-t-[1px]">
|
||||||
|
<div className="flex justify-center items-center mt-2">
|
||||||
|
<div role="tablist" className="op-tabs op-tabs-bordered">
|
||||||
|
{tabName.map((tabData, ind) => (
|
||||||
|
<div
|
||||||
|
onClick={() => setActiveTab(ind)}
|
||||||
|
key={ind}
|
||||||
|
role="tab"
|
||||||
|
className={`${
|
||||||
|
activeTab === ind ? "op-tab-active" : ""
|
||||||
|
} op-tab flex items-center`}
|
||||||
|
>
|
||||||
|
<i
|
||||||
|
className={`${tabData.icon}`}
|
||||||
|
style={{ color: tabData.color }}
|
||||||
|
></i>
|
||||||
|
<span className="ml-1 text-[10px] font-medium md:font-normal md:text-[15px]">
|
||||||
|
{tabData.title}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
{activeTab === 0 ? (
|
||||||
|
<div className="mt-4">
|
||||||
|
{reactCode.map((data, ind) => {
|
||||||
|
return (
|
||||||
|
<div key={ind}>
|
||||||
|
<p className="font-medium text-[18px]">
|
||||||
|
{t(`${data.title}`)}
|
||||||
|
</p>
|
||||||
|
<p className="text-[13px] mt-2">
|
||||||
|
{t("public-template-mssg-1")}
|
||||||
|
</p>
|
||||||
|
<div className="relative p-1">
|
||||||
|
<div
|
||||||
|
onClick={() => handleCopy(data.codeString, ind)}
|
||||||
|
className="absolute top-[20px] right-[20px] cursor-pointer"
|
||||||
|
>
|
||||||
|
<i className="fa-light fa-copy text-white mr-[2px]" />
|
||||||
|
<span className=" text-white">
|
||||||
|
{isCopied[ind] ? t("copied-code") : t("copy-code")}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<SyntaxHighlighter
|
||||||
|
customStyle={{
|
||||||
|
borderRadius: "15px"
|
||||||
|
}}
|
||||||
|
language="javascript"
|
||||||
|
style={tomorrow}
|
||||||
|
>
|
||||||
|
{data.codeString}
|
||||||
|
</SyntaxHighlighter>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
|
||||||
|
<p className="font-medium text-[15px]">
|
||||||
|
{t("public-template-mssg-3")}
|
||||||
|
</p>
|
||||||
|
<p className="my-[6px]">
|
||||||
|
{" "}
|
||||||
|
{t("public-template-mssg-4")}
|
||||||
|
<a
|
||||||
|
href="https://www.npmjs.com/package/@opensign/react"
|
||||||
|
target="_blank"
|
||||||
|
rel="noreferrer"
|
||||||
|
className="cursor-pointer text-blue-700 "
|
||||||
|
>
|
||||||
|
{" "}
|
||||||
|
OpenSign React package{" "}
|
||||||
|
</a>
|
||||||
|
{t("public-template-mssg-5")}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
) : activeTab === 1 ? (
|
||||||
|
<div className="mt-4">
|
||||||
|
<div>
|
||||||
|
{/* <p className="font-medium text-[18px]">{t(`${data.title}`)}</p> */}
|
||||||
|
|
||||||
|
<div className="relative p-1">
|
||||||
|
<div
|
||||||
|
onClick={() => handleCopy(jsCodeString, 0)}
|
||||||
|
className="absolute top-[20px] right-[20px] cursor-pointer"
|
||||||
|
>
|
||||||
|
<i className="fa-light fa-copy text-white mr-[2px]" />
|
||||||
|
<span className=" text-white">
|
||||||
|
{isCopied[0] ? t("copied-code") : t("copy-code")}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<SyntaxHighlighter
|
||||||
|
customStyle={{
|
||||||
|
borderRadius: "15px"
|
||||||
|
}}
|
||||||
|
language="javascript"
|
||||||
|
style={tomorrow}
|
||||||
|
>
|
||||||
|
{jsCodeString}
|
||||||
|
</SyntaxHighlighter>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
activeTab === 2 && (
|
||||||
|
<div className="mt-4">
|
||||||
|
{angularCode.map((data, ind) => {
|
||||||
|
return (
|
||||||
|
<div key={ind}>
|
||||||
|
<p className="font-medium text-[18px]">
|
||||||
|
{t(`${data.title}`)}
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p className="text-[13px] mt-2">
|
||||||
|
{t("angular-npm-mssg-1")}
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div className="relative p-1">
|
||||||
|
<div
|
||||||
|
onClick={() => handleCopy(data.codeString, ind)}
|
||||||
|
className="absolute top-[20px] right-[20px] cursor-pointer"
|
||||||
|
>
|
||||||
|
<i className="fa-light fa-copy text-white mr-[2px]" />
|
||||||
|
<span className=" text-white">
|
||||||
|
{isCopied[ind] ? t("copied-code") : t("copy-code")}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<SyntaxHighlighter
|
||||||
|
customStyle={{
|
||||||
|
borderRadius: "15px"
|
||||||
|
}}
|
||||||
|
language="javascript"
|
||||||
|
style={tomorrow}
|
||||||
|
>
|
||||||
|
{data.codeString}
|
||||||
|
</SyntaxHighlighter>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
|
||||||
|
<p className="font-medium text-[15px]">
|
||||||
|
{t("public-template-mssg-3")}
|
||||||
|
</p>
|
||||||
|
<p className="my-[6px]">
|
||||||
|
{" "}
|
||||||
|
{t("public-template-mssg-4")}
|
||||||
|
<a
|
||||||
|
href="https://www.npmjs.com/package/@opensign/angular"
|
||||||
|
target="_blank"
|
||||||
|
rel="noreferrer"
|
||||||
|
className="cursor-pointer text-blue-700 "
|
||||||
|
>
|
||||||
|
{" "}
|
||||||
|
OpenSign Angular package{" "}
|
||||||
|
</a>
|
||||||
|
{t("public-template-mssg-5")}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default EmbedTab;
|
||||||
@@ -39,7 +39,8 @@ function Header({
|
|||||||
clickOnZoomOut,
|
clickOnZoomOut,
|
||||||
handleRotationFun,
|
handleRotationFun,
|
||||||
isDisableRotate,
|
isDisableRotate,
|
||||||
templateId
|
templateId,
|
||||||
|
setIsDownloadModal
|
||||||
}) {
|
}) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const filterPrefill =
|
const filterPrefill =
|
||||||
@@ -94,9 +95,13 @@ function Header({
|
|||||||
>
|
>
|
||||||
<DropdownMenu.Item
|
<DropdownMenu.Item
|
||||||
className="DropdownMenuItem"
|
className="DropdownMenuItem"
|
||||||
onClick={() =>
|
onClick={() => {
|
||||||
handleDownloadPdf(pdfDetails, pdfUrl, setIsDownloading)
|
if (isCompleted) {
|
||||||
}
|
setIsDownloadModal(true);
|
||||||
|
} else {
|
||||||
|
handleDownloadPdf(pdfDetails, setIsDownloading);
|
||||||
|
}
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<div className="flex flex-row">
|
<div className="flex flex-row">
|
||||||
<i
|
<i
|
||||||
@@ -209,57 +214,67 @@ function Header({
|
|||||||
sideOffset={5}
|
sideOffset={5}
|
||||||
>
|
>
|
||||||
<DropdownMenu.Item
|
<DropdownMenu.Item
|
||||||
className="flex flex-row justify-center items-center text-[13px] focus:outline-none cursor-pointer"
|
className="DropdownMenuItem"
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
handleDownloadPdf(
|
handleDownloadPdf(pdfDetails, setIsDownloading)
|
||||||
pdfDetails,
|
|
||||||
pdfDetails[0]?.URL,
|
|
||||||
setIsDownloading
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<i
|
<div className="flex flex-row">
|
||||||
className="fa-light fa-arrow-down mr-[3px]"
|
<i
|
||||||
aria-hidden="true"
|
className="fa-light fa-arrow-down mr-[3px]"
|
||||||
></i>
|
aria-hidden="true"
|
||||||
<span className="font-[500]">{t("download")}</span>
|
></i>
|
||||||
|
<span className="font-[500]">
|
||||||
|
{t("download")}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
</DropdownMenu.Item>
|
</DropdownMenu.Item>
|
||||||
{!isDisableRotate && (
|
{!isDisableRotate && (
|
||||||
<>
|
<>
|
||||||
<DropdownMenu.Item
|
<DropdownMenu.Item
|
||||||
className="flex flex-row justify-center items-center text-[13px] focus:outline-none cursor-pointer"
|
className="DropdownMenuItem"
|
||||||
onClick={() => handleRotationFun(90)}
|
onClick={() => handleRotationFun(90)}
|
||||||
>
|
>
|
||||||
<i className="fa-light fa-rotate-right text-gray-500 2xl:text-[30px] mr-[3px]"></i>
|
<div className="flex flex-row">
|
||||||
<span className="font-[500]">
|
<i className="fa-light fa-rotate-right text-gray-500 2xl:text-[30px] mr-[3px]"></i>
|
||||||
{t("rotate-right")}
|
<span className="font-[500]">
|
||||||
</span>
|
{t("rotate-right")}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
</DropdownMenu.Item>
|
</DropdownMenu.Item>
|
||||||
<DropdownMenu.Item
|
<DropdownMenu.Item
|
||||||
className="flex flex-row justify-center items-center text-[13px] focus:outline-none cursor-pointer"
|
className="DropdownMenuItem"
|
||||||
onClick={() => handleRotationFun(-90)}
|
onClick={() => handleRotationFun(-90)}
|
||||||
>
|
>
|
||||||
<i className="fa-light fa-rotate-left text-gray-500 2xl:text-[30px] mr-[3px]"></i>
|
<div className="flex flex-row">
|
||||||
<span className="font-[500]">
|
<i className="fa-light fa-rotate-left text-gray-500 2xl:text-[30px] mr-[3px]"></i>
|
||||||
{t("rotate-left")}
|
<span className="font-[500]">
|
||||||
</span>
|
{t("rotate-left")}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
</DropdownMenu.Item>
|
</DropdownMenu.Item>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<DropdownMenu.Item
|
<DropdownMenu.Item
|
||||||
className="flex flex-row justify-center items-center text-[13px] focus:outline-none cursor-pointer"
|
className="DropdownMenuItem"
|
||||||
onClick={() => clickOnZoomIn()}
|
onClick={() => clickOnZoomIn()}
|
||||||
>
|
>
|
||||||
<i className="fa-light fa-magnifying-glass-plus text-gray-500 2xl:text-[30px]"></i>
|
<div className="flex flex-row">
|
||||||
<span className="font-[500]">{t("zoom-in")}</span>
|
<i className="fa-light fa-magnifying-glass-plus text-gray-500 2xl:text-[30px] mr-[3px]"></i>
|
||||||
|
<span className="font-[500]">{t("zoom-in")}</span>
|
||||||
|
</div>
|
||||||
</DropdownMenu.Item>
|
</DropdownMenu.Item>
|
||||||
<DropdownMenu.Item
|
<DropdownMenu.Item
|
||||||
className="flex flex-row justify-center items-center text-[13px] focus:outline-none cursor-pointer"
|
className="DropdownMenuItem"
|
||||||
onClick={() => clickOnZoomOut()}
|
onClick={() => clickOnZoomOut()}
|
||||||
>
|
>
|
||||||
<i className="fa-light fa-magnifying-glass-minus text-gray-500 2xl:text-[30px]"></i>
|
<div className="flex flex-row">
|
||||||
<span className="font-[500]">{t("zoom-out")}</span>
|
<i className="fa-light fa-magnifying-glass-minus text-gray-500 2xl:text-[30px] mr-[3px]"></i>
|
||||||
|
<span className="font-[500]">
|
||||||
|
{t("zoom-out")}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
</DropdownMenu.Item>
|
</DropdownMenu.Item>
|
||||||
</DropdownMenu.Content>
|
</DropdownMenu.Content>
|
||||||
</DropdownMenu.Portal>
|
</DropdownMenu.Portal>
|
||||||
@@ -372,9 +387,13 @@ function Header({
|
|||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className="op-btn op-btn-primary op-btn-sm mr-[3px] shadow"
|
className="op-btn op-btn-primary op-btn-sm mr-[3px] shadow"
|
||||||
onClick={() =>
|
onClick={() => {
|
||||||
handleDownloadPdf(pdfDetails, pdfUrl, setIsDownloading)
|
if (isCompleted) {
|
||||||
}
|
setIsDownloadModal(true);
|
||||||
|
} else {
|
||||||
|
handleDownloadPdf(pdfDetails, setIsDownloading);
|
||||||
|
}
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<i
|
<i
|
||||||
className="fa-light fa-download py-[3px]"
|
className="fa-light fa-download py-[3px]"
|
||||||
@@ -429,11 +448,7 @@ function Header({
|
|||||||
type="button"
|
type="button"
|
||||||
className="op-btn op-btn-neutral op-btn-sm mr-[3px] shadow"
|
className="op-btn op-btn-neutral op-btn-sm mr-[3px] shadow"
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
handleDownloadPdf(
|
handleDownloadPdf(pdfDetails, setIsDownloading)
|
||||||
pdfDetails,
|
|
||||||
pdfUrl,
|
|
||||||
setIsDownloading
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<i className="fa-light fa-arrow-down font-semibold lg:hidden"></i>
|
<i className="fa-light fa-arrow-down font-semibold lg:hidden"></i>
|
||||||
@@ -473,9 +488,9 @@ function Header({
|
|||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className="op-btn op-btn-primary op-btn-sm gap-0 font-medium text-[12px] mr-[3px] shadow"
|
className="op-btn op-btn-primary op-btn-sm gap-0 font-medium text-[12px] mr-[3px] shadow"
|
||||||
onClick={() =>
|
onClick={() => {
|
||||||
handleDownloadPdf(pdfDetails, pdfUrl, setIsDownloading)
|
setIsDownloadModal(true);
|
||||||
}
|
}}
|
||||||
>
|
>
|
||||||
<i className="fa-light fa-download" aria-hidden="true"></i>
|
<i className="fa-light fa-download" aria-hidden="true"></i>
|
||||||
<span className="hidden lg:block ml-1">{t("download")}</span>
|
<span className="hidden lg:block ml-1">{t("download")}</span>
|
||||||
|
|||||||
@@ -33,14 +33,15 @@ export const openInNewTab = (url, target) => {
|
|||||||
export async function fetchSubscription(
|
export async function fetchSubscription(
|
||||||
extUserId,
|
extUserId,
|
||||||
contactObjId,
|
contactObjId,
|
||||||
isGuestSign = false
|
isGuestSign = false,
|
||||||
|
isPublic = false
|
||||||
) {
|
) {
|
||||||
try {
|
try {
|
||||||
const Extand_Class = localStorage.getItem("Extand_Class");
|
const Extand_Class = localStorage.getItem("Extand_Class");
|
||||||
const extClass = Extand_Class && JSON.parse(Extand_Class);
|
const extClass = Extand_Class && JSON.parse(Extand_Class);
|
||||||
// console.log("extClass ", extClass);
|
// console.log("extClass ", extClass);
|
||||||
let extUser;
|
let extUser;
|
||||||
if (extClass && extClass.length > 0) {
|
if (extClass && extClass.length > 0 && !isPublic) {
|
||||||
extUser = extClass[0].objectId;
|
extUser = extClass[0].objectId;
|
||||||
} else {
|
} else {
|
||||||
extUser = extUserId;
|
extUser = extUserId;
|
||||||
@@ -54,7 +55,7 @@ export async function fetchSubscription(
|
|||||||
};
|
};
|
||||||
const params = isGuestSign
|
const params = isGuestSign
|
||||||
? { contactId: contactObjId }
|
? { contactId: contactObjId }
|
||||||
: { extUserId: extUser };
|
: { extUserId: extUser, ispublic: isPublic };
|
||||||
const tenatRes = await axios.post(url, params, { headers: headers });
|
const tenatRes = await axios.post(url, params, { headers: headers });
|
||||||
let plan, status, billingDate, adminId;
|
let plan, status, billingDate, adminId;
|
||||||
if (isGuestSign) {
|
if (isGuestSign) {
|
||||||
@@ -2038,31 +2039,32 @@ export const fetchUrl = async (url, pdfName) => {
|
|||||||
console.error("Error downloading the file:", error);
|
console.error("Error downloading the file:", error);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
export const getSignedUrl = async (pdfUrl, docId) => {
|
||||||
|
//use only axios here due to public template sign
|
||||||
|
const axiosRes = await axios.post(
|
||||||
|
`${localStorage.getItem("baseUrl")}/functions/getsignedurl`,
|
||||||
|
{ url: pdfUrl, docId: docId || "" },
|
||||||
|
{
|
||||||
|
headers: {
|
||||||
|
"content-type": "Application/json",
|
||||||
|
"X-Parse-Application-Id": localStorage.getItem("parseAppId"),
|
||||||
|
"X-Parse-Session-Token": localStorage.getItem("accesstoken")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
const url = axiosRes.data.result;
|
||||||
|
return url;
|
||||||
|
};
|
||||||
//handle download signed pdf
|
//handle download signed pdf
|
||||||
export const handleDownloadPdf = async (
|
export const handleDownloadPdf = async (pdfDetails, setIsDownloading) => {
|
||||||
pdfDetails,
|
const pdfName = pdfDetails[0] && pdfDetails[0]?.Name;
|
||||||
pdfUrl,
|
const pdfUrl = pdfDetails?.[0]?.SignedUrl || pdfDetails?.[0]?.URL;
|
||||||
setIsDownloading
|
setIsDownloading && setIsDownloading("pdf");
|
||||||
) => {
|
|
||||||
const pdfName = pdfDetails[0] && pdfDetails[0].Name;
|
|
||||||
setIsDownloading("pdf");
|
|
||||||
const docId = !pdfDetails?.[0]?.IsEnableOTP ? pdfDetails?.[0]?.objectId : "";
|
const docId = !pdfDetails?.[0]?.IsEnableOTP ? pdfDetails?.[0]?.objectId : "";
|
||||||
try {
|
try {
|
||||||
// const url = await Parse.Cloud.run("getsignedurl", { url: pdfUrl });
|
const url = await getSignedUrl(pdfUrl, docId);
|
||||||
const axiosRes = await axios.post(
|
|
||||||
`${localStorage.getItem("baseUrl")}/functions/getsignedurl`,
|
|
||||||
{ url: pdfUrl, docId: docId },
|
|
||||||
{
|
|
||||||
headers: {
|
|
||||||
"content-type": "Application/json",
|
|
||||||
"X-Parse-Application-Id": localStorage.getItem("parseAppId"),
|
|
||||||
"X-Parse-Session-Token": localStorage.getItem("accesstoken")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
const url = axiosRes.data.result;
|
|
||||||
await fetchUrl(url, pdfName);
|
await fetchUrl(url, pdfName);
|
||||||
setIsDownloading("");
|
setIsDownloading && setIsDownloading("");
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.log("err in getsignedurl", err);
|
console.log("err in getsignedurl", err);
|
||||||
setIsDownloading("");
|
setIsDownloading("");
|
||||||
@@ -2130,13 +2132,18 @@ export const handleToPrint = async (
|
|||||||
//handle download signed pdf
|
//handle download signed pdf
|
||||||
export const handleDownloadCertificate = async (
|
export const handleDownloadCertificate = async (
|
||||||
pdfDetails,
|
pdfDetails,
|
||||||
setIsDownloading
|
setIsDownloading,
|
||||||
|
isZip
|
||||||
) => {
|
) => {
|
||||||
if (pdfDetails?.length > 0 && pdfDetails[0]?.CertificateUrl) {
|
if (pdfDetails?.length > 0 && pdfDetails[0]?.CertificateUrl) {
|
||||||
try {
|
try {
|
||||||
await fetch(pdfDetails[0] && pdfDetails[0]?.CertificateUrl);
|
await fetch(pdfDetails[0] && pdfDetails[0]?.CertificateUrl);
|
||||||
const certificateUrl = pdfDetails[0] && pdfDetails[0]?.CertificateUrl;
|
const certificateUrl = pdfDetails[0] && pdfDetails[0]?.CertificateUrl;
|
||||||
saveAs(certificateUrl, `Certificate_signed_by_OpenSign™.pdf`);
|
if (isZip) {
|
||||||
|
return certificateUrl;
|
||||||
|
} else {
|
||||||
|
saveAs(certificateUrl, `Certificate_signed_by_OpenSign™.pdf`);
|
||||||
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.log("err in download in certificate", err);
|
console.log("err in download in certificate", err);
|
||||||
}
|
}
|
||||||
@@ -2162,7 +2169,13 @@ export const handleDownloadCertificate = async (
|
|||||||
if (doc?.CertificateUrl) {
|
if (doc?.CertificateUrl) {
|
||||||
await fetch(doc?.CertificateUrl);
|
await fetch(doc?.CertificateUrl);
|
||||||
const certificateUrl = doc?.CertificateUrl;
|
const certificateUrl = doc?.CertificateUrl;
|
||||||
saveAs(certificateUrl, `Certificate_signed_by_OpenSign™.pdf`);
|
if (isZip) {
|
||||||
|
setIsDownloading("");
|
||||||
|
return certificateUrl;
|
||||||
|
} else {
|
||||||
|
saveAs(certificateUrl, `Certificate_signed_by_OpenSign™.pdf`);
|
||||||
|
}
|
||||||
|
|
||||||
setIsDownloading("");
|
setIsDownloading("");
|
||||||
} else {
|
} else {
|
||||||
setIsDownloading("certificate");
|
setIsDownloading("certificate");
|
||||||
@@ -2462,3 +2475,45 @@ export const handleRotateWarning = (signerPos, pageNumber) => {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// `generateTitleFromFilename` to generate Title of document from file name
|
||||||
|
export function generateTitleFromFilename(filename) {
|
||||||
|
try {
|
||||||
|
// Step 1: Trim whitespace
|
||||||
|
let title = filename.trim();
|
||||||
|
|
||||||
|
// Step 2: Remove the file extension (everything after the last '.')
|
||||||
|
const lastDotIndex = title.lastIndexOf(".");
|
||||||
|
if (lastDotIndex > 0) {
|
||||||
|
title = title.substring(0, lastDotIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step 3: Replace special characters (except Unicode letters, digits, spaces, and hyphens)
|
||||||
|
title = title.replace(/[^\p{L}\p{N}\s-]/gu, " ");
|
||||||
|
|
||||||
|
// Step 4: Replace multiple spaces with a single space
|
||||||
|
title = title.replace(/\s+/g, " ");
|
||||||
|
|
||||||
|
// Step 5: Capitalize first letter of each word (Title Case), handling Unicode characters
|
||||||
|
title = title.replace(
|
||||||
|
/\p{L}\S*/gu,
|
||||||
|
(txt) => txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase()
|
||||||
|
);
|
||||||
|
|
||||||
|
// Step 6: Restrict length of title (optional, let's say 100 characters)
|
||||||
|
if (title.length > 100) {
|
||||||
|
title = title.substring(0, 100).trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step 7: Handle empty or invalid title by falling back to "Untitled Document"
|
||||||
|
if (!title || title.length === 0) {
|
||||||
|
return "Untitled Document";
|
||||||
|
}
|
||||||
|
|
||||||
|
return title;
|
||||||
|
} catch (error) {
|
||||||
|
// Handle unexpected errors gracefully by returning a default title
|
||||||
|
console.error("Error generating title from filename:", error);
|
||||||
|
return "Untitled Document";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import { isEnableSubscription } from "../constant/const";
|
||||||
|
|
||||||
export default function reportJson(id) {
|
export default function reportJson(id) {
|
||||||
// console.log("json ", json);
|
// console.log("json ", json);
|
||||||
const head = ["Sr.No", "Title", "Note", "Folder", "File", "Owner", "Signers"];
|
const head = ["Sr.No", "Title", "Note", "Folder", "File", "Owner", "Signers"];
|
||||||
@@ -10,9 +12,36 @@ export default function reportJson(id) {
|
|||||||
"Owner",
|
"Owner",
|
||||||
"Signers"
|
"Signers"
|
||||||
];
|
];
|
||||||
|
const iphead = [
|
||||||
|
"Sr.No",
|
||||||
|
"Title",
|
||||||
|
"Note",
|
||||||
|
"Folder",
|
||||||
|
"File",
|
||||||
|
"Status",
|
||||||
|
"Signers"
|
||||||
|
];
|
||||||
const contactbook = ["Sr.No", "Name", "Email", "Phone"];
|
const contactbook = ["Sr.No", "Name", "Email", "Phone"];
|
||||||
const dashboardReportHead = ["Title", "File", "Owner", "Signers"];
|
const dashboardReportHead = ["Title", "File", "Owner", "Signers"];
|
||||||
const templateReport = ["Sr.No", "Title", "File", "Owner", "Signers"];
|
const templateReport = ["Sr.No", "Title", "File", "Owner", "Signers"];
|
||||||
|
const templateSubAction = isEnableSubscription
|
||||||
|
? [
|
||||||
|
{
|
||||||
|
btnId: "2434",
|
||||||
|
btnLabel: "Embed",
|
||||||
|
hoverLabel: "Embed",
|
||||||
|
btnIcon: "fa-light fa-code",
|
||||||
|
action: "Embed"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
btnId: "2434",
|
||||||
|
btnLabel: "Copy TemplateId",
|
||||||
|
hoverLabel: "Copy TemplateId",
|
||||||
|
btnIcon: "fa-light fa-copy",
|
||||||
|
action: "CopyTemplateId"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
: [];
|
||||||
switch (id) {
|
switch (id) {
|
||||||
// draft documents report
|
// draft documents report
|
||||||
case "ByHuevtCFY":
|
case "ByHuevtCFY":
|
||||||
@@ -63,7 +92,7 @@ export default function reportJson(id) {
|
|||||||
case "1MwEuxLEkF":
|
case "1MwEuxLEkF":
|
||||||
return {
|
return {
|
||||||
reportName: "In-progress documents",
|
reportName: "In-progress documents",
|
||||||
heading: head,
|
heading: iphead,
|
||||||
actions: [
|
actions: [
|
||||||
{
|
{
|
||||||
btnId: "8901",
|
btnId: "8901",
|
||||||
@@ -354,13 +383,7 @@ export default function reportJson(id) {
|
|||||||
redirectUrl: "template",
|
redirectUrl: "template",
|
||||||
action: "redirect"
|
action: "redirect"
|
||||||
},
|
},
|
||||||
{
|
...templateSubAction,
|
||||||
btnId: "2434",
|
|
||||||
btnLabel: "Embed",
|
|
||||||
hoverLabel: "Embed",
|
|
||||||
btnIcon: "fa-light fa-code",
|
|
||||||
action: "Embed"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
btnId: "1834",
|
btnId: "1834",
|
||||||
btnLabel: "Delete",
|
btnLabel: "Delete",
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ const DebugPdf = () => {
|
|||||||
|
|
||||||
const inferPdfType = async (pdf) => {
|
const inferPdfType = async (pdf) => {
|
||||||
try {
|
try {
|
||||||
const firstPage = await pdf.getPage(2);
|
const firstPage = await pdf.getPage(pdf?.numPages > 1 ? 2 : 1);
|
||||||
const scale = 1;
|
const scale = 1;
|
||||||
const { width, height } = firstPage.getViewport({ scale });
|
const { width, height } = firstPage.getViewport({ scale });
|
||||||
setPdfDimension({ width: width, height: height });
|
setPdfDimension({ width: width, height: height });
|
||||||
|
|||||||
@@ -9,7 +9,12 @@ import SignersInput from "../components/shared/fields/SignersInput";
|
|||||||
import Title from "../components/Title";
|
import Title from "../components/Title";
|
||||||
import PageNotFound from "./PageNotFound";
|
import PageNotFound from "./PageNotFound";
|
||||||
import { SaveFileSize } from "../constant/saveFileSize";
|
import { SaveFileSize } from "../constant/saveFileSize";
|
||||||
import { checkIsSubscribed, getFileName, toDataUrl } from "../constant/Utils";
|
import {
|
||||||
|
checkIsSubscribed,
|
||||||
|
generateTitleFromFilename,
|
||||||
|
getFileName,
|
||||||
|
toDataUrl
|
||||||
|
} from "../constant/Utils";
|
||||||
import { PDFDocument } from "pdf-lib";
|
import { PDFDocument } from "pdf-lib";
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import { isEnableSubscription } from "../constant/const";
|
import { isEnableSubscription } from "../constant/const";
|
||||||
@@ -143,7 +148,7 @@ const Forms = (props) => {
|
|||||||
setIsDecrypting(true);
|
setIsDecrypting(true);
|
||||||
const size = files?.[0].size;
|
const size = files?.[0].size;
|
||||||
const name = generatePdfName(16);
|
const name = generatePdfName(16);
|
||||||
const url = "https://ai.nxglabs.in/decryptpdf"; //"https://ai.nxglabs.in/decryptpdf"; //
|
const url = "https://ai.nxglabs.in/decryptpdf"; //
|
||||||
let formData = new FormData();
|
let formData = new FormData();
|
||||||
formData.append("file", files[0]);
|
formData.append("file", files[0]);
|
||||||
formData.append("password", "");
|
formData.append("password", "");
|
||||||
@@ -186,6 +191,9 @@ const Forms = (props) => {
|
|||||||
if (parseFile.url()) {
|
if (parseFile.url()) {
|
||||||
setFileUpload(parseFile.url());
|
setFileUpload(parseFile.url());
|
||||||
setfileload(false);
|
setfileload(false);
|
||||||
|
const title = generateTitleFromFilename(files?.[0]?.name);
|
||||||
|
setFormData((obj) => ({ ...obj, Name: title }));
|
||||||
|
SaveFileSize(size, response.url(), tenantId);
|
||||||
const tenantId = localStorage.getItem("TenantId");
|
const tenantId = localStorage.getItem("TenantId");
|
||||||
SaveFileSize(size, parseFile.url(), tenantId);
|
SaveFileSize(size, parseFile.url(), tenantId);
|
||||||
return parseFile.url();
|
return parseFile.url();
|
||||||
@@ -259,6 +267,8 @@ const Forms = (props) => {
|
|||||||
setfileload(false);
|
setfileload(false);
|
||||||
if (response.url()) {
|
if (response.url()) {
|
||||||
const tenantId = localStorage.getItem("TenantId");
|
const tenantId = localStorage.getItem("TenantId");
|
||||||
|
const title = generateTitleFromFilename(files?.[0]?.name);
|
||||||
|
setFormData((obj) => ({ ...obj, Name: title }));
|
||||||
SaveFileSize(size, response.url(), tenantId);
|
SaveFileSize(size, response.url(), tenantId);
|
||||||
return response.url();
|
return response.url();
|
||||||
}
|
}
|
||||||
@@ -286,12 +296,17 @@ const Forms = (props) => {
|
|||||||
if (res.data) {
|
if (res.data) {
|
||||||
setFileUpload(res.data.url);
|
setFileUpload(res.data.url);
|
||||||
setfileload(false);
|
setfileload(false);
|
||||||
|
const title = generateTitleFromFilename(files?.[0]?.name);
|
||||||
|
setFormData((obj) => ({ ...obj, Name: title }));
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
e.target.value = "";
|
e.target.value = "";
|
||||||
setfileload(false);
|
setfileload(false);
|
||||||
setpercentage(0);
|
setpercentage(0);
|
||||||
console.log("err in libreconverter ", err);
|
console.log("err in libreconverter ", err);
|
||||||
|
alert(
|
||||||
|
"We are currently experiencing some issues with processing DOCX files. Please upload the PDF version or contact us on support@opensignlabs.com"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -330,6 +345,8 @@ const Forms = (props) => {
|
|||||||
setfileload(false);
|
setfileload(false);
|
||||||
if (response.url()) {
|
if (response.url()) {
|
||||||
const tenantId = localStorage.getItem("TenantId");
|
const tenantId = localStorage.getItem("TenantId");
|
||||||
|
const title = generateTitleFromFilename(file.name);
|
||||||
|
setFormData((obj) => ({ ...obj, Name: title }));
|
||||||
SaveFileSize(size, response.url(), tenantId);
|
SaveFileSize(size, response.url(), tenantId);
|
||||||
return response.url();
|
return response.url();
|
||||||
}
|
}
|
||||||
@@ -367,9 +384,10 @@ const Forms = (props) => {
|
|||||||
});
|
});
|
||||||
setFileUpload(response.url());
|
setFileUpload(response.url());
|
||||||
setfileload(false);
|
setfileload(false);
|
||||||
|
|
||||||
if (response.url()) {
|
if (response.url()) {
|
||||||
const tenantId = localStorage.getItem("TenantId");
|
const tenantId = localStorage.getItem("TenantId");
|
||||||
|
const title = generateTitleFromFilename(file.name);
|
||||||
|
setFormData((obj) => ({ ...obj, Name: title }));
|
||||||
SaveFileSize(size, response.url(), tenantId);
|
SaveFileSize(size, response.url(), tenantId);
|
||||||
return response.url();
|
return response.url();
|
||||||
}
|
}
|
||||||
@@ -548,6 +566,8 @@ const Forms = (props) => {
|
|||||||
setFormData((prev) => ({ ...prev, password: "" }));
|
setFormData((prev) => ({ ...prev, password: "" }));
|
||||||
setFileUpload(parseFile.url());
|
setFileUpload(parseFile.url());
|
||||||
setfileload(false);
|
setfileload(false);
|
||||||
|
const title = generateTitleFromFilename(formData?.file?.name);
|
||||||
|
setFormData((obj) => ({ ...obj, Name: title }));
|
||||||
const tenantId = localStorage.getItem("TenantId");
|
const tenantId = localStorage.getItem("TenantId");
|
||||||
SaveFileSize(size, parseFile.url(), tenantId);
|
SaveFileSize(size, parseFile.url(), tenantId);
|
||||||
return parseFile.url();
|
return parseFile.url();
|
||||||
@@ -827,7 +847,7 @@ const Forms = (props) => {
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{isAdvanceOpt && (
|
{isAdvanceOpt && (
|
||||||
<div className={` overflow-y-auto z-[500] transition-all`}>
|
<div className="overflow-y-auto z-[500] transition-all">
|
||||||
{props.title === "Request Signatures" && (
|
{props.title === "Request Signatures" && (
|
||||||
<div className="text-xs mt-2">
|
<div className="text-xs mt-2">
|
||||||
<label className="block">
|
<label className="block">
|
||||||
|
|||||||
@@ -28,7 +28,6 @@ import {
|
|||||||
contractUsers,
|
contractUsers,
|
||||||
handleSendOTP,
|
handleSendOTP,
|
||||||
contactBook,
|
contactBook,
|
||||||
handleDownloadPdf,
|
|
||||||
handleToPrint,
|
handleToPrint,
|
||||||
handleDownloadCertificate,
|
handleDownloadCertificate,
|
||||||
getDefaultSignature,
|
getDefaultSignature,
|
||||||
@@ -36,21 +35,23 @@ import {
|
|||||||
onClickZoomOut,
|
onClickZoomOut,
|
||||||
fetchUrl
|
fetchUrl
|
||||||
} from "../constant/Utils";
|
} from "../constant/Utils";
|
||||||
import LoaderWithMsg from "../primitives/LoaderWithMsg";
|
|
||||||
import HandleError from "../primitives/HandleError";
|
|
||||||
import Header from "../components/pdf/PdfHeader";
|
import Header from "../components/pdf/PdfHeader";
|
||||||
import RenderPdf from "../components/pdf/RenderPdf";
|
import RenderPdf from "../components/pdf/RenderPdf";
|
||||||
import PdfDeclineModal from "../primitives/PdfDeclineModal";
|
|
||||||
import Title from "../components/Title";
|
import Title from "../components/Title";
|
||||||
import DefaultSignature from "../components/pdf/DefaultSignature";
|
import DefaultSignature from "../components/pdf/DefaultSignature";
|
||||||
import ModalUi from "../primitives/ModalUi";
|
|
||||||
import TourContentWithBtn from "../primitives/TourContentWithBtn";
|
|
||||||
import Loader from "../primitives/Loader";
|
|
||||||
import { useSelector } from "react-redux";
|
import { useSelector } from "react-redux";
|
||||||
import SignerListComponent from "../components/pdf/SignerListComponent";
|
import SignerListComponent from "../components/pdf/SignerListComponent";
|
||||||
import VerifyEmail from "../components/pdf/VerifyEmail";
|
import VerifyEmail from "../components/pdf/VerifyEmail";
|
||||||
import PdfZoom from "../components/pdf/PdfZoom";
|
import PdfZoom from "../components/pdf/PdfZoom";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
|
import ModalUi from "../primitives/ModalUi";
|
||||||
|
import TourContentWithBtn from "../primitives/TourContentWithBtn";
|
||||||
|
import HandleError from "../primitives/HandleError";
|
||||||
|
import LoaderWithMsg from "../primitives/LoaderWithMsg";
|
||||||
|
import DownloadPdfZip from "../primitives/DownloadPdfZip";
|
||||||
|
import Loader from "../primitives/Loader";
|
||||||
|
import PdfDeclineModal from "../primitives/PdfDeclineModal";
|
||||||
|
import Agreement from "../primitives/Agreement";
|
||||||
|
|
||||||
function PdfRequestFiles(props) {
|
function PdfRequestFiles(props) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
@@ -136,6 +137,9 @@ function PdfRequestFiles(props) {
|
|||||||
const [plancode, setPlanCode] = useState("");
|
const [plancode, setPlanCode] = useState("");
|
||||||
const isHeader = useSelector((state) => state.showHeader);
|
const isHeader = useSelector((state) => state.showHeader);
|
||||||
const divRef = useRef(null);
|
const divRef = useRef(null);
|
||||||
|
const [isDownloadModal, setIsDownloadModal] = useState(false);
|
||||||
|
const [isAgree, setIsAgree] = useState(false);
|
||||||
|
const [isAgreeTour, setIsAgreeTour] = useState(false);
|
||||||
|
|
||||||
const isMobile = window.innerWidth < 767;
|
const isMobile = window.innerWidth < 767;
|
||||||
|
|
||||||
@@ -243,7 +247,13 @@ function PdfRequestFiles(props) {
|
|||||||
};
|
};
|
||||||
async function checkIsSubscribed(extUserId, contactId) {
|
async function checkIsSubscribed(extUserId, contactId) {
|
||||||
const isGuestSign = isGuestSignFlow || false;
|
const isGuestSign = isGuestSignFlow || false;
|
||||||
const res = await fetchSubscription(extUserId, contactId, isGuestSign);
|
const isPublic = props.templateId ? true : false;
|
||||||
|
const res = await fetchSubscription(
|
||||||
|
extUserId,
|
||||||
|
contactId,
|
||||||
|
isGuestSign,
|
||||||
|
isPublic
|
||||||
|
);
|
||||||
const plan = res.plan;
|
const plan = res.plan;
|
||||||
const billingDate = res?.billingDate;
|
const billingDate = res?.billingDate;
|
||||||
const status = res?.status;
|
const status = res?.status;
|
||||||
@@ -291,19 +301,21 @@ function PdfRequestFiles(props) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
const documentData =
|
const documentData = templateDeatils?.data?.result
|
||||||
templateDeatils.data && templateDeatils.data.result
|
? [templateDeatils?.data?.result]
|
||||||
? [templateDeatils.data.result]
|
: [];
|
||||||
: [];
|
|
||||||
if (documentData && documentData[0]?.error) {
|
if (documentData && documentData[0]?.error) {
|
||||||
props?.setTemplateStatus({
|
props?.setTemplateStatus &&
|
||||||
status: "Invalid"
|
props?.setTemplateStatus({
|
||||||
});
|
status: "Invalid"
|
||||||
|
});
|
||||||
|
throw new Error("error: Invalid TemplateId");
|
||||||
} else if (documentData && documentData.length > 0) {
|
} else if (documentData && documentData.length > 0) {
|
||||||
if (documentData[0]?.IsPublic) {
|
if (documentData[0]?.IsPublic) {
|
||||||
props?.setTemplateStatus({
|
props?.setTemplateStatus &&
|
||||||
status: "Success"
|
props?.setTemplateStatus({
|
||||||
});
|
status: "Success"
|
||||||
|
});
|
||||||
const url =
|
const url =
|
||||||
documentData[0] &&
|
documentData[0] &&
|
||||||
(documentData[0]?.SignedUrl || documentData[0]?.URL);
|
(documentData[0]?.SignedUrl || documentData[0]?.URL);
|
||||||
@@ -347,22 +359,34 @@ function PdfRequestFiles(props) {
|
|||||||
isLoad: false
|
isLoad: false
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
props?.setTemplateStatus({
|
props?.setTemplateStatus &&
|
||||||
status: "Private"
|
props?.setTemplateStatus({
|
||||||
});
|
status: "Private"
|
||||||
|
});
|
||||||
|
setIsLoading(false);
|
||||||
|
setHandleError(t("something-went-wrong-mssg"));
|
||||||
|
console.error("error: TemplateId is not public");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
props?.setTemplateStatus({
|
props?.setTemplateStatus &&
|
||||||
status: "Invalid"
|
props?.setTemplateStatus({
|
||||||
});
|
status: "Invalid"
|
||||||
|
});
|
||||||
|
setIsLoading(false);
|
||||||
|
setHandleError(t("something-went-wrong-mssg"));
|
||||||
|
console.error("error: Invalid TemplateId");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.log("err in get template details ", err);
|
setIsLoading(false);
|
||||||
if (err?.response?.data?.code === 101) {
|
if (err?.response?.data?.code === 101) {
|
||||||
setHandleError(t("error-template"));
|
setHandleError(t("error-template"));
|
||||||
} else {
|
} else {
|
||||||
setHandleError(t("something-went-wrong-mssg"));
|
setHandleError(t("something-went-wrong-mssg"));
|
||||||
}
|
}
|
||||||
|
console.error("error: Invalid TemplateId");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
//function for get document details for perticular signer with signer'object id
|
//function for get document details for perticular signer with signer'object id
|
||||||
@@ -1286,7 +1310,11 @@ function PdfRequestFiles(props) {
|
|||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
console.log("error updating field is decline ", err);
|
console.log("error updating field is decline ", err);
|
||||||
setIsUiLoading(false);
|
setIsUiLoading(false);
|
||||||
alert(t("something-went-wrong-mssg"));
|
setIsAlert({
|
||||||
|
title: "Error",
|
||||||
|
isShow: true,
|
||||||
|
alertMessage: t("something-went-wrong-mssg")
|
||||||
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
//function to add default signature for all requested placeholder of sign
|
//function to add default signature for all requested placeholder of sign
|
||||||
@@ -1487,11 +1515,32 @@ function PdfRequestFiles(props) {
|
|||||||
await SendOtp();
|
await SendOtp();
|
||||||
} else {
|
} else {
|
||||||
console.log("error in public-sign to create user details");
|
console.log("error in public-sign to create user details");
|
||||||
alert(t("something-went-wrong-mssg"));
|
setIsAlert({
|
||||||
|
title: "Error",
|
||||||
|
isShow: true,
|
||||||
|
alertMessage: t("something-went-wrong-mssg")
|
||||||
|
});
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log("e", e);
|
console.log("e", e);
|
||||||
// setIsLoader(false);
|
if (
|
||||||
|
e?.response?.data?.error === "Insufficient Credit" ||
|
||||||
|
e?.response?.data?.error === "Plan expired"
|
||||||
|
) {
|
||||||
|
handleCloseOtp();
|
||||||
|
setIsAlert({
|
||||||
|
title: t("insufficient-credits"),
|
||||||
|
isShow: true,
|
||||||
|
alertMessage: t("insufficient-credits-mssg")
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
handleCloseOtp();
|
||||||
|
setIsAlert({
|
||||||
|
title: "Error",
|
||||||
|
isShow: true,
|
||||||
|
alertMessage: t("something-went-wrong-mssg")
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1523,7 +1572,11 @@ function PdfRequestFiles(props) {
|
|||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log("error in verify otp in public-sign", error);
|
console.log("error in verify otp in public-sign", error);
|
||||||
alert(t("something-went-wrong-mssg"));
|
setIsAlert({
|
||||||
|
title: "Error",
|
||||||
|
isShow: true,
|
||||||
|
alertMessage: t("something-went-wrong-mssg")
|
||||||
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1622,6 +1675,17 @@ function PdfRequestFiles(props) {
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
const AgreementTour = [
|
||||||
|
{
|
||||||
|
selector: '[data-tut="IsAgree"]',
|
||||||
|
content: "Please agree & continue to start signing",
|
||||||
|
position: "top",
|
||||||
|
style: { fontSize: "13px" }
|
||||||
|
}
|
||||||
|
];
|
||||||
|
const handleCloseAgreeTour = () => {
|
||||||
|
setIsAgreeTour(false);
|
||||||
|
};
|
||||||
return (
|
return (
|
||||||
<DndProvider backend={HTML5Backend}>
|
<DndProvider backend={HTML5Backend}>
|
||||||
<Title title={props.templateId ? "Public Sign" : "Request Sign"} />
|
<Title title={props.templateId ? "Public Sign" : "Request Sign"} />
|
||||||
@@ -1644,7 +1708,23 @@ function PdfRequestFiles(props) {
|
|||||||
) : handleError ? (
|
) : handleError ? (
|
||||||
<HandleError handleError={handleError} />
|
<HandleError handleError={handleError} />
|
||||||
) : (
|
) : (
|
||||||
<div>
|
<div onClick={() => !isAgree && setIsAgreeTour(true)}>
|
||||||
|
{!isAgree && (
|
||||||
|
<Agreement
|
||||||
|
setIsAgree={setIsAgree}
|
||||||
|
setIsAgreeTour={setIsAgreeTour}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
<Tour
|
||||||
|
showNumber={false}
|
||||||
|
showNavigation={false}
|
||||||
|
showNavigationNumber={false}
|
||||||
|
onRequestClose={handleCloseAgreeTour}
|
||||||
|
steps={AgreementTour}
|
||||||
|
isOpen={isAgreeTour}
|
||||||
|
rounded={5}
|
||||||
|
closeWithMask={false}
|
||||||
|
/>
|
||||||
{isUiLoading && (
|
{isUiLoading && (
|
||||||
<div className="absolute h-[100vh] w-full flex flex-col justify-center items-center z-[999] bg-[#e6f2f2] bg-opacity-80">
|
<div className="absolute h-[100vh] w-full flex flex-col justify-center items-center z-[999] bg-[#e6f2f2] bg-opacity-80">
|
||||||
<Loader />
|
<Loader />
|
||||||
@@ -1658,9 +1738,12 @@ function PdfRequestFiles(props) {
|
|||||||
<Confetti
|
<Confetti
|
||||||
width={window.innerWidth}
|
width={window.innerWidth}
|
||||||
height={window.innerHeight}
|
height={window.innerHeight}
|
||||||
|
recycle={false} // Prevents confetti from repeating
|
||||||
|
gravity={0.1} // Adjust the gravity to control the speed
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
pointerEvents:
|
pointerEvents:
|
||||||
@@ -1670,33 +1753,13 @@ function PdfRequestFiles(props) {
|
|||||||
: "auto"
|
: "auto"
|
||||||
}}
|
}}
|
||||||
className={`${
|
className={`${
|
||||||
props.templateId && "m-1 border-[0.5px] border-gray-300"
|
(props.templateId || isGuestSignFlow) &&
|
||||||
|
"mx-2 border-[0.5px] border-gray-300"
|
||||||
} relative op-card overflow-hidden flex flex-col md:flex-row justify-between bg-base-300`}
|
} relative op-card overflow-hidden flex flex-col md:flex-row justify-between bg-base-300`}
|
||||||
>
|
>
|
||||||
{!requestSignTour &&
|
{!requestSignTour &&
|
||||||
signerObjectId &&
|
signerObjectId &&
|
||||||
requestSignTourFunction()}
|
requestSignTourFunction()}
|
||||||
<ModalUi
|
|
||||||
isOpen={isAlert.isShow}
|
|
||||||
title={t("alert-message")}
|
|
||||||
handleClose={() =>
|
|
||||||
setIsAlert({ isShow: false, alertMessage: "" })
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<div className="h-full p-[20px]">
|
|
||||||
<p>{isAlert.alertMessage}</p>
|
|
||||||
<button
|
|
||||||
onClick={() =>
|
|
||||||
setIsAlert({ isShow: false, alertMessage: "" })
|
|
||||||
}
|
|
||||||
type="button"
|
|
||||||
className="op-btn op-btn-primary mt-3 px-4"
|
|
||||||
>
|
|
||||||
{t("ok")}
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</ModalUi>
|
|
||||||
|
|
||||||
<Tour
|
<Tour
|
||||||
showNumber={false}
|
showNumber={false}
|
||||||
showNavigation={false}
|
showNavigation={false}
|
||||||
@@ -1993,13 +2056,13 @@ function PdfRequestFiles(props) {
|
|||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className="font-[500] text-[13px] mr-[5px] op-btn op-btn-primary"
|
className="font-[500] text-[13px] mr-[5px] op-btn op-btn-primary"
|
||||||
onClick={() =>
|
onClick={() => {
|
||||||
handleDownloadPdf(
|
setIsCompleted((prev) => ({
|
||||||
pdfDetails,
|
...prev,
|
||||||
pdfUrl,
|
isModal: false
|
||||||
setIsDownloading
|
}));
|
||||||
)
|
setIsDownloadModal(true);
|
||||||
}
|
}}
|
||||||
>
|
>
|
||||||
<i
|
<i
|
||||||
className="fa-light fa-download"
|
className="fa-light fa-download"
|
||||||
@@ -2079,6 +2142,7 @@ function PdfRequestFiles(props) {
|
|||||||
clickOnZoomOut={clickOnZoomOut}
|
clickOnZoomOut={clickOnZoomOut}
|
||||||
isDisableRotate={true}
|
isDisableRotate={true}
|
||||||
templateId={props.templateId}
|
templateId={props.templateId}
|
||||||
|
setIsDownloadModal={setIsDownloadModal}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div ref={divRef} data-tut="pdfArea" className="h-[95%]">
|
<div ref={divRef} data-tut="pdfArea" className="h-[95%]">
|
||||||
@@ -2205,6 +2269,28 @@ function PdfRequestFiles(props) {
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</ModalUi>
|
</ModalUi>
|
||||||
|
<DownloadPdfZip
|
||||||
|
setIsDownloadModal={setIsDownloadModal}
|
||||||
|
isDownloadModal={isDownloadModal}
|
||||||
|
pdfDetails={pdfDetails}
|
||||||
|
isDocId={true}
|
||||||
|
/>
|
||||||
|
<ModalUi
|
||||||
|
isOpen={isAlert.isShow}
|
||||||
|
title={isAlert?.title || t("alert-message")}
|
||||||
|
handleClose={() => setIsAlert({ isShow: false, alertMessage: "" })}
|
||||||
|
>
|
||||||
|
<div className="h-full p-[20px]">
|
||||||
|
<p>{isAlert.alertMessage}</p>
|
||||||
|
<button
|
||||||
|
onClick={() => setIsAlert({ isShow: false, alertMessage: "" })}
|
||||||
|
type="button"
|
||||||
|
className="op-btn op-btn-primary mt-3 px-4"
|
||||||
|
>
|
||||||
|
{t("close")}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</ModalUi>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</DndProvider>
|
</DndProvider>
|
||||||
|
|||||||
@@ -11,8 +11,6 @@ import RenderAllPdfPage from "../components/pdf/RenderAllPdfPage";
|
|||||||
import WidgetComponent from "../components/pdf/WidgetComponent";
|
import WidgetComponent from "../components/pdf/WidgetComponent";
|
||||||
import Tour from "reactour";
|
import Tour from "reactour";
|
||||||
import { useLocation, useParams } from "react-router-dom";
|
import { useLocation, useParams } from "react-router-dom";
|
||||||
import LoaderWithMsg from "../primitives/LoaderWithMsg";
|
|
||||||
import HandleError from "../primitives/HandleError";
|
|
||||||
import SignerListPlace from "../components/pdf/SignerListPlace";
|
import SignerListPlace from "../components/pdf/SignerListPlace";
|
||||||
import Header from "../components/pdf/PdfHeader";
|
import Header from "../components/pdf/PdfHeader";
|
||||||
import { RWebShare } from "react-web-share";
|
import { RWebShare } from "react-web-share";
|
||||||
@@ -45,23 +43,25 @@ import {
|
|||||||
import RenderPdf from "../components/pdf/RenderPdf";
|
import RenderPdf from "../components/pdf/RenderPdf";
|
||||||
import { useNavigate } from "react-router-dom";
|
import { useNavigate } from "react-router-dom";
|
||||||
import PlaceholderCopy from "../components/pdf/PlaceholderCopy";
|
import PlaceholderCopy from "../components/pdf/PlaceholderCopy";
|
||||||
import LinkUserModal from "../primitives/LinkUserModal";
|
|
||||||
import Title from "../components/Title";
|
import Title from "../components/Title";
|
||||||
import TourContentWithBtn from "../primitives/TourContentWithBtn";
|
|
||||||
import ModalUi from "../primitives/ModalUi";
|
|
||||||
import DropdownWidgetOption from "../components/pdf/DropdownWidgetOption";
|
import DropdownWidgetOption from "../components/pdf/DropdownWidgetOption";
|
||||||
import WidgetNameModal from "../components/pdf/WidgetNameModal";
|
import WidgetNameModal from "../components/pdf/WidgetNameModal";
|
||||||
import { SaveFileSize } from "../constant/saveFileSize";
|
import { SaveFileSize } from "../constant/saveFileSize";
|
||||||
import { EmailBody } from "../components/pdf/EmailBody";
|
import { EmailBody } from "../components/pdf/EmailBody";
|
||||||
import Upgrade from "../primitives/Upgrade";
|
|
||||||
import Alert from "../primitives/Alert";
|
|
||||||
import Loader from "../primitives/Loader";
|
|
||||||
import { useSelector } from "react-redux";
|
import { useSelector } from "react-redux";
|
||||||
import PdfZoom from "../components/pdf/PdfZoom";
|
import PdfZoom from "../components/pdf/PdfZoom";
|
||||||
import LottieWithLoader from "../primitives/DotLottieReact";
|
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import RotateAlert from "../components/RotateAlert";
|
import RotateAlert from "../components/RotateAlert";
|
||||||
|
import Loader from "../primitives/Loader";
|
||||||
|
import ModalUi from "../primitives/ModalUi";
|
||||||
|
import TourContentWithBtn from "../primitives/TourContentWithBtn";
|
||||||
|
import HandleError from "../primitives/HandleError";
|
||||||
|
import LoaderWithMsg from "../primitives/LoaderWithMsg";
|
||||||
|
import LinkUserModal from "../primitives/LinkUserModal";
|
||||||
import QuotaCard from "../primitives/QuotaCard";
|
import QuotaCard from "../primitives/QuotaCard";
|
||||||
|
import LottieWithLoader from "../primitives/DotLottieReact";
|
||||||
|
import Alert from "../primitives/Alert";
|
||||||
|
import Upgrade from "../primitives/Upgrade";
|
||||||
|
|
||||||
function PlaceHolderSign() {
|
function PlaceHolderSign() {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
@@ -1047,7 +1047,7 @@ function PlaceHolderSign() {
|
|||||||
type="button"
|
type="button"
|
||||||
className="flex flex-row items-center op-link op-link-primary"
|
className="flex flex-row items-center op-link op-link-primary"
|
||||||
>
|
>
|
||||||
<i className="fa-light fa-link" aria-hidden="true"></i>
|
<i className="fa-light fa-copy" />
|
||||||
<span className=" hidden md:block ml-1 ">{t("copy-link")}</span>
|
<span className=" hidden md:block ml-1 ">{t("copy-link")}</span>
|
||||||
</button>
|
</button>
|
||||||
<RWebShare data={{ url: data.url, title: t("sign-url") }}>
|
<RWebShare data={{ url: data.url, title: t("sign-url") }}>
|
||||||
@@ -1250,7 +1250,7 @@ function PlaceHolderSign() {
|
|||||||
selector: '[data-tut="addWidgets"]',
|
selector: '[data-tut="addWidgets"]',
|
||||||
content: () => (
|
content: () => (
|
||||||
<TourContentWithBtn
|
<TourContentWithBtn
|
||||||
message={t("tour-mssg.placeholder-sign-3")}
|
message={t("tour-mssg.placeholder-sign-4")}
|
||||||
isChecked={handleDontShow}
|
isChecked={handleDontShow}
|
||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
@@ -1261,19 +1261,18 @@ function PlaceHolderSign() {
|
|||||||
selector: '[data-tut="pdfArea"]',
|
selector: '[data-tut="pdfArea"]',
|
||||||
content: () => (
|
content: () => (
|
||||||
<TourContentWithBtn
|
<TourContentWithBtn
|
||||||
message={t("tour-mssg.placeholder-sign-4")}
|
message={t("tour-mssg.placeholder-sign-5")}
|
||||||
isChecked={handleDontShow}
|
isChecked={handleDontShow}
|
||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
position: "top",
|
position: "top",
|
||||||
style: { fontSize: "13px" }
|
style: { fontSize: "13px" }
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
selector: '[data-tut="headerArea"]',
|
selector: '[data-tut="headerArea"]',
|
||||||
content: () => (
|
content: () => (
|
||||||
<TourContentWithBtn
|
<TourContentWithBtn
|
||||||
message={t("tour-mssg.placeholder-sign-5")}
|
message={t("tour-mssg.placeholder-sign-6")}
|
||||||
isChecked={handleDontShow}
|
isChecked={handleDontShow}
|
||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import "../styles/signature.css";
|
|||||||
import Parse from "parse";
|
import Parse from "parse";
|
||||||
import Confetti from "react-confetti";
|
import Confetti from "react-confetti";
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import LoaderWithMsg from "../primitives/LoaderWithMsg";
|
|
||||||
import RenderAllPdfPage from "../components/pdf/RenderAllPdfPage";
|
import RenderAllPdfPage from "../components/pdf/RenderAllPdfPage";
|
||||||
import { DndProvider } from "react-dnd";
|
import { DndProvider } from "react-dnd";
|
||||||
import { HTML5Backend } from "react-dnd-html5-backend";
|
import { HTML5Backend } from "react-dnd-html5-backend";
|
||||||
@@ -42,21 +41,23 @@ import {
|
|||||||
import { useParams } from "react-router-dom";
|
import { useParams } from "react-router-dom";
|
||||||
import Tour from "reactour";
|
import Tour from "reactour";
|
||||||
import Signedby from "../components/pdf/Signedby";
|
import Signedby from "../components/pdf/Signedby";
|
||||||
import HandleError from "../primitives/HandleError";
|
|
||||||
import Header from "../components/pdf/PdfHeader";
|
import Header from "../components/pdf/PdfHeader";
|
||||||
import RenderPdf from "../components/pdf/RenderPdf";
|
import RenderPdf from "../components/pdf/RenderPdf";
|
||||||
import PlaceholderCopy from "../components/pdf/PlaceholderCopy";
|
import PlaceholderCopy from "../components/pdf/PlaceholderCopy";
|
||||||
import TourContentWithBtn from "../primitives/TourContentWithBtn";
|
|
||||||
import Title from "../components/Title";
|
import Title from "../components/Title";
|
||||||
import ModalUi from "../primitives/ModalUi";
|
|
||||||
import DropdownWidgetOption from "../components/pdf/DropdownWidgetOption";
|
import DropdownWidgetOption from "../components/pdf/DropdownWidgetOption";
|
||||||
import { useSelector } from "react-redux";
|
import { useSelector } from "react-redux";
|
||||||
import TextFontSetting from "../components/pdf/TextFontSetting";
|
import TextFontSetting from "../components/pdf/TextFontSetting";
|
||||||
import VerifyEmail from "../components/pdf/VerifyEmail";
|
import VerifyEmail from "../components/pdf/VerifyEmail";
|
||||||
import PdfZoom from "../components/pdf/PdfZoom";
|
import PdfZoom from "../components/pdf/PdfZoom";
|
||||||
import Loader from "../primitives/Loader";
|
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import RotateAlert from "../components/RotateAlert";
|
import RotateAlert from "../components/RotateAlert";
|
||||||
|
import DownloadPdfZip from "../primitives/DownloadPdfZip";
|
||||||
|
import Loader from "../primitives/Loader";
|
||||||
|
import ModalUi from "../primitives/ModalUi";
|
||||||
|
import TourContentWithBtn from "../primitives/TourContentWithBtn";
|
||||||
|
import HandleError from "../primitives/HandleError";
|
||||||
|
import LoaderWithMsg from "../primitives/LoaderWithMsg";
|
||||||
//For signYourself inProgress section signer can add sign and complete doc sign.
|
//For signYourself inProgress section signer can add sign and complete doc sign.
|
||||||
function SignYourSelf() {
|
function SignYourSelf() {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
@@ -130,6 +131,7 @@ function SignYourSelf() {
|
|||||||
const [pdfRotateBase64, setPdfRotatese64] = useState("");
|
const [pdfRotateBase64, setPdfRotatese64] = useState("");
|
||||||
const [isRotate, setIsRotate] = useState({ status: false, degree: 0 });
|
const [isRotate, setIsRotate] = useState({ status: false, degree: 0 });
|
||||||
const [isSubscribe, setIsSubscribe] = useState({ plan: "", isValid: true });
|
const [isSubscribe, setIsSubscribe] = useState({ plan: "", isValid: true });
|
||||||
|
const [isDownloadModal, setIsDownloadModal] = useState(false);
|
||||||
const divRef = useRef(null);
|
const divRef = useRef(null);
|
||||||
const nodeRef = useRef(null);
|
const nodeRef = useRef(null);
|
||||||
const [, drop] = useDrop({
|
const [, drop] = useDrop({
|
||||||
@@ -1190,7 +1192,12 @@ function SignYourSelf() {
|
|||||||
)}
|
)}
|
||||||
{isCelebration && (
|
{isCelebration && (
|
||||||
<div className="relative z-[1000]">
|
<div className="relative z-[1000]">
|
||||||
<Confetti width={window.innerWidth} height={window.innerHeight} />
|
<Confetti
|
||||||
|
width={window.innerWidth}
|
||||||
|
height={window.innerHeight}
|
||||||
|
recycle={false} // Prevents confetti from repeating
|
||||||
|
gravity={0.1} // Adjust the gravity to control the speed
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<div className="relative op-card overflow-hidden flex flex-col md:flex-row justify-between bg-base-300">
|
<div className="relative op-card overflow-hidden flex flex-col md:flex-row justify-between bg-base-300">
|
||||||
@@ -1327,6 +1334,7 @@ function SignYourSelf() {
|
|||||||
setIsAlert={setIsAlert}
|
setIsAlert={setIsAlert}
|
||||||
extUserId={extUserId}
|
extUserId={extUserId}
|
||||||
activeMailAdapter={activeMailAdapter}
|
activeMailAdapter={activeMailAdapter}
|
||||||
|
setIsDownloadModal={setIsDownloadModal}
|
||||||
/>
|
/>
|
||||||
{/* pdf header which contain funish back button */}
|
{/* pdf header which contain funish back button */}
|
||||||
<Header
|
<Header
|
||||||
@@ -1346,6 +1354,7 @@ function SignYourSelf() {
|
|||||||
clickOnZoomIn={clickOnZoomIn}
|
clickOnZoomIn={clickOnZoomIn}
|
||||||
clickOnZoomOut={clickOnZoomOut}
|
clickOnZoomOut={clickOnZoomOut}
|
||||||
widgetsDetails={xyPostion}
|
widgetsDetails={xyPostion}
|
||||||
|
setIsDownloadModal={setIsDownloadModal}
|
||||||
/>
|
/>
|
||||||
<div ref={divRef} data-tut="reactourSecond" className="h-full">
|
<div ref={divRef} data-tut="reactourSecond" className="h-full">
|
||||||
{containerWH?.width && containerWH?.height && (
|
{containerWH?.width && containerWH?.height && (
|
||||||
@@ -1450,6 +1459,12 @@ function SignYourSelf() {
|
|||||||
setIsRotate={setIsRotate}
|
setIsRotate={setIsRotate}
|
||||||
handleRemoveWidgets={handleRemoveWidgets}
|
handleRemoveWidgets={handleRemoveWidgets}
|
||||||
/>
|
/>
|
||||||
|
<DownloadPdfZip
|
||||||
|
setIsDownloadModal={setIsDownloadModal}
|
||||||
|
isDownloadModal={isDownloadModal}
|
||||||
|
pdfDetails={pdfDetails}
|
||||||
|
isDocId={true}
|
||||||
|
/>
|
||||||
<TextFontSetting
|
<TextFontSetting
|
||||||
isTextSetting={isTextSetting}
|
isTextSetting={isTextSetting}
|
||||||
setIsTextSetting={setIsTextSetting}
|
setIsTextSetting={setIsTextSetting}
|
||||||
|
|||||||
@@ -9,8 +9,6 @@ import { HTML5Backend } from "react-dnd-html5-backend";
|
|||||||
import { useDrag, useDrop } from "react-dnd";
|
import { useDrag, useDrop } from "react-dnd";
|
||||||
import WidgetComponent from "../components/pdf/WidgetComponent";
|
import WidgetComponent from "../components/pdf/WidgetComponent";
|
||||||
import Tour from "reactour";
|
import Tour from "reactour";
|
||||||
import LoaderWithMsg from "../primitives/LoaderWithMsg";
|
|
||||||
import HandleError from "../primitives/HandleError";
|
|
||||||
import SignerListPlace from "../components/pdf/SignerListPlace";
|
import SignerListPlace from "../components/pdf/SignerListPlace";
|
||||||
import Header from "../components/pdf/PdfHeader";
|
import Header from "../components/pdf/PdfHeader";
|
||||||
import WidgetNameModal from "../components/pdf/WidgetNameModal";
|
import WidgetNameModal from "../components/pdf/WidgetNameModal";
|
||||||
@@ -36,18 +34,21 @@ import {
|
|||||||
import RenderPdf from "../components/pdf/RenderPdf";
|
import RenderPdf from "../components/pdf/RenderPdf";
|
||||||
import "../styles/AddUser.css";
|
import "../styles/AddUser.css";
|
||||||
import Title from "../components/Title";
|
import Title from "../components/Title";
|
||||||
import LinkUserModal from "../primitives/LinkUserModal";
|
|
||||||
import EditTemplate from "../components/pdf/EditTemplate";
|
import EditTemplate from "../components/pdf/EditTemplate";
|
||||||
import ModalUi from "../primitives/ModalUi";
|
|
||||||
import AddRoleModal from "../components/pdf/AddRoleModal";
|
import AddRoleModal from "../components/pdf/AddRoleModal";
|
||||||
import PlaceholderCopy from "../components/pdf/PlaceholderCopy";
|
import PlaceholderCopy from "../components/pdf/PlaceholderCopy";
|
||||||
import TourContentWithBtn from "../primitives/TourContentWithBtn";
|
|
||||||
import DropdownWidgetOption from "../components/pdf/DropdownWidgetOption";
|
import DropdownWidgetOption from "../components/pdf/DropdownWidgetOption";
|
||||||
import Parse from "parse";
|
import Parse from "parse";
|
||||||
import { useSelector } from "react-redux";
|
import { useSelector } from "react-redux";
|
||||||
import PdfZoom from "../components/pdf/PdfZoom";
|
import PdfZoom from "../components/pdf/PdfZoom";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import RotateAlert from "../components/RotateAlert";
|
import RotateAlert from "../components/RotateAlert";
|
||||||
|
import ModalUi from "../primitives/ModalUi";
|
||||||
|
import TourContentWithBtn from "../primitives/TourContentWithBtn";
|
||||||
|
import HandleError from "../primitives/HandleError";
|
||||||
|
import LoaderWithMsg from "../primitives/LoaderWithMsg";
|
||||||
|
import LinkUserModal from "../primitives/LinkUserModal";
|
||||||
|
|
||||||
const TemplatePlaceholder = () => {
|
const TemplatePlaceholder = () => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|||||||
@@ -596,7 +596,7 @@ function UserProfile() {
|
|||||||
className="op-btn op-btn-primary op-btn-outline op-btn-xs md:op-btn-sm"
|
className="op-btn op-btn-primary op-btn-outline op-btn-xs md:op-btn-sm"
|
||||||
onClick={() => copytoclipboard()}
|
onClick={() => copytoclipboard()}
|
||||||
>
|
>
|
||||||
<i className="fa-light fa-link"></i>{" "}
|
<i className="fa-light fa-copy" />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -0,0 +1,43 @@
|
|||||||
|
import React, { useState } from "react";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
|
||||||
|
function Agreement(props) {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const [isChecked, setIsChecked] = useState(false);
|
||||||
|
return (
|
||||||
|
<div className="flex justify-between mx-2 mb-2 pt-1" data-tut="IsAgree">
|
||||||
|
<div className="flex items-center">
|
||||||
|
<input
|
||||||
|
className="mr-3 op-checkbox op-checkbox-m"
|
||||||
|
type="checkbox"
|
||||||
|
value={isChecked}
|
||||||
|
onChange={(e) => {
|
||||||
|
setIsChecked(e.target.checked);
|
||||||
|
if (e.target.checked) {
|
||||||
|
props.setIsAgreeTour(false);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
I confirm that I have read and understood the 'Electronic Record
|
||||||
|
and Signature Disclosure' and consent to use electronic records and
|
||||||
|
signatures.
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="flex">
|
||||||
|
<button
|
||||||
|
onClick={() => {
|
||||||
|
if (isChecked) {
|
||||||
|
props.setIsAgreeTour(false);
|
||||||
|
props.setIsAgree(true);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
className="op-btn op-btn-primary op-btn-sm"
|
||||||
|
>
|
||||||
|
Agree & Continue
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Agreement;
|
||||||
@@ -25,8 +25,8 @@ const Alert = ({ children, type, className }) => {
|
|||||||
: "z-[1000] fixed top-20 left-1/2 transform -translate-x-1/2 text-sm"
|
: "z-[1000] fixed top-20 left-1/2 transform -translate-x-1/2 text-sm"
|
||||||
} `}
|
} `}
|
||||||
>
|
>
|
||||||
<div className={`op-alert ${textcolor}`}>
|
<div className={`op-alert ${textcolor} flex justify-center`}>
|
||||||
<span className="ml-3">{children}</span>
|
<span className="px-1">{children}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -0,0 +1,136 @@
|
|||||||
|
import React, { useState } from "react";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
import ModalUi from "./ModalUi";
|
||||||
|
import {
|
||||||
|
getSignedUrl,
|
||||||
|
handleDownloadCertificate,
|
||||||
|
handleDownloadPdf,
|
||||||
|
sanitizeFileName
|
||||||
|
} from "../constant/Utils";
|
||||||
|
import Loader from "./Loader";
|
||||||
|
import JSZip from "jszip";
|
||||||
|
import { saveAs } from "file-saver";
|
||||||
|
|
||||||
|
function DownloadPdfZip(props) {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const [selectType, setSelectType] = useState(1);
|
||||||
|
const [isDownloading, setIsDownloading] = useState(false);
|
||||||
|
const downloadType = [
|
||||||
|
{ id: 1, label: t("download-pdf") },
|
||||||
|
{ id: 2, label: t("pdf-certificate") }
|
||||||
|
];
|
||||||
|
|
||||||
|
const handleDownload = async () => {
|
||||||
|
if (selectType === 1) {
|
||||||
|
await handleDownloadPdf(props.pdfDetails, setIsDownloading);
|
||||||
|
setSelectType(1);
|
||||||
|
props.setIsDownloadModal(false);
|
||||||
|
} else if (selectType === 2) {
|
||||||
|
setIsDownloading("pdf");
|
||||||
|
const zip = new JSZip();
|
||||||
|
const pdfDetails = props.pdfDetails;
|
||||||
|
const pdfName = pdfDetails?.[0]?.Name || "Document";
|
||||||
|
const pdfUrl = pdfDetails?.[0]?.SignedUrl || "";
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Fetch the first PDF (Signed Document)
|
||||||
|
const docId =
|
||||||
|
props.isDocId && !pdfDetails?.[0]?.IsEnableOTP
|
||||||
|
? pdfDetails?.[0]?.objectId
|
||||||
|
: "";
|
||||||
|
const signedUrl = await getSignedUrl(pdfUrl, docId);
|
||||||
|
const pdf1Response = await fetch(signedUrl);
|
||||||
|
if (!pdf1Response.ok) {
|
||||||
|
throw new Error(`Failed to fetch PDF: ${signedUrl}`);
|
||||||
|
}
|
||||||
|
const pdf1Blob = await pdf1Response.blob();
|
||||||
|
const isZip = true;
|
||||||
|
// Fetch the Certificate (or generate its URL dynamically)
|
||||||
|
const certificateUrl = await handleDownloadCertificate(
|
||||||
|
pdfDetails,
|
||||||
|
setIsDownloading,
|
||||||
|
isZip
|
||||||
|
);
|
||||||
|
const pdf2Response = await fetch(certificateUrl);
|
||||||
|
if (!pdf2Response.ok) {
|
||||||
|
throw new Error(`Failed to fetch certificate PDF: ${certificateUrl}`);
|
||||||
|
}
|
||||||
|
const pdf2Blob = await pdf2Response.blob();
|
||||||
|
// Add files to ZIP
|
||||||
|
zip.file(
|
||||||
|
`${sanitizeFileName(pdfName)}_signed_by_OpenSign™.pdf`,
|
||||||
|
pdf1Blob
|
||||||
|
);
|
||||||
|
zip.file("Certificate_signed_by_OpenSign™.pdf", pdf2Blob);
|
||||||
|
|
||||||
|
// Generate the ZIP and trigger download
|
||||||
|
const zipBlob = await zip.generateAsync({ type: "blob" });
|
||||||
|
saveAs(
|
||||||
|
zipBlob,
|
||||||
|
`${sanitizeFileName(pdfName)}_signed_by_OpenSign™.zip`
|
||||||
|
);
|
||||||
|
setSelectType(1);
|
||||||
|
props.setIsDownloadModal(false);
|
||||||
|
setIsDownloading("");
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error creating ZIP file:", error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return (
|
||||||
|
<ModalUi
|
||||||
|
isOpen={props.isDownloadModal}
|
||||||
|
title={t("download-files")}
|
||||||
|
handleClose={() => props.setIsDownloadModal(false)}
|
||||||
|
>
|
||||||
|
<div className="p-[20px] h-full">
|
||||||
|
{downloadType.map((data, ind) => {
|
||||||
|
return (
|
||||||
|
<label
|
||||||
|
key={ind}
|
||||||
|
className="flex items-center gap-1 mb-2 cursor-pointer"
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
className="mr-[8px] op-radio op-radio-xs"
|
||||||
|
type="radio"
|
||||||
|
value={data.id}
|
||||||
|
onChange={() => setSelectType(data.id)}
|
||||||
|
checked={selectType === data.id}
|
||||||
|
/>
|
||||||
|
{data.label}
|
||||||
|
</label>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
<div className="h-[1px] w-full my-[15px] bg-[#9f9f9f]"></div>
|
||||||
|
<button
|
||||||
|
onClick={() => handleDownload()}
|
||||||
|
type="submit"
|
||||||
|
className="op-btn op-btn-primary"
|
||||||
|
>
|
||||||
|
{t("download")}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
{isDownloading === "pdf" && (
|
||||||
|
<div className="fixed z-[200] inset-0 flex justify-center items-center bg-black bg-opacity-30">
|
||||||
|
<Loader />
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
<ModalUi
|
||||||
|
isOpen={isDownloading === "certificate"}
|
||||||
|
title={
|
||||||
|
isDownloading === "certificate"
|
||||||
|
? t("generating-certificate")
|
||||||
|
: t("pdf-download")
|
||||||
|
}
|
||||||
|
handleClose={() => setIsDownloading("")}
|
||||||
|
>
|
||||||
|
<div className="p-3 md:p-5 text-[13px] md:text-base text-center text-base-content">
|
||||||
|
{isDownloading === "certificate"}{" "}
|
||||||
|
<p>{t("generate-certificate-alert")}</p>
|
||||||
|
</div>
|
||||||
|
</ModalUi>
|
||||||
|
</ModalUi>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default DownloadPdfZip;
|
||||||
@@ -14,6 +14,7 @@ import {
|
|||||||
checkIsSubscribed,
|
checkIsSubscribed,
|
||||||
copytoData,
|
copytoData,
|
||||||
fetchUrl,
|
fetchUrl,
|
||||||
|
getSignedUrl,
|
||||||
replaceMailVaribles
|
replaceMailVaribles
|
||||||
} from "../constant/Utils";
|
} from "../constant/Utils";
|
||||||
import Confetti from "react-confetti";
|
import Confetti from "react-confetti";
|
||||||
@@ -30,6 +31,8 @@ import SubscribeCard from "./SubscribeCard";
|
|||||||
import { validplan } from "../json/plansArr";
|
import { validplan } from "../json/plansArr";
|
||||||
import { serverUrl_fn } from "../constant/appinfo";
|
import { serverUrl_fn } from "../constant/appinfo";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
|
import DownloadPdfZip from "./DownloadPdfZip";
|
||||||
|
import EmbedTab from "../components/pdf/EmbedTab";
|
||||||
|
|
||||||
const ReportTable = (props) => {
|
const ReportTable = (props) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
@@ -69,7 +72,10 @@ const ReportTable = (props) => {
|
|||||||
const [publicUserName, setIsPublicUserName] = useState("");
|
const [publicUserName, setIsPublicUserName] = useState("");
|
||||||
const [isViewShare, setIsViewShare] = useState({});
|
const [isViewShare, setIsViewShare] = useState({});
|
||||||
const [isSubscribe, setIsSubscribe] = useState(true);
|
const [isSubscribe, setIsSubscribe] = useState(true);
|
||||||
|
const [isModal, setIsModal] = useState({});
|
||||||
const [reason, setReason] = useState("");
|
const [reason, setReason] = useState("");
|
||||||
|
const [isDownloadModal, setIsDownloadModal] = useState(false);
|
||||||
|
const [isEmbed, setIsEmbed] = useState(false);
|
||||||
const Extand_Class = localStorage.getItem("Extand_Class");
|
const Extand_Class = localStorage.getItem("Extand_Class");
|
||||||
const extClass = Extand_Class && JSON.parse(Extand_Class);
|
const extClass = Extand_Class && JSON.parse(Extand_Class);
|
||||||
const startIndex = (currentPage - 1) * props.docPerPage;
|
const startIndex = (currentPage - 1) * props.docPerPage;
|
||||||
@@ -365,6 +371,8 @@ const ReportTable = (props) => {
|
|||||||
setIsShareWith({ [item.objectId]: true });
|
setIsShareWith({ [item.objectId]: true });
|
||||||
} else if (act.action === "Embed") {
|
} else if (act.action === "Embed") {
|
||||||
handleEmbedFunction(item);
|
handleEmbedFunction(item);
|
||||||
|
} else if (act.action === "CopyTemplateId") {
|
||||||
|
copyTemplateId(item.objectId);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
// Get current list
|
// Get current list
|
||||||
@@ -648,10 +656,15 @@ const ReportTable = (props) => {
|
|||||||
setActLoader({ [`${item.objectId}`]: true });
|
setActLoader({ [`${item.objectId}`]: true });
|
||||||
const url = item?.SignedUrl || item?.URL || "";
|
const url = item?.SignedUrl || item?.URL || "";
|
||||||
const pdfName = item?.Name || "exported_file";
|
const pdfName = item?.Name || "exported_file";
|
||||||
|
const isCompleted = item?.IsCompleted || false;
|
||||||
if (url) {
|
if (url) {
|
||||||
try {
|
try {
|
||||||
const signedUrl = await Parse.Cloud.run("getsignedurl", { url: url });
|
if (isCompleted) {
|
||||||
await fetchUrl(signedUrl, pdfName);
|
setIsDownloadModal({ [item.objectId]: true });
|
||||||
|
} else {
|
||||||
|
const signedUrl = await getSignedUrl(url);
|
||||||
|
await fetchUrl(signedUrl, pdfName);
|
||||||
|
}
|
||||||
setActLoader({});
|
setActLoader({});
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.log("err in getsignedurl", err);
|
console.log("err in getsignedurl", err);
|
||||||
@@ -777,7 +790,7 @@ const ReportTable = (props) => {
|
|||||||
sessionToken: localStorage.getItem("accesstoken")
|
sessionToken: localStorage.getItem("accesstoken")
|
||||||
};
|
};
|
||||||
let params = {
|
let params = {
|
||||||
mailProvider: doc?.ExtUserPtr?.active_mail_adapter,
|
mailProvider: doc?.ExtUserPtr?.active_mail_adapter || "",
|
||||||
extUserId: doc?.ExtUserPtr?.objectId,
|
extUserId: doc?.ExtUserPtr?.objectId,
|
||||||
recipient: userDetails?.Email,
|
recipient: userDetails?.Email,
|
||||||
subject: mail.subject,
|
subject: mail.subject,
|
||||||
@@ -1112,12 +1125,14 @@ const ReportTable = (props) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
const handleEmbedFunction = async (item) => {
|
const handleEmbedFunction = async (item) => {
|
||||||
|
setIsEmbed(true);
|
||||||
setIsPublicProfile({
|
setIsPublicProfile({
|
||||||
[item.objectId]: props.isPublic[item.objectId]
|
[item.objectId]: true
|
||||||
});
|
});
|
||||||
let extendUser = JSON.parse(localStorage.getItem("Extand_Class"));
|
let extendUser = JSON.parse(localStorage.getItem("Extand_Class"));
|
||||||
setIsPublicUserName(extendUser[0]?.UserName || "");
|
setIsPublicUserName(extendUser[0]?.UserName || "");
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="relative">
|
<div className="relative">
|
||||||
{Object.keys(actLoader)?.length > 0 && (
|
{Object.keys(actLoader)?.length > 0 && (
|
||||||
@@ -1125,10 +1140,15 @@ const ReportTable = (props) => {
|
|||||||
<Loader />
|
<Loader />
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<div className="p-2 w-full overflow-auto bg-base-100 text-base-content op-card shadow-lg">
|
<div className="p-2 w-full overflow-hidden bg-base-100 text-base-content op-card shadow-lg">
|
||||||
{isCelebration && (
|
{isCelebration && (
|
||||||
<div className="relative z-[1000]">
|
<div className="relative z-[1000]">
|
||||||
<Confetti width={window.innerWidth} height={window.innerHeight} />
|
<Confetti
|
||||||
|
width={window.innerWidth}
|
||||||
|
height={window.innerHeight}
|
||||||
|
recycle={false} // Prevents confetti from repeating
|
||||||
|
gravity={0.1} // Adjust the gravity to control the speed
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{isAlert && <Alert type={alertMsg.type}>{alertMsg.message}</Alert>}
|
{isAlert && <Alert type={alertMsg.type}>{alertMsg.message}</Alert>}
|
||||||
@@ -1168,8 +1188,8 @@ const ReportTable = (props) => {
|
|||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
className={`${
|
className={`${
|
||||||
isDashboard && props.List?.length > 0 ? "h-[317px]" : "h-full"
|
isDashboard && props.List?.length > 0 ? "min-h-[317px]" : "h-full"
|
||||||
} w-full`}
|
} overflow-auto w-full`}
|
||||||
>
|
>
|
||||||
<table className="op-table border-collapse w-full ">
|
<table className="op-table border-collapse w-full ">
|
||||||
<thead className="text-[14px]">
|
<thead className="text-[14px]">
|
||||||
@@ -1205,48 +1225,50 @@ const ReportTable = (props) => {
|
|||||||
</td>
|
</td>
|
||||||
<td className="px-4 py-2 ">{item?.Email || "-"}</td>
|
<td className="px-4 py-2 ">{item?.Email || "-"}</td>
|
||||||
<td className="px-4 py-2">{item?.Phone || "-"}</td>
|
<td className="px-4 py-2">{item?.Phone || "-"}</td>
|
||||||
<td className="px-3 py-2 text-white grid grid-cols-2">
|
<td className="px-3 py-2">
|
||||||
{props.actions?.length > 0 &&
|
<div className="text-base-content min-w-max flex flex-row gap-x-2 gap-y-1 justify-start items-center">
|
||||||
props.actions.map((act, index) => (
|
{props.actions?.length > 0 &&
|
||||||
<button
|
props.actions.map((act, index) => (
|
||||||
key={index}
|
<button
|
||||||
onClick={() => handleActionBtn(act, item)}
|
key={index}
|
||||||
title={t(`btnLabel.${act.hoverLabel}`)}
|
onClick={() => handleActionBtn(act, item)}
|
||||||
className={`${
|
title={t(`btnLabel.${act.hoverLabel}`)}
|
||||||
act?.btnColor ? act.btnColor : ""
|
className={`${
|
||||||
} op-btn op-btn-sm`}
|
act?.btnColor ? act.btnColor : ""
|
||||||
|
} op-btn op-btn-sm`}
|
||||||
|
>
|
||||||
|
<i className={act.btnIcon}></i>
|
||||||
|
</button>
|
||||||
|
))}
|
||||||
|
{isDeleteModal[item.objectId] && (
|
||||||
|
<ModalUi
|
||||||
|
isOpen
|
||||||
|
title={"Delete Contact"}
|
||||||
|
handleClose={handleClose}
|
||||||
>
|
>
|
||||||
<i className={act.btnIcon}></i>
|
<div className="m-[20px]">
|
||||||
</button>
|
<div className="text-lg font-normal text-black">
|
||||||
))}
|
{t("contact-delete-alert")}
|
||||||
{isDeleteModal[item.objectId] && (
|
</div>
|
||||||
<ModalUi
|
<hr className="bg-[#ccc] mt-4 " />
|
||||||
isOpen
|
<div className="flex items-center mt-3 gap-2 text-white">
|
||||||
title={"Delete Contact"}
|
<button
|
||||||
handleClose={handleClose}
|
onClick={() => handleDelete(item)}
|
||||||
>
|
className="op-btn op-btn-primary"
|
||||||
<div className="m-[20px]">
|
>
|
||||||
<div className="text-lg font-normal text-black">
|
{t("yes")}
|
||||||
{t("contact-delete-alert")}
|
</button>
|
||||||
|
<button
|
||||||
|
onClick={handleClose}
|
||||||
|
className="op-btn op-btn-secondary"
|
||||||
|
>
|
||||||
|
{t("no")}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<hr className="bg-[#ccc] mt-4 " />
|
</ModalUi>
|
||||||
<div className="flex items-center mt-3 gap-2 text-white">
|
)}
|
||||||
<button
|
</div>
|
||||||
onClick={() => handleDelete(item)}
|
|
||||||
className="op-btn op-btn-primary"
|
|
||||||
>
|
|
||||||
{t("yes")}
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
onClick={handleClose}
|
|
||||||
className="op-btn op-btn-secondary"
|
|
||||||
>
|
|
||||||
{t("no")}
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</ModalUi>
|
|
||||||
)}
|
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
) : (
|
) : (
|
||||||
@@ -1288,9 +1310,55 @@ const ReportTable = (props) => {
|
|||||||
{item?.URL ? t("download") : "-"}
|
{item?.URL ? t("download") : "-"}
|
||||||
</button>
|
</button>
|
||||||
</td>
|
</td>
|
||||||
<td className="px-4 py-2">
|
{props.ReportName === "In-progress documents" ? (
|
||||||
{formatRow(item?.ExtUserPtr)}
|
<td className="px-4 py-2">
|
||||||
</td>
|
<button
|
||||||
|
onClick={() =>
|
||||||
|
item?.AuditTrail?.length > 0 &&
|
||||||
|
setIsModal({ [item?.objectId]: true })
|
||||||
|
}
|
||||||
|
className={`${
|
||||||
|
item?.AuditTrail?.length
|
||||||
|
? "border-green-400"
|
||||||
|
: "cursor-default op-border-primary"
|
||||||
|
} focus:outline-none w-[60px] border-[2px] text-[12px] rounded-full md:self-center`}
|
||||||
|
>
|
||||||
|
{item?.AuditTrail?.length ? "VIEWED" : "SENT"}
|
||||||
|
</button>
|
||||||
|
{isModal[item.objectId] && (
|
||||||
|
<ModalUi
|
||||||
|
isOpen
|
||||||
|
title={t("document-logs")}
|
||||||
|
handleClose={() => setIsModal({})}
|
||||||
|
>
|
||||||
|
{item?.AuditTrail?.map((x, i) => (
|
||||||
|
<div
|
||||||
|
key={i}
|
||||||
|
className="pl-3 first:mt-2 text-sm font-medium flex flex-col md:flex-row items-start md:gap-4 border-t-[1px] border-gray-600"
|
||||||
|
>
|
||||||
|
<div className="py-2 break-all font-bold md:text-[12px] md:col-span-2 w-full md:w-[210px]">
|
||||||
|
{x?.UserPtr?.Email || "-"}
|
||||||
|
</div>
|
||||||
|
<button className="px-2 cursor-default border-[2px] text-[12px] border-green-400 rounded-full md:self-center">
|
||||||
|
{x?.Activity?.toUpperCase() || "-"}
|
||||||
|
</button>
|
||||||
|
<div className=" text-[12px] py-2">
|
||||||
|
{x?.Activity === "Signed"
|
||||||
|
? new Date(x?.SignedOn)?.toUTCString()
|
||||||
|
: new Date(
|
||||||
|
x?.ViewedOn
|
||||||
|
)?.toUTCString() || "-"}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</ModalUi>
|
||||||
|
)}
|
||||||
|
</td>
|
||||||
|
) : (
|
||||||
|
<td className="px-4 py-2">
|
||||||
|
{formatRow(item?.ExtUserPtr)}
|
||||||
|
</td>
|
||||||
|
)}
|
||||||
<td className="px-4 py-2">
|
<td className="px-4 py-2">
|
||||||
{!item?.IsSignyourself && item?.Placeholders ? (
|
{!item?.IsSignyourself && item?.Placeholders ? (
|
||||||
<button
|
<button
|
||||||
@@ -1308,11 +1376,7 @@ const ReportTable = (props) => {
|
|||||||
<td className=" pl-[20px] py-2">
|
<td className=" pl-[20px] py-2">
|
||||||
{props.ReportName === "Templates" && (
|
{props.ReportName === "Templates" && (
|
||||||
<div className="flex flex-row">
|
<div className="flex flex-row">
|
||||||
<label
|
<label className="cursor-pointer relative inline-flex items-center mb-0">
|
||||||
className={
|
|
||||||
"cursor-pointer relative inline-flex items-center mb-0"
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<input
|
<input
|
||||||
checked={props.isPublic?.[item.objectId]}
|
checked={props.isPublic?.[item.objectId]}
|
||||||
onChange={(e) =>
|
onChange={(e) =>
|
||||||
@@ -1388,22 +1452,27 @@ const ReportTable = (props) => {
|
|||||||
<ModalUi
|
<ModalUi
|
||||||
isOpen
|
isOpen
|
||||||
title={t("public-url")}
|
title={t("public-url")}
|
||||||
handleClose={() => setIsPublicProfile({})}
|
handleClose={() => {
|
||||||
|
setIsPublicProfile({});
|
||||||
|
setIsEmbed(false);
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<div className="m-[20px]">
|
<div className="m-[20px]">
|
||||||
{publicUserName ? (
|
{isEmbed && !item?.IsPublic ? (
|
||||||
|
<>
|
||||||
|
<p>{t("public-template-mssg-6")}</p>
|
||||||
|
<EmbedTab templateId={item.objectId} />
|
||||||
|
</>
|
||||||
|
) : publicUserName ? (
|
||||||
<div className="font-normal text-black">
|
<div className="font-normal text-black">
|
||||||
<p>{t("public-url-copy-mssg")}</p>
|
<span>{t("public-url-copy")}</span>
|
||||||
<div className=" flex items-center justify-between gap-3 mt-2 p-[2px] ">
|
<div className=" flex items-center justify-between gap-3 p-[2px] ">
|
||||||
<div className="w-[280px] whitespace-nowrap overflow-hidden text-ellipsis">
|
<div className="w-[280px] whitespace-nowrap overflow-hidden text-ellipsis">
|
||||||
<span className="font-bold">
|
|
||||||
{t("public-url")} :
|
|
||||||
</span>
|
|
||||||
<span
|
<span
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
copytoProfileLink()
|
copytoProfileLink()
|
||||||
}
|
}
|
||||||
className="ml-[2px] underline underline-offset-2 cursor-pointer"
|
className="ml-[2px] underline underline-offset-2 cursor-pointer text-blue-800"
|
||||||
>
|
>
|
||||||
{publicUrl()}
|
{publicUrl()}
|
||||||
</span>
|
</span>
|
||||||
@@ -1428,7 +1497,7 @@ const ReportTable = (props) => {
|
|||||||
copytoProfileLink()
|
copytoProfileLink()
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<i className="fa-light fa-link"></i>{" "}
|
<i className="fa-light fa-copy" />
|
||||||
<span className="hidden md:inline-block">
|
<span className="hidden md:inline-block">
|
||||||
{copied["publicprofile"]
|
{copied["publicprofile"]
|
||||||
? t("copied")
|
? t("copied")
|
||||||
@@ -1437,36 +1506,10 @@ const ReportTable = (props) => {
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className=" flex items-center justify-between gap-3 mt-2 p-[2px] ">
|
<p className="text-[13px] mt-[5px]">
|
||||||
<div>
|
{t("public-url-copy-mssg")}
|
||||||
<span className="font-bold">
|
</p>
|
||||||
{t("templateid")} :
|
<EmbedTab templateId={item.objectId} />
|
||||||
</span>
|
|
||||||
<span
|
|
||||||
onClick={() =>
|
|
||||||
copyTemplateId(item.objectId)
|
|
||||||
}
|
|
||||||
className="underline ml-[2px] underline-offset-2 w-[150px] md:w-[350px] whitespace-nowrap overflow-hidden text-ellipsis cursor-pointer"
|
|
||||||
>
|
|
||||||
{item.objectId}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div className="flex items-center gap-2">
|
|
||||||
<button
|
|
||||||
className="op-btn op-btn-primary op-btn-outline op-btn-xs md:op-btn-sm"
|
|
||||||
onClick={() =>
|
|
||||||
copyTemplateId(item.objectId)
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<i className="fa-light fa-link"></i>{" "}
|
|
||||||
<span className="hidden md:inline-block">
|
|
||||||
{copied["templateid"]
|
|
||||||
? t("copied")
|
|
||||||
: t("copy")}
|
|
||||||
</span>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div className="font-normal text-black">
|
<div className="font-normal text-black">
|
||||||
@@ -1485,7 +1528,7 @@ const ReportTable = (props) => {
|
|||||||
</td>
|
</td>
|
||||||
)}
|
)}
|
||||||
<td className="px-2 py-2">
|
<td className="px-2 py-2">
|
||||||
<div className="text-base-content flex flex-row gap-x-2 gap-y-1 justify-start items-center">
|
<div className="text-base-content min-w-max flex flex-row gap-x-2 gap-y-1 justify-start items-center">
|
||||||
{props.actions?.length > 0 &&
|
{props.actions?.length > 0 &&
|
||||||
props.actions.map((act, index) =>
|
props.actions.map((act, index) =>
|
||||||
props.ReportName === "Templates" ? (
|
props.ReportName === "Templates" ? (
|
||||||
@@ -1526,65 +1569,33 @@ const ReportTable = (props) => {
|
|||||||
{isOption[item.objectId] &&
|
{isOption[item.objectId] &&
|
||||||
act.action === "option" && (
|
act.action === "option" && (
|
||||||
<ul className="absolute -right-1 top-auto z-[70] w-max op-dropdown-content op-menu shadow bg-base-100 text-base-content rounded-box">
|
<ul className="absolute -right-1 top-auto z-[70] w-max op-dropdown-content op-menu shadow bg-base-100 text-base-content rounded-box">
|
||||||
{act.subaction?.map((subact) =>
|
{act.subaction?.map((subact) => (
|
||||||
props.isPublic[
|
<li
|
||||||
item.objectId
|
key={subact.btnId}
|
||||||
] ? (
|
onClick={() =>
|
||||||
<li
|
handleActionBtn(
|
||||||
key={subact.btnId}
|
subact,
|
||||||
onClick={() =>
|
item
|
||||||
handleActionBtn(
|
)
|
||||||
subact,
|
}
|
||||||
item
|
title={t(
|
||||||
)
|
`btnLabel.${subact.btnLabel}`
|
||||||
}
|
)}
|
||||||
title={t(
|
>
|
||||||
`btnLabel.${subact.btnLabel}`
|
<span>
|
||||||
)}
|
<i
|
||||||
>
|
className={`${subact.btnIcon} mr-1.5`}
|
||||||
<span>
|
></i>
|
||||||
<i
|
{subact.btnLabel && (
|
||||||
className={`${subact.btnIcon} mr-1.5`}
|
<span className="text-[13px] capitalize font-medium">
|
||||||
></i>
|
{t(
|
||||||
{subact.btnLabel && (
|
`btnLabel.${subact.btnLabel}`
|
||||||
<span className="text-[13px] capitalize font-medium">
|
|
||||||
{t(
|
|
||||||
`btnLabel.${subact.btnLabel}`
|
|
||||||
)}
|
|
||||||
</span>
|
|
||||||
)}
|
|
||||||
</span>
|
|
||||||
</li>
|
|
||||||
) : (
|
|
||||||
subact.action !== "Embed" && (
|
|
||||||
<li
|
|
||||||
key={subact.btnId}
|
|
||||||
onClick={() =>
|
|
||||||
handleActionBtn(
|
|
||||||
subact,
|
|
||||||
item
|
|
||||||
)
|
|
||||||
}
|
|
||||||
title={t(
|
|
||||||
`btnLabel.${subact.btnLabel}`
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
<span>
|
|
||||||
<i
|
|
||||||
className={`${subact.btnIcon} mr-1.5`}
|
|
||||||
></i>
|
|
||||||
{subact.btnLabel && (
|
|
||||||
<span className="text-[13px] capitalize font-medium">
|
|
||||||
{t(
|
|
||||||
`btnLabel.${subact.btnLabel}`
|
|
||||||
)}
|
|
||||||
</span>
|
|
||||||
)}
|
)}
|
||||||
</span>
|
</span>
|
||||||
</li>
|
)}
|
||||||
)
|
</span>
|
||||||
)
|
</li>
|
||||||
)}
|
))}
|
||||||
</ul>
|
</ul>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
@@ -1905,7 +1916,7 @@ const ReportTable = (props) => {
|
|||||||
className="op-btn op-btn-primary op-btn-outline op-btn-xs md:op-btn-sm"
|
className="op-btn op-btn-primary op-btn-outline op-btn-xs md:op-btn-sm"
|
||||||
onClick={() => copytoclipboard(share)}
|
onClick={() => copytoclipboard(share)}
|
||||||
>
|
>
|
||||||
<i className="fa-light fa-link"></i>{" "}
|
<i className="fa-light fa-copy" />
|
||||||
{copied[share.email]
|
{copied[share.email]
|
||||||
? t("copied")
|
? t("copied")
|
||||||
: t("copy")}
|
: t("copy")}
|
||||||
@@ -2059,6 +2070,14 @@ const ReportTable = (props) => {
|
|||||||
</div>
|
</div>
|
||||||
</ModalUi>
|
</ModalUi>
|
||||||
)}
|
)}
|
||||||
|
{isDownloadModal[item.objectId] && (
|
||||||
|
<DownloadPdfZip
|
||||||
|
setIsDownloadModal={setIsDownloadModal}
|
||||||
|
isDownloadModal={isDownloadModal[item.objectId]}
|
||||||
|
pdfDetails={[item]}
|
||||||
|
isDocId={false}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ export default function TourContentWithBtn({ message, isChecked, video }) {
|
|||||||
></iframe>
|
></iframe>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<label className="flex items-center justify-center mb-0">
|
<label className="flex items-center justify-center mt-3 mb-0">
|
||||||
<input
|
<input
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
className="op-checkbox op-checkbox-xs mr-1"
|
className="op-checkbox op-checkbox-xs mr-1"
|
||||||
|
|||||||
@@ -11,28 +11,37 @@ import { isPublicStaging } from "../constant/const";
|
|||||||
pdfjs.GlobalWorkerOptions.workerSrc = `//cdnjs.cloudflare.com/ajax/libs/pdf.js/${pdfjs.version}/pdf.worker.min.mjs`;
|
pdfjs.GlobalWorkerOptions.workerSrc = `//cdnjs.cloudflare.com/ajax/libs/pdf.js/${pdfjs.version}/pdf.worker.min.mjs`;
|
||||||
|
|
||||||
// Wrapper component to manage props
|
// Wrapper component to manage props
|
||||||
const PublicScriptFileWrapper = ({ initialProps }) => {
|
const PublicScriptFileWrapper = () => {
|
||||||
const [props, setProps] = useState(initialProps);
|
const [props, setProps] = useState("");
|
||||||
|
|
||||||
// Make the setProps function globally accessible
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
// Assigns the function 'setProps' to the global 'window' object as 'updatePublicTemplateProps'.
|
||||||
|
// This allows 'setProps' to be accessed and called globally across different scripts or components,
|
||||||
|
// enabling dynamic updates to the public template's properties.
|
||||||
window.updatePublicTemplateProps = setProps;
|
window.updatePublicTemplateProps = setProps;
|
||||||
|
const publicScript = document.getElementById("opensign-script");
|
||||||
|
// condition for using plan js load opensign-script then get templateId
|
||||||
|
if (publicScript) {
|
||||||
|
// Get the custom templateId attribute
|
||||||
|
const templateId = publicScript.getAttribute("templateId");
|
||||||
|
if (templateId) {
|
||||||
|
setProps({ templateId: templateId });
|
||||||
|
} else {
|
||||||
|
const error = "error: TemplateId is missing";
|
||||||
|
throw new Error(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
return () => {
|
return () => {
|
||||||
window.updatePublicTemplateProps = undefined;
|
window.updatePublicTemplateProps = undefined;
|
||||||
};
|
};
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
return <PdfRequestFiles {...props} />;
|
return <PdfRequestFiles {...props} />;
|
||||||
};
|
};
|
||||||
|
|
||||||
const appId = isPublicStaging ? "opensign" : "legadranaxn";
|
const appId = isPublicStaging ? "opensign" : "legadranaxn";
|
||||||
//"opensign"
|
|
||||||
|
|
||||||
const serverUrl = isPublicStaging
|
const serverUrl = isPublicStaging
|
||||||
? "https://staging-app.opensignlabs.com/api/app"
|
? "https://staging-app.opensignlabs.com/api/app"
|
||||||
: "https://app.opensignlabs.com/api/app";
|
: "https://app.opensignlabs.com/api/app";
|
||||||
// "https://staging-app.opensignlabs.com/api/app"
|
|
||||||
|
|
||||||
localStorage.setItem("baseUrl", `${serverUrl}/`);
|
localStorage.setItem("baseUrl", `${serverUrl}/`);
|
||||||
localStorage.setItem("parseAppId", appId);
|
localStorage.setItem("parseAppId", appId);
|
||||||
@@ -58,7 +67,7 @@ const root = ReactDOM.createRoot(document.getElementById("script-component"));
|
|||||||
root.render(
|
root.render(
|
||||||
<div data-theme="opensigncss">
|
<div data-theme="opensigncss">
|
||||||
<Provider store={store}>
|
<Provider store={store}>
|
||||||
<PublicScriptFileWrapper initialProps={{ text: "templateId" }} />
|
<PublicScriptFileWrapper />
|
||||||
</Provider>
|
</Provider>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -41,7 +41,7 @@
|
|||||||
"upgrade-now": "Upgrade now",
|
"upgrade-now": "Upgrade now",
|
||||||
"upgrade-to": "Upgrade to",
|
"upgrade-to": "Upgrade to",
|
||||||
"plan": "Plan",
|
"plan": "Plan",
|
||||||
"subscribe-card-teamplan": "Unlock the full power of collaboration! Create unlimited organizations, teams, and hierarchies. Share templates seamlessly across teams and assign custom user roles. Elevate your workflow today!",
|
"subscribe-card-teamplan":"Unlock the full power of collaboration! Create unlimited organizations, teams, and hierarchies. Share templates seamlessly across teams and assign custom user roles. Elevate your workflow today!",
|
||||||
"subscribe-card-plan": "Unlock premium features starting at just {{premiumPrice}}/month. Enjoy enhanced performance and only {{addonPrice}} per additional credit after your included premium credits.",
|
"subscribe-card-plan": "Unlock premium features starting at just {{premiumPrice}}/month. Enjoy enhanced performance and only {{addonPrice}} per additional credit after your included premium credits.",
|
||||||
"user-name-limit-char": "To have a username less than 8 character please subscribe",
|
"user-name-limit-char": "To have a username less than 8 character please subscribe",
|
||||||
"tour-content": "Don't show this again",
|
"tour-content": "Don't show this again",
|
||||||
@@ -131,7 +131,8 @@
|
|||||||
"Share": "Share",
|
"Share": "Share",
|
||||||
"View": "View",
|
"View": "View",
|
||||||
"option": "Option",
|
"option": "Option",
|
||||||
"Embed": "Embed"
|
"Embed": "Embed",
|
||||||
|
"Copy TemplateId":"Copy TemplateId"
|
||||||
},
|
},
|
||||||
"report-heading": {
|
"report-heading": {
|
||||||
"Sr.No": "Sr.No",
|
"Sr.No": "Sr.No",
|
||||||
@@ -151,7 +152,8 @@
|
|||||||
"Name": "Name",
|
"Name": "Name",
|
||||||
"Status": "Status",
|
"Status": "Status",
|
||||||
"created-date": "Created Date",
|
"created-date": "Created Date",
|
||||||
"Type": "Type"
|
"Type": "Type",
|
||||||
|
"Logs": "Logs"
|
||||||
},
|
},
|
||||||
"report-help": {
|
"report-help": {
|
||||||
"Draft Documents": "These are documents you have started but have not finalized for sending.",
|
"Draft Documents": "These are documents you have started but have not finalized for sending.",
|
||||||
@@ -263,7 +265,8 @@
|
|||||||
"make-template-private-alert": "Are you sure you want to make this template private? This will remove it from your public profile.",
|
"make-template-private-alert": "Are you sure you want to make this template private? This will remove it from your public profile.",
|
||||||
"public-role": "Public role",
|
"public-role": "Public role",
|
||||||
"public-url": "Public URL",
|
"public-url": "Public URL",
|
||||||
"public-url-copy-mssg": " Here’s your public URL: Copy it or share it with the signer, and you will be able to see all your publicly set templates.",
|
"public-url-copy": "Here’s your public URL: ",
|
||||||
|
"public-url-copy-mssg":"Copy it or share it with the signer, and you will be able to see all your publicly set templates.",
|
||||||
"add-public-url-alert": "Please add your public URL, and you will be able to make a public template.",
|
"add-public-url-alert": "Please add your public URL, and you will be able to make a public template.",
|
||||||
"share-with-alert": "You cannot share a template if any roles already have contacts assigned. Please remove all contact assignments from the roles before sharing the template.",
|
"share-with-alert": "You cannot share a template if any roles already have contacts assigned. Please remove all contact assignments from the roles before sharing the template.",
|
||||||
"share-with": "Share with",
|
"share-with": "Share with",
|
||||||
@@ -572,9 +575,10 @@
|
|||||||
"pdf-request-file-5": "You can click 'Auto Sign All' to automatically sign at all the locations meant to be signed by you. Make sure that you review the document properly before you click this button .",
|
"pdf-request-file-5": "You can click 'Auto Sign All' to automatically sign at all the locations meant to be signed by you. Make sure that you review the document properly before you click this button .",
|
||||||
"placeholder-sign-1": "Select a recipient from this list to add a place-holder where he is supposed to sign.The placeholder will appear in the same colour as the recipient name once you drop it on the document.",
|
"placeholder-sign-1": "Select a recipient from this list to add a place-holder where he is supposed to sign.The placeholder will appear in the same colour as the recipient name once you drop it on the document.",
|
||||||
"placeholder-sign-2": "Clicking 'Add recipients' button will allow you to add more signers.",
|
"placeholder-sign-2": "Clicking 'Add recipients' button will allow you to add more signers.",
|
||||||
"placeholder-sign-3": "Drag or click on a field to add it to the document.",
|
"placeholder-sign-3": "Click this button to add more recipients/signers to the document.",
|
||||||
"placeholder-sign-4": "The PDF content area already displays the template's existing placeholders. For your convenience, these placeholders will match the color of the recipient's name, making them easily identifiable.",
|
"placeholder-sign-4": "Drag or click on a field to add it to the document.",
|
||||||
"placeholder-sign-5": "Clicking 'Send' will save the document. In the next step you can customize the emails to be sent out to the recipients or copy the signing links and share those with the recipients yourself.",
|
"placeholder-sign-5": "The PDF content area already displays the template's existing placeholders. For your convenience, these placeholders will match the color of the recipient's name, making them easily identifiable.",
|
||||||
|
"placeholder-sign-6": "Clicking 'Send' will save the document. In the next step you can customize the emails to be sent out to the recipients or copy the signing links and share those with the recipients yourself.",
|
||||||
"report-1": "Click the 'Add' button to create a new template. Templates are reusable documents designed to quickly generate new documents with the same structure and varying signers. For example, an HR template for onboarding could have predefined roles like ‘HR Manager’ and ‘New Employee’. Each time you use the template, you can assign the ‘New Employee’ role to different incoming staff members, while the ‘HR Manager’ role remains constant, facilitating a seamless onboarding process for each recruit. ",
|
"report-1": "Click the 'Add' button to create a new template. Templates are reusable documents designed to quickly generate new documents with the same structure and varying signers. For example, an HR template for onboarding could have predefined roles like ‘HR Manager’ and ‘New Employee’. Each time you use the template, you can assign the ‘New Employee’ role to different incoming staff members, while the ‘HR Manager’ role remains constant, facilitating a seamless onboarding process for each recruit. ",
|
||||||
"redirect": "Click the 'Use' button to create a new document from an existing template.",
|
"redirect": "Click the 'Use' button to create a new document from an existing template.",
|
||||||
"bulksend": "To quickly create and send multiple documents using an existing template, click the 'Quick Send' button.",
|
"bulksend": "To quickly create and send multiple documents using an existing template, click the 'Quick Send' button.",
|
||||||
@@ -593,7 +597,7 @@
|
|||||||
"Recently sent for signatures": "This is a list of documents you've sent to other parties for signature.",
|
"Recently sent for signatures": "This is a list of documents you've sent to other parties for signature.",
|
||||||
"Drafts": "This are documents you have started but have not finalized for sending.",
|
"Drafts": "This are documents you have started but have not finalized for sending.",
|
||||||
"public-template": "This video demonstrates how to set up your personalized public profile, such as ‘https://opensign.me/your-username’. You’ll also learn how to customize your tagline and make your templates available for public signing."
|
"public-template": "This video demonstrates how to set up your personalized public profile, such as ‘https://opensign.me/your-username’. You’ll also learn how to customize your tagline and make your templates available for public signing."
|
||||||
},
|
},
|
||||||
"enter-email-plaholder": "Add an email address and hit enter",
|
"enter-email-plaholder": "Add an email address and hit enter",
|
||||||
"success-email-alert": "Email sent successfully!",
|
"success-email-alert": "Email sent successfully!",
|
||||||
"expired-doc-title": "Expired Document",
|
"expired-doc-title": "Expired Document",
|
||||||
@@ -614,28 +618,44 @@
|
|||||||
"select-date-format": "Select a date format",
|
"select-date-format": "Select a date format",
|
||||||
"quantity-of-credits": "Quantity of premium credits",
|
"quantity-of-credits": "Quantity of premium credits",
|
||||||
"remaining-credits": "Premium credits available:",
|
"remaining-credits": "Premium credits available:",
|
||||||
"remaining-credits-help": "Use premium credits for API document signing, bulk sending, or embedding OpenSign integration on your website. You have {{allowedcredits}} included credits and {{addoncredits}} additional purchased credits remaining.",
|
"remaining-credits-help":"Use premium credits for API document signing, bulk sending, or embedding OpenSign integration on your website. You have {{allowedcredits}} included credits and {{addoncredits}} additional purchased credits remaining.",
|
||||||
"additional-credits": "Please purchase premium credits",
|
"additional-credits": "Please purchase premium credits",
|
||||||
"quota-err-quicksend": "Quota Reached, You don't have enough credits.",
|
"quota-err-quicksend": "Quota Reached, You don't have enough credits.",
|
||||||
"buy-credits": "Buy Premium Credits",
|
"buy-credits": "Buy Premium Credits",
|
||||||
"rotate-right": "Rotate right",
|
"rotate-right":"Rotate right",
|
||||||
"rotate-left": "Rotate left",
|
"rotate-left":"Rotate left",
|
||||||
"rotate-alert-mssg": "All widgets on this page will be lost. Are you sure you want to proceed?",
|
"rotate-alert-mssg":"All widgets on this page will be lost. Are you sure you want to proceed?",
|
||||||
"templateid": "Template-Id",
|
"templateid":"Template-Id",
|
||||||
"bulk-send-subcription-alert": "Please upgrade to Professional or Team plan to use bulk send.",
|
"bulk-send-subcription-alert":"Please upgrade to Professional or Team plan to use bulk send.",
|
||||||
"generate-test-token": "Generate Test Token",
|
"generate-test-token":"Generate Test Token",
|
||||||
"regenerate-test-token": "Regenerate Test Token",
|
"regenerate-test-token":"Regenerate Test Token",
|
||||||
"help-test-token": "This token can be used to test the APIs at the https://sandbox.opensignlabs.com/api/v1 endpoint, allowing you to conduct unlimited document signatures. Please note that the sandbox API will sign your documents with self-signed certificates, which may not be recognized as valid by Adobe. Once you’ve completed your testing, you can upgrade to one of our paid plans to generate a production token.",
|
"help-test-token":"This token can be used to test the APIs at the https://sandbox.opensignlabs.com/api/v1 endpoint, allowing you to conduct unlimited document signatures. Please note that the sandbox API will sign your documents with self-signed certificates, which may not be recognized as valid by Adobe. Once you’ve completed your testing, you can upgrade to one of our paid plans to generate a production token.",
|
||||||
"help-api-token": "This token can be used to access the production APIs at the {{origin}}/api/v1 endpoint. It can only be generated on one of our paid plans.",
|
"help-api-token":"This token can be used to access the production APIs at the {{origin}}/api/v1 endpoint. It can only be generated on one of our paid plans.",
|
||||||
"quota-mail-info-head": "Monthly request signatures email limit",
|
"reason":"Reason",
|
||||||
|
"decline-by":"Declined/revoked by",
|
||||||
|
"document-declined": "Document declined",
|
||||||
|
"public-template-mssg-1":"To integrate OpenSign into your React or Next.js project, simply run the following command:",
|
||||||
|
"public-template-mssg-2" :"Ensure you have npm or yarn set up in your project. If you’re using Yarn, you can replace npm install with yarn add @opensign/react.",
|
||||||
|
"public-template-mssg-3" :"Need more details or examples?",
|
||||||
|
"public-template-mssg-4": "Visit the",
|
||||||
|
"public-template-mssg-5": " npm for the latest updates, detailed documentation, and version history.",
|
||||||
|
"public-template-mssg-6" :"You need to set this template as public before you can utilize this code snippet.",
|
||||||
|
"copy-code":"COPY",
|
||||||
|
"copied-code":"COPIED",
|
||||||
|
"Installation":"Installation",
|
||||||
|
"Usage" :"Usage",
|
||||||
|
"insufficient-credits":"Insufficient Signing Credits",
|
||||||
|
"insufficient-credits-mssg":"The owner of this document currently lacks the necessary OpenSign credits for you to sign. Please reach out to the owner if you require further details.",
|
||||||
|
"angular-npm-mssg-1": "To integrate OpenSign into your Angular project, simply run the following command:",
|
||||||
|
"quota-mail-info-head":"Monthly request signatures email limit",
|
||||||
"quota-mail-info": "You can send upto 15 signature request emails every month. Upgrade now to send unlimited signing requests directly.",
|
"quota-mail-info": "You can send upto 15 signature request emails every month. Upgrade now to send unlimited signing requests directly.",
|
||||||
"quota-mail": "You've reached your limit of 15 signature request emails for this month. Upgrade now to continue sending emails directly.",
|
"quota-mail": "You've reached your limit of 15 signature request emails for this month. Upgrade now to continue sending emails directly.",
|
||||||
"quota-mail-tip": "Tip: You can still sign <1>unlimited documents</1> by manually sharing the signing request links.",
|
"quota-mail-tip":"Tip: You can still sign <1>unlimited documents</1> by manually sharing the signing request links.",
|
||||||
"quota-mail-head": "Quota Reached",
|
"quota-mail-head":"Quota Reached",
|
||||||
"unauthorized-modal": "You don't have permission to perform this action, please contact {{adminEmail}}.",
|
"unauthorized-modal":"You don't have permission to perform this action, please contact {{adminEmail}}.",
|
||||||
"sent-this-month": "Sent this month",
|
"sent-this-month":"Sent this month",
|
||||||
"available-seats": "Available seats",
|
"available-seats":"Available seats",
|
||||||
"buy-users": "Buy more users",
|
"buy-users":"Buy more users",
|
||||||
"isenable-otp": "Enable OTP verification",
|
"isenable-otp": "Enable OTP verification",
|
||||||
"isenable-otp-help": {
|
"isenable-otp-help": {
|
||||||
"p1": "Would you like to enable the verification process using a one-time password (OTP)?",
|
"p1": "Would you like to enable the verification process using a one-time password (OTP)?",
|
||||||
@@ -643,6 +663,10 @@
|
|||||||
"p3": "Selecting this option will disable OTP verification, allowing users to sign the document directly without additional steps.",
|
"p3": "Selecting this option will disable OTP verification, allowing users to sign the document directly without additional steps.",
|
||||||
"p4": "Please choose the option that best suits your document signing requirements."
|
"p4": "Please choose the option that best suits your document signing requirements."
|
||||||
},
|
},
|
||||||
"advanced-options": "Advanced options",
|
"advanced-options":"Advanced options",
|
||||||
"hide-advanced-options": "Hide Advanced options"
|
"hide-advanced-options":"Hide Advanced options",
|
||||||
|
"download-files":"Download files",
|
||||||
|
"download-pdf":"Download Pdf",
|
||||||
|
"pdf-certificate":"Download Pdf + Certificate",
|
||||||
|
"document-logs":"Document logs"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,7 +42,7 @@
|
|||||||
"upgrade-to": "Mettre à niveau vers",
|
"upgrade-to": "Mettre à niveau vers",
|
||||||
"pro": "PRO",
|
"pro": "PRO",
|
||||||
"plan": "Offre",
|
"plan": "Offre",
|
||||||
"subscribe-card-teamplan": "Libérez toute la puissance de la collaboration ! Créez un nombre illimité d'organisations, d'équipes et de hiérarchies. Partagez des modèles de manière transparente entre les équipes et attribuez des rôles d'utilisateur personnalisés. Améliorez votre flux de travail dès aujourd'hui !",
|
"subscribe-card-teamplan":"Libérez toute la puissance de la collaboration ! Créez un nombre illimité d'organisations, d'équipes et de hiérarchies. Partagez des modèles de manière transparente entre les équipes et attribuez des rôles d'utilisateur personnalisés. Améliorez votre flux de travail dès aujourd'hui !",
|
||||||
"subscribe-card-plan": "Débloquez des fonctionnalités premium à partir de seulement {{premiumPrice}}/mois. Bénéficiez de performances améliorées et de seulement {{addonPrice}} par crédit supplémentaire après vos crédits premium inclus.",
|
"subscribe-card-plan": "Débloquez des fonctionnalités premium à partir de seulement {{premiumPrice}}/mois. Bénéficiez de performances améliorées et de seulement {{addonPrice}} par crédit supplémentaire après vos crédits premium inclus.",
|
||||||
"user-name-limit-char": "Pour avoir un nom d'utilisateur de moins de 8 caractères s'il vous plaît s'abonner",
|
"user-name-limit-char": "Pour avoir un nom d'utilisateur de moins de 8 caractères s'il vous plaît s'abonner",
|
||||||
"tour-content": "Ne plus afficher",
|
"tour-content": "Ne plus afficher",
|
||||||
@@ -136,7 +136,8 @@
|
|||||||
"Name": "Nom",
|
"Name": "Nom",
|
||||||
"Status": "Statut",
|
"Status": "Statut",
|
||||||
"created-date": "Date de création",
|
"created-date": "Date de création",
|
||||||
"Type": "Saisir"
|
"Type": "Saisir",
|
||||||
|
"Logs": "Journaux"
|
||||||
},
|
},
|
||||||
"btnLabel": {
|
"btnLabel": {
|
||||||
"sign": "Signer",
|
"sign": "Signer",
|
||||||
@@ -150,7 +151,8 @@
|
|||||||
"Share": "Partager",
|
"Share": "Partager",
|
||||||
"View": "Voir",
|
"View": "Voir",
|
||||||
"option": "Option",
|
"option": "Option",
|
||||||
"Embed": "Intégrer"
|
"Embed": "Intégrer",
|
||||||
|
"Copy TemplateId": "Copier l'ID du modèle"
|
||||||
},
|
},
|
||||||
"report-help": {
|
"report-help": {
|
||||||
"Draft Documents": "Il s'agit de documents que vous avez commencés mais que vous n'avez pas finalisés pour envoi.",
|
"Draft Documents": "Il s'agit de documents que vous avez commencés mais que vous n'avez pas finalisés pour envoi.",
|
||||||
@@ -262,7 +264,8 @@
|
|||||||
"make-template-private-alert": "Êtes-vous sûr de vouloir rendre ce modèle privé ? Cela le supprimera de votre profil public.",
|
"make-template-private-alert": "Êtes-vous sûr de vouloir rendre ce modèle privé ? Cela le supprimera de votre profil public.",
|
||||||
"public-role": "Rôle public",
|
"public-role": "Rôle public",
|
||||||
"public-url": "URL publique",
|
"public-url": "URL publique",
|
||||||
"public-url-copy-mssg": "Voici votre URL publique : copiez-la ou partagez-le avec le signataire et vous pouvoir voir tous vos paramètres publics modèles.",
|
"public-url-copy": "Voici votre URL publique : ",
|
||||||
|
"public-url-copy-mssg": "copiez-la ou partagez-le avec le signataire et vous pouvoir voir tous vos paramètres publics modèles.",
|
||||||
"add-public-url-alert": "Veuillez ajouter votre URL publique et vous pourra rendre public modèle.",
|
"add-public-url-alert": "Veuillez ajouter votre URL publique et vous pourra rendre public modèle.",
|
||||||
"share-with-alert": "Vous ne pouvez pas partager un modèle si des contacts sont déjà attribués à des rôles. Veuillez supprimer toutes les attributions de contacts des rôles avant de partager le modèle.",
|
"share-with-alert": "Vous ne pouvez pas partager un modèle si des contacts sont déjà attribués à des rôles. Veuillez supprimer toutes les attributions de contacts des rôles avant de partager le modèle.",
|
||||||
"share-with": "Partager avec",
|
"share-with": "Partager avec",
|
||||||
@@ -571,9 +574,10 @@
|
|||||||
"pdf-request-file-5": "Vous pouvez cliquer sur 'Signer automatiquement tout' pour signer automatiquement à tous les emplacements que vous êtes censé signer. Assurez-vous de lire correctement le document avant de cliquer sur ce bouton.",
|
"pdf-request-file-5": "Vous pouvez cliquer sur 'Signer automatiquement tout' pour signer automatiquement à tous les emplacements que vous êtes censé signer. Assurez-vous de lire correctement le document avant de cliquer sur ce bouton.",
|
||||||
"placeholder-sign-1": "Sélectionnez un destinataire dans cette liste pour ajouter un espace réservé à l'endroit où il est censé signer. L'espace réservé apparaîtra de la même couleur que le nom du destinataire une fois que vous le déposerez sur le document.",
|
"placeholder-sign-1": "Sélectionnez un destinataire dans cette liste pour ajouter un espace réservé à l'endroit où il est censé signer. L'espace réservé apparaîtra de la même couleur que le nom du destinataire une fois que vous le déposerez sur le document.",
|
||||||
"placeholder-sign-2": "Cliquer sur le bouton 'Ajouter des destinataires' vous permettra d'ajouter plus de signataires.",
|
"placeholder-sign-2": "Cliquer sur le bouton 'Ajouter des destinataires' vous permettra d'ajouter plus de signataires.",
|
||||||
"placeholder-sign-3": "Faites glisser ou cliquez sur un champ pour l'ajouter au document.",
|
"placeholder-sign-3": "Cliquez sur ce bouton pour ajouter plus de destinataires/signataires au document",
|
||||||
"placeholder-sign-4": "La zone de contenu PDF affiche déjà les espaces réservés existants du modèle. Pour votre commodité, ces espaces réservés correspondront à la couleur du nom du destinataire, ce qui les rendra facilement identifiables.",
|
"placeholder-sign-4": "Faites glisser ou cliquez sur un champ pour l'ajouter au document.",
|
||||||
"placeholder-sign-5": "Cliquer sur 'Envoyer' enregistrera le document. À l'étape suivante, vous pourrez personnaliser les e-mails à envoyer aux destinataires ou copier les liens de signature et les partager vous-même avec les destinataires.",
|
"placeholder-sign-5": "La zone de contenu PDF affiche déjà les espaces réservés existants du modèle. Pour votre commodité, ces espaces réservés correspondront à la couleur du nom du destinataire, ce qui les rendra facilement identifiables.",
|
||||||
|
"placeholder-sign-6": "Cliquer sur 'Envoyer' enregistrera le document. À l'étape suivante, vous pourrez personnaliser les e-mails à envoyer aux destinataires ou copier les liens de signature et les partager vous-même avec les destinataires.",
|
||||||
"report-1": "Cliquez sur le bouton 'Ajouter' pour créer un nouveau modèle. Les modèles sont des documents réutilisables conçus pour générer rapidement de nouveaux documents avec la même structure et différents signataires. Par exemple, un modèle RH pour l'intégration peut avoir des rôles prédéfinis tels que 'Responsable RH' et ' Nouvel employé'. Chaque fois que vous utilisez le modèle, vous pouvez attribuer le rôle 'Nouvel employé' à différents membres du personnel entrants, tandis que le rôle 'Responsable RH' reste constant, facilitant ainsi un processus d'intégration fluide pour chaque recrue",
|
"report-1": "Cliquez sur le bouton 'Ajouter' pour créer un nouveau modèle. Les modèles sont des documents réutilisables conçus pour générer rapidement de nouveaux documents avec la même structure et différents signataires. Par exemple, un modèle RH pour l'intégration peut avoir des rôles prédéfinis tels que 'Responsable RH' et ' Nouvel employé'. Chaque fois que vous utilisez le modèle, vous pouvez attribuer le rôle 'Nouvel employé' à différents membres du personnel entrants, tandis que le rôle 'Responsable RH' reste constant, facilitant ainsi un processus d'intégration fluide pour chaque recrue",
|
||||||
"redirect": "Cliquez sur le bouton 'Utiliser' pour créer un nouveau document à partir d'un modèle existant.",
|
"redirect": "Cliquez sur le bouton 'Utiliser' pour créer un nouveau document à partir d'un modèle existant.",
|
||||||
"bulksend": "Pour créer et envoyer rapidement plusieurs documents à l'aide d'un modèle existant, cliquez sur le bouton 'Envoi rapide'.",
|
"bulksend": "Pour créer et envoyer rapidement plusieurs documents à l'aide d'un modèle existant, cliquez sur le bouton 'Envoi rapide'.",
|
||||||
@@ -611,30 +615,46 @@
|
|||||||
"Add-seats": "Ajouter des sièges",
|
"Add-seats": "Ajouter des sièges",
|
||||||
"format": "format",
|
"format": "format",
|
||||||
"select-date-format": "Sélectionnez un format de date",
|
"select-date-format": "Sélectionnez un format de date",
|
||||||
"quantity-of-credits": "Quantité de crédits de prime",
|
"quantity-of-credits":"Quantité de crédits de prime",
|
||||||
"remaining-credits": "Crédits premium disponibles :",
|
"remaining-credits":"Crédits premium disponibles :",
|
||||||
"additional-credits": "Veuillez acheter des crédits premium",
|
"additional-credits":"Veuillez acheter des crédits premium",
|
||||||
"remaining-credits-help": "Utilisez des crédits premium pour la signature de documents API, l'envoi groupé ou l'intégration d'OpenSign sur votre site Web. Il vous reste {{allowedcredits}} crédits inclus et {{addoncredits}} crédits achetés supplémentaires.",
|
"remaining-credits-help":"Utilisez des crédits premium pour la signature de documents API, l'envoi groupé ou l'intégration d'OpenSign sur votre site Web. Il vous reste {{allowedcredits}} crédits inclus et {{addoncredits}} crédits achetés supplémentaires.",
|
||||||
"quota-err-quicksend": "Quota atteint, vous n'avez pas assez de crédits.",
|
"quota-err-quicksend": "Quota atteint, vous n'avez pas assez de crédits.",
|
||||||
"buy-credits": "Acheter des crédits premium",
|
"buy-credits": "Acheter des crédits premium",
|
||||||
"rotate-right": "Faire pivoter à droite",
|
"rotate-right" :"Faire pivoter à droite",
|
||||||
"rotate-left": "Faire pivoter à gauche",
|
"rotate-left" :"Faire pivoter à gauche",
|
||||||
"rotate-alert-mssg": "Tous les widgets de cette page seront perdus. Êtes-vous sûr de vouloir continuer ?",
|
"rotate-alert-mssg" :"Tous les widgets de cette page seront perdus. Êtes-vous sûr de vouloir continuer ?",
|
||||||
"templateid": "ID de modèle",
|
"templateid":"ID de modèle",
|
||||||
"bulk-send-subcription-alert": "Veuillez passer au forfait Professionnel ou Équipe pour utiliser Quicksend.",
|
"bulk-send-subcription-alert":"Veuillez passer au forfait Professionnel ou Équipe pour utiliser Quicksend.",
|
||||||
"generate-test-token": "Générer jeton de test",
|
"generate-test-token": "Générer jeton de test",
|
||||||
"regenerate-test-token": "Régénérer le jeton de test",
|
"regenerate-test-token":"Régénérer le jeton de test",
|
||||||
"help-test-token": "Ce jeton peut être utilisé pour tester les API au niveau du point de terminaison https://sandbox.opensignlabs.com/api/v1, vous permettant ainsi d'effectuer un nombre illimité de signatures de documents. Veuillez noter que l'API sandbox signera vos documents avec des certificats auto-signés, qui peuvent ne pas être reconnus comme valides par Adobe. Une fois vos tests terminés, vous pouvez passer à l’un de nos forfaits payants pour générer un jeton de production.",
|
"help-test-token":"Ce jeton peut être utilisé pour tester les API au niveau du point de terminaison https://sandbox.opensignlabs.com/api/v1, vous permettant ainsi d'effectuer un nombre illimité de signatures de documents. Veuillez noter que l'API sandbox signera vos documents avec des certificats auto-signés, qui peuvent ne pas être reconnus comme valides par Adobe. Une fois vos tests terminés, vous pouvez passer à l’un de nos forfaits payants pour générer un jeton de production.",
|
||||||
"help-api-token": "Ce jeton peut être utilisé pour accéder aux API de production au point de terminaison {{origin}}/api/v1. Il ne peut être généré que sur l'un de nos forfaits payants.",
|
"help-api-token":"Ce jeton peut être utilisé pour accéder aux API de production au point de terminaison {{origin}}/api/v1. Il ne peut être généré que sur l'un de nos forfaits payants.",
|
||||||
"quota-mail-info-head": "Limite mensuelle d'e-mails de signatures de demandes",
|
"reason" :"Raison",
|
||||||
|
"decline-by" :"Refusé/révoqué par",
|
||||||
|
"document-declined":"document refusé",
|
||||||
|
"public-template-mssg-1" :"Pour intégrer OpenSign dans votre projet React ou Next.js, exécutez simplement la commande suivante :",
|
||||||
|
"public-template-mssg-2" :"Assurez-vous que npm ou Yarn est configuré dans votre projet. Si vous utilisez Yarn, vous pouvez remplacer npm install par Yarn Add @opensign/react.",
|
||||||
|
"public-template-mssg-3" :"Besoin de plus de détails ou d'exemples ?",
|
||||||
|
"public-template-mssg-4": "Visitez le",
|
||||||
|
"public-template-mssg-5": "npm pour les dernières mises à jour, une documentation détaillée et l'historique des versions.",
|
||||||
|
"public-template-mssg-6":"Vous devez définir ce modèle comme public avant de pouvoir utiliser cet extrait de code.",
|
||||||
|
"copy-code":"COPIE",
|
||||||
|
"copied-code":"COPIÉ",
|
||||||
|
"Installation":"Installation",
|
||||||
|
"Usage" :"Usage",
|
||||||
|
"insufficient-credits":"Crédits de signature insuffisants",
|
||||||
|
"insufficient-credits-mssg" :"Le propriétaire de ce document ne dispose actuellement pas des crédits OpenSign nécessaires pour que vous puissiez le signer. Veuillez contacter le propriétaire si vous avez besoin de plus de détails.",
|
||||||
|
"angular-npm-mssg-1" :"Pour intégrer OpenSign dans votre projet Angular, exécutez simplement la commande suivante :",
|
||||||
|
"quota-mail-info-head":"Limite mensuelle d'e-mails de signatures de demandes",
|
||||||
"quota-mail-info": "Vous pouvez envoyer jusqu'à 15 e-mails de demande de signature chaque mois. Mettez à niveau maintenant pour envoyer directement des demandes de signature illimitées.",
|
"quota-mail-info": "Vous pouvez envoyer jusqu'à 15 e-mails de demande de signature chaque mois. Mettez à niveau maintenant pour envoyer directement des demandes de signature illimitées.",
|
||||||
"quota-mail": "Vous avez atteint votre limite de 15 e-mails de demande de signature pour ce mois. Mettez à niveau maintenant pour continuer à envoyer des e-mails directement.",
|
"quota-mail": "Vous avez atteint votre limite de 15 e-mails de demande de signature pour ce mois. Mettez à niveau maintenant pour continuer à envoyer des e-mails directement.",
|
||||||
"quota-mail-tip": "Astuce : Vous pouvez toujours signer un nombre <1>illimité de documents</1> en partageant manuellement les liens de demande de signature.",
|
"quota-mail-tip-tip":"Astuce : Vous pouvez toujours signer un nombre <1>illimité de documents</1> en partageant manuellement les liens de demande de signature.",
|
||||||
"quota-mail-head": "Quota atteint",
|
"quota-mail-head":"Quota atteint",
|
||||||
"unauthorized-modal": "Vous n'êtes pas autorisé à effectuer cette action, veuillez contacter {{adminEmail}}.",
|
"unauthorized-modal":"Vous n'êtes pas autorisé à effectuer cette action, veuillez contacter {{adminEmail}}.",
|
||||||
"sent-this-month": "envoyé ce mois-ci",
|
"sent-this-month":"envoyé ce mois-ci",
|
||||||
"available-seats": "Disponible sièges",
|
"available-seats":"Disponible sièges",
|
||||||
"buy-users": "Acheter plus d'utilisateurs",
|
"buy-users":"Acheter plus d'utilisateurs",
|
||||||
"isenable-otp": "Activer la vérification OTP",
|
"isenable-otp": "Activer la vérification OTP",
|
||||||
"isenable-otp-help": {
|
"isenable-otp-help": {
|
||||||
"p1": "Souhaitez-vous activer le processus de vérification à l'aide d'un mot de passe à usage unique (OTP)?",
|
"p1": "Souhaitez-vous activer le processus de vérification à l'aide d'un mot de passe à usage unique (OTP)?",
|
||||||
@@ -642,6 +662,11 @@
|
|||||||
"p3": "La sélection de cette option désactivera la vérification OTP, permettant aux utilisateurs de signer le document directement sans étapes supplémentaires.",
|
"p3": "La sélection de cette option désactivera la vérification OTP, permettant aux utilisateurs de signer le document directement sans étapes supplémentaires.",
|
||||||
"p4": "Veuillez choisir l'option qui correspond le mieux à vos exigences en matière de signature de documents."
|
"p4": "Veuillez choisir l'option qui correspond le mieux à vos exigences en matière de signature de documents."
|
||||||
},
|
},
|
||||||
"advanced-options": "Options avancées",
|
"advanced-options":"Options avancées",
|
||||||
"hide-advanced-options": "Masquer les options avancées"
|
"hide-advanced-options": "Masquer les options avancées",
|
||||||
|
"download-files" :"Télécharger des fichiers",
|
||||||
|
"download-pdf" :"Télécharger le PDF",
|
||||||
|
"pdf-certificate" :"Télécharger Pdf + Certificat",
|
||||||
|
"document-logs":"Journaux de documents"
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import dotenv from 'dotenv';
|
|||||||
dotenv.config();
|
dotenv.config();
|
||||||
|
|
||||||
export const cloudServerUrl = 'http://localhost:8080/app';
|
export const cloudServerUrl = 'http://localhost:8080/app';
|
||||||
|
export const appName = process.env.APP_NAME || 'OpenSign™';
|
||||||
export function customAPIurl() {
|
export function customAPIurl() {
|
||||||
const url = new URL(cloudServerUrl);
|
const url = new URL(cloudServerUrl);
|
||||||
return url.pathname === '/api/app' ? url.origin + '/api' : url.origin;
|
return url.pathname === '/api/app' ? url.origin + '/api' : url.origin;
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import saveInvoice from './saveInvoice.js';
|
|||||||
import savePayments from './savePayments.js';
|
import savePayments from './savePayments.js';
|
||||||
import gooogleauth from './googleauth.js';
|
import gooogleauth from './googleauth.js';
|
||||||
import autoReminder from './autoReminder.js';
|
import autoReminder from './autoReminder.js';
|
||||||
|
import validateSmtp from './validateSmtp.js';
|
||||||
export const app = express();
|
export const app = express();
|
||||||
|
|
||||||
dotenv.config();
|
dotenv.config();
|
||||||
@@ -22,3 +23,4 @@ app.post('/saveinvoice', saveInvoice);
|
|||||||
app.post('/savepayment', savePayments);
|
app.post('/savepayment', savePayments);
|
||||||
app.post('/googleauth', gooogleauth);
|
app.post('/googleauth', gooogleauth);
|
||||||
app.post('/sendreminder', autoReminder);
|
app.post('/sendreminder', autoReminder);
|
||||||
|
app.post('/validatesmtp', validateSmtp);
|
||||||
|
|||||||
@@ -315,6 +315,7 @@ export default async function createDocumentWithTemplate(request, response) {
|
|||||||
from: sender,
|
from: sender,
|
||||||
html: html,
|
html: html,
|
||||||
extUserId: template.ExtUserPtr.objectId,
|
extUserId: template.ExtUserPtr.objectId,
|
||||||
|
mailProvider: template?.ExtUserPtr?.active_mail_adapter || '',
|
||||||
};
|
};
|
||||||
sendMail = await axios.post(url, params, { headers: headers });
|
sendMail = await axios.post(url, params, { headers: headers });
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|||||||
@@ -371,6 +371,7 @@ export default async function createDocumentwithCoordinate(request, response) {
|
|||||||
from: sender,
|
from: sender,
|
||||||
html: html,
|
html: html,
|
||||||
extUserId: extUser.id,
|
extUserId: extUser.id,
|
||||||
|
mailProvider: parseExtUser?.active_mail_adapter || '',
|
||||||
};
|
};
|
||||||
|
|
||||||
await axios.post(url, params, { headers: headers });
|
await axios.post(url, params, { headers: headers });
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ export default async function resendMail(request, response) {
|
|||||||
if (resDoc) {
|
if (resDoc) {
|
||||||
const _resDoc = resDoc.toJSON();
|
const _resDoc = resDoc.toJSON();
|
||||||
const contact = _resDoc.Signers.find(x => x.Email === userMail);
|
const contact = _resDoc.Signers.find(x => x.Email === userMail);
|
||||||
|
const activeMailAdapter = _resDoc?.ExtUserPtr?.active_mail_adapter || '';
|
||||||
if (contact) {
|
if (contact) {
|
||||||
try {
|
try {
|
||||||
const imgPng = 'https://qikinnovation.ams3.digitaloceanspaces.com/logo.png';
|
const imgPng = 'https://qikinnovation.ams3.digitaloceanspaces.com/logo.png';
|
||||||
@@ -131,6 +132,7 @@ export default async function resendMail(request, response) {
|
|||||||
from: sender,
|
from: sender,
|
||||||
html: html,
|
html: html,
|
||||||
extUserId: _resDoc.ExtUserPtr.objectId,
|
extUserId: _resDoc.ExtUserPtr.objectId,
|
||||||
|
mailProvider: activeMailAdapter,
|
||||||
};
|
};
|
||||||
|
|
||||||
const res = await axios.post(url, params, { headers: headers });
|
const res = await axios.post(url, params, { headers: headers });
|
||||||
|
|||||||
@@ -0,0 +1,72 @@
|
|||||||
|
import { createTransport } from 'nodemailer';
|
||||||
|
import { appName } from '../../Utils.js';
|
||||||
|
// Online Javascript Editor for free
|
||||||
|
// Write, Edit and Run your Javascript code using JS Online Compiler
|
||||||
|
|
||||||
|
function generateOtpWithSum10() {
|
||||||
|
let otp = [];
|
||||||
|
let sum = 0;
|
||||||
|
|
||||||
|
// First, generate 3 random digits (0-9) and add them to the sum
|
||||||
|
for (let i = 0; i < 3; i++) {
|
||||||
|
let digit = Math.floor(Math.random() * 10);
|
||||||
|
otp.push(digit);
|
||||||
|
sum += digit;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate the last digit to ensure the sum equals 10
|
||||||
|
let lastDigit = 10 - sum;
|
||||||
|
|
||||||
|
// If the last digit is not valid (e.g., greater than 9), regenerate
|
||||||
|
if (lastDigit >= 0 && lastDigit <= 9) {
|
||||||
|
otp.push(lastDigit);
|
||||||
|
} else {
|
||||||
|
return generateOtpWithSum10(); // Recursively generate again
|
||||||
|
}
|
||||||
|
|
||||||
|
return otp.join('');
|
||||||
|
}
|
||||||
|
|
||||||
|
export default async function validateSmtp(request, response) {
|
||||||
|
const host = request.body.host;
|
||||||
|
const port = request.body?.port?.toString();
|
||||||
|
const username = request.body.username;
|
||||||
|
const password = request.body.password;
|
||||||
|
const secure = request.body?.secure;
|
||||||
|
const email = request.body?.email;
|
||||||
|
const otp = generateOtpWithSum10();
|
||||||
|
// console.log('Generated OTP:', otp);
|
||||||
|
|
||||||
|
try {
|
||||||
|
const smtpsecure = secure || port !== '465' ? false : true;
|
||||||
|
const transporterSMTP = createTransport({
|
||||||
|
host: host,
|
||||||
|
port: port,
|
||||||
|
secure: smtpsecure,
|
||||||
|
auth: { user: username, pass: password },
|
||||||
|
});
|
||||||
|
const from = appName;
|
||||||
|
const mailsender = username;
|
||||||
|
const messageParams = {
|
||||||
|
from: from + ' <' + mailsender + '>',
|
||||||
|
to: email,
|
||||||
|
subject: `Your ${appName} SMTP credentials verification code`,
|
||||||
|
text: 'mail',
|
||||||
|
html:
|
||||||
|
`<html><head><meta http-equiv='Content-Type' content='text/html; charset=UTF-8' /></head><body><div style='background-color:#f5f5f5;padding:20px'><div style='box-shadow: rgba(0, 0, 0, 0.1) 0px 4px 12px;background-color:white;'><div style='background-color:red;padding:2px;font-family:system-ui; background-color:#47a3ad;'> <p style='font-size:20px;font-weight:400;color:white;padding-left:20px',>SMTP Verification Code</p></div><div style='padding:20px'><p style='font-family:system-ui;font-size:14px'>Your verification code is:</p><p style=' text-decoration: none; font-weight: bolder; color:blue;font-size:45px;margin:20px'>` +
|
||||||
|
otp +
|
||||||
|
'</p></div> </div> </div></body></html>',
|
||||||
|
};
|
||||||
|
|
||||||
|
const res = await transporterSMTP.sendMail(messageParams);
|
||||||
|
console.log('custom smtp transporter res: ', res?.response);
|
||||||
|
if (!res.err) {
|
||||||
|
response.status(200).json({ message: 'success' });
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.log('err ', err);
|
||||||
|
const code = err?.responseCode || 400;
|
||||||
|
const message = err?.response || 'failed!';
|
||||||
|
response.status(code).json({ error: message });
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -68,6 +68,8 @@ import BuyCredits from './parsefunction/BuyCredits.js';
|
|||||||
import getContact from './parsefunction/getContact.js';
|
import getContact from './parsefunction/getContact.js';
|
||||||
import updateContactTour from './parsefunction/updateContactTour.js';
|
import updateContactTour from './parsefunction/updateContactTour.js';
|
||||||
import declinedocument from './parsefunction/declinedocument.js';
|
import declinedocument from './parsefunction/declinedocument.js';
|
||||||
|
import addcustomsmtp from './parsefunction/addcustomsmtp.js';
|
||||||
|
import deactivateMailAdapter from './parsefunction/deactivateMailAdapter.js';
|
||||||
|
|
||||||
// This afterSave function triggers after an object is added or updated in the specified class, allowing for post-processing logic.
|
// This afterSave function triggers after an object is added or updated in the specified class, allowing for post-processing logic.
|
||||||
Parse.Cloud.afterSave('contracts_Document', DocumentAftersave);
|
Parse.Cloud.afterSave('contracts_Document', DocumentAftersave);
|
||||||
@@ -148,3 +150,5 @@ Parse.Cloud.define('buycredits', BuyCredits);
|
|||||||
Parse.Cloud.define('getcontact', getContact);
|
Parse.Cloud.define('getcontact', getContact);
|
||||||
Parse.Cloud.define('updatecontacttour', updateContactTour);
|
Parse.Cloud.define('updatecontacttour', updateContactTour);
|
||||||
Parse.Cloud.define('declinedoc', declinedocument);
|
Parse.Cloud.define('declinedoc', declinedocument);
|
||||||
|
Parse.Cloud.define('addsmtp', addcustomsmtp);
|
||||||
|
Parse.Cloud.define('deactivatemailadapter', deactivateMailAdapter);
|
||||||
|
|||||||
@@ -222,6 +222,25 @@ const sendMailToAllSigners = async docId => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const deductcount = async _resSub => {
|
||||||
|
try {
|
||||||
|
const subscriptionCls = new Parse.Object('contracts_Subscriptions');
|
||||||
|
subscriptionCls.id = _resSub.objectId;
|
||||||
|
const allowedCredits = _resSub?.AllowedCredits || 0;
|
||||||
|
const addonCredits = _resSub?.AddonCredits || 0;
|
||||||
|
if (allowedCredits > 0) {
|
||||||
|
const updateAllowedcredits = allowedCredits - 1 || 0;
|
||||||
|
subscriptionCls.set('AllowedCredits', updateAllowedcredits);
|
||||||
|
} else {
|
||||||
|
const updateAddonCredits = addonCredits > 0 ? addonCredits - 1 : 0;
|
||||||
|
subscriptionCls.set('AddonCredits', updateAddonCredits);
|
||||||
|
}
|
||||||
|
await subscriptionCls.save(null, { useMasterKey: true });
|
||||||
|
} catch (err) {
|
||||||
|
console.log('Err in deductcount in PublicUserLinkContacttoDoc cloud function', err);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// `PublicUserLinkContactToDoc` cloud function is used to create contact, add this contact in contracts_Guest role and
|
// `PublicUserLinkContactToDoc` cloud function is used to create contact, add this contact in contracts_Guest role and
|
||||||
// create new document from template and save contact pointer in placeholder, signers and ACL of Document
|
// create new document from template and save contact pointer in placeholder, signers and ACL of Document
|
||||||
export default async function PublicUserLinkContactToDoc(req) {
|
export default async function PublicUserLinkContactToDoc(req) {
|
||||||
@@ -241,126 +260,163 @@ export default async function PublicUserLinkContactToDoc(req) {
|
|||||||
throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'Template not found.');
|
throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'Template not found.');
|
||||||
}
|
}
|
||||||
const _tempRes = JSON.parse(JSON.stringify(tempRes));
|
const _tempRes = JSON.parse(JSON.stringify(tempRes));
|
||||||
const Placeholders = _tempRes?.Placeholders || [];
|
const subscription = new Parse.Query('contracts_Subscriptions');
|
||||||
let index;
|
subscription.equalTo('TenantId', {
|
||||||
if (role) {
|
__type: 'Pointer',
|
||||||
index = Placeholders?.findIndex(x => x.Role && x.Role === role);
|
className: 'partners_Tenant',
|
||||||
} else {
|
objectId: _tempRes?.ExtUserPtr?.TenantId?.objectId,
|
||||||
throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, '');
|
});
|
||||||
}
|
subscription.include('ExtUserPtr');
|
||||||
if (index !== -1) {
|
const date = new Date();
|
||||||
// Execute the query to check if a contact already exists in the 'contracts_Contactbook' class
|
subscription.greaterThanOrEqualTo('Next_billing_date', date);
|
||||||
const contactCls = new Parse.Query('contracts_Contactbook');
|
const resSub = await subscription.first({ useMasterKey: true });
|
||||||
contactCls.equalTo('Email', email);
|
if (resSub) {
|
||||||
contactCls.equalTo('CreatedBy', _tempRes.CreatedBy);
|
const _resSub = JSON.parse(JSON.stringify(resSub));
|
||||||
contactCls.notEqualTo('IsDeleted', true);
|
const allowedCredits = _resSub?.AllowedCredits || 0;
|
||||||
const existContact = await contactCls.first({ useMasterKey: true });
|
const addonCredits = _resSub?.AddonCredits || 0;
|
||||||
if (existContact) {
|
const totalcredits = allowedCredits + addonCredits;
|
||||||
const template_json = JSON.parse(JSON.stringify(tempRes));
|
if (totalcredits > 0) {
|
||||||
//update contact in placeholder, signers and update ACl in provide document
|
const Placeholders = _tempRes?.Placeholders || [];
|
||||||
const docRes = await createDocumentFromTemplate(template_json, existContact, index);
|
let index;
|
||||||
if (docRes) {
|
if (role) {
|
||||||
//condition will execute only if sendInOrder will be false for send email to all signers at a time.
|
index = Placeholders?.findIndex(x => x.Role && x.Role === role);
|
||||||
if (!template_json?.SendinOrder) {
|
} else {
|
||||||
await sendMailToAllSigners(docRes.id);
|
throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, '');
|
||||||
}
|
|
||||||
return { contactId: existContact.id, docId: docRes.id };
|
|
||||||
}
|
}
|
||||||
} else {
|
if (index !== -1) {
|
||||||
// Execute the query to check if a user already exists in the 'contracts_Users' class
|
// Execute the query to check if a contact already exists in the 'contracts_Contactbook' class
|
||||||
const extUserQuery = new Parse.Query('contracts_Users');
|
const contactCls = new Parse.Query('contracts_Contactbook');
|
||||||
extUserQuery.equalTo('Email', email);
|
contactCls.equalTo('Email', email);
|
||||||
const extUser = await extUserQuery.first({ useMasterKey: true });
|
contactCls.equalTo('CreatedBy', _tempRes.CreatedBy);
|
||||||
if (extUser) {
|
contactCls.notEqualTo('IsDeleted', true);
|
||||||
const _extUser = JSON.parse(JSON.stringify(extUser));
|
const existContact = await contactCls.first({ useMasterKey: true });
|
||||||
const contact = {
|
if (existContact) {
|
||||||
UserId: _extUser.UserId,
|
const template_json = JSON.parse(JSON.stringify(tempRes));
|
||||||
Name: _extUser.Name,
|
//update contact in placeholder, signers and update ACl in provide document
|
||||||
Email: email,
|
const docRes = await createDocumentFromTemplate(template_json, existContact, index);
|
||||||
Phone: _extUser?.Phone ? _extUser.Phone : '',
|
if (docRes) {
|
||||||
CreatedBy: _tempRes.CreatedBy,
|
await deductcount(_resSub);
|
||||||
TenantId: _tempRes.ExtUserPtr.TenantId,
|
//condition will execute only if sendInOrder will be false for send email to all signers at a time.
|
||||||
};
|
if (!template_json?.SendinOrder) {
|
||||||
const template_json = JSON.parse(JSON.stringify(tempRes));
|
await sendMailToAllSigners(docRes.id);
|
||||||
// if user present on platform create contact on the basis of extended user details
|
}
|
||||||
const contactRes = await saveRoleContact(contact);
|
return { contactId: existContact.id, docId: docRes.id };
|
||||||
const docRes = await createDocumentFromTemplate(template_json, contactRes, index);
|
|
||||||
if (docRes) {
|
|
||||||
//condition will execute only if sendInOrder will be false for send email to all signers at a time.
|
|
||||||
if (!template_json?.SendinOrder) {
|
|
||||||
await sendMailToAllSigners(docRes.id);
|
|
||||||
}
|
}
|
||||||
return { contactId: contactRes.id, docId: docRes.id };
|
} else {
|
||||||
}
|
// Execute the query to check if a user already exists in the 'contracts_Users' class
|
||||||
} else if (name) {
|
const extUserQuery = new Parse.Query('contracts_Users');
|
||||||
try {
|
extUserQuery.equalTo('Email', email);
|
||||||
// Execute the query to check if a user already exists in the '_User' class
|
const extUser = await extUserQuery.first({ useMasterKey: true });
|
||||||
const userQuery = new Parse.Query(Parse.User);
|
if (extUser) {
|
||||||
userQuery.equalTo('email', email);
|
const _extUser = JSON.parse(JSON.stringify(extUser));
|
||||||
const userRes = await userQuery.first({ useMasterKey: true });
|
|
||||||
if (userRes) {
|
|
||||||
const contact = {
|
const contact = {
|
||||||
UserId: { __type: 'Pointer', className: '_User', objectId: userRes.id },
|
UserId: _extUser.UserId,
|
||||||
Name: name,
|
Name: _extUser.Name,
|
||||||
Email: email,
|
Email: email,
|
||||||
Phone: phone,
|
Phone: _extUser?.Phone ? _extUser.Phone : '',
|
||||||
CreatedBy: _tempRes.CreatedBy,
|
CreatedBy: _tempRes.CreatedBy,
|
||||||
TenantId: _tempRes.ExtUserPtr.TenantId,
|
TenantId: _tempRes.ExtUserPtr.TenantId,
|
||||||
};
|
};
|
||||||
const template_json = JSON.parse(JSON.stringify(tempRes));
|
const template_json = JSON.parse(JSON.stringify(tempRes));
|
||||||
// Create new contract on the basis provided contact details by user and userId from _User class
|
// if user present on platform create contact on the basis of extended user details
|
||||||
const contactRes = await saveRoleContact(contact);
|
const contactRes = await saveRoleContact(contact);
|
||||||
//update contact in placeholder, signers and update ACl in provide document
|
|
||||||
const docRes = await createDocumentFromTemplate(template_json, contactRes, index);
|
const docRes = await createDocumentFromTemplate(template_json, contactRes, index);
|
||||||
if (docRes) {
|
if (docRes) {
|
||||||
|
await deductcount(_resSub);
|
||||||
//condition will execute only if sendInOrder will be false for send email to all signers at a time.
|
//condition will execute only if sendInOrder will be false for send email to all signers at a time.
|
||||||
if (!template_json?.SendinOrder) {
|
if (!template_json?.SendinOrder) {
|
||||||
await sendMailToAllSigners(docRes.id);
|
await sendMailToAllSigners(docRes.id);
|
||||||
}
|
}
|
||||||
return { contactId: contactRes.id, docId: docRes.id };
|
return { contactId: contactRes.id, docId: docRes.id };
|
||||||
}
|
}
|
||||||
|
} else if (name) {
|
||||||
|
try {
|
||||||
|
// Execute the query to check if a user already exists in the '_User' class
|
||||||
|
const userQuery = new Parse.Query(Parse.User);
|
||||||
|
userQuery.equalTo('email', email);
|
||||||
|
const userRes = await userQuery.first({ useMasterKey: true });
|
||||||
|
if (userRes) {
|
||||||
|
const contact = {
|
||||||
|
UserId: { __type: 'Pointer', className: '_User', objectId: userRes.id },
|
||||||
|
Name: name,
|
||||||
|
Email: email,
|
||||||
|
Phone: phone,
|
||||||
|
CreatedBy: _tempRes.CreatedBy,
|
||||||
|
TenantId: _tempRes.ExtUserPtr.TenantId,
|
||||||
|
};
|
||||||
|
const template_json = JSON.parse(JSON.stringify(tempRes));
|
||||||
|
// Create new contract on the basis provided contact details by user and userId from _User class
|
||||||
|
const contactRes = await saveRoleContact(contact);
|
||||||
|
//update contact in placeholder, signers and update ACl in provide document
|
||||||
|
const docRes = await createDocumentFromTemplate(
|
||||||
|
template_json,
|
||||||
|
contactRes,
|
||||||
|
index
|
||||||
|
);
|
||||||
|
if (docRes) {
|
||||||
|
await deductcount(_resSub);
|
||||||
|
//condition will execute only if sendInOrder will be false for send email to all signers at a time.
|
||||||
|
if (!template_json?.SendinOrder) {
|
||||||
|
await sendMailToAllSigners(docRes.id);
|
||||||
|
}
|
||||||
|
return { contactId: contactRes.id, docId: docRes.id };
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// create new user in _User class on the basis of details provide by user
|
||||||
|
const _users = Parse.Object.extend('User');
|
||||||
|
const _user = new _users();
|
||||||
|
_user.set('name', name);
|
||||||
|
_user.set('username', email);
|
||||||
|
_user.set('email', email);
|
||||||
|
_user.set('password', email);
|
||||||
|
if (phone) {
|
||||||
|
_user.set('phone', phone);
|
||||||
|
}
|
||||||
|
const newUserRes = await _user.save();
|
||||||
|
const contact = {
|
||||||
|
UserId: { __type: 'Pointer', className: '_User', objectId: newUserRes.id },
|
||||||
|
Name: name,
|
||||||
|
Email: email,
|
||||||
|
Phone: phone,
|
||||||
|
CreatedBy: _tempRes.CreatedBy,
|
||||||
|
TenantId: _tempRes.ExtUserPtr.TenantId,
|
||||||
|
};
|
||||||
|
const template_json = JSON.parse(JSON.stringify(tempRes));
|
||||||
|
// Create new contract on the basis provided contact details by user and userId from _User class
|
||||||
|
const contactRes = await saveRoleContact(contact);
|
||||||
|
//update contact in placeholder, signers and update ACl in provide document
|
||||||
|
const docRes = await createDocumentFromTemplate(
|
||||||
|
template_json,
|
||||||
|
contactRes,
|
||||||
|
index
|
||||||
|
);
|
||||||
|
if (docRes) {
|
||||||
|
await deductcount(_resSub);
|
||||||
|
//condition will execute only if sendInOrder will be false for send email to all signers at a time.
|
||||||
|
if (!template_json?.SendinOrder) {
|
||||||
|
await sendMailToAllSigners(docRes.id);
|
||||||
|
}
|
||||||
|
return { contactId: contactRes.id, docId: docRes.id };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.log('Err', err);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// create new user in _User class on the basis of details provide by user
|
throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'User not found.');
|
||||||
const _users = Parse.Object.extend('User');
|
|
||||||
const _user = new _users();
|
|
||||||
_user.set('name', name);
|
|
||||||
_user.set('username', email);
|
|
||||||
_user.set('email', email);
|
|
||||||
_user.set('password', email);
|
|
||||||
if (phone) {
|
|
||||||
_user.set('phone', phone);
|
|
||||||
}
|
|
||||||
const newUserRes = await _user.save();
|
|
||||||
const contact = {
|
|
||||||
UserId: { __type: 'Pointer', className: '_User', objectId: newUserRes.id },
|
|
||||||
Name: name,
|
|
||||||
Email: email,
|
|
||||||
Phone: phone,
|
|
||||||
CreatedBy: _tempRes.CreatedBy,
|
|
||||||
TenantId: _tempRes.ExtUserPtr.TenantId,
|
|
||||||
};
|
|
||||||
const template_json = JSON.parse(JSON.stringify(tempRes));
|
|
||||||
// Create new contract on the basis provided contact details by user and userId from _User class
|
|
||||||
const contactRes = await saveRoleContact(contact);
|
|
||||||
//update contact in placeholder, signers and update ACl in provide document
|
|
||||||
const docRes = await createDocumentFromTemplate(template_json, contactRes, index);
|
|
||||||
if (docRes) {
|
|
||||||
//condition will execute only if sendInOrder will be false for send email to all signers at a time.
|
|
||||||
if (!template_json?.SendinOrder) {
|
|
||||||
await sendMailToAllSigners(docRes.id);
|
|
||||||
}
|
|
||||||
return { contactId: contactRes.id, docId: docRes.id };
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} catch (err) {
|
|
||||||
console.log('Err', err);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'User not found.');
|
throw new Parse.Error(
|
||||||
|
Parse.Error.OBJECT_NOT_FOUND,
|
||||||
|
'Please provide required parameters!'
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
throw new Parse.Error(Parse.Error.REQUEST_LIMIT_EXCEEDED, 'Insufficient Credit');
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'Please provide required parameters!');
|
throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'Plan expired');
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'Template not found.');
|
throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'Template not found.');
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { smtpenable, updateMailCount } from '../../Utils.js';
|
import { appName, smtpenable, updateMailCount } from '../../Utils.js';
|
||||||
async function getDocument(docId) {
|
async function getDocument(docId) {
|
||||||
try {
|
try {
|
||||||
const query = new Parse.Query('contracts_Document');
|
const query = new Parse.Query('contracts_Document');
|
||||||
@@ -28,12 +28,12 @@ async function sendMailOTPv1(request) {
|
|||||||
const mailsender = smtpenable ? process.env.SMTP_USER_EMAIL : process.env.MAILGUN_SENDER;
|
const mailsender = smtpenable ? process.env.SMTP_USER_EMAIL : process.env.MAILGUN_SENDER;
|
||||||
try {
|
try {
|
||||||
await Parse.Cloud.sendEmail({
|
await Parse.Cloud.sendEmail({
|
||||||
from: 'Opensign™' + ' <' + mailsender + '>',
|
from: appName + ' <' + mailsender + '>',
|
||||||
recipient: recipient,
|
recipient: recipient,
|
||||||
subject: 'Your OpenSign™ OTP',
|
subject: `Your ${appName} OTP`,
|
||||||
text: 'This email is a test.',
|
text: 'This email is a test.',
|
||||||
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;'><div style='background-color:red;padding:2px;font-family:system-ui; background-color:#47a3ad;'> <p style='font-size:20px;font-weight:400;color:white;padding-left:20px',>OTP Verification</p></div><div style='padding:20px'><p style='font-family:system-ui;font-size:14px'>Your OTP for OpenSign™ verification is:</p><p style=' text-decoration: none; font-weight: bolder; color:blue;font-size:45px;margin:20px'>" +
|
`<html><head><meta http-equiv='Content-Type' content='text/html; charset=UTF-8' /></head><body><div style='background-color:#f5f5f5;padding:20px'><div style='box-shadow: rgba(0, 0, 0, 0.1) 0px 4px 12px;background-color:white;'><div style='background-color:red;padding:2px;font-family:system-ui; background-color:#47a3ad;'> <p style='font-size:20px;font-weight:400;color:white;padding-left:20px',>OTP Verification</p></div><div style='padding:20px'><p style='font-family:system-ui;font-size:14px'>Your OTP for ${appName} verification is:</p><p style=' text-decoration: none; font-weight: bolder; color:blue;font-size:45px;margin:20px'>` +
|
||||||
code +
|
code +
|
||||||
'</p></div> </div> </div></body></html>',
|
'</p></div> </div> </div></body></html>',
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -0,0 +1,33 @@
|
|||||||
|
export default async function addcustomsmtp(request) {
|
||||||
|
if (!request?.user) {
|
||||||
|
throw new Parse.Error(Parse.Error.INVALID_SESSION_TOKEN, 'User is not authenticated.');
|
||||||
|
}
|
||||||
|
const host = request.params.host;
|
||||||
|
const port = request.params.port;
|
||||||
|
const username = request.params.username;
|
||||||
|
const password = request.params.password;
|
||||||
|
if (host && port && username && password) {
|
||||||
|
try {
|
||||||
|
const extUserCls = new Parse.Query('contracts_Users');
|
||||||
|
extUserCls.equalTo('UserId', request.user);
|
||||||
|
const extUser = await extUserCls.first({ useMasterKey: true });
|
||||||
|
if (extUser) {
|
||||||
|
const extUserCls = new Parse.Object('contracts_Users');
|
||||||
|
extUserCls.id = extUser.id;
|
||||||
|
extUserCls.set('SmtpConfig', { host, port, username, password });
|
||||||
|
extUserCls.set('active_mail_adapter', 'smtp');
|
||||||
|
const updateExtUser = await extUserCls.save(null, { useMasterKey: true });
|
||||||
|
// console.log('updateExtUser ', updateExtUser);
|
||||||
|
return updateExtUser.updatedAt;
|
||||||
|
}
|
||||||
|
return extUser;
|
||||||
|
} catch (err) {
|
||||||
|
console.log('Err in add custom smtp', err);
|
||||||
|
const code = err.code || 400;
|
||||||
|
const msg = err.message || 'Something went wrong.';
|
||||||
|
throw new Parse.Error(code, msg);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw new Parse.Error(Parse.Error.INVALID_QUERY, 'Please provide all parameters.');
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -74,6 +74,7 @@ async function sendMail(document, sessionToken) {
|
|||||||
const orgName = document.ExtUserPtr.Company ? document.ExtUserPtr.Company : '';
|
const orgName = document.ExtUserPtr.Company ? document.ExtUserPtr.Company : '';
|
||||||
const themeBGcolor = '#47a3ad';
|
const themeBGcolor = '#47a3ad';
|
||||||
let params = {
|
let params = {
|
||||||
|
mailProvider: document?.ExtUserPtr?.active_mail_adapter || '',
|
||||||
extUserId: document.ExtUserPtr.objectId,
|
extUserId: document.ExtUserPtr.objectId,
|
||||||
recipient: objectId ? existSigner?.Email : signerMail[i].email,
|
recipient: objectId ? existSigner?.Email : signerMail[i].email,
|
||||||
subject: `${document.ExtUserPtr.Name} has requested you to sign "${document.Name}"`,
|
subject: `${document.ExtUserPtr.Name} has requested you to sign "${document.Name}"`,
|
||||||
|
|||||||
@@ -0,0 +1,24 @@
|
|||||||
|
export default async function deactivateMailAdapter(request) {
|
||||||
|
if (!request?.user) {
|
||||||
|
throw new Parse.Error(Parse.Error.INVALID_SESSION_TOKEN, 'User is not authenticated.');
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
const extUserCls = new Parse.Query('contracts_Users');
|
||||||
|
extUserCls.equalTo('UserId', request.user);
|
||||||
|
const extUser = await extUserCls.first({ useMasterKey: true });
|
||||||
|
if (extUser) {
|
||||||
|
const extUserCls = new Parse.Object('contracts_Users');
|
||||||
|
extUserCls.id = extUser.id;
|
||||||
|
extUserCls.unset('active_mail_adapter');
|
||||||
|
const updateExtUser = await extUserCls.save(null, { useMasterKey: true });
|
||||||
|
// console.log('updateExtUser ', updateExtUser);
|
||||||
|
return updateExtUser.updatedAt;
|
||||||
|
}
|
||||||
|
return extUser;
|
||||||
|
} catch (err) {
|
||||||
|
console.log('Err in add custom smtp', err);
|
||||||
|
const code = err.code || 400;
|
||||||
|
const msg = err.message || 'Something went wrong.';
|
||||||
|
throw new Parse.Error(code, msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -65,6 +65,8 @@ export default function reportJson(id, userId) {
|
|||||||
'Folder.Name',
|
'Folder.Name',
|
||||||
'URL',
|
'URL',
|
||||||
'ExtUserPtr.Name',
|
'ExtUserPtr.Name',
|
||||||
|
'ExtUserPtr.Email',
|
||||||
|
'ExtUserPtr.active_mail_adapter',
|
||||||
'Signers.Name',
|
'Signers.Name',
|
||||||
'Signers.Email',
|
'Signers.Email',
|
||||||
'Signers.Phone',
|
'Signers.Phone',
|
||||||
@@ -100,6 +102,8 @@ export default function reportJson(id, userId) {
|
|||||||
'Folder.Name',
|
'Folder.Name',
|
||||||
'URL',
|
'URL',
|
||||||
'ExtUserPtr.Name',
|
'ExtUserPtr.Name',
|
||||||
|
'ExtUserPtr.Email',
|
||||||
|
'ExtUserPtr.active_mail_adapter',
|
||||||
'Signers.Name',
|
'Signers.Name',
|
||||||
'Signers.Email',
|
'Signers.Email',
|
||||||
'Signers.Phone',
|
'Signers.Phone',
|
||||||
@@ -139,6 +143,7 @@ export default function reportJson(id, userId) {
|
|||||||
'TimeToCompleteDays',
|
'TimeToCompleteDays',
|
||||||
'Placeholders',
|
'Placeholders',
|
||||||
'IsSignyourself',
|
'IsSignyourself',
|
||||||
|
'IsCompleted',
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
// declined documents report
|
// declined documents report
|
||||||
@@ -227,6 +232,8 @@ export default function reportJson(id, userId) {
|
|||||||
'Folder.Name',
|
'Folder.Name',
|
||||||
'URL',
|
'URL',
|
||||||
'ExtUserPtr.Name',
|
'ExtUserPtr.Name',
|
||||||
|
'ExtUserPtr.Email',
|
||||||
|
'ExtUserPtr.active_mail_adapter',
|
||||||
'Signers.Name',
|
'Signers.Name',
|
||||||
'Signers.Email',
|
'Signers.Email',
|
||||||
'Signers.Phone',
|
'Signers.Phone',
|
||||||
@@ -268,6 +275,8 @@ export default function reportJson(id, userId) {
|
|||||||
'Name',
|
'Name',
|
||||||
'URL',
|
'URL',
|
||||||
'ExtUserPtr.Name',
|
'ExtUserPtr.Name',
|
||||||
|
'ExtUserPtr.Email',
|
||||||
|
'ExtUserPtr.active_mail_adapter',
|
||||||
'Signers.Name',
|
'Signers.Name',
|
||||||
'Signers.UserId',
|
'Signers.UserId',
|
||||||
'AuditTrail',
|
'AuditTrail',
|
||||||
@@ -335,6 +344,7 @@ export default function reportJson(id, userId) {
|
|||||||
'Folder.Name',
|
'Folder.Name',
|
||||||
'URL',
|
'URL',
|
||||||
'ExtUserPtr.Name',
|
'ExtUserPtr.Name',
|
||||||
|
'ExtUserPtr.active_mail_adapter',
|
||||||
'Signers.Name',
|
'Signers.Name',
|
||||||
'Signers.Email',
|
'Signers.Email',
|
||||||
'Signers.Phone',
|
'Signers.Phone',
|
||||||
|
|||||||
@@ -68,7 +68,11 @@ const makeEmail = async (to, from, subject, html, url, pdfName) => {
|
|||||||
type: 'application/pdf',
|
type: 'application/pdf',
|
||||||
path: './exports/certificate.pdf',
|
path: './exports/certificate.pdf',
|
||||||
};
|
};
|
||||||
attachments = [file, certificate];
|
if (fs.existsSync(certificate.path)) {
|
||||||
|
attachments = [file, certificate];
|
||||||
|
} else {
|
||||||
|
attachments = [file];
|
||||||
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
attachments = [file];
|
attachments = [file];
|
||||||
console.log('Err in read certificate sendmailv3', err);
|
console.log('Err in read certificate sendmailv3', err);
|
||||||
@@ -143,6 +147,14 @@ export default async function sendMailGmailProvider(_extRes, template) {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
console.log('gmail provider res: ', response?.status);
|
console.log('gmail provider res: ', response?.status);
|
||||||
|
const certificatePath = './exports/certificate.pdf';
|
||||||
|
if (fs.existsSync(certificatePath)) {
|
||||||
|
try {
|
||||||
|
fs.unlinkSync(certificatePath);
|
||||||
|
} catch (err) {
|
||||||
|
console.log('Err in unlink certificate sendmailgmail provider');
|
||||||
|
}
|
||||||
|
}
|
||||||
return { code: 200, message: 'Email sent successfully' };
|
return { code: 200, message: 'Email sent successfully' };
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error sending email:', error);
|
console.error('Error sending email:', error);
|
||||||
|
|||||||
@@ -187,6 +187,111 @@ async function sendMailProvider(req, plan, monthchange) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
async function sendcustomsmtp(extRes, req) {
|
||||||
|
const smtpsecure = extRes.SmtpConfig.port !== '465' ? false : true;
|
||||||
|
const transporterSMTP = createTransport({
|
||||||
|
host: extRes.SmtpConfig.host,
|
||||||
|
port: extRes.SmtpConfig.port,
|
||||||
|
secure: smtpsecure,
|
||||||
|
auth: { user: extRes.SmtpConfig.username, pass: extRes.SmtpConfig.password },
|
||||||
|
});
|
||||||
|
if (req.params.url) {
|
||||||
|
let Pdf = fs.createWriteStream('test.pdf');
|
||||||
|
const writeToLocalDisk = () => {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
if (useLocal !== 'true') {
|
||||||
|
https.get(req.params.url, async function (response) {
|
||||||
|
response.pipe(Pdf);
|
||||||
|
response.on('end', () => resolve('success'));
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
const path = new URL(req.params.url)?.pathname;
|
||||||
|
const localurl = 'http://localhost:8080' + path;
|
||||||
|
http.get(localurl, async function (response) {
|
||||||
|
response.pipe(Pdf);
|
||||||
|
response.on('end', () => resolve('success'));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
// `writeToLocalDisk` is used to create pdf file from doc url
|
||||||
|
const ress = await writeToLocalDisk();
|
||||||
|
if (ress) {
|
||||||
|
function readTolocal() {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
setTimeout(() => {
|
||||||
|
let PdfBuffer = fs.readFileSync(Pdf.path);
|
||||||
|
resolve(PdfBuffer);
|
||||||
|
}, 100);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// `PdfBuffer` used to create buffer from pdf file
|
||||||
|
let PdfBuffer = await readTolocal();
|
||||||
|
const pdfName = req.params.pdfName ? `${req.params.pdfName}.pdf` : 'exported.pdf';
|
||||||
|
const file = { filename: pdfName, content: PdfBuffer };
|
||||||
|
let attachment;
|
||||||
|
const certificatePath = './exports/certificate.pdf';
|
||||||
|
if (fs.existsSync(certificatePath)) {
|
||||||
|
try {
|
||||||
|
// `certificateBuffer` used to create buffer from pdf file
|
||||||
|
const certificateBuffer = fs.readFileSync(certificatePath);
|
||||||
|
const certificate = { filename: 'certificate.pdf', content: certificateBuffer };
|
||||||
|
attachment = [file, certificate];
|
||||||
|
} catch (err) {
|
||||||
|
attachment = [file];
|
||||||
|
console.log('Err in read certificate sendmailv3', err);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
attachment = [file];
|
||||||
|
}
|
||||||
|
const from = req.params.from || '';
|
||||||
|
const mailsender = extRes.SmtpConfig.username;
|
||||||
|
|
||||||
|
const messageParams = {
|
||||||
|
from: from + ' <' + mailsender + '>',
|
||||||
|
to: req.params.recipient,
|
||||||
|
subject: req.params.subject,
|
||||||
|
text: req.params.text || 'mail',
|
||||||
|
html: req.params.html || '',
|
||||||
|
attachments: attachment,
|
||||||
|
};
|
||||||
|
const res = await transporterSMTP.sendMail(messageParams);
|
||||||
|
console.log('custom smtp transporter res: ', res?.response);
|
||||||
|
if (!res.err) {
|
||||||
|
if (req.params?.extUserId) {
|
||||||
|
await updateMailCount(req.params.extUserId); //, plan, monthchange
|
||||||
|
}
|
||||||
|
if (fs.existsSync(certificatePath)) {
|
||||||
|
try {
|
||||||
|
fs.unlinkSync(certificatePath);
|
||||||
|
} catch (err) {
|
||||||
|
console.log('Err in unlink certificate sendmailv3');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return { status: 'success', code: 200 };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const from = req.params.from || '';
|
||||||
|
const mailsender = extRes.SmtpConfig.username;
|
||||||
|
const messageParams = {
|
||||||
|
from: from + ' <' + mailsender + '>',
|
||||||
|
to: req.params.recipient,
|
||||||
|
subject: req.params.subject,
|
||||||
|
text: req.params.text || 'mail',
|
||||||
|
html: req.params.html || '',
|
||||||
|
};
|
||||||
|
|
||||||
|
const res = await transporterSMTP.sendMail(messageParams);
|
||||||
|
console.log('custom smtp transporter res: ', res?.response);
|
||||||
|
if (!res.err) {
|
||||||
|
if (req.params?.extUserId) {
|
||||||
|
await updateMailCount(req.params.extUserId); //, plan, monthchange
|
||||||
|
}
|
||||||
|
return { status: 'success', code: 200 };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
async function sendmailv3(req) {
|
async function sendmailv3(req) {
|
||||||
const mailProvider = req.params.mailProvider || 'default';
|
const mailProvider = req.params.mailProvider || 'default';
|
||||||
if (mailProvider) {
|
if (mailProvider) {
|
||||||
@@ -206,7 +311,11 @@ async function sendmailv3(req) {
|
|||||||
const extRes = await extUserQuery.get(extUserId, { useMasterKey: true });
|
const extRes = await extUserQuery.get(extUserId, { useMasterKey: true });
|
||||||
if (extRes) {
|
if (extRes) {
|
||||||
const _extRes = JSON.parse(JSON.stringify(extRes));
|
const _extRes = JSON.parse(JSON.stringify(extRes));
|
||||||
if (_extRes.google_refresh_token && mailProvider === 'google') {
|
if (
|
||||||
|
_extRes.active_mail_adapter === 'google' &&
|
||||||
|
_extRes.google_refresh_token &&
|
||||||
|
mailProvider === 'google'
|
||||||
|
) {
|
||||||
const res = await sendMailGmailProvider(_extRes, template);
|
const res = await sendMailGmailProvider(_extRes, template);
|
||||||
if (res.code === 200) {
|
if (res.code === 200) {
|
||||||
await updateMailCount(req.params.extUserId);
|
await updateMailCount(req.params.extUserId);
|
||||||
@@ -214,6 +323,14 @@ async function sendmailv3(req) {
|
|||||||
} else {
|
} else {
|
||||||
return { status: 'error' };
|
return { status: 'error' };
|
||||||
}
|
}
|
||||||
|
} else if (_extRes.active_mail_adapter === 'smtp' && mailProvider === 'smtp') {
|
||||||
|
const res = await sendcustomsmtp(_extRes, req);
|
||||||
|
if (res.code === 200) {
|
||||||
|
await updateMailCount(req.params.extUserId);
|
||||||
|
return { status: 'success' };
|
||||||
|
} else {
|
||||||
|
return { status: 'error' };
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
if (Plan && Plan === 'freeplan') {
|
if (Plan && Plan === 'freeplan') {
|
||||||
let MonthlyFreeEmails = _extRes?.MonthlyFreeEmails || 0;
|
let MonthlyFreeEmails = _extRes?.MonthlyFreeEmails || 0;
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
<br />
|
<br />
|
||||||
<p><a href="{{{link}}}" style="background-color: lightskyblue; cursor: pointer; border-radius: 5px; padding: 10px; border-style: solid; border-width: 2px; text-decoration: none; font-weight: bolder; color:blue">Verify email</a></p>
|
<p><a href="{{{link}}}" style="background-color: lightskyblue; cursor: pointer; border-radius: 5px; padding: 10px; border-style: solid; border-width: 2px; text-decoration: none; font-weight: bolder; color:blue">Verify email</a></p>
|
||||||
<br />
|
<br />
|
||||||
<p><a href="https://www.opensignlabs.com">OpenSign™</a></p>
|
<p><a href="https://www.opensignlabs.com">{{appName}}</a></p>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
OpenSign™ Email Address Verification
|
{{appName}} Email Address Verification
|
||||||
@@ -17,7 +17,7 @@ import { exec } from 'child_process';
|
|||||||
import { createTransport } from 'nodemailer';
|
import { createTransport } from 'nodemailer';
|
||||||
import { app as v1 } from './cloud/customRoute/v1/apiV1.js';
|
import { app as v1 } from './cloud/customRoute/v1/apiV1.js';
|
||||||
import { PostHog } from 'posthog-node';
|
import { PostHog } from 'posthog-node';
|
||||||
import { cloudServerUrl, smtpenable, smtpsecure, useLocal } from './Utils.js';
|
import { appName, cloudServerUrl, smtpenable, smtpsecure, useLocal } from './Utils.js';
|
||||||
import { SSOAuth } from './auth/authadapter.js';
|
import { SSOAuth } from './auth/authadapter.js';
|
||||||
let fsAdapter;
|
let fsAdapter;
|
||||||
if (useLocal !== 'true') {
|
if (useLocal !== 'true') {
|
||||||
@@ -102,7 +102,7 @@ export const config = {
|
|||||||
verifyUserEmails: false,
|
verifyUserEmails: false,
|
||||||
publicServerURL: process.env.SERVER_URL || cloudServerUrl,
|
publicServerURL: process.env.SERVER_URL || cloudServerUrl,
|
||||||
// Your apps name. This will appear in the subject and body of the emails that are sent.
|
// Your apps name. This will appear in the subject and body of the emails that are sent.
|
||||||
appName: 'Opensign',
|
appName: appName,
|
||||||
allowClientClassCreation: false,
|
allowClientClassCreation: false,
|
||||||
allowExpiredAuthDataToken: false,
|
allowExpiredAuthDataToken: false,
|
||||||
encodeParseObjectInCloudFunction: true,
|
encodeParseObjectInCloudFunction: true,
|
||||||
@@ -112,7 +112,7 @@ export const config = {
|
|||||||
module: 'parse-server-api-mail-adapter',
|
module: 'parse-server-api-mail-adapter',
|
||||||
options: {
|
options: {
|
||||||
// The email address from which emails are sent.
|
// The email address from which emails are sent.
|
||||||
sender: 'Opensign™' + ' <' + mailsender + '>',
|
sender: appName + ' <' + mailsender + '>',
|
||||||
// The email templates.
|
// The email templates.
|
||||||
templates: {
|
templates: {
|
||||||
// The template used by Parse Server to send an email for password
|
// The template used by Parse Server to send an email for password
|
||||||
@@ -141,12 +141,7 @@ export const config = {
|
|||||||
}
|
}
|
||||||
: {}),
|
: {}),
|
||||||
filesAdapter: fsAdapter,
|
filesAdapter: fsAdapter,
|
||||||
auth: {
|
auth: { google: { enabled: true }, sso: SSOAuth },
|
||||||
google: {
|
|
||||||
enabled: true,
|
|
||||||
},
|
|
||||||
sso: SSOAuth,
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
// Client-keys like the javascript key or the .NET key are not necessary with parse-server
|
// Client-keys like the javascript key or the .NET key are not necessary with parse-server
|
||||||
// If you wish you require them, you can set them as options in the initialization above:
|
// If you wish you require them, you can set them as options in the initialization above:
|
||||||
|
|||||||
Generated
+184
-696
File diff suppressed because it is too large
Load Diff
@@ -24,24 +24,24 @@
|
|||||||
"@signpdf/placeholder-pdf-lib": "^3.2.4",
|
"@signpdf/placeholder-pdf-lib": "^3.2.4",
|
||||||
"@signpdf/signer-p12": "^3.2.4",
|
"@signpdf/signer-p12": "^3.2.4",
|
||||||
"@signpdf/signpdf": "^3.2.4",
|
"@signpdf/signpdf": "^3.2.4",
|
||||||
"aws-sdk": "^2.1687.0",
|
"aws-sdk": "^2.1691.0",
|
||||||
"axios": "^1.7.7",
|
"axios": "^1.7.7",
|
||||||
"cors": "^2.8.5",
|
"cors": "^2.8.5",
|
||||||
"dotenv": "^16.4.5",
|
"dotenv": "^16.4.5",
|
||||||
"express": "^4.21.0",
|
"express": "^4.21.0",
|
||||||
"form-data": "^4.0.0",
|
"form-data": "^4.0.0",
|
||||||
"generate-api-key": "^1.0.2",
|
"generate-api-key": "^1.0.2",
|
||||||
"googleapis": "^140.0.1",
|
"googleapis": "^144.0.0",
|
||||||
"jsonschema": "^1.4.1",
|
"jsonschema": "^1.4.1",
|
||||||
"mailgun.js": "^10.2.3",
|
"mailgun.js": "^10.2.3",
|
||||||
"mongoose": "^8.6.1",
|
"mongoose": "^8.6.3",
|
||||||
"multer": "^1.4.5-lts.1",
|
"multer": "^1.4.5-lts.1",
|
||||||
"multer-s3": "^3.0.1",
|
"multer-s3": "^3.0.1",
|
||||||
"node-forge": "^1.3.1",
|
"node-forge": "^1.3.1",
|
||||||
"nodemailer": "^6.9.15",
|
"nodemailer": "^6.9.15",
|
||||||
"parse": "^5.3.0",
|
"parse": "^5.3.0",
|
||||||
"parse-dbtool": "^1.2.0",
|
"parse-dbtool": "^1.2.0",
|
||||||
"parse-server": "^7.2.0",
|
"parse-server": "^7.3.0-alpha.8",
|
||||||
"parse-server-api-mail-adapter": "^4.0.0",
|
"parse-server-api-mail-adapter": "^4.0.0",
|
||||||
"pdf-lib": "^1.17.1",
|
"pdf-lib": "^1.17.1",
|
||||||
"posthog-node": "^4.2.0",
|
"posthog-node": "^4.2.0",
|
||||||
@@ -50,11 +50,11 @@
|
|||||||
"type": "module",
|
"type": "module",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/eslint-parser": "^7.25.1",
|
"@babel/eslint-parser": "^7.25.1",
|
||||||
"eslint": "^9.9.1",
|
"eslint": "^9.11.1",
|
||||||
"jasmine": "^5.3.0",
|
"jasmine": "^5.3.0",
|
||||||
"mongodb-runner": "^5.6.6",
|
"mongodb-runner": "^5.6.6",
|
||||||
"nodemon": "^3.1.4",
|
"nodemon": "^3.1.7",
|
||||||
"nyc": "^17.0.0",
|
"nyc": "^17.1.0",
|
||||||
"prettier": "^3.3.3"
|
"prettier": "^3.3.3"
|
||||||
},
|
},
|
||||||
"overrides": {
|
"overrides": {
|
||||||
|
|||||||
Reference in New Issue
Block a user