mirror of
https://github.com/OpenSignLabs/OpenSign.git
synced 2026-09-03 16:28:56 +02:00
Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
98aa69b884 |
+3
-4
@@ -8,11 +8,13 @@ PUBLIC_URL=https://localhost:3001
|
||||
GENERATE_SOURCEMAP=false
|
||||
# Set it to the URL from where APIs will be accessible, for local development it should be localhost:3000/api/app (use your local port number instead)
|
||||
# REACT_APP_SERVERURL=http://localhost:8080/app
|
||||
# (DEPRECATED) This should not be changed if provided; it should be 'opensign'.
|
||||
# A 12 character long random app identifier. The value of this should be same as APP_ID which is a variable used by backend API.
|
||||
REACT_APP_APPID=opensign
|
||||
|
||||
|
||||
# Backend ExpressJS config ****************************************************************************************************************************************************************************************
|
||||
# A 12 character long random app identifier. The value of this should be same as REACT_APP_APPID which is a variable used by Frontend React App.
|
||||
APP_ID=opensign
|
||||
# Name of the app. It will be visible in the verification emails sent out.
|
||||
appName=open_sign_server
|
||||
# A 12 character long random secret key that allows access to all the data. It is used in Parse dashboard config to view all the data in the database.
|
||||
@@ -109,6 +111,3 @@ CRUxFgQUDYlgGVxSxuOknhQc256x3++7BDwwMTAhMAkGBSsOAwIaBQAEFFjASdYl
|
||||
|
||||
# Provide Pass pharse of above PFX or p12 document
|
||||
PASS_PHRASE=opensign
|
||||
|
||||
# (DEPRECATED) This should not be changed if provided; it should be 'opensign'.
|
||||
APP_ID=opensign
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{$HOST_URL} {
|
||||
reverse_proxy client:3000
|
||||
handle_path /api/* {
|
||||
handle_path /app/* {
|
||||
reverse_proxy server:8080
|
||||
rewrite * {uri}
|
||||
rewrite * /app{uri}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,7 +77,7 @@ Welcome to OpenSign, the premier open source docusign alternative - document e-s
|
||||
|
||||
The simplest way to install OpenSign on your own server is using official docker images by running the following command -
|
||||
```
|
||||
export HOST_URL=https://opensign.yourdomain.com && curl --remote-name-all https://raw.githubusercontent.com/OpenSignLabs/OpenSign/main/docker-compose.yml https://raw.githubusercontent.com/OpenSignLabs/OpenSign/main/Caddyfile https://raw.githubusercontent.com/OpenSignLabs/OpenSign/main/.env.local_dev && mv .env.local_dev .env.prod && docker compose up --force-recreate
|
||||
export HOST_URL=https://opensign.yourdomain.com && curl --remote-name-all https://raw.githubusercontent.com/OpenSignLabs/OpenSign/docker_beta/docker-compose.yml https://raw.githubusercontent.com/OpenSignLabs/OpenSign/docker_beta/Caddyfile https://raw.githubusercontent.com/OpenSignLabs/OpenSign/docker_beta/.env.local_dev && mv .env.local_dev .env.prod && docker compose up --force-recreate
|
||||
```
|
||||
Make sure that you have `Docker` and `git` installed before you run this command -
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Use an official Node runtime as the base image
|
||||
FROM node:22.14.0
|
||||
FROM node:18
|
||||
|
||||
# Set the working directory inside the container
|
||||
WORKDIR /usr/src/app
|
||||
@@ -16,7 +16,8 @@ COPY apps/OpenSign/.husky .
|
||||
|
||||
# Define environment variables if needed
|
||||
ENV NODE_ENV=production
|
||||
ENV GENERATE_SOURCEMAP=false
|
||||
ENV REACT_APP_DEPLOYMENT=free_selfhost
|
||||
|
||||
# build
|
||||
RUN npm run build
|
||||
|
||||
|
||||
Generated
+161
-67
@@ -9,7 +9,7 @@
|
||||
"version": "0.1.0",
|
||||
"dependencies": {
|
||||
"@formkit/auto-animate": "^0.8.2",
|
||||
"@lottiefiles/dotlottie-react": "^0.13.0",
|
||||
"@lottiefiles/dotlottie-react": "^0.12.3",
|
||||
"@pdf-lib/fontkit": "^1.1.1",
|
||||
"@radix-ui/themes": "^3.1.6",
|
||||
"@react-pdf/renderer": "^4.1.6",
|
||||
@@ -47,7 +47,7 @@
|
||||
"react-redux": "^9.2.0",
|
||||
"react-rnd": "^10.4.14",
|
||||
"react-router": "^7.1.5",
|
||||
"react-scripts": "^5.0.1",
|
||||
"react-scripts": "5.0.1",
|
||||
"react-scrollbars-custom": "^4.1.1",
|
||||
"react-select": "^5.10.0",
|
||||
"react-signature-canvas": "^1.0.7",
|
||||
@@ -63,13 +63,13 @@
|
||||
"styled-components": "^5.3.0",
|
||||
"web-vitals": "^4.2.4",
|
||||
"ws": "^8.18.0",
|
||||
"xlsx": "https://cdn.sheetjs.com/xlsx-0.20.3/xlsx-0.20.3.tgz"
|
||||
"xlsx": "^0.18.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.26.9",
|
||||
"@babel/preset-env": "^7.26.9",
|
||||
"@babel/core": "^7.26.8",
|
||||
"@babel/preset-env": "^7.26.8",
|
||||
"@babel/preset-react": "^7.26.3",
|
||||
"@babel/runtime-corejs2": "^7.26.9",
|
||||
"@babel/runtime-corejs2": "^7.26.7",
|
||||
"autoprefixer": "^10.4.20",
|
||||
"babel-loader": "^9.2.1",
|
||||
"commitizen": "^4.3.1",
|
||||
@@ -156,21 +156,22 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/core": {
|
||||
"version": "7.26.9",
|
||||
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.26.9.tgz",
|
||||
"integrity": "sha512-lWBYIrF7qK5+GjY5Uy+/hEgp8OJWOD/rpy74GplYRhEauvbHDeFB8t5hPOZxCZ0Oxf4Cc36tK51/l3ymJysrKw==",
|
||||
"version": "7.26.8",
|
||||
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.26.8.tgz",
|
||||
"integrity": "sha512-l+lkXCHS6tQEc5oUpK28xBOZ6+HwaH7YwoYQbLFiYb4nS2/l1tKnZEtEWkD0GuiYdvArf9qBS0XlQGXzPMsNqQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@ampproject/remapping": "^2.2.0",
|
||||
"@babel/code-frame": "^7.26.2",
|
||||
"@babel/generator": "^7.26.9",
|
||||
"@babel/generator": "^7.26.8",
|
||||
"@babel/helper-compilation-targets": "^7.26.5",
|
||||
"@babel/helper-module-transforms": "^7.26.0",
|
||||
"@babel/helpers": "^7.26.9",
|
||||
"@babel/parser": "^7.26.9",
|
||||
"@babel/template": "^7.26.9",
|
||||
"@babel/traverse": "^7.26.9",
|
||||
"@babel/types": "^7.26.9",
|
||||
"@babel/helpers": "^7.26.7",
|
||||
"@babel/parser": "^7.26.8",
|
||||
"@babel/template": "^7.26.8",
|
||||
"@babel/traverse": "^7.26.8",
|
||||
"@babel/types": "^7.26.8",
|
||||
"@types/gensync": "^1.0.0",
|
||||
"convert-source-map": "^2.0.0",
|
||||
"debug": "^4.1.0",
|
||||
"gensync": "^1.0.0-beta.2",
|
||||
@@ -211,13 +212,13 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/generator": {
|
||||
"version": "7.26.9",
|
||||
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.26.9.tgz",
|
||||
"integrity": "sha512-kEWdzjOAUMW4hAyrzJ0ZaTOu9OmpyDIQicIh0zg0EEcEkYXZb2TjtBhnHi2ViX7PKwZqF4xwqfAm299/QMP3lg==",
|
||||
"version": "7.26.8",
|
||||
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.26.8.tgz",
|
||||
"integrity": "sha512-ef383X5++iZHWAXX0SXQR6ZyQhw/0KtTkrTz61WXRhFM6dhpHulO/RJz79L8S6ugZHJkOOkUrUdxgdF2YiPFnA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/parser": "^7.26.9",
|
||||
"@babel/types": "^7.26.9",
|
||||
"@babel/parser": "^7.26.8",
|
||||
"@babel/types": "^7.26.8",
|
||||
"@jridgewell/gen-mapping": "^0.3.5",
|
||||
"@jridgewell/trace-mapping": "^0.3.25",
|
||||
"jsesc": "^3.0.2"
|
||||
@@ -445,25 +446,24 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/helpers": {
|
||||
"version": "7.26.9",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.26.9.tgz",
|
||||
"integrity": "sha512-Mz/4+y8udxBKdmzt/UjPACs4G3j5SshJJEFFKxlCGPydG4JAHXxjWjAwjd09tf6oINvl1VfMJo+nB7H2YKQ0dA==",
|
||||
"license": "MIT",
|
||||
"version": "7.26.7",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.26.7.tgz",
|
||||
"integrity": "sha512-8NHiL98vsi0mbPQmYAGWwfcFaOy4j2HY49fXJCfuDcdE7fMIsH9a7GdaeXpIBsbT7307WU8KCMp5pUVDNL4f9A==",
|
||||
"dependencies": {
|
||||
"@babel/template": "^7.26.9",
|
||||
"@babel/types": "^7.26.9"
|
||||
"@babel/template": "^7.25.9",
|
||||
"@babel/types": "^7.26.7"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/parser": {
|
||||
"version": "7.26.9",
|
||||
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.9.tgz",
|
||||
"integrity": "sha512-81NWa1njQblgZbQHxWHpxxCzNsa3ZwvFqpUg7P+NNUU6f3UU2jBEg4OlF/J6rl8+PQGh1q6/zWScd001YwcA5A==",
|
||||
"version": "7.26.8",
|
||||
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.8.tgz",
|
||||
"integrity": "sha512-TZIQ25pkSoaKEYYaHbbxkfL36GNsQ6iFiBbeuzAkLnXayKR1yP1zFe+NxuZWWsUyvt8icPU9CCq0sgWGXR1GEw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/types": "^7.26.9"
|
||||
"@babel/types": "^7.26.8"
|
||||
},
|
||||
"bin": {
|
||||
"parser": "bin/babel-parser.js"
|
||||
@@ -1171,12 +1171,11 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/plugin-transform-for-of": {
|
||||
"version": "7.26.9",
|
||||
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.26.9.tgz",
|
||||
"integrity": "sha512-Hry8AusVm8LW5BVFgiyUReuoGzPUpdHQQqJY5bZnbbf+ngOHWuCuYFKw/BqaaWlvEUrF91HMhDtEaI1hZzNbLg==",
|
||||
"license": "MIT",
|
||||
"version": "7.25.9",
|
||||
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.25.9.tgz",
|
||||
"integrity": "sha512-LqHxduHoaGELJl2uhImHwRQudhCM50pT46rIBNvtT/Oql3nqiS3wOwP+5ten7NpYSXrrVLgtZU3DZmPtWZo16A==",
|
||||
"dependencies": {
|
||||
"@babel/helper-plugin-utils": "^7.26.5",
|
||||
"@babel/helper-plugin-utils": "^7.25.9",
|
||||
"@babel/helper-skip-transparent-expression-wrappers": "^7.25.9"
|
||||
},
|
||||
"engines": {
|
||||
@@ -1784,9 +1783,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/preset-env": {
|
||||
"version": "7.26.9",
|
||||
"resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.26.9.tgz",
|
||||
"integrity": "sha512-vX3qPGE8sEKEAZCWk05k3cpTAE3/nOYca++JA+Rd0z2NCNzabmYvEiSShKzm10zdquOIAVXsy2Ei/DTW34KlKQ==",
|
||||
"version": "7.26.8",
|
||||
"resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.26.8.tgz",
|
||||
"integrity": "sha512-um7Sy+2THd697S4zJEfv/U5MHGJzkN2xhtsR3T/SWRbVSic62nbISh51VVfU9JiO/L/Z97QczHTaFVkOU8IzNg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/compat-data": "^7.26.8",
|
||||
@@ -1818,7 +1817,7 @@
|
||||
"@babel/plugin-transform-dynamic-import": "^7.25.9",
|
||||
"@babel/plugin-transform-exponentiation-operator": "^7.26.3",
|
||||
"@babel/plugin-transform-export-namespace-from": "^7.25.9",
|
||||
"@babel/plugin-transform-for-of": "^7.26.9",
|
||||
"@babel/plugin-transform-for-of": "^7.25.9",
|
||||
"@babel/plugin-transform-function-name": "^7.25.9",
|
||||
"@babel/plugin-transform-json-strings": "^7.25.9",
|
||||
"@babel/plugin-transform-literals": "^7.25.9",
|
||||
@@ -1941,11 +1940,10 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/runtime-corejs2": {
|
||||
"version": "7.26.9",
|
||||
"resolved": "https://registry.npmjs.org/@babel/runtime-corejs2/-/runtime-corejs2-7.26.9.tgz",
|
||||
"integrity": "sha512-DHEUkm9RD4RfIThlLTemmHNFVTj9Z/augVFMuyheFjwoFv1jFjauncHrcSW6Kv1TpzTupB01zFk2iRFAh2iE9A==",
|
||||
"version": "7.26.7",
|
||||
"resolved": "https://registry.npmjs.org/@babel/runtime-corejs2/-/runtime-corejs2-7.26.7.tgz",
|
||||
"integrity": "sha512-C7fo97gUfsUP54j6GcQ+rJXyW6vgRRqF7J1ZxXesWcQtSRyzH1+eYrqFGzmU2JSUGFV0hQA2zLY/Z8AMrEx0qg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"core-js": "^2.6.12",
|
||||
"regenerator-runtime": "^0.14.0"
|
||||
@@ -1967,30 +1965,30 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/template": {
|
||||
"version": "7.26.9",
|
||||
"resolved": "https://registry.npmjs.org/@babel/template/-/template-7.26.9.tgz",
|
||||
"integrity": "sha512-qyRplbeIpNZhmzOysF/wFMuP9sctmh2cFzRAZOn1YapxBsE1i9bJIY586R/WBLfLcmcBlM8ROBiQURnnNy+zfA==",
|
||||
"version": "7.26.8",
|
||||
"resolved": "https://registry.npmjs.org/@babel/template/-/template-7.26.8.tgz",
|
||||
"integrity": "sha512-iNKaX3ZebKIsCvJ+0jd6embf+Aulaa3vNBqZ41kM7iTWjx5qzWKXGHiJUW3+nTpQ18SG11hdF8OAzKrpXkb96Q==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/code-frame": "^7.26.2",
|
||||
"@babel/parser": "^7.26.9",
|
||||
"@babel/types": "^7.26.9"
|
||||
"@babel/parser": "^7.26.8",
|
||||
"@babel/types": "^7.26.8"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/traverse": {
|
||||
"version": "7.26.9",
|
||||
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.26.9.tgz",
|
||||
"integrity": "sha512-ZYW7L+pL8ahU5fXmNbPF+iZFHCv5scFak7MZ9bwaRPLUhHh7QQEMjZUg0HevihoqCM5iSYHN61EyCoZvqC+bxg==",
|
||||
"version": "7.26.8",
|
||||
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.26.8.tgz",
|
||||
"integrity": "sha512-nic9tRkjYH0oB2dzr/JoGIm+4Q6SuYeLEiIiZDwBscRMYFJ+tMAz98fuel9ZnbXViA2I0HVSSRRK8DW5fjXStA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/code-frame": "^7.26.2",
|
||||
"@babel/generator": "^7.26.9",
|
||||
"@babel/parser": "^7.26.9",
|
||||
"@babel/template": "^7.26.9",
|
||||
"@babel/types": "^7.26.9",
|
||||
"@babel/generator": "^7.26.8",
|
||||
"@babel/parser": "^7.26.8",
|
||||
"@babel/template": "^7.26.8",
|
||||
"@babel/types": "^7.26.8",
|
||||
"debug": "^4.3.1",
|
||||
"globals": "^11.1.0"
|
||||
},
|
||||
@@ -1999,9 +1997,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/types": {
|
||||
"version": "7.26.9",
|
||||
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.9.tgz",
|
||||
"integrity": "sha512-Y3IR1cRnOxOCDvMmNiym7XpXQ93iGDDPHx+Zj+NM+rg0fBaShfQLkg+hKPaZCEvg5N/LeCo4+Rj/i3FuJsIQaw==",
|
||||
"version": "7.26.8",
|
||||
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.8.tgz",
|
||||
"integrity": "sha512-eUuWapzEGWFEpHFxgEaBG8e3n6S8L3MSu0oda755rOfabWPnh0Our1AozNFVUxGFIhbKgd1ksprsoDGMinTOTA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/helper-string-parser": "^7.25.9",
|
||||
@@ -3659,10 +3657,9 @@
|
||||
"integrity": "sha512-Vo+PSpZG2/fmgmiNzYK9qWRh8h/CHrwD0mo1h1DzL4yzHNSfWYujGTYsWGreD000gcgmZ7K4Ys6Tx9TxtsKdDw=="
|
||||
},
|
||||
"node_modules/@lottiefiles/dotlottie-react": {
|
||||
"version": "0.13.0",
|
||||
"resolved": "https://registry.npmjs.org/@lottiefiles/dotlottie-react/-/dotlottie-react-0.13.0.tgz",
|
||||
"integrity": "sha512-zSOqA/P6MAOjHWTBiQd2T/NAbIFDVM2rsCSVHjjBHvYZ1yB5ehdggUBVnj83Fb99xAgCdcHYWTC1c9Yl70zxMg==",
|
||||
"license": "MIT",
|
||||
"version": "0.12.3",
|
||||
"resolved": "https://registry.npmjs.org/@lottiefiles/dotlottie-react/-/dotlottie-react-0.12.3.tgz",
|
||||
"integrity": "sha512-b0k0Lakj2hmhyIkwJSpKySh6xoelpgWRaijyrCb6fraOCnzuitKglVTtYs0VWf72rk+2aSmC/0IK8j8wruVfOw==",
|
||||
"dependencies": {
|
||||
"@lottiefiles/dotlottie-web": "0.40.1"
|
||||
},
|
||||
@@ -6841,6 +6838,22 @@
|
||||
"@types/send": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/gensync": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@types/gensync/-/gensync-1.0.4.tgz",
|
||||
"integrity": "sha512-C3YYeRQWp2fmq9OryX+FoDy8nXS6scQ7dPptD8LnFDAUNcKWJjXQKDNJD3HVm+kOUsXhTOkpi69vI4EuAr95bA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/glob": {
|
||||
"version": "7.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.2.0.tgz",
|
||||
"integrity": "sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/minimatch": "*",
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/graceful-fs": {
|
||||
"version": "4.1.9",
|
||||
"resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz",
|
||||
@@ -7592,6 +7605,14 @@
|
||||
"node": ">=8.9"
|
||||
}
|
||||
},
|
||||
"node_modules/adler-32": {
|
||||
"version": "1.3.1",
|
||||
"resolved": "https://registry.npmjs.org/adler-32/-/adler-32-1.3.1.tgz",
|
||||
"integrity": "sha512-ynZ4w/nUUv5rrsR8UUGoe1VC9hZj6V5hU9Qw1HlMDJGEJw5S7TfTErWTjMys6M7vr0YWcPqs3qAr4ss0nDfP+A==",
|
||||
"engines": {
|
||||
"node": ">=0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/agent-base": {
|
||||
"version": "6.0.2",
|
||||
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz",
|
||||
@@ -8951,6 +8972,18 @@
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/cfb": {
|
||||
"version": "1.2.2",
|
||||
"resolved": "https://registry.npmjs.org/cfb/-/cfb-1.2.2.tgz",
|
||||
"integrity": "sha512-KfdUZsSOw19/ObEWasvBP/Ac4reZvAGauZhs6S/gqNhXhI7cKwvlH7ulj+dOEYnca4bm4SGo8C1bTAQvnTjgQA==",
|
||||
"dependencies": {
|
||||
"adler-32": "~1.3.0",
|
||||
"crc-32": "~1.2.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/chalk": {
|
||||
"version": "2.4.2",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
|
||||
@@ -9476,6 +9509,14 @@
|
||||
"node": ">= 4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/codepage": {
|
||||
"version": "1.15.0",
|
||||
"resolved": "https://registry.npmjs.org/codepage/-/codepage-1.15.0.tgz",
|
||||
"integrity": "sha512-3g6NUTPd/YtuuGrhMnOMRjFc+LJw/bnMp3+0r/Wcz3IXUuCosKRJvMphm5+Q+bvTVGcJJuRvVLuYba+WojaFaA==",
|
||||
"engines": {
|
||||
"node": ">=0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/collect-v8-coverage": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz",
|
||||
@@ -9900,6 +9941,17 @@
|
||||
"typescript": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/crc-32": {
|
||||
"version": "1.2.2",
|
||||
"resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz",
|
||||
"integrity": "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==",
|
||||
"bin": {
|
||||
"crc32": "bin/crc32.njs"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/cross-spawn": {
|
||||
"version": "7.0.6",
|
||||
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
|
||||
@@ -12923,6 +12975,14 @@
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/frac": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/frac/-/frac-1.1.2.tgz",
|
||||
"integrity": "sha512-w/XBfkibaTl3YDqASwfDUqkna4Z2p9cFSr1aHDt0WoMTECnRfBOv2WArlZILlqgWlmdIlALXGpM2AOhEk5W3IA==",
|
||||
"engines": {
|
||||
"node": ">=0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/fraction.js": {
|
||||
"version": "4.3.7",
|
||||
"resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz",
|
||||
@@ -22222,7 +22282,6 @@
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/react-scripts/-/react-scripts-5.0.1.tgz",
|
||||
"integrity": "sha512-8VAmEm/ZAwQzJ+GOMLbBsTdDKOpuZh7RPs0UymvBR2vRk4iZWCskjbFnxqjrzoIvlNNRZ3QJFx6/qDSi6zSnaQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/core": "^7.16.0",
|
||||
"@pmmmwh/react-refresh-webpack-plugin": "^0.5.3",
|
||||
@@ -25395,6 +25454,17 @@
|
||||
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
|
||||
"integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g=="
|
||||
},
|
||||
"node_modules/ssf": {
|
||||
"version": "0.11.2",
|
||||
"resolved": "https://registry.npmjs.org/ssf/-/ssf-0.11.2.tgz",
|
||||
"integrity": "sha512-+idbmIXoYET47hH+d7dfm2epdOMUDjqcB4648sTZ+t2JwoyBFL/insLfB/racrDmsKB3diwsDA696pZMieAC5g==",
|
||||
"dependencies": {
|
||||
"frac": "~1.1.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/stable": {
|
||||
"version": "0.1.8",
|
||||
"resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz",
|
||||
@@ -27750,6 +27820,22 @@
|
||||
"integrity": "sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/wmf": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/wmf/-/wmf-1.0.2.tgz",
|
||||
"integrity": "sha512-/p9K7bEh0Dj6WbXg4JG0xvLQmIadrner1bi45VMJTfnbVHsc7yIajZyoSoK60/dtVBs12Fm6WkUI5/3WAVsNMw==",
|
||||
"engines": {
|
||||
"node": ">=0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/word": {
|
||||
"version": "0.3.0",
|
||||
"resolved": "https://registry.npmjs.org/word/-/word-0.3.0.tgz",
|
||||
"integrity": "sha512-OELeY0Q61OXpdUfTp+oweA/vtLVg5VDOXh+3he3PNzLGG/y0oylSOC1xRVj0+l4vQ3tj/bB1HVHv1ocXkQceFA==",
|
||||
"engines": {
|
||||
"node": ">=0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/word-wrap": {
|
||||
"version": "1.2.5",
|
||||
"resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz",
|
||||
@@ -28147,10 +28233,18 @@
|
||||
}
|
||||
},
|
||||
"node_modules/xlsx": {
|
||||
"version": "0.20.3",
|
||||
"resolved": "https://cdn.sheetjs.com/xlsx-0.20.3/xlsx-0.20.3.tgz",
|
||||
"integrity": "sha512-oLDq3jw7AcLqKWH2AhCpVTZl8mf6X2YReP+Neh0SJUzV/BdZYjth94tG5toiMB1PPrYtxOCfaoUCkvtuH+3AJA==",
|
||||
"license": "Apache-2.0",
|
||||
"version": "0.18.5",
|
||||
"resolved": "https://registry.npmjs.org/xlsx/-/xlsx-0.18.5.tgz",
|
||||
"integrity": "sha512-dmg3LCjBPHZnQp5/F/+nnTa+miPJxUXB6vtk42YjBBKayDNagxGEeIdWApkYPOf3Z3pm3k62Knjzp7lMeTEtFQ==",
|
||||
"dependencies": {
|
||||
"adler-32": "~1.3.0",
|
||||
"cfb": "~1.2.1",
|
||||
"codepage": "~1.15.0",
|
||||
"crc-32": "~1.2.1",
|
||||
"ssf": "~0.11.2",
|
||||
"wmf": "~1.0.1",
|
||||
"word": "~0.3.0"
|
||||
},
|
||||
"bin": {
|
||||
"xlsx": "bin/xlsx.njs"
|
||||
},
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"@formkit/auto-animate": "^0.8.2",
|
||||
"@lottiefiles/dotlottie-react": "^0.13.0",
|
||||
"@lottiefiles/dotlottie-react": "^0.12.3",
|
||||
"@pdf-lib/fontkit": "^1.1.1",
|
||||
"@radix-ui/themes": "^3.1.6",
|
||||
"@react-pdf/renderer": "^4.1.6",
|
||||
@@ -42,7 +42,7 @@
|
||||
"react-redux": "^9.2.0",
|
||||
"react-rnd": "^10.4.14",
|
||||
"react-router": "^7.1.5",
|
||||
"react-scripts": "^5.0.1",
|
||||
"react-scripts": "5.0.1",
|
||||
"react-scrollbars-custom": "^4.1.1",
|
||||
"react-select": "^5.10.0",
|
||||
"react-signature-canvas": "^1.0.7",
|
||||
@@ -58,7 +58,7 @@
|
||||
"styled-components": "^5.3.0",
|
||||
"web-vitals": "^4.2.4",
|
||||
"ws": "^8.18.0",
|
||||
"xlsx": "https://cdn.sheetjs.com/xlsx-0.20.3/xlsx-0.20.3.tgz"
|
||||
"xlsx": "^0.18.5"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "npm run version && react-scripts build",
|
||||
@@ -96,10 +96,10 @@
|
||||
}
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.26.9",
|
||||
"@babel/preset-env": "^7.26.9",
|
||||
"@babel/core": "^7.26.8",
|
||||
"@babel/preset-env": "^7.26.8",
|
||||
"@babel/preset-react": "^7.26.3",
|
||||
"@babel/runtime-corejs2": "^7.26.9",
|
||||
"@babel/runtime-corejs2": "^7.26.7",
|
||||
"autoprefixer": "^10.4.20",
|
||||
"babel-loader": "^9.2.1",
|
||||
"commitizen": "^4.3.1",
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en" data-theme="opensigncss">
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<link rel="icon" href="/favicon.ico" />
|
||||
@@ -12,8 +11,8 @@
|
||||
<link rel="manifest" href="/manifest.json" />
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.0.0/dist/css/bootstrap.min.css"
|
||||
integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous" />
|
||||
<link rel="stylesheet" href="https://cdn.opensignlabs.com/fonts.css" />
|
||||
<title>...Loading</title>
|
||||
<link rel="stylesheet" href="https://cdn.opensignlabs.com/fonts.css" />
|
||||
<title>OpenSign™</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root" style="touch-action:pan-x pan-y;"></div>
|
||||
|
||||
@@ -51,6 +51,7 @@
|
||||
"docs": "Dokumente",
|
||||
"session-expired": "Ihre Sitzung ist abgelaufen.",
|
||||
"public-profile-help": "Dies ist Ihre öffentliche URL. Kopieren oder teilen Sie sie mit dem Unterzeichner, und Sie können alle öffentlich eingestellten Vorlagen sehen.",
|
||||
"tagline-help": "Dieser Slogan wird in Ihrem öffentlichen OpenSign-Profil angezeigt, z. B. https://opensign.me/alex",
|
||||
"welcome": "Willkommen zurück!",
|
||||
"Login-to-your-account": "Melden Sie sich bei Ihrem Konto an",
|
||||
"password": "Passwort",
|
||||
@@ -73,23 +74,12 @@
|
||||
"Sign yourself": "Selbst unterschreiben",
|
||||
"Request signatures": "Signaturen anfordern",
|
||||
"Templates": "Vorlagen",
|
||||
"Analytics": "Analytik",
|
||||
"Branding": "Markenbildung",
|
||||
"Mail": "Mail",
|
||||
"Storage": "Speicher",
|
||||
"Signing certificate": "Signierzertifikat",
|
||||
"Teams": "Teams",
|
||||
"General": "Allgemein",
|
||||
"Teams-Children": {
|
||||
"Organizations": "Organisationen",
|
||||
"OrgAdmins": "OrgAdmins"
|
||||
},
|
||||
"Templates-Children": {
|
||||
"Create template": "Vorlage erstellen",
|
||||
"Manage templates": "Vorlagen verwalten",
|
||||
"Embedding": "Einbetten"
|
||||
},
|
||||
"OpenSign™ Drive": "{{appName}} Drive",
|
||||
"OpenSign™ Drive": "OpenSign™ drive",
|
||||
"Documents": "Dokumente",
|
||||
"Reports": "Berichte",
|
||||
"Documents-Children": {
|
||||
@@ -150,8 +140,7 @@
|
||||
"Copy Public URL": "Öffentliche URL kopieren",
|
||||
"extend-expiry-date": "Ablaufdatum verlängern",
|
||||
"Duplicate Template": "Vorlage duplizieren",
|
||||
"Duplicate": "Duplikat",
|
||||
"daily-mail-quota": "Tägliches E-Mail-Kontingent"
|
||||
"Duplicate": "Duplikat"
|
||||
},
|
||||
"report-heading": {
|
||||
"Sr.No": "Nr.",
|
||||
@@ -171,7 +160,7 @@
|
||||
"Name": "Name",
|
||||
"Status": "Status",
|
||||
"created-date": "Erstellungsdatum",
|
||||
"Type": "Type",
|
||||
"Type": "Typ",
|
||||
"Logs": "Protokolle",
|
||||
"Expiry-date": "Ablaufdatum"
|
||||
},
|
||||
@@ -209,7 +198,7 @@
|
||||
"remind-once": "Einmal erinnern alle (Tage)",
|
||||
"next": "Weiter",
|
||||
"select-folder": "Ordner auswählen",
|
||||
"OpenSign-drive": "{{appName}} Drive",
|
||||
"OpenSign-drive": "OpenSign™ Drive",
|
||||
"drive-document-status": {
|
||||
"Completed": "Abgeschlossen",
|
||||
"Declined": "Abgelehnt",
|
||||
@@ -217,7 +206,7 @@
|
||||
"Expired": "Abgelaufen",
|
||||
"In Progress": "In Bearbeitung"
|
||||
},
|
||||
"select-folder-help": "Wenn Sie keinen Ordner auswählen, wird Ihr unterzeichnetes Dokument im Hauptordner des {{appName}} Drive gespeichert.",
|
||||
"select-folder-help": "Wenn Sie keinen Ordner auswählen, wird Ihr unterzeichnetes Dokument im Hauptordner des OpenSign-Drives gespeichert.",
|
||||
"no-data": "Keine Daten gefunden",
|
||||
"save-here": "Hier speichern",
|
||||
"back": "Zurück",
|
||||
@@ -289,7 +278,7 @@
|
||||
"embed-template": "Vorlage einbetten",
|
||||
"public-url-copy": "Hier ist Ihre öffentliche URL: ",
|
||||
"public-url-copy-mssg": "Kopieren oder teilen Sie diese URL, und Sie können alle öffentlich eingestellten Vorlagen sehen.",
|
||||
"add-public-url-alert": "Sie können Ihr öffentliches {{appName}} Profil generieren",
|
||||
"add-public-url-alert": "Sie können Ihr öffentliches OpenSign-Profil generieren",
|
||||
"share-with-alert": "Sie können eine Vorlage nicht teilen, wenn Rollen bereits Kontakte zugewiesen haben. Entfernen Sie bitte alle Kontaktzuweisungen von den Rollen, bevor Sie die Vorlage teilen.",
|
||||
"share-with": "Teilen mit",
|
||||
"team-not-found": "Team nicht gefunden",
|
||||
@@ -504,7 +493,7 @@
|
||||
"role-not-found": "Rolle nicht gefunden.",
|
||||
"do-not-access": "Sie haben keinen Zugriff. Bitte kontaktieren Sie den Administrator.",
|
||||
"add-admin": "Admin hinzufügen",
|
||||
"opensign-setup": "{{appName}} Einrichtung",
|
||||
"opensign-setup": "OpenSign-Einrichtung",
|
||||
"join-discord": "Treten Sie unserem Discord-Server bei",
|
||||
"admin-already-exist": "Admin existiert bereits.",
|
||||
"password-update-alert-1": "Passwort erfolgreich aktualisiert.",
|
||||
@@ -561,6 +550,7 @@
|
||||
"filed-required-correctly": "Bitte füllen Sie die erforderlichen Details korrekt aus.",
|
||||
"admin-created": "Admin erstellt",
|
||||
"invalid-masterkey": "Ungültiger Hauptschlüssel",
|
||||
"opensign-Setup": "OpenSign-Einrichtung",
|
||||
"master-key": "Hauptschlüssel",
|
||||
"profile-update-alert": "Profil erfolgreich aktualisiert.",
|
||||
"date": "Datum",
|
||||
@@ -585,7 +575,7 @@
|
||||
"tour-mssg": {
|
||||
"home-layout-1": "Sie haben sich erfolgreich angemeldet! Werfen wir einen Blick darauf.",
|
||||
"home-layout-2": "Um Dokumente zum Selbstunterzeichnen hochzuladen oder um Unterschriften anderer anzufordern, wählen Sie einfach die entsprechenden Schaltflächen.",
|
||||
"home-layout-3": "Sie sind bereit, {{appName}} zu verwenden! Wenn Sie Unterstützung benötigen, kontaktieren Sie uns gerne.",
|
||||
"home-layout-3": "Sie sind bereit, OpenSign zu verwenden! Wenn Sie Unterstützung benötigen, kontaktieren Sie uns gerne.",
|
||||
"generate-token": "Jetzt upgraden, um ein Produktions-API-Token zu generieren.",
|
||||
"opensign-drive-1": "Klicken Sie auf die Breadcrumb-Links, um einfach durch die Ordnerhierarchie zu navigieren und die Dokumente in jedem Ordner anzuzeigen.",
|
||||
"opensign-drive-2": "Klicken Sie auf die Schaltfläche Hinzufügen, um einen neuen Ordner oder ein neues Dokument zu erstellen.",
|
||||
@@ -606,7 +596,6 @@
|
||||
"placeholder-sign-4": "Ziehen Sie ein Feld in das Dokument oder klicken Sie darauf, um es hinzuzufügen.",
|
||||
"placeholder-sign-5": "Der PDF-Inhaltsbereich zeigt bereits die vorhandenen Platzhalter der Vorlage an. Diese Platzhalter entsprechen der Farbe des Empfängernamens, um sie leicht erkennbar zu machen.",
|
||||
"placeholder-sign-6": "Mit einem Klick auf 'Weiter' wird das Dokument gespeichert. Im nächsten Schritt können Sie die E-Mails, die an die Empfänger versendet werden sollen, anpassen oder die Signaturlinks kopieren und diese selbst mit den Empfängern teilen.",
|
||||
"report-1":"Klicken Sie auf die Schaltfläche „Hinzufügen“, um eine neue Vorlage zu erstellen. Vorlagen sind wiederverwendbare Dokumente, mit denen schnell neue Dokumente mit derselben Struktur und unterschiedlichen Unterzeichnern erstellt werden können. Eine HR-Vorlage für die Einarbeitung könnte beispielsweise vordefinierte Rollen wie „Personalleiter“ und „Neuer Mitarbeiter“ enthalten. Bei jeder Verwendung der Vorlage können Sie die Rolle „Neuer Mitarbeiter“ verschiedenen neuen Mitarbeitern zuweisen, während die Rolle „Personalleiter“ unverändert bleibt. So wird ein nahtloser Einarbeitungsprozess für jeden neuen Mitarbeiter ermöglicht.",
|
||||
"redirect": "Klicken Sie auf die Schaltfläche 'Verwenden', um ein neues Dokument aus einer bestehenden Vorlage zu erstellen.",
|
||||
"bulksend": "Um schnell mehrere Dokumente mithilfe einer vorhandenen Vorlage zu versenden, indem Sie einfach die E-Mail-Adressen der Empfänger erstellen, klicken Sie auf die Schaltfläche ‚Massenversand‘",
|
||||
"option": "Dieses Menü zeigt weitere Optionen wie Bearbeiten und Löschen. Verwenden Sie die Schaltfläche 'Bearbeiten', um Unterzeichnerrollen hinzuzufügen, Felder zu ändern und Ihre Vorlage zu aktualisieren. Änderungen gelten für alle zukünftigen Dokumente, die aus dieser Vorlage erstellt werden, wirken sich jedoch nicht auf vorhandene Dokumente aus. Verwenden Sie die Schaltfläche 'Löschen', um die Vorlage zu entfernen.",
|
||||
@@ -700,19 +689,19 @@
|
||||
"download-pdf": "PDF herunterladen",
|
||||
"pdf-certificate": "PDF + Zertifikat herunterladen",
|
||||
"document-logs": "Dokumentenprotokolle",
|
||||
"server-down": "Verbindung zum {{appName}} Server nicht möglich. Wenn Sie {{appName}} selbst hosten, stellen Sie bitte sicher, dass alle Schritte in der Dokumentation korrekt befolgt wurden. Wenn Sie {{appName}} lokal ausführen, verwenden Sie möglicherweise eine falsche Portnummer.",
|
||||
"server-down": "Verbindung zum OpenSign-Server nicht möglich. Wenn Sie OpenSign selbst hosten, stellen Sie bitte sicher, dass alle Schritte in der Dokumentation korrekt befolgt wurden. Wenn Sie OpenSign lokal ausführen, verwenden Sie möglicherweise eine falsche Portnummer.",
|
||||
"admin-exists": "Admin existiert bereits. Bitte melden Sie sich mit den Admin-Anmeldedaten an, um Benutzer zu verwalten.",
|
||||
"enable-tour": "Tour aktivieren",
|
||||
"istourenabled-help": {
|
||||
"p1": "Dies aktiviert eine geführte Tour für Unterzeichner, die während des Unterzeichnungsprozesses Anweisungen gibt.",
|
||||
"p2": "Dies deaktiviert die geführte Tour, wodurch ein schneller, ununterbrochener Unterzeichnungsprozess gewährleistet wird.",
|
||||
"p3": "Tipp: Wenn Ihre Unterzeichner mit {{appName}} vertraut sind und es häufig verwenden, können Sie die geführte Tour deaktivieren, um ein nahtloses Erlebnis zu gewährleisten. Wählen Sie die Option, die am besten zu Ihren Anforderungen passt."
|
||||
"p3": "Tipp: Wenn Ihre Unterzeichner mit OpenSign vertraut sind und es häufig verwenden, können Sie die geführte Tour deaktivieren, um ein nahtloses Erlebnis zu gewährleisten. Wählen Sie die Option, die am besten zu Ihren Anforderungen passt."
|
||||
},
|
||||
"form-title-1": "Dokumentenfluss-Einstellungen",
|
||||
"form-title-2": "Sicherheitseinstellungen",
|
||||
"public-tour-message": "Die Vorlage muss öffentlich sein, bevor Sie einen teilbaren Link generieren können.",
|
||||
"add-user-template": "Sie müssen eine Rolle hinzufügen, bevor Sie Felder dafür hinzufügen können.",
|
||||
"pdf-uncompatible": "Diese PDF-Datei ist nicht kompatibel, bitte kontaktieren Sie {{appName}}",
|
||||
"pdf-uncompatible": "Dieses PDF ist nicht kompatibel mit OpenSign. Bitte kontaktieren Sie <support@opensignlabs.com>",
|
||||
"text-field-tour": "Felder vom Typ 'Text' müssen im Voraus ausgefüllt werden, bevor das Dokument versendet wird. Wenn Sie möchten, dass die Unterzeichner Eingaben machen, verwenden Sie das Feld 'Texteingabe'.",
|
||||
"attach-signer-tour": "Sie müssen einen Unterzeichner jeder Rolle zuweisen. Dies können Sie durch Klicken auf dieses Symbol tun. Sobald Sie einen Unterzeichner auswählen, wird er allen Feldern der zugehörigen Rolle zugewiesen, die in derselben Farbe erscheinen.",
|
||||
"allowed-signature-types": "Erlaubte Signaturtypen",
|
||||
@@ -752,7 +741,7 @@
|
||||
"delete-folder-alert": "Sind Sie sicher, dass Sie diesen Ordner löschen möchten?",
|
||||
"delete-folder-alert-1": "Löschen nicht möglich: Der Ordner muss leer sein.",
|
||||
"defaultSign-alert": "{{widgetsType}} Widgets sind nicht für die automatische Signatur verfügbar.",
|
||||
"embed-heading": "{{appName}} Vorlagen einbetten",
|
||||
"embed-heading": "OpenSign-Vorlagen einbetten",
|
||||
"public-template-edit-title": "Öffentliche Vorlage bearbeiten",
|
||||
"public-template-edit-mssg": "Eine öffentliche Vorlage können Sie nicht direkt bearbeiten. Um Änderungen vorzunehmen, wird die Vorlage auf privat gesetzt und Sie müssen sie anschließend wieder öffentlich machen. Möchten Sie fortfahren?",
|
||||
"agree-p1": "Ich bestätige, dass ich die ",
|
||||
@@ -761,46 +750,46 @@
|
||||
"agrre-button": "Zustimmen & Fortfahren",
|
||||
"term-cond-title": "Allgemeine Geschäftsbedingungen",
|
||||
"term-cond-h": "OFFENLEGUNG ELEKTRONISCHER AUFZEICHNUNGEN UND SIGNATUREN",
|
||||
"term-cond-p1": "Diese Offenlegung elektronischer Aufzeichnungen und Signaturen ('Offenlegung') ist eine Vereinbarung zwischen dem Dokumentersteller ('Sender') und dem Unterzeichner ('Ihnen'), bereitgestellt über die {{appName}} Plattform ('Plattform'). Durch das Signieren von Dokumenten über {{appName}} stimmen Sie den in dieser Offenlegung beschriebenen Bedingungen zu. Bitte lesen Sie sie sorgfältig durch, bevor Sie fortfahren.",
|
||||
"term-cond-p1": "Diese Offenlegung elektronischer Aufzeichnungen und Signaturen ('Offenlegung') ist eine Vereinbarung zwischen dem Dokumentersteller ('Sender') und dem Unterzeichner ('Ihnen'), bereitgestellt über die OpenSign-Plattform ('Plattform'). Durch das Signieren von Dokumenten über OpenSign stimmen Sie den in dieser Offenlegung beschriebenen Bedingungen zu. Bitte lesen Sie sie sorgfältig durch, bevor Sie fortfahren.",
|
||||
"term-cond-h1": "1. Zweck und Geltungsbereich",
|
||||
"term-cond-p2": "Diese Offenlegung regelt die Nutzung elektronischer Aufzeichnungen und Signaturen für Dokumente, die vom Sender bereitgestellt und von Ihnen über die {{appName}} Plattform unterzeichnet werden. Mit Ihrer Zustimmung erkennen Sie an, dass:",
|
||||
"term-cond-p3": "Sie Dokumente elektronisch über {{appName}} empfangen und unterzeichnen werden.",
|
||||
"term-cond-p2": "Diese Offenlegung regelt die Nutzung elektronischer Aufzeichnungen und Signaturen für Dokumente, die vom Sender bereitgestellt und von Ihnen über die OpenSign-Plattform unterzeichnet werden. Mit Ihrer Zustimmung erkennen Sie an, dass:",
|
||||
"term-cond-p3": "Sie Dokumente elektronisch über OpenSign empfangen und unterzeichnen werden.",
|
||||
"term-cond-p4": "Ihre elektronische Signatur rechtlich bindend und einer handschriftlichen Signatur gleichgestellt ist.",
|
||||
"term-cond-h2": "2. Zustimmung zur Nutzung elektronischer Aufzeichnungen und Signaturen",
|
||||
"term-cond-p5": "Durch Ihre Zustimmung zu dieser Offenlegung:",
|
||||
"term-cond-p6": "Erklären Sie sich einverstanden, elektronisch mit dem Sender über {{appName}} zu kommunizieren, und verstehen, dass diese Zustimmung gültig ist, bis sie widerrufen wird.",
|
||||
"term-cond-p7": "Stimmen Sie zu, Dokumente über {{appName}} elektronisch zu prüfen, zu unterzeichnen und zurückzusenden.",
|
||||
"term-cond-p6": "Erklären Sie sich einverstanden, elektronisch mit dem Sender über OpenSign zu kommunizieren, und verstehen, dass diese Zustimmung gültig ist, bis sie widerrufen wird.",
|
||||
"term-cond-p7": "Stimmen Sie zu, Dokumente über OpenSign elektronisch zu prüfen, zu unterzeichnen und zurückzusenden.",
|
||||
"term-cond-p8": "Diese Zustimmung gilt nur für die spezifischen Dokumente, die vom Sender bereitgestellt werden.",
|
||||
"term-cond-h3": "3. Recht auf Widerruf der Zustimmung",
|
||||
"term-cond-p9": "Sie haben das Recht, Ihre Zustimmung zur Nutzung elektronischer Aufzeichnungen und Unterschriften zu widerrufen, indem Sie:",
|
||||
"term-cond-p10": "Den Absender direkt über die in seiner Kommunikation angegebenen Kontaktdaten kontaktieren.",
|
||||
"term-cond-p11": "Den Absender vor Abschluss des Unterschriftsprozesses benachrichtigen.",
|
||||
"term-cond-h4": "4. Hardware- und Softwareanforderungen",
|
||||
"term-cond-p12": "Um Dokumente mit {{appName}} zu unterzeichnen, benötigen Sie:",
|
||||
"term-cond-p12": "Um Dokumente mit OpenSign zu unterzeichnen, benötigen Sie:",
|
||||
"term-cond-p13": "Ein Gerät mit Internetzugang.",
|
||||
"term-cond-p14": "Einen kompatiblen Webbrowser mit aktiviertem JavaScript.",
|
||||
"term-cond-p15": "Ein E-Mail-Konto, um Benachrichtigungen und unterzeichnete Dokumente zu erhalten.",
|
||||
"term-cond-p16": "Wenn sich diese Anforderungen ändern, werden Sie vom Absender oder {{appName}} über die Aktualisierungen informiert.",
|
||||
"term-cond-p16": "Wenn sich diese Anforderungen ändern, werden Sie vom Absender oder OpenSign über die Aktualisierungen informiert.",
|
||||
"term-cond-h5": "5. Aufbewahrung von Unterlagen und Anforderung von Papierkopien",
|
||||
"term-cond-p17": "Sie sind dafür verantwortlich, sicherzustellen, dass Sie auf die elektronisch unterzeichneten Dokumente zugreifen und diese aufbewahren können. {{appName}} stellt Tools zur Verfügung, mit denen Sie das unterzeichnete Dokument unmittelbar nach Abschluss des Unterzeichnungsprozesses herunterladen oder ausdrucken können.",
|
||||
"term-cond-p17": "Sie sind dafür verantwortlich, sicherzustellen, dass Sie auf die elektronisch unterzeichneten Dokumente zugreifen und diese aufbewahren können. OpenSign stellt Tools zur Verfügung, mit denen Sie das unterzeichnete Dokument unmittelbar nach Abschluss des Unterzeichnungsprozesses herunterladen oder ausdrucken können.",
|
||||
"term-cond-p18": "Wenn Sie eine Papierkopie eines elektronisch unterzeichneten Dokuments bevorzugen, können Sie diese direkt beim Absender anfordern. Der Absender kann eine angemessene Gebühr für die Bereitstellung von Papierkopien erheben, sofern dies nicht durch geltendes Recht verboten ist.",
|
||||
"term-cond-h6": "6. Anerkennung und Zustimmung",
|
||||
"term-cond-p19": "Durch das Fortfahren bestätigen Sie:",
|
||||
"term-cond-p20": "Dass Sie in der Lage sind, elektronische Dokumente wie in dieser Offenlegung beschrieben zu öffnen und zu überprüfen.",
|
||||
"term-cond-p21": "Der Nutzung elektronischer Aufzeichnungen und Unterschriften für die angegebenen Transaktionen mit dem Absender zuzustimmen.",
|
||||
"term-cond-p22": "Zu verstehen, dass {{appName}} eine Plattform zur Unterstützung der Transaktion ist und keine Partei der Vereinbarung ist.",
|
||||
"term-cond-p22": "Zu verstehen, dass OpenSign eine Plattform zur Unterstützung der Transaktion ist und keine Partei der Vereinbarung ist.",
|
||||
"term-cond-h7": "7. Rechtliche Wirkung",
|
||||
"term-cond-p23": "Ihre durch {{appName}} vermittelte elektronische Unterschrift:",
|
||||
"term-cond-p23": "Ihre durch OpenSign vermittelte elektronische Unterschrift:",
|
||||
"term-cond-p24": "Entspricht den geltenden Gesetzen über elektronische Unterschriften, einschließlich, aber nicht beschränkt auf den E-SIGN Act in den Vereinigten Staaten, die EU-eIDAS-Verordnung und das indische Information Technology Act.",
|
||||
"term-cond-p25": "Ist rechtlich bindend zwischen Ihnen und dem Absender für die unterzeichneten Dokumente.",
|
||||
"term-cond-h8": "8. Plattformrolle und Haftungsbeschränkung",
|
||||
"term-cond-p26": "{{appName}} dient als Plattform zur Unterstützung elektronischer Transaktionen. Es ist nicht verantwortlich für den Inhalt, die Gültigkeit oder die Durchsetzbarkeit der vom Absender gesendeten Dokumente. Alle Streitigkeiten oder Probleme im Zusammenhang mit dem Dokument oder seiner Unterzeichnung müssen direkt zwischen Ihnen und dem Absender gelöst werden.",
|
||||
"term-cond-p26": "OpenSign dient als Plattform zur Unterstützung elektronischer Transaktionen. Es ist nicht verantwortlich für den Inhalt, die Gültigkeit oder die Durchsetzbarkeit der vom Absender gesendeten Dokumente. Alle Streitigkeiten oder Probleme im Zusammenhang mit dem Dokument oder seiner Unterzeichnung müssen direkt zwischen Ihnen und dem Absender gelöst werden.",
|
||||
"term-cond-h9": "9. Beendigung der Vereinbarung",
|
||||
"term-cond-p27": "Ihre Zustimmung gilt nur für die aktuelle Transaktion, es sei denn, der Absender gibt etwas anderes an. {{appName}} behält sich das Recht vor, den Zugriff auf seine Plattform bei Verstößen gegen die Nutzungsbedingungen oder Richtlinien zu beenden.",
|
||||
"term-cond-p28": "Durch Auswahl von 'Ich stimme zu' bestätigen Sie, dass Sie die Bedingungen dieser Offenlegung über elektronische Aufzeichnungen und Unterschriften verstanden haben und diesen zustimmen sowie der elektronischen Unterzeichnung der vom Absender über {{appName}} bereitgestellten Dokumente zustimmen.",
|
||||
"term-cond-p29": "Wenn Sie Fragen zu dieser Offenlegung haben, kontaktieren Sie den Absender direkt. Für technischen Support mit {{appName}} besuchen Sie ",
|
||||
"term-cond-p30": " oder senden Sie eine E-Mail an",
|
||||
"js-snippet-msg": "Um {{appName}} Vorlagen in Ihre HTML-Websites oder Landingpages zu integrieren, können Sie den folgenden Code verwenden:",
|
||||
"term-cond-p27": "Ihre Zustimmung gilt nur für die aktuelle Transaktion, es sei denn, der Absender gibt etwas anderes an. OpenSign behält sich das Recht vor, den Zugriff auf seine Plattform bei Verstößen gegen die Nutzungsbedingungen oder Richtlinien zu beenden.",
|
||||
"term-cond-p28": "Durch Auswahl von 'Ich stimme zu' bestätigen Sie, dass Sie die Bedingungen dieser Offenlegung über elektronische Aufzeichnungen und Unterschriften verstanden haben und diesen zustimmen sowie der elektronischen Unterzeichnung der vom Absender über OpenSign bereitgestellten Dokumente zustimmen.",
|
||||
"term-cond-p29": "Wenn Sie Fragen zu dieser Offenlegung haben, kontaktieren Sie den Absender direkt. Für technischen Support mit OpenSign besuchen Sie",
|
||||
"term-cond-p30": "oder senden Sie eine E-Mail an",
|
||||
"js-snippet-msg": "Um OpenSign-Vorlagen in Ihre HTML-Websites oder Landingpages zu integrieren, können Sie den folgenden Code verwenden:",
|
||||
"js-snippet-msg-1": "Die TemplateId erhalten Sie von der",
|
||||
"js-snippet-msg-2": "Vorlagen verwalten",
|
||||
"js-snippet-msg-3": "Seite.",
|
||||
@@ -825,8 +814,8 @@
|
||||
},
|
||||
"signature-setting": "Signatur-Einstellungen",
|
||||
"activation-key": "Aktivierungsschlüssel",
|
||||
"paid-selfhost-help": "Bitte kontaktieren Sie {{appName}} für weitere Informationen unter ",
|
||||
"remaining-credits-selfhost-help": "Verwenden Sie Premium-Credits für API-Dokumentensignaturen, den Massenversand und die {{appName}} Integration auf Ihrer Website. Sie haben {{allowedcredits}} enthaltene Credits und {{addoncredits}} zusätzlich gekaufte Credits übrig.",
|
||||
"paid-selfhost-help": "Bitte kontaktieren Sie OpenSign für weitere Informationen unter ",
|
||||
"remaining-credits-selfhost-help": "Verwenden Sie Premium-Credits für API-Dokumentensignaturen, den Massenversand und die OpenSign-Integration auf Ihrer Website. Sie haben {{allowedcredits}} enthaltene Credits und {{addoncredits}} zusätzlich gekaufte Credits übrig.",
|
||||
"signature-type": "Ihre Signatur",
|
||||
"initial-type": "Ihre Initialen",
|
||||
"redirect-url": "Weiterleitungs-URL",
|
||||
@@ -845,16 +834,5 @@
|
||||
"send-to-sign": "hat Sie gebeten zu unterschreiben",
|
||||
"use-template": "Vorlage verwenden",
|
||||
"contact-already-exists": "Der Kontakt existiert bereits.",
|
||||
"docx-error": "Wir haben derzeit Probleme mit der Verarbeitung von DOCX-Dateien. Bitte laden Sie die PDF-Datei hoch",
|
||||
"docx-error-contact": "oder kontaktieren Sie uns unter support@opensignlabs.com",
|
||||
"agreement-note": "Hinweis: Durch Ihre Zustimmung unterzeichnen Sie das Dokument nicht sofort. Sie können das Dokument nur elektronisch einsehen. Sie haben die Möglichkeit, es vollständig zu lesen und anschließend zu entscheiden, ob Sie es unterzeichnen möchten.",
|
||||
"draft-template-info-p1": "Um Ihre Vorlage öffentlich zu machen, muss sie entweder eine einzelne Rolle enthalten oder, wenn sie mehrere Rollen umfasst, müssen alle zusätzlichen Rollen bereits den Unterzeichnern zugewiesen sein. Die nicht zugewiesene öffentliche Rolle muss leer bleiben und an erster Stelle stehen.",
|
||||
"visit-below-link": "Besuchen Sie den untenstehenden Link, um mehr zu erfahren -",
|
||||
"storage-help": "Durch die Aktivierung von BYOC können Sie Ihren eigenen S3-Speicher verbinden, sodass Ihre Dateien vollständig unter Ihrer Kontrolle bleiben und keine externen Kopien gespeichert werden. Wenn Ihnen Datenautonomie wichtig ist, erwägen Sie ein Upgrade auf Teams, um diese Funktion freizuschalten.",
|
||||
"daily-quota-reached": "Sie haben Ihr tägliches Kontingent erreicht. Für Unterstützung kontaktieren Sie bitte quotas@opensignlabs.com.",
|
||||
"enabled-signature-type": "Aktivierte Signaturtypen",
|
||||
"enabled-signature-type-help": "Die Einstellung 'Aktivierte Signaturtypen' bestimmt, welche Signaturoptionen in Ihrer Organisation verfügbar sind. Wenn Sie beispielsweise die Option 'Zeichnen' deaktivieren, wird sie den Mitgliedern Ihrer Organisation im Signatur-Widget nicht angezeigt, während die anderen drei Optionen weiterhin zugänglich bleiben.",
|
||||
"indexing-public-profile": "Erlaube die Indexierung des öffentlichen Profils durch Suchmaschinen",
|
||||
"user-created-successfully": "Benutzer erfolgreich erstellt.",
|
||||
"only-15-reminder-allowed": "Sie können bis zu 15 automatische Erinnerungen festlegen. Wenn zum Beispiel 'TimeToComplete' auf 15 Tage und 'RemindOnceInEvery' auf 1 Tag eingestellt ist, erreichen Sie das maximale Limit von 15 Erinnerungen. Passen Sie Ihre Einstellungen entsprechend an."
|
||||
"agreement-note": "Hinweis: Durch Ihre Zustimmung unterzeichnen Sie das Dokument nicht sofort. Sie können das Dokument nur elektronisch einsehen. Sie haben die Möglichkeit, es vollständig zu lesen und anschließend zu entscheiden, ob Sie es unterzeichnen möchten."
|
||||
}
|
||||
|
||||
@@ -51,6 +51,7 @@
|
||||
"docs": "Docs",
|
||||
"session-expired": "Your session has expired.",
|
||||
"public-profile-help": "This is your public URL. Copy or share it with the signer, and you will be able to see all your publicly set templates.",
|
||||
"tagline-help": "This tagline will appear on your OpenSign public profile for ex. https://opensign.me/alex",
|
||||
"welcome": "Welcome back!",
|
||||
"Login-to-your-account": "Login to your account",
|
||||
"password": "Password",
|
||||
@@ -73,23 +74,12 @@
|
||||
"Sign yourself": "Sign yourself",
|
||||
"Request signatures": "Request signatures",
|
||||
"Templates": "Templates",
|
||||
"Analytics": "Analytics",
|
||||
"Branding": "Branding",
|
||||
"Mail": "Mail",
|
||||
"Storage": "Storage",
|
||||
"Signing certificate": "Signing certificate",
|
||||
"Teams": "Teams",
|
||||
"General": "General",
|
||||
"Teams-Children": {
|
||||
"Organizations": "Organizations",
|
||||
"OrgAdmins": "OrgAdmins"
|
||||
},
|
||||
"Templates-Children": {
|
||||
"Create template": "Create template",
|
||||
"Manage templates": "Manage templates",
|
||||
"Embedding": "Embedding"
|
||||
},
|
||||
"OpenSign™ Drive": "{{appName}} Drive",
|
||||
"OpenSign™ Drive": "OpenSign™ drive",
|
||||
"Reports": "Reports",
|
||||
"Documents": "Documents",
|
||||
"Documents-Children": {
|
||||
@@ -150,8 +140,7 @@
|
||||
"Copy Public URL": "Copy public URL",
|
||||
"extend-expiry-date": "Extend expiry date",
|
||||
"Duplicate Template": "Duplicate template",
|
||||
"Duplicate": "Duplicate",
|
||||
"daily-mail-quota": "Daily Email Quota"
|
||||
"Duplicate": "Duplicate"
|
||||
},
|
||||
"report-heading": {
|
||||
"Sr.No": "Sr.No",
|
||||
@@ -209,7 +198,7 @@
|
||||
"remind-once": " Remind once in every (Days)",
|
||||
"next": "Next",
|
||||
"select-folder": "Select folder",
|
||||
"OpenSign-drive": "{{appName}} Drive",
|
||||
"OpenSign-drive": "OpenSign™ drive",
|
||||
"drive-document-status": {
|
||||
"Completed": "Completed",
|
||||
"Declined": "Declined",
|
||||
@@ -217,7 +206,7 @@
|
||||
"Expired": "Expired",
|
||||
"In Progress": "In progress"
|
||||
},
|
||||
"select-folder-help": "If you do not select a folder, your signed document will be saved in the Main {{appName}} Drive folder.",
|
||||
"select-folder-help": "If you do not select a folder, your signed document will be saved in the Main OpenSign drive folder.",
|
||||
"no-data": "No data found",
|
||||
"save-here": "Save here",
|
||||
"back": "Back",
|
||||
@@ -289,7 +278,7 @@
|
||||
"embed-template": "Embed template",
|
||||
"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": "You can generate your {{appName}} public profile",
|
||||
"add-public-url-alert": "You can generate your OpenSign public profile",
|
||||
"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",
|
||||
"team-not-found": "Team not found",
|
||||
@@ -504,7 +493,7 @@
|
||||
"role-not-found": "Role not found.",
|
||||
"do-not-access": "You don't have access, please contact the admin.",
|
||||
"add-admin": "Add admin",
|
||||
"opensign-setup": "{{appName}} setup",
|
||||
"opensign-setup": "OpenSign setup",
|
||||
"join-discord": "Join our discord server",
|
||||
"admin-already-exist": "Admin already exist.",
|
||||
"password-update-alert-1": "Password updated successfully.",
|
||||
@@ -561,6 +550,7 @@
|
||||
"filed-required-correctly": "Please fill required details correctly.",
|
||||
"admin-created": "Admin created",
|
||||
"invalid-masterkey": "Invalid masterkey",
|
||||
"opensign-Setup": "OpenSign setup",
|
||||
"master-key": " Master key",
|
||||
"profile-update-alert": "Profile updated successfully.",
|
||||
"date": "Date",
|
||||
@@ -585,7 +575,7 @@
|
||||
"tour-mssg": {
|
||||
"home-layout-1": "You have logged in successfully! Let's take a look.",
|
||||
"home-layout-2": "To upload documents for self-signing or to request others’ signatures, simply select the respective buttons.",
|
||||
"home-layout-3": "You are ready to start using {{appName}}! If you need support feel free to contact us.",
|
||||
"home-layout-3": "You are ready to start using OpenSign! If you need support feel free to contact us.",
|
||||
"generate-token": "Upgrade now to generate production API token.",
|
||||
"opensign-drive-1": "Click on the breadcrumb links to easily navigate through the folder hierarchy and view the documents within each folder.",
|
||||
"opensign-drive-2": "Click the add button to create a new folder or document.",
|
||||
@@ -700,19 +690,19 @@
|
||||
"download-pdf": "Download pdf",
|
||||
"pdf-certificate": "Download pdf + Certificate",
|
||||
"document-logs": "Document logs",
|
||||
"server-down": "Unable to connect to the {{appName}} server. If you are self-hosting {{appName}}, please ensure that all the steps in the documentation have been followed correctly. If you're running {{appName}} locally, you might be accessing it through an incorrect port number.",
|
||||
"server-down": "Unable to connect to the OpenSign server. If you are self-hosting OpenSign, please ensure that all the steps in the documentation have been followed correctly. If you're running OpenSign locally, you might be accessing it through an incorrect port number.",
|
||||
"admin-exists": "Admin already exists. Please login to the application using admin credentials in order to manage users.",
|
||||
"enable-tour": "Enable tour",
|
||||
"istourenabled-help": {
|
||||
"p1": "This will enable a guided tour for signers, providing instructions during the signing process.",
|
||||
"p2": "This will disable the guided tour, ensuring a faster, uninterrupted signing experience.",
|
||||
"p3": "Tip: If your signers are familiar with {{appName}} and frequently use it, you may want to disable the guided tour for a more seamless experience. Choose the option that best fits your document signing needs."
|
||||
"p3": "Tip: If your signers are familiar with OpenSign and frequently use it, you may want to disable the guided tour for a more seamless experience. Choose the option that best fits your document signing needs."
|
||||
},
|
||||
"form-title-1": "Document flow setting",
|
||||
"form-title-2": "Security settings",
|
||||
"public-tour-message": "The template needs to be public before you can generate a shareable link.",
|
||||
"add-user-template": "You need to add a role before you can add fields for it.",
|
||||
"pdf-uncompatible": "This pdf is not compatible, please contact {{appName}}",
|
||||
"pdf-uncompatible": "This pdf is not compatible with opensign, please contact <support@opensignlabs.com>",
|
||||
"text-field-tour": "Fields of type 'Text' must be filled in advance before the document is sent. If you need the signers to provide input, use the 'Text Input' field instead.",
|
||||
"attach-signer-tour": "You need to attach a Signer to every role. You can do that by clicking this icon. Once you select a Signer it will be attached to all the fields associated with that role which appear in the same colour.",
|
||||
"allowed-signature-types": "Allowed signature types",
|
||||
@@ -752,7 +742,7 @@
|
||||
"delete-folder-alert": "Are you sure you want to delete this Folder ?",
|
||||
"delete-folder-alert-1": "Unable to delete: The folder must be empty.",
|
||||
"defaultSign-alert": "{{widgetsType}} widgets are not available for auto sign.",
|
||||
"embed-heading": "Embed {{appName}} Templates",
|
||||
"embed-heading": "Embed OpenSign Templates",
|
||||
"public-template-edit-title": "Edit Public Template",
|
||||
"public-template-edit-mssg": "You cannot edit a public template directly. To make changes, the template will be set to private, and you'll need to make it public again afterward. Do you want to continue?",
|
||||
"agree-p1": "I confirm that I have read and understood the ",
|
||||
@@ -761,46 +751,46 @@
|
||||
"agrre-button": " Agree & Continue",
|
||||
"term-cond-title": "Terms and conditions",
|
||||
"term-cond-h": "ELECTRONIC RECORD AND SIGNATURE DISCLOSURE",
|
||||
"term-cond-p1": "This Electronic Record and Signature Disclosure ('Disclosure') is an agreement between the Document Creator ('Sender') and the Signer ('You'), facilitated through the {{appName}} platform ('Platform'). By signing documents via {{appName}}, you agree to the terms outlined in this Disclosure. Please read it carefully before proceeding.",
|
||||
"term-cond-p1": "This Electronic Record and Signature Disclosure ('Disclosure') is an agreement between the Document Creator ('Sender') and the Signer ('You'), facilitated through the OpenSign platform ('Platform'). By signing documents via OpenSign, you agree to the terms outlined in this Disclosure. Please read it carefully before proceeding.",
|
||||
"term-cond-h1": "1. Purpose and Scope",
|
||||
"term-cond-p2": "This Disclosure governs the use of electronic records and signatures for documents sent by the Sender and signed by You through the {{appName}} platform. By agreeing, You acknowledge that:",
|
||||
"term-cond-p3": "You will receive and sign documents electronically via {{appName}}.",
|
||||
"term-cond-p2": "This Disclosure governs the use of electronic records and signatures for documents sent by the Sender and signed by You through the OpenSign platform. By agreeing, You acknowledge that:",
|
||||
"term-cond-p3": "You will receive and sign documents electronically via OpenSign.",
|
||||
"term-cond-p4": "Your electronic signature is legally binding and equivalent to a handwritten signature.",
|
||||
"term-cond-h2": "2. Consent to Use Electronic Records and Signatures",
|
||||
"term-cond-p5": "By agreeing to this Disclosure:",
|
||||
"term-cond-p6": "You consent to transact electronically with the Sender using {{appName}} and understand that this consent is valid until withdrawn.",
|
||||
"term-cond-p7": "You agree to review, sign, and return documents electronically using {{appName}}.",
|
||||
"term-cond-p6": "You consent to transact electronically with the Sender using OpenSign and understand that this consent is valid until withdrawn.",
|
||||
"term-cond-p7": "You agree to review, sign, and return documents electronically using OpenSign.",
|
||||
"term-cond-p8": "This consent applies only to the specific document(s) provided by the Sender.",
|
||||
"term-cond-h3": "3. Right to Withdraw Consent",
|
||||
"term-cond-p9": "You have the right to withdraw your consent to use electronic records and signatures by:",
|
||||
"term-cond-p10": "Contacting the Sender directly using the contact information provided in their communication.",
|
||||
"term-cond-p11": "Notifying the Sender before completing the signing process.",
|
||||
"term-cond-h4": "4. Hardware and Software Requirements",
|
||||
"term-cond-p12": "To sign documents using {{appName}}, You must have:",
|
||||
"term-cond-p12": "To sign documents using OpenSign, You must have:",
|
||||
"term-cond-p13": "A device with internet access.",
|
||||
"term-cond-p14": "A compatible web browser with JavaScript enabled.",
|
||||
"term-cond-p15": "An email account to receive notifications and signed documents.",
|
||||
"term-cond-p16": "If these requirements change, the Sender or {{appName}} will notify You of the updates.",
|
||||
"term-cond-p16": "If these requirements change, the Sender or OpenSign will notify You of the updates.",
|
||||
"term-cond-h5": "5. Retention of Records and Request for Paper Copies",
|
||||
"term-cond-p17": "You are responsible for ensuring You can access and retain the electronically signed document(s). {{appName}} provides tools to download or print the signed document immediately after the signing process is complete.",
|
||||
"term-cond-p17": "You are responsible for ensuring You can access and retain the electronically signed document(s). OpenSign provides tools to download or print the signed document immediately after the signing process is complete.",
|
||||
"term-cond-p18": "If You prefer a paper copy of any electronically signed document, You may request it directly from the Sender. The Sender may charge a reasonable fee for providing paper copies unless prohibited by applicable law.",
|
||||
"term-cond-h6": "6. Acknowledgment and Agreement",
|
||||
"term-cond-p19": "By proceeding, You:",
|
||||
"term-cond-p20": "Confirm that You can access and review electronic documents as described in this Disclosure.",
|
||||
"term-cond-p21": "Agree to use electronic records and signatures for the specified transaction(s) with the Sender.",
|
||||
"term-cond-p22": "Understand that {{appName}} is a platform facilitating the transaction and is not a party to the agreement.",
|
||||
"term-cond-p22": "Understand that OpenSign is a platform facilitating the transaction and is not a party to the agreement.",
|
||||
"term-cond-h7": "7. Legal Effect",
|
||||
"term-cond-p23": "Your electronic signature facilitated through {{appName}}:",
|
||||
"term-cond-p23": "Your electronic signature facilitated through OpenSign:",
|
||||
"term-cond-p24": "Complies with applicable electronic signature laws, including but not limited to the E-SIGN Act in the United States, the EU eIDAS Regulation, and India’s Information Technology Act.",
|
||||
"term-cond-p25": "Is legally binding between You and the Sender for the signed document(s).",
|
||||
"term-cond-h8": "8. Platform Role and Limitation of Liability",
|
||||
"term-cond-p26": "{{appName}} serves as a platform to facilitate electronic transactions. It is not responsible for the content, validity, or enforceability of the documents sent by the Sender. Any disputes or issues related to the document or its signing must be resolved directly between You and the Sender.",
|
||||
"term-cond-p26": "OpenSign serves as a platform to facilitate electronic transactions. It is not responsible for the content, validity, or enforceability of the documents sent by the Sender. Any disputes or issues related to the document or its signing must be resolved directly between You and the Sender.",
|
||||
"term-cond-h9": "9. Termination of Agreement",
|
||||
"term-cond-p27": "Your consent applies only to the current transaction unless otherwise specified by the Sender. {{appName}} reserves the right to terminate access to its platform for violations of its Terms of Service or policies.",
|
||||
"term-cond-p28": "By selecting 'I Agree,' You confirm that You understand and agree to the terms of this Electronic Record and Signature Disclosure and consent to electronically sign the document(s) provided by the Sender through {{appName}}.",
|
||||
"term-cond-p29": "If You have questions about this Disclosure, contact the Sender directly. For technical support with {{appName}}, visit ",
|
||||
"term-cond-p30": " or email",
|
||||
"js-snippet-msg": "To integrate {{appName}} Templates into your HTML websites or landing pages, you can use below code:",
|
||||
"term-cond-p27": "Your consent applies only to the current transaction unless otherwise specified by the Sender. OpenSign reserves the right to terminate access to its platform for violations of its Terms of Service or policies.",
|
||||
"term-cond-p28": "By selecting 'I Agree,' You confirm that You understand and agree to the terms of this Electronic Record and Signature Disclosure and consent to electronically sign the document(s) provided by the Sender through OpenSign.",
|
||||
"term-cond-p29": "If You have questions about this Disclosure, contact the Sender directly. For technical support with OpenSign, visit",
|
||||
"term-cond-p30": "or email",
|
||||
"js-snippet-msg": "To integrate OpenSign Templates into your HTML websites or landing pages, you can use below code:",
|
||||
"js-snippet-msg-1": "You can get the TemplateId from the",
|
||||
"js-snippet-msg-2": "Manage Templates",
|
||||
"js-snippet-msg-3": "page.",
|
||||
@@ -825,8 +815,8 @@
|
||||
},
|
||||
"signature-setting": "Signature settings",
|
||||
"activation-key": "Activation key",
|
||||
"paid-selfhost-help": "Please contact to {{appName}} for more info at ",
|
||||
"remaining-credits-selfhost-help": "Use premium credits for API document signing, bulk sending {{appName}} integration on your website. You have {{allowedcredits}} included credits and {{addoncredits}} additional purchased credits remaining.",
|
||||
"paid-selfhost-help": "Please contact to opensign for more info at ",
|
||||
"remaining-credits-selfhost-help": "Use premium credits for API document signing, bulk sending OpenSign integration on your website. You have {{allowedcredits}} included credits and {{addoncredits}} additional purchased credits remaining.",
|
||||
"signature-type": "Your signature",
|
||||
"initial-type": "Your initials",
|
||||
"redirect-url": "Redirect url",
|
||||
@@ -845,16 +835,5 @@
|
||||
"send-to-sign": "has requested you to sign",
|
||||
"use-template": "Use Template",
|
||||
"contact-already-exists": "contact already exists.",
|
||||
"docx-error": "We are currently experiencing some issues with processing DOCX files. Please upload the PDF file",
|
||||
"docx-error-contact": "or contact us on support@opensignlabs.com",
|
||||
"agreement-note": "Note: Agreeing to this does not mean you are signing the document immediately. This only allows you to review the document electronically. You will have the opportunity to read it in full and decide whether to sign it afterward.",
|
||||
"draft-template-info-p1": "To make your template public, it must either contain a single role, or, if it includes multiple roles, all additional roles must already be assigned to signers. The unassigned public role should remain empty and must be placed in the first position.",
|
||||
"visit-below-link": "Visit below link to know more -",
|
||||
"storage-help": "Enabling BYOC lets you connect your own S3 storage so your files remain entirely under your control—no external copies retained. If data autonomy matters to you, consider upgrading to Teams to unlock this feature.",
|
||||
"daily-quota-reached": "You’ve reached your daily quota. For assistance, please contact quotas@opensignlabs.com.",
|
||||
"enabled-signature-type": "Enabled Signature Types",
|
||||
"enabled-signature-type-help": "The 'Enabled Signature Types' setting determines which signature options are available across your organization. For example, if you disable the 'Draw' option, members of your organization will not see it in the signature widget, while the other three options will remain accessible.",
|
||||
"indexing-public-profile": "Allow indexing of public profile by search engines",
|
||||
"user-created-successfully": "user created successfully.",
|
||||
"only-15-reminder-allowed": "You can set up to 15 automatic reminders. For example, if 'TimeToComplete' is 15 days and 'RemindOnceInEvery' is 1 day, you'll reach the maximum limit of 15 reminders. Adjust your settings accordingly."
|
||||
"agreement-note": "Note: Agreeing to this does not mean you are signing the document immediately. This only allows you to review the document electronically. You will have the opportunity to read it in full and decide whether to sign it afterward."
|
||||
}
|
||||
|
||||
@@ -51,6 +51,7 @@
|
||||
"docs": "Documentación",
|
||||
"session-expired": "Tu sesión ha expirado.",
|
||||
"public-profile-help": "Esta es tu URL pública. Cópiala o compártela con el firmante, y podrás ver todas tus plantillas públicas.",
|
||||
"tagline-help": "Este eslogan aparecerá en tu perfil público de OpenSign, por ejem. https://opensign.me/alex",
|
||||
"welcome": "¡Bienvenido de nuevo!",
|
||||
"Login-to-your-account": "Ingresa a tu cuenta",
|
||||
"password": "Contraseña",
|
||||
@@ -73,23 +74,12 @@
|
||||
"Sign yourself": "Firma tu mismo",
|
||||
"Request signatures": "Solicitar firmas",
|
||||
"Templates": "Plantillas",
|
||||
"Analytics": "Analítica",
|
||||
"Branding": "Marca",
|
||||
"Mail": "Correo",
|
||||
"Storage": "Almacenamiento",
|
||||
"Signing certificate": "Certificado de firma",
|
||||
"Teams": "Equipos",
|
||||
"General": "General",
|
||||
"Teams-Children": {
|
||||
"Organizations": "Organizaciones",
|
||||
"OrgAdmins": "OrgAdmins"
|
||||
},
|
||||
"Templates-Children": {
|
||||
"Create template": "Crear plantilla",
|
||||
"Manage templates": "Administrar plantillas",
|
||||
"Embedding": "Incrustar"
|
||||
},
|
||||
"OpenSign™ Drive": "{{appName}} Drive",
|
||||
"OpenSign™ Drive": "OpenSign™ Drive",
|
||||
"Reports": "Reportes",
|
||||
"Documents": "Documentos",
|
||||
"Documents-Children": {
|
||||
@@ -150,8 +140,7 @@
|
||||
"Copy Public URL": "Copiar URL pública",
|
||||
"extend-expiry-date": "Date d'expiration",
|
||||
"Duplicate Template": "Plantilla duplicada",
|
||||
"Duplicate": "Duplicada",
|
||||
"daily-mail-quota": "Cuota diaria de correos electrónicos"
|
||||
"Duplicate": "Duplicada"
|
||||
},
|
||||
"report-heading": {
|
||||
"Sr.No": "Nº",
|
||||
@@ -209,7 +198,7 @@
|
||||
"remind-once": " Recordar una vez cada (Días)",
|
||||
"next": "Siguiente",
|
||||
"select-folder": "Seleccionar carpeta",
|
||||
"OpenSign-drive": "{{appName}} Drive",
|
||||
"OpenSign-drive": "OpenSign™ Drive",
|
||||
"drive-document-status": {
|
||||
"Completed": "Completado",
|
||||
"Declined": "Rechazado",
|
||||
@@ -217,7 +206,7 @@
|
||||
"Expired": "Expirado",
|
||||
"In Progress": "En progreso"
|
||||
},
|
||||
"select-folder-help": "Si no seleccionas una carpeta, tu documento firmado se guardará en la carpeta principal de {{appName}} Drive.",
|
||||
"select-folder-help": "Si no seleccionas una carpeta, tu documento firmado se guardará en la carpeta principal de OpenSign Drive.",
|
||||
"no-data": "No se encontraron datos",
|
||||
"save-here": "Guardar aquí",
|
||||
"back": "Atrás",
|
||||
@@ -290,7 +279,7 @@
|
||||
"embed-template": "Insertar plantilla",
|
||||
"public-url-copy": "Aquí está tu URL pública: ",
|
||||
"public-url-copy-mssg": "Cópiala o compártela con el firmante y podrás ver todas tus plantillas públicas.",
|
||||
"add-public-url-alert": "Puedes generar tu perfil público {{appName}}",
|
||||
"add-public-url-alert": "Puedes generar tu perfil público OpenSign",
|
||||
"share-with-alert": "No puedes compartir una plantilla si alguno de los roles ya tiene contactos asignados. Elimina todas las asignaciones de contactos de los roles antes de compartir la plantilla.",
|
||||
"share-with": "Compartir con",
|
||||
"team-not-found": "Equipo no encontrado",
|
||||
@@ -504,7 +493,7 @@
|
||||
"role-not-found": "Rol no encontrado.",
|
||||
"do-not-access": "No tienes acceso, por favor, contacta al administrador.",
|
||||
"add-admin": "Agregar administrador",
|
||||
"opensign-setup": "Instalación de {{appName}}",
|
||||
"opensign-setup": "Instalación de OpenSign",
|
||||
"join-discord": "Únete a nuestro servidor de Discord",
|
||||
"admin-already-exist": "El administrador ya existe.",
|
||||
"password-update-alert-1": "Contraseña actualizada exitosamente.",
|
||||
@@ -561,6 +550,7 @@
|
||||
"filed-required-correctly": "Por favor, rellena correctamente los detalles requeridos.",
|
||||
"admin-created": "Administrador creado",
|
||||
"invalid-masterkey": "Llave maestra inválida",
|
||||
"opensign-Setup": "Instalación de OpenSign",
|
||||
"master-key": " Llave maestra",
|
||||
"profile-update-alert": "Perfil actualizado exitosamente.",
|
||||
"date": "Fecha",
|
||||
@@ -585,7 +575,7 @@
|
||||
"tour-mssg": {
|
||||
"home-layout-1": "¡Has iniciado sesión exitosamente! Echemos un vistazo.",
|
||||
"home-layout-2": "Para subir documentos para firmar tú mismo o para solicitar la firma de otros, simplemente selecciona los botones correspondientes.",
|
||||
"home-layout-3": "¡Ya puedes empezar a utilizar {{appName}}! Si necesitas soporte siéntete libre de contactarnos.",
|
||||
"home-layout-3": "¡Ya puedes empezar a utilizar OpenSign! Si necesitas soporte siéntete libre de contactarnos.",
|
||||
"generate-token": "Mejora ahora para generar un token API de producción.",
|
||||
"opensign-drive-1": "Haz clic en los enlaces para navegar fácilmente por la estructura jerárquica de carpetas y ver los documentos de cada carpeta.",
|
||||
"opensign-drive-2": "Haz clic en el botón «Agregar» para crear una nueva carpeta o documento.",
|
||||
@@ -700,16 +690,16 @@
|
||||
"download-pdf": "Descargar PDF",
|
||||
"pdf-certificate": "Descargar PDF + Certificado",
|
||||
"document-logs": "Registros de documentos",
|
||||
"server-down": "No se pudo conectar al servidor de {{appName}}. Si estás alojando {{appName}} por tu cuenta, por favor, asegúrate de que todos los pasos de la documentación han sido seguidos correctamente. Si estás ejecutando {{appName}} localmente, puedes estar accediendo a {{appName}} por un número de puerto incorrecto.",
|
||||
"server-down": "No se pudo conectar al servidor de OpenSign. Si estás alojando OpenSign por tu cuenta, por favor, asegúrate de que todos los pasos de la documentación han sido seguidos correctamente. Si estás ejecutando OpenSign localmente, puedes estar accediendo a OpenSign por un número de puerto incorrecto.",
|
||||
"admin-exists": "El administrador ya existe. Por favor, inicia sesión en la aplicación usando las credenciales de administrador para poder administrar los usuarios.",
|
||||
"public-tour-message": "Por favor, convierte la plantilla en pública para copiar la URL pública",
|
||||
"add-user-template": "Es necesario agregar un rol antes de poder agregarle campos.",
|
||||
"pdf-uncompatible": "Este PDF no es compatible, por favor contacta con {{appName}}",
|
||||
"pdf-uncompatible": "Este pdf no es compatible con opensign, comuníquese con <support@opensignlabs.com>",
|
||||
"enable-tour": "Habilitar recorrido",
|
||||
"istourenabled-help": {
|
||||
"p1": "Esto permitirá realizar una visita guiada para los firmantes, brindando instrucciones durante el proceso de firma.",
|
||||
"p2": "Esto desactivará la visita guiada, lo que garantizará una experiencia de firma más rápida e ininterrumpida.",
|
||||
"p3": "Consejo: si sus firmantes están familiarizados con {{appName}} y lo utilizan con frecuencia, es posible que desee desactivar la visita guiada para disfrutar de una experiencia más fluida. Elija la opción que mejor se adapte a sus necesidades de firma de documentos"
|
||||
"p3": "Consejo: si sus firmantes están familiarizados con OpenSign y lo utilizan con frecuencia, es posible que desee desactivar la visita guiada para disfrutar de una experiencia más fluida. Elija la opción que mejor se adapte a sus necesidades de firma de documentos"
|
||||
},
|
||||
"form-title-1": "Configuración del flujo de documentos",
|
||||
"form-title-2": "Configuración de seguridad",
|
||||
@@ -752,7 +742,7 @@
|
||||
"delete-folder-alert": "¿Está seguro de que desea eliminar este Carpeta?",
|
||||
"delete-folder-alert-1": "No se puede eliminar: la carpeta debe estar vacía",
|
||||
"defaultSign-alert": "Los widgets {{widgetsType}} no están disponibles para la firma automática",
|
||||
"embed-heading": "Incrustar plantillas de {{appName}}",
|
||||
"embed-heading": "Incrustar plantillas de OpenSign",
|
||||
"public-template-edit-title": "Editar plantilla pública",
|
||||
"public-template-edit-mssg": "No puede editar una plantilla pública directamente. Para realizar cambios, la plantilla se configurará como privada y luego tendrás que volver a hacerla pública. ¿Quieres continuar?",
|
||||
"agree-p1": "Confirmo que he leído y comprendido el ",
|
||||
@@ -761,49 +751,49 @@
|
||||
"agrre-button": "Aceptar y continuar",
|
||||
"term-cond-title": "Términos y condiciones",
|
||||
"term-cond-h": "DIVULGACIÓN DE REGISTRO ELECTRÓNICO Y FIRMA",
|
||||
"term-cond-p1": "Esta Divulgación de Firma y Registro Electrónico ('Divulgación') es un acuerdo entre el Creador del Documento ('Remitente') y el Firmante ('Usted'), facilitado a través de la plataforma {{appName}} ('Plataforma'). Al firmar documentos a través de {{appName}}, usted acepta los términos descritos en esta Divulgación. Léala detenidamente antes de continuar.",
|
||||
"term-cond-p1": "Esta Divulgación de Firma y Registro Electrónico ('Divulgación') es un acuerdo entre el Creador del Documento ('Remitente') y el Firmante ('Usted'), facilitado a través de la plataforma OpenSign ('Plataforma'). Al firmar documentos a través de OpenSign, usted acepta los términos descritos en esta Divulgación. Léala detenidamente antes de continuar.",
|
||||
"term-cond-h1": "1. Objet et portée",
|
||||
"term-cond-p2": "Esta Divulgación rige el uso de registros y firmas electrónicas para los documentos enviados por el Remitente y firmados por Usted a través de la plataforma {{appName}}. Al aceptar, Usted reconoce que:",
|
||||
"term-cond-p3": "Recibirá y firmará documentos electrónicamente a través de {{appName}}.",
|
||||
"term-cond-p2": "Esta Divulgación rige el uso de registros y firmas electrónicas para los documentos enviados por el Remitente y firmados por Usted a través de la plataforma OpenSign. Al aceptar, Usted reconoce que:",
|
||||
"term-cond-p3": "Recibirá y firmará documentos electrónicamente a través de OpenSign.",
|
||||
"term-cond-p4": "Su firma electrónica es jurídicamente vinculante y equivalente a una firma manuscrita.",
|
||||
"term-cond-h2": "2. Consentimiento para el uso de registros y firmas electrónicas",
|
||||
"js-snippet-msg-2": "Administrar plantillas",
|
||||
"js-snippet-msg-3": "página.",
|
||||
"term-cond-p5": "Al aceptar esta Divulgación:",
|
||||
"term-cond-p6": "Usted acepta realizar transacciones electrónicas con el Remitente utilizando {{appName}} y comprende que este consentimiento es válido hasta que se retire.",
|
||||
"term-cond-p7": "Usted acepta revisar, firmar y devolver documentos electrónicamente utilizando {{appName}}.",
|
||||
"term-cond-p6": "Usted acepta realizar transacciones electrónicas con el Remitente utilizando OpenSign y comprende que este consentimiento es válido hasta que se retire.",
|
||||
"term-cond-p7": "Usted acepta revisar, firmar y devolver documentos electrónicamente utilizando OpenSign.",
|
||||
"term-cond-p8": "Este consentimiento se aplica únicamente a los documentos específicos proporcionados por el Remitente.",
|
||||
"term-cond-h3": "3. Derecho a retirar el consentimiento",
|
||||
"term-cond-p9": "Tiene derecho a retirar su consentimiento para el uso de registros y firmas electrónicas mediante:",
|
||||
"term-cond-p10": "Contactar directamente con el Remitente utilizando la información de contacto proporcionada en su comunicación.",
|
||||
"term-cond-p11": "Notificar al remitente antes de completar el proceso de firma.",
|
||||
"term-cond-h4": "4. Requisitos de hardware y software",
|
||||
"term-cond-p12": "Para firmar documentos usando {{appName}}, debe tener:",
|
||||
"term-cond-p12": "Para firmar documentos usando OpenSign, debe tener:",
|
||||
"term-cond-p13": "Un dispositivo con acceso a Internet.",
|
||||
"term-cond-p14": "Un navegador web compatible con JavaScript habilitado.",
|
||||
"term-cond-p15": "Una cuenta de correo electrónico para recibir notificaciones y documentos firmados.",
|
||||
"term-cond-p16": "Si estos requisitos cambian, el Remitente u {{appName}} le notificarán las actualizaciones.",
|
||||
"term-cond-p16": "Si estos requisitos cambian, el Remitente u OpenSign le notificarán las actualizaciones.",
|
||||
"term-cond-h5": "5. Conservación de registros y solicitud de copias en papel",
|
||||
"term-cond-p17": "Usted es responsable de garantizar que pueda acceder y conservar los documentos firmados electrónicamente. {{appName}} proporciona herramientas para descargar o imprimir el documento firmado inmediatamente después de que se complete el proceso de firma.",
|
||||
"term-cond-p17": "Usted es responsable de garantizar que pueda acceder y conservar los documentos firmados electrónicamente. OpenSign proporciona herramientas para descargar o imprimir el documento firmado inmediatamente después de que se complete el proceso de firma.",
|
||||
"term-cond-p18": "Si prefiere una copia en papel de cualquier documento firmado electrónicamente, puede solicitarla directamente al Remitente. El Remitente puede cobrar una tarifa razonable por proporcionar copias en papel, a menos que lo prohíba la ley aplicable.",
|
||||
"term-cond-h6": "6. Reconocimiento y Acuerdo",
|
||||
"term-cond-p19": "Al continuar, usted:",
|
||||
"term-cond-p20": "Confirme que puede acceder y revisar documentos electrónicos como se describe en esta Divulgación.",
|
||||
"term-cond-p21": "Acepta utilizar registros y firmas electrónicas para las transacciones especificadas con el Remitente.",
|
||||
"term-cond-p22": "Comprenda que {{appName}} es una plataforma que facilita la transacción y no es parte del acuerdo.",
|
||||
"term-cond-p22": "Comprenda que OpenSign es una plataforma que facilita la transacción y no es parte del acuerdo.",
|
||||
"term-cond-h7": "7. Efecto jurídico",
|
||||
"term-cond-p23": "Tu firma electrónica facilitada a través de {{appName}}:",
|
||||
"term-cond-p23": "Tu firma electrónica facilitada a través de OpenSign:",
|
||||
"term-cond-p24": "Cumple con las leyes de firma electrónica aplicables, incluidas, entre otras, la Ley E-SIGN de los Estados Unidos, el Reglamento eIDAS de la UE y la Ley de tecnología de la información de la India",
|
||||
"term-cond-p25": "Es legalmente vinculante entre Usted y el Remitente para los documentos firmados",
|
||||
"term-cond-h8": "8. Platform Role and Limitation of Liability",
|
||||
"term-cond-p26": "{{appName}} sirve como plataforma para facilitar transacciones electrónicas. No es responsable del contenido, validez o aplicabilidad de los documentos enviados por el Remitente. Cualquier disputa o problema relacionado con el documento o su firma debe resolverse directamente entre Usted y el Remitente.",
|
||||
"term-cond-p26": "OpenSign sirve como plataforma para facilitar transacciones electrónicas. No es responsable del contenido, validez o aplicabilidad de los documentos enviados por el Remitente. Cualquier disputa o problema relacionado con el documento o su firma debe resolverse directamente entre Usted y el Remitente.",
|
||||
"term-cond-h9": "9. Terminación del Acuerdo",
|
||||
"term-cond-p27": "Su consentimiento se aplica únicamente a la transacción actual a menos que el Remitente especifique lo contrario. {{appName}} se reserva el derecho de cancelar el acceso a su plataforma por violaciones de sus Términos de Servicio o políticas.",
|
||||
"term-cond-p28": "Al seleccionar 'Acepto', usted confirma que comprende y acepta los términos de este Registro electrónico y Divulgación de firma y acepta firmar electrónicamente los documentos proporcionados por el Remitente a través de {{appName}}.",
|
||||
"term-cond-p29": "Si tiene preguntas sobre esta Divulgación, comuníquese directamente con el Remitente. Para obtener soporte técnico con {{appName}}, visite ",
|
||||
"term-cond-p30": " o correo electrónico",
|
||||
"js-snippet-msg": "Para integrar plantillas {{appName}} en sus sitios web HTML o páginas de destino, puede utilizar el siguiente código:",
|
||||
"term-cond-p27": "Su consentimiento se aplica únicamente a la transacción actual a menos que el Remitente especifique lo contrario. OpenSign se reserva el derecho de cancelar el acceso a su plataforma por violaciones de sus Términos de Servicio o políticas.",
|
||||
"term-cond-p28": "Al seleccionar 'Acepto', usted confirma que comprende y acepta los términos de este Registro electrónico y Divulgación de firma y acepta firmar electrónicamente los documentos proporcionados por el Remitente a través de OpenSign.",
|
||||
"term-cond-p29": "Si tiene preguntas sobre esta Divulgación, comuníquese directamente con el Remitente. Para obtener soporte técnico con OpenSign, visite",
|
||||
"term-cond-p30": "o correo electrónico",
|
||||
"js-snippet-msg": "Para integrar plantillas OpenSign en sus sitios web HTML o páginas de destino, puede utilizar el siguiente código:",
|
||||
"js-snippet-msg-1": "Puede obtener el TemplateId en la página Administrar plantillas",
|
||||
"js-snippet-msg-2": "Administrar plantillas",
|
||||
"js-snippet-msg-3": "página.",
|
||||
"agrrement-alert": "Para continuar, debe consentir la divulgación de registros y firmas electrónicas.",
|
||||
"webhook-already-exists": "¡La URL ya existe! Pruebe con uno diferente.",
|
||||
"webhook-must-be-secure": "La URL del webhook debe ser segura y utilizar https://",
|
||||
@@ -825,8 +815,8 @@
|
||||
"template-form-description": "Utilice este formulario para crear plantillas reutilizables para sus documentos.",
|
||||
"change-signer": "Cambiar firmante",
|
||||
"activation-key": "Clave de activación",
|
||||
"paid-selfhost-help": "Por favor, póngase en contacto con {{appName}} para más información en ",
|
||||
"remaining-credits-selfhost-help": "Use créditos premium para firmar documentos mediante la API, enviar en masa e integrar {{appName}} en su sitio web. Tiene {{allowedcredits}} créditos incluidos y {{addoncredits}} créditos adicionales comprados restantes.",
|
||||
"paid-selfhost-help": "Por favor, póngase en contacto con OpenSign para más información en ",
|
||||
"remaining-credits-selfhost-help": "Use créditos premium para firmar documentos mediante la API, enviar en masa e integrar OpenSign en su sitio web. Tiene {{allowedcredits}} créditos incluidos y {{addoncredits}} créditos adicionales comprados restantes.",
|
||||
"signature-type": "Tu firma",
|
||||
"initial-type": "Tus iniciales",
|
||||
"redirect-url": "URL de redireccionamiento",
|
||||
@@ -845,16 +835,5 @@
|
||||
"send-to-sign": "le ha solicitado que firme",
|
||||
"use-template": "Usar plantilla",
|
||||
"contact-already-exists": "El contacto ya existe.",
|
||||
"docx-error": "Actualmente estamos experimentando problemas con el procesamiento de archivos DOCX. Por favor, sube el archivo PDF",
|
||||
"docx-error-contact": "o contáctanos en support@opensignlabs.com",
|
||||
"agreement-note": "Nota: Aceptar esto no significa que esté firmando el documento de inmediato. Esto solo le permite revisar el documento electrónicamente. Tendrá la oportunidad de leerlo en su totalidad y decidir si desea firmarlo después.",
|
||||
"draft-template-info-p1": "Para hacer que tu plantilla sea pública, debe contener un único rol o, si incluye múltiples roles, todos los roles adicionales deben estar ya asignados a firmantes. El rol público no asignado debe permanecer vacío y debe estar en la primera posición.",
|
||||
"visit-below-link": "Visita el siguiente enlace para saber más -",
|
||||
"storage-help": "Habilitar BYOC te permite conectar tu propio almacenamiento S3 para que tus archivos permanezcan completamente bajo tu control, sin copias externas retenidas. Si la autonomía de los datos es importante para ti, considera actualizar a Teams para desbloquear esta función.",
|
||||
"daily-quota-reached": "Ha alcanzado su cuota diaria. Para obtener ayuda, comuníquese con quotas@opensignlabs.com.",
|
||||
"enabled-signature-type": "Tipos de firma habilitados",
|
||||
"enabled-signature-type-help": "La configuración de 'Tipos de firma habilitados' determina qué opciones de firma están disponibles en su organización. Por ejemplo, si desactiva la opción 'Dibujar', los miembros de su organización no la verán en el widget de firma, mientras que las otras tres opciones seguirán siendo accesibles.",
|
||||
"indexing-public-profile": "Permitir la indexación del perfil público por los motores de búsqueda",
|
||||
"user-created-successfully": "Usuario creado con éxito.",
|
||||
"only-15-reminder-allowed": "Puede configurar hasta 15 recordatorios automáticos. Por ejemplo, si 'TimeToComplete' es de 15 días y 'RemindOnceInEvery' es de 1 día, alcanzará el límite máximo de 15 recordatorios. Ajuste su configuración en consecuencia."
|
||||
"agreement-note": "Nota: Aceptar esto no significa que esté firmando el documento de inmediato. Esto solo le permite revisar el documento electrónicamente. Tendrá la oportunidad de leerlo en su totalidad y decidir si desea firmarlo después."
|
||||
}
|
||||
|
||||
@@ -51,6 +51,7 @@
|
||||
"session-expired": "Votre session a expiré.",
|
||||
"user": "Utilisateur",
|
||||
"public-profile-help": "Il s'agit de votre URL publique. Copiez-le ou partagez-le avec le signataire et vous pourrez voir tous vos modèles définis publiquement.",
|
||||
"tagline-help": "Ce surnom apparaîtra sur votre profil public OpenSign par exemple. https://opensign.me/alex",
|
||||
"welcome": "Content de te revoir!",
|
||||
"Login-to-your-account": "Se connecter à son compte",
|
||||
"password": "Mot de passe",
|
||||
@@ -73,23 +74,12 @@
|
||||
"Sign yourself": "signez vous-même",
|
||||
"Request signatures": "Demander des signatures",
|
||||
"Templates": "Modèles",
|
||||
"Analytics": "Analytique",
|
||||
"Branding": "Image de marque",
|
||||
"Mail": "Courrier",
|
||||
"Storage": "Stockage",
|
||||
"Signing certificate": "Certificat de signature",
|
||||
"Teams": "Équipes",
|
||||
"General": "Général",
|
||||
"Teams-Children": {
|
||||
"Organizations": "Organisations",
|
||||
"OrgAdmins": "OrgAdmins"
|
||||
},
|
||||
"Templates-Children": {
|
||||
"Create template": "Créer un modèle",
|
||||
"Manage templates": "Gérer les modèles",
|
||||
"Embedding": "Intégration"
|
||||
},
|
||||
"OpenSign™ Drive": "Lecteur {{appName}}",
|
||||
"OpenSign™ Drive": "Lecteur OpenSign™",
|
||||
"Reports": "Rapports",
|
||||
"Documents": "Documents",
|
||||
"Documents-Children": {
|
||||
@@ -171,8 +161,7 @@
|
||||
"Copy Public URL": "Copier l'URL publique",
|
||||
"extend-expiry-date": "Prolonger la date d'expiration",
|
||||
"Duplicate Template": "dupliquer le modèle",
|
||||
"Duplicate": "Double",
|
||||
"daily-mail-quota": "Quota d'e-mails quotidien"
|
||||
"Duplicate": "Double"
|
||||
},
|
||||
"report-help": {
|
||||
"Draft Documents": "Il s'agit de documents que vous avez commencés mais que vous n'avez pas finalisés pour envoi.",
|
||||
@@ -208,7 +197,7 @@
|
||||
"remind-once": "Rappeler une fois tous les (jours)",
|
||||
"next": "Suivant",
|
||||
"select-folder": "Sélectionner le dossier",
|
||||
"OpenSign-drive": "Lecteur {{appName}}",
|
||||
"OpenSign-drive": "Lecteur OpenSign™",
|
||||
"drive-document-status": {
|
||||
"Completed": "Complété",
|
||||
"Declined": "Refuser",
|
||||
@@ -216,7 +205,7 @@
|
||||
"Expired": "Expiré",
|
||||
"In Progress": "En cours"
|
||||
},
|
||||
"select-folder-help": "Si vous ne sélectionnez pas de dossier, votre document signé sera enregistré dans le dossier du lecteur principal {{appName}}.",
|
||||
"select-folder-help": "Si vous ne sélectionnez pas de dossier, votre document signé sera enregistré dans le dossier du lecteur principal OpenSign.",
|
||||
"no-data": "Aucune données disponible",
|
||||
"save-here": "Enregistrer ici",
|
||||
"back": "Retour",
|
||||
@@ -289,7 +278,7 @@
|
||||
"embed-template": "Intégrer le modèle",
|
||||
"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": "Vous pouvez générer votre profil public {{appName}}",
|
||||
"add-public-url-alert": "Vous pouvez générer votre profil public OpenSign",
|
||||
"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",
|
||||
"team-not-found": "Équipe introuvable",
|
||||
@@ -452,7 +441,6 @@
|
||||
"add-recipients": "Ajouter des destinataires",
|
||||
"loading-mssg": "Cela pourrait prendre du temps",
|
||||
"send-mail": "Envoyer un mail",
|
||||
"signature-field-widget": "Au moins un champ de signature doit être ajouté pour chaque utilisateur. Vous n'avez pas ajouté de champs de signature pour {{signersName}}",
|
||||
"placeholder-alert-1": "Veuillez vous assurer qu'au moins un widget de signature est ajouté pour tous les destinataires.",
|
||||
"placeholder-alert-2": "Veuillez confirmer que vous avez rempli le champ de texte.",
|
||||
"placeholder-alert-3": "Etes-vous sûr de vouloir envoyer ce document pour signature ? ",
|
||||
@@ -504,7 +492,7 @@
|
||||
"role-not-found": "Rôle introuvable.",
|
||||
"do-not-access": "Vous n'y avez pas accès, veuillez contacter l'administrateur.",
|
||||
"add-admin": "Ajouter un administrateur",
|
||||
"opensign-setup": "Configuration {{appName}}",
|
||||
"opensign-setup": "Configuration d'OpenSign",
|
||||
"join-discord": "Rejoignez notre serveur Discord",
|
||||
"admin-already-exist": "L'administrateur existe déjà.",
|
||||
"password-update-alert-1": "Mot de passe mis à jour avec succès.",
|
||||
@@ -561,6 +549,7 @@
|
||||
"filed-required-correctly": "Veuillez remplir correctement les informations requises.",
|
||||
"admin-created": "Administrateur créé",
|
||||
"invalid-masterkey": "Clé principale invalide",
|
||||
"opensign-Setup": "Configuration d'OpenSign",
|
||||
"master-key": "La clef maitresse",
|
||||
"profile-update-alert": "Mise à jour du profil réussie.",
|
||||
"date": "Date",
|
||||
@@ -585,7 +574,7 @@
|
||||
"tour-mssg": {
|
||||
"home-layout-1": "Vous vous êtes connecté avec succès ! Jetons un coup d'oeil.",
|
||||
"home-layout-2": "Pour télécharger des documents à auto-signature ou pour demander la signature d'autres personnes, sélectionnez simplement les boutons correspondants.",
|
||||
"home-layout-3": "Vous êtes prêt à commencer à utiliser {{appName}} ! Si vous avez besoin d'aide, n'hésitez pas à nous contacter.",
|
||||
"home-layout-3": "Vous êtes prêt à commencer à utiliser OpenSign ! Si vous avez besoin d'aide, n'hésitez pas à nous contacter.",
|
||||
"generate-token": "Effectuez la mise à niveau maintenant pour générer un jeton API de production.",
|
||||
"opensign-drive-1": "Cliquez sur les liens du fil d'Ariane pour naviguer facilement dans la hiérarchie des dossiers et afficher les documents dans chaque dossier.",
|
||||
"opensign-drive-2": "Cliquez sur le bouton Ajouter pour créer un nouveau dossier ou document.",
|
||||
@@ -700,19 +689,19 @@
|
||||
"download-pdf": "Télécharger le PDF",
|
||||
"pdf-certificate": "Télécharger Pdf + Certificat",
|
||||
"document-logs": "Journaux de documents",
|
||||
"server-down": "Impossible de se connecter au serveur {{appName}}. Si vous hébergez vous-même {{appName}}, veuillez vous assurer que toutes les étapes de la documentation ont été correctement suivies. Si vous exécutez {{appName}} localement, vous y accédez peut-être via un numéro de port incorrect.",
|
||||
"server-down": "Impossible de se connecter au serveur OpenSign. Si vous hébergez vous-même OpenSign, veuillez vous assurer que toutes les étapes de la documentation ont été correctement suivies. Si vous exécutez OpenSign localement, vous y accédez peut-être via un numéro de port incorrect.",
|
||||
"admin-exists": "L'administrateur existe déjà. Veuillez vous connecter à l'application en utilisant les informations d'identification de l'administrateur afin de gérer les utilisateurs.",
|
||||
"enable-tour": "Activer la visite",
|
||||
"istourenabled-otp-help": {
|
||||
"p1": "Cela permettra une visite guidée pour les signataires, fournissant des instructions pendant le processus de signature.",
|
||||
"p2": "Cela désactivera la visite guidée, garantissant ainsi une expérience de signature plus rapide et ininterrompue.",
|
||||
"p3": "Conseil: si vos signataires connaissent {{appName}} et l'utilisent fréquemment, vous souhaiterez peut-être désactiver la visite guidée pour une expérience plus fluide. Choisissez l'option qui correspond le mieux à vos besoins en matière de signature de documents."
|
||||
"p3": "Conseil : si vos signataires connaissent OpenSign et l'utilisent fréquemment, vous souhaiterez peut-être désactiver la visite guidée pour une expérience plus fluide. Choisissez l'option qui correspond le mieux à vos besoins en matière de signature de documents."
|
||||
},
|
||||
"form-title-1": "Paramètre du flux de documents",
|
||||
"form-title-2": "Paramètre de sécurité",
|
||||
"public-tour-message": "Le modèle doit être public avant que vous puissiez générer un lien partageable.",
|
||||
"add-user-template": "Vous devez ajouter un rôle avant de pouvoir lui ajouter des champs. ",
|
||||
"pdf-uncompatible": "PDF n'est pas compatible, veuillez contacter {{appName}}",
|
||||
"pdf-uncompatible": "Ce pdf n'est pas compatible avec opensign, veuillez contacter <support@opensignlabs.com>",
|
||||
"text-field-tour": "Les champs de type 'Texte' doivent être remplis à l'avance avant l'envoi du document. Si vous avez besoin que les signataires fournissent des informations, utilisez plutôt le champ 'Saisie de texte'.",
|
||||
"attach-signer-tour": "Vous devez associer un signataire à chaque rôle. Vous pouvez le faire en cliquant sur cette icône. Une fois que vous avez sélectionné un signataire, il sera attaché à tous les champs associés à ce rôle qui apparaissent dans la même couleur.",
|
||||
"allowed-signature-types": "Types de signature autorisés",
|
||||
@@ -752,7 +741,7 @@
|
||||
"delete-folder-alert": "Êtes-vous sûr de vouloir supprimer ce Dossier ?",
|
||||
"delete-folder-alert-1": "Impossible de supprimer : le dossier doit être vide.",
|
||||
"defaultSign-alert": "Les widgets {{widgetsType}} ne sont pas disponibles pour la signature automatique.",
|
||||
"embed-heading": "Intégrer des modèles {{appName}}",
|
||||
"embed-heading": "Intégrer des modèles OpenSign",
|
||||
"public-template-edit-title": "Modifier le modèle public",
|
||||
"public-template-edit-mssg": "Vous ne pouvez pas modifier directement un modèle public. Pour apporter des modifications, le modèle sera défini comme privé et vous devrez ensuite le rendre à nouveau public. Voulez-vous continuer ?",
|
||||
"agree-p1": "Je confirme avoir lu et compris les ",
|
||||
@@ -761,48 +750,48 @@
|
||||
"agrre-button": " Accepter et continuer ",
|
||||
"term-cond-title": "Termes et conditions",
|
||||
"term-cond-h": "DIVULGATION D'ENREGISTREMENT ÉLECTRONIQUE ET DE SIGNATURE",
|
||||
"term-cond-p1": "Cette divulgation d'enregistrement électronique et de signature (' Divulgation ') est un accord entre le créateur du document (' Expéditeur ') et le signataire (' Vous '), facilité via la plateforme {{appName}} ( Plateforme ). En signant des documents via {{appName}}, vous acceptez les conditions décrites dans cette divulgation. Veuillez la lire attentivement avant de continuer.",
|
||||
"term-cond-p1": "Cette divulgation d'enregistrement électronique et de signature (' Divulgation ') est un accord entre le créateur du document (' Expéditeur ') et le signataire (' Vous '), facilité via la plateforme OpenSign (' Plateforme '). En signant des documents via OpenSign, vous acceptez les conditions décrites dans cette divulgation. Veuillez la lire attentivement avant de continuer.",
|
||||
"term-cond-h1": "1. Objet et portée",
|
||||
"term-cond-p2": "Cette divulgation régit l'utilisation d'enregistrements et de signatures électroniques pour les documents envoyés par l'expéditeur et signés par vous via la plateforme {{appName}}. En acceptant, vous reconnaissez que :",
|
||||
"term-cond-p3": "Vous recevrez et signerez des documents électroniquement via {{appName}}.",
|
||||
"term-cond-p2": "Cette divulgation régit l'utilisation d'enregistrements et de signatures électroniques pour les documents envoyés par l'expéditeur et signés par vous via la plateforme OpenSign. En acceptant, vous reconnaissez que :",
|
||||
"term-cond-p3": "Vous recevrez et signerez des documents électroniquement via OpenSign.",
|
||||
"term-cond-p4": "Votre signature électronique est juridiquement contraignante et équivaut à une signature manuscrite.",
|
||||
"js-snippet-msg-2": "Gérer les modèles",
|
||||
"js-snippet-msg-3": "page.",
|
||||
"term-cond-h2": "2. Consentement à l'utilisation d'enregistrements et de signatures électroniques",
|
||||
"term-cond-p5": "En acceptant cette divulgation:",
|
||||
"term-cond-p6": "Vous consentez à effectuer des transactions électroniques avec l'expéditeur en utilisant {{appName}} et comprenez que ce consentement est valable jusqu'à son retrait.",
|
||||
"term-cond-p7": "Vous acceptez de consulter, de signer et de renvoyer des documents par voie électronique à l'aide d'{{appName}}.",
|
||||
"term-cond-p5": "En acceptant cette divulgation :",
|
||||
"term-cond-p6": "Vous consentez à effectuer des transactions électroniques avec l'expéditeur en utilisant OpenSign et comprenez que ce consentement est valable jusqu'à son retrait.",
|
||||
"term-cond-p7": "Vous acceptez de consulter, de signer et de renvoyer des documents par voie électronique à l'aide d'OpenSign.",
|
||||
"term-cond-p8": "Ce consentement s'applique uniquement au(x) document(s) spécifique(s) fourni(s) par l'Expéditeur.",
|
||||
"term-cond-h3": "3. Droit de retirer le consentement",
|
||||
"term-cond-p9": "Vous avez le droit de retirer votre consentement à l'utilisation d'enregistrements et de signatures électroniques en :",
|
||||
"term-cond-p10": "Contacter directement l'expéditeur en utilisant les coordonnées fournies dans sa communication.",
|
||||
"term-cond-p11": "Notifier l'expéditeur avant de terminer le processus de signature.",
|
||||
"term-cond-h4": "4. Configuration matérielle et logicielle requise",
|
||||
"term-cond-p12": "Pour signer des documents avec {{appName}}, vous devez avoir:",
|
||||
"term-cond-p12": "Pour signer des documents avec OpenSign, vous devez avoir :",
|
||||
"term-cond-p13": "Un appareil avec accès à Internet.",
|
||||
"term-cond-p14": "Un navigateur Web compatible avec JavaScript activé.",
|
||||
"term-cond-p15": "Un compte email pour recevoir des notifications et des documents signés.",
|
||||
"term-cond-p16": "Si ces exigences changent, l'expéditeur ou {{appName}} vous informera des mises à jour.",
|
||||
"term-cond-p16": "Si ces exigences changent, l'expéditeur ou OpenSign vous informera des mises à jour.",
|
||||
"term-cond-h5": "5. Conservation des dossiers et demande de copies papier",
|
||||
"term-cond-p17": "Vous êtes responsable de vous assurer que vous pouvez accéder et conserver le(s) document(s) signé(s) électroniquement. {{appName}} fournit des outils pour télécharger ou imprimer le document signé immédiatement une fois le processus de signature terminé.",
|
||||
"term-cond-p17": "Vous êtes responsable de vous assurer que vous pouvez accéder et conserver le(s) document(s) signé(s) électroniquement. OpenSign fournit des outils pour télécharger ou imprimer le document signé immédiatement une fois le processus de signature terminé.",
|
||||
"term-cond-p18": "Si vous préférez une copie papier de tout document signé électroniquement, vous pouvez la demander directement à l'expéditeur. L'expéditeur peut facturer des frais raisonnables pour la fourniture de copies papier, sauf interdiction par la loi applicable.",
|
||||
"term-cond-h6": "6. Reconnaissance et accord",
|
||||
"term-cond-p19": "En procédant, Vous :",
|
||||
"term-cond-p20": "Confirmez que vous pouvez accéder et consulter les documents électroniques comme décrit dans cette divulgation.",
|
||||
"term-cond-p21": "Accepter d'utiliser des enregistrements et des signatures électroniques pour la ou les transactions spécifiées avec l'expéditeur.",
|
||||
"term-cond-p22": "Comprenez qu'{{appName}} est une plateforme facilitant la transaction et n'est pas partie à l'accord.",
|
||||
"term-cond-p22": "Comprenez qu'OpenSign est une plateforme facilitant la transaction et n'est pas partie à l'accord.",
|
||||
"term-cond-h7": "7. Effet juridique",
|
||||
"term-cond-p23": "Votre signature électronique facilitée grâce à {{appName}}:",
|
||||
"term-cond-p23": "Votre signature électronique facilitée grâce à OpenSign :",
|
||||
"term-cond-p24": "Conforme aux lois applicables sur les signatures électroniques, y compris, mais sans s'y limiter, la loi E-SIGN aux États-Unis, le règlement eIDAS de l'UE et la loi indienne sur les technologies de l'information.",
|
||||
"term-cond-p25": "Est juridiquement contraignant entre vous et l'expéditeur pour le(s) document(s) signé(s).",
|
||||
"term-cond-h8": "8. Rôle de la plateforme et limitation de responsabilité",
|
||||
"term-cond-p26": "{{appName}} sert de plateforme pour faciliter les transactions électroniques. Il n'est pas responsable du contenu, de la validité ou du caractère exécutoire des documents envoyés par l'expéditeur. Tout litige ou problème lié au document ou à sa signature doit être résolu directement entre vous et l'expéditeur. Expéditeur.",
|
||||
"term-cond-p26": "OpenSign sert de plateforme pour faciliter les transactions électroniques. Il n'est pas responsable du contenu, de la validité ou du caractère exécutoire des documents envoyés par l'expéditeur. Tout litige ou problème lié au document ou à sa signature doit être résolu directement entre vous et l'expéditeur. Expéditeur.",
|
||||
"term-cond-h9": "9. Résiliation du Contrat",
|
||||
"term-cond-p27": "Votre consentement s'applique uniquement à la transaction en cours, sauf indication contraire de la part de l'expéditeur. {{appName}} se réserve le droit de mettre fin à l'accès à sa plateforme en cas de violation de ses conditions d'utilisation ou de ses politiques.",
|
||||
"term-cond-p28": "En sélectionnant J'accepte, vous confirmez que vous comprenez et acceptez les termes de cette divulgation d'enregistrement électronique et de signature et consentez à signer électroniquement le(s) document(s) fourni(s) par l'expéditeur via {{appName}}.",
|
||||
"term-cond-p29": "Si vous avez des questions sur cette divulgation, contactez directement l'expéditeur. Pour obtenir une assistance technique avec {{appName}}, visitez ",
|
||||
"term-cond-p30": " ou par email",
|
||||
"js-snippet-msg": "Pour intégrer des modèles {{appName}} dans vos sites Web ou pages de destination HTML, vous pouvez utiliser le code ci-dessous:",
|
||||
"term-cond-p27": "Votre consentement s'applique uniquement à la transaction en cours, sauf indication contraire de la part de l'expéditeur. OpenSign se réserve le droit de mettre fin à l'accès à sa plateforme en cas de violation de ses conditions d'utilisation ou de ses politiques.",
|
||||
"term-cond-p28": "En sélectionnant J'accepte, vous confirmez que vous comprenez et acceptez les termes de cette divulgation d'enregistrement électronique et de signature et consentez à signer électroniquement le(s) document(s) fourni(s) par l'expéditeur via OpenSign.",
|
||||
"term-cond-p29": "Si vous avez des questions sur cette divulgation, contactez directement l'expéditeur. Pour obtenir une assistance technique avec OpenSign, visitez",
|
||||
"term-cond-p30": "ou par email",
|
||||
"js-snippet-msg": "Pour intégrer des modèles OpenSign dans vos sites Web ou pages de destination HTML, vous pouvez utiliser le code ci-dessous :",
|
||||
"js-snippet-msg-1": "Vous pouvez obtenir le TemplateId à partir de la page Gérer les modèles.",
|
||||
"agrrement-alert": "Pour procéder, vous devez consentir à la divulgation des enregistrements et signatures électroniques.",
|
||||
"webhook-already-exists": "L'URL existe déjà ! Veuillez en essayer un autre.",
|
||||
@@ -825,8 +814,8 @@
|
||||
"requestsign-description": "Utilisez ce formulaire pour demander les signatures des autres et de vous-même.",
|
||||
"template-form-description": "Utilisez ce formulaire pour créer des modèles réutilisables pour vos documents.",
|
||||
"activation-key": "Clé d'activation",
|
||||
"paid-selfhost-help": "Veuillez contacter {{appName}} pour plus d'informations à l'adresse ",
|
||||
"remaining-credits-selfhost-help": "Utilisez des crédits premium pour la signature de documents via l'API, l'envoi en masse et l'intégration d'{{appName}} sur votre site web. Vous avez {{allowedcredits}} crédits inclus et {{addoncredits}} crédits supplémentaires achetés restants.",
|
||||
"paid-selfhost-help": "Veuillez contacter OpenSign pour plus d'informations à l'adresse ",
|
||||
"remaining-credits-selfhost-help": "Utilisez des crédits premium pour la signature de documents via l'API, l'envoi en masse et l'intégration d'OpenSign sur votre site web. Vous avez {{allowedcredits}} crédits inclus et {{addoncredits}} crédits supplémentaires achetés restants.",
|
||||
"signature-type": "Votre signature",
|
||||
"initial-type": "Vos initiales",
|
||||
"redirect-url": "URL de redirection",
|
||||
@@ -845,16 +834,6 @@
|
||||
"send-to-sign": "vous a demandé de signer",
|
||||
"use-template": "Utiliser le modèle",
|
||||
"contact-already-exists": "Le contact existe déjà.",
|
||||
"docx-error": "Nous rencontrons actuellement des problèmes avec le traitement des fichiers DOCX. Veuillez télécharger le fichier PDF",
|
||||
"docx-error-contact": "ou contactez-nous à support@opensignlabs.com",
|
||||
"agreement-note": "Remarque : Accepter cela ne signifie pas que vous signez immédiatement le document. Cela vous permet uniquement de consulter le document électroniquement. Vous aurez l'opportunité de le lire entièrement et de décider ensuite si vous souhaitez le signer.",
|
||||
"draft-template-info-p1": "Pour rendre votre modèle public, il doit contenir un seul rôle ou, s'il inclut plusieurs rôles, tous les rôles supplémentaires doivent déjà être attribués aux signataires. Le rôle public non attribué doit rester vide et être placé en première position.",
|
||||
"visit-below-link": "Visitez le lien ci-dessous pour en savoir plus -",
|
||||
"storage-help": "Activer BYOC vous permet de connecter votre propre stockage S3 afin que vos fichiers restent entièrement sous votre contrôle, sans copie externe conservée. Si l'autonomie des données est importante pour vous, envisagez de passer à l'offre Teams pour débloquer cette fonctionnalité.",
|
||||
"daily-quota-reached": "Vous avez atteint votre quota quotidien. Pour obtenir de l'aide, veuillez contacter quotas@opensignlabs.com.",
|
||||
"enabled-signature-type": "Types de signature activés",
|
||||
"enabled-signature-type-help": "Le paramètre 'Types de signature activés' détermine quelles options de signature sont disponibles dans votre organisation. Par exemple, si vous désactivez l'option 'Dessiner', les membres de votre organisation ne la verront pas dans le widget de signature, tandis que les trois autres options resteront accessibles.",
|
||||
"indexing-public-profile": "Autoriser l'indexation du profil public par les moteurs de recherche",
|
||||
"user-created-successfully": "Utilisateur créé avec succès.",
|
||||
"only-15-reminder-allowed": "Vous pouvez définir jusqu'à 15 rappels automatiques. Par exemple, si 'TimeToComplete' est de 15 jours et 'RemindOnceInEvery' est de 1 jour, vous atteindrez la limite maximale de 15 rappels. Ajustez vos paramètres en conséquence."
|
||||
"agreement-note": "Remarque : Accepter cela ne signifie pas que vous signez immédiatement le document. Cela vous permet uniquement de consulter le document électroniquement. Vous aurez l'opportunité de le lire entièrement et de décider ensuite si vous souhaitez le signer."
|
||||
|
||||
}
|
||||
|
||||
@@ -51,6 +51,7 @@
|
||||
"docs": "Documenti",
|
||||
"session-expired": "La tua sessione è scaduta.",
|
||||
"public-profile-help": "Questo è il tuo URL pubblico. Copialo o condividilo con il firmatario, e potrai visualizzare tutti i tuoi modelli pubblici.",
|
||||
"tagline-help": "Questo slogan apparirà nel tuo profilo pubblico OpenSign, es. https://opensign.me/alex",
|
||||
"welcome": "Bentornato!",
|
||||
"Login-to-your-account": "Accedi al tuo account",
|
||||
"password": "Password",
|
||||
@@ -73,23 +74,12 @@
|
||||
"Sign yourself": "Firma tu stesso",
|
||||
"Request signatures": "Richiedi firme",
|
||||
"Templates": "Modelli",
|
||||
"Analytics": "Analitica",
|
||||
"Branding": "Marchio",
|
||||
"Mail": "Posta",
|
||||
"Storage": "Archiviazione",
|
||||
"Signing certificate": "Certificato di firma",
|
||||
"Teams": "Squadre",
|
||||
"General": "Generale",
|
||||
"Teams-Children": {
|
||||
"Organizations": "Organizzazioni",
|
||||
"OrgAdmins": "OrgAdmins"
|
||||
},
|
||||
"Templates-Children": {
|
||||
"Create template": "Crea modello",
|
||||
"Manage templates": "Gestisci modelli",
|
||||
"Embedding": "Incorporazione"
|
||||
},
|
||||
"OpenSign™ Drive": "{{appName}} Drive",
|
||||
"OpenSign™ Drive": "OpenSign™ Drive",
|
||||
"Reports": "Report",
|
||||
"Documents": "Documenti",
|
||||
"Documents-Children": {
|
||||
@@ -150,8 +140,7 @@
|
||||
"Copy Public URL": "Copia URL pubblico",
|
||||
"extend-expiry-date": "Estendi data di scadenza",
|
||||
"Duplicate Template": "Duplica modello",
|
||||
"Duplicate": "Duplica",
|
||||
"daily-mail-quota": "Quota e-mail giornaliera"
|
||||
"Duplicate": "Duplica"
|
||||
},
|
||||
"report-heading": {
|
||||
"Sr.No": "Nr.",
|
||||
@@ -209,7 +198,7 @@
|
||||
"remind-once": "Ricorda una volta ogni (giorni)",
|
||||
"next": "Avanti",
|
||||
"select-folder": "Seleziona cartella",
|
||||
"OpenSign-drive": "{{appName}} Drive",
|
||||
"OpenSign-drive": "OpenSign™ Drive",
|
||||
"drive-document-status": {
|
||||
"Completed": "Completato",
|
||||
"Declined": "Rifiutato",
|
||||
@@ -217,7 +206,7 @@
|
||||
"Expired": "Scaduto",
|
||||
"In Progress": "In corso"
|
||||
},
|
||||
"select-folder-help": "Se non selezioni una cartella, il tuo documento firmato verrà salvato nella cartella principale di {{appName}} Drive.",
|
||||
"select-folder-help": "Se non selezioni una cartella, il tuo documento firmato verrà salvato nella cartella principale di OpenSign drive.",
|
||||
"no-data": "Nessun dato trovato",
|
||||
"save-here": "Salva qui",
|
||||
"back": "Indietro",
|
||||
@@ -289,7 +278,7 @@
|
||||
"embed-template": "Incorpora Modello",
|
||||
"public-url-copy": "Ecco il tuo URL pubblico: ",
|
||||
"public-url-copy-mssg": "Copialo o condividilo con il firmatario; potrai vedere tutti i tuoi modelli impostati come pubblici.",
|
||||
"add-public-url-alert": "Completa la configurazione del tuo profilo pubblico {{appName}}. Dopo, potrai rendere i modelli pubblici. Questo processo è necessario solo una volta.",
|
||||
"add-public-url-alert": "Completa la configurazione del tuo profilo pubblico OpenSign. Dopo, potrai rendere i modelli pubblici. Questo processo è necessario solo una volta.",
|
||||
"share-with-alert": "Non puoi condividere un modello se alcuni ruoli hanno già contatti assegnati. Rimuovi tutte le assegnazioni di contatti dai ruoli prima di condividere il modello.",
|
||||
"share-with": "Condividi con",
|
||||
"team-not-found": "Team non trovato",
|
||||
@@ -452,7 +441,6 @@
|
||||
"add-recipients": "Aggiungi destinatari",
|
||||
"loading-mssg": "Questo potrebbe richiedere del tempo",
|
||||
"send-mail": "Invia Mail",
|
||||
"signature-field-widget":"È necessario aggiungere almeno un campo firma per ogni utente. Non hai aggiunto campi firma per {{signersName}}",
|
||||
"placeholder-alert-1": "Assicurati che sia stato aggiunto almeno un widget per la firma per tutti i destinatari.",
|
||||
"placeholder-alert-2": "Conferma di aver compilato il campo di testo.",
|
||||
"placeholder-alert-3": "Sei sicuro di voler inviare questo documento per le firme?",
|
||||
@@ -504,7 +492,7 @@
|
||||
"role-not-found": "Ruolo non trovato.",
|
||||
"do-not-access": "Non hai accesso, contatta l'amministratore.",
|
||||
"add-admin": "Aggiungi amministratore",
|
||||
"opensign-setup": "Configurazione {{appName}}",
|
||||
"opensign-setup": "Configurazione OpenSign",
|
||||
"join-discord": "Unisciti al nostro server Discord",
|
||||
"admin-already-exist": "L'amministratore esiste già.",
|
||||
"password-update-alert-1": "Password aggiornata con successo.",
|
||||
@@ -561,6 +549,7 @@
|
||||
"filed-required-correctly": "Compila i dettagli richiesti correttamente.",
|
||||
"admin-created": "Amministratore creato",
|
||||
"invalid-masterkey": "Masterkey non valida",
|
||||
"opensign-Setup": "Configurazione OpenSign",
|
||||
"master-key": "Chiave principale",
|
||||
"profile-update-alert": "Profilo aggiornato con successo.",
|
||||
"date": "Data",
|
||||
@@ -585,7 +574,7 @@
|
||||
"tour-mssg": {
|
||||
"home-layout-1": "Accesso effettuato con successo! Diamo un'occhiata.",
|
||||
"home-layout-2": "Per caricare documenti da firmare personalmente o richiedere le firme di altri, seleziona semplicemente i pulsanti corrispondenti.",
|
||||
"home-layout-3": "Sei pronto per iniziare a usare {{appName}}! Se hai bisogno di supporto, contattaci pure.",
|
||||
"home-layout-3": "Sei pronto per iniziare a usare OpenSign! Se hai bisogno di supporto, contattaci pure.",
|
||||
"generate-token": "Esegui l'upgrade ora per generare un token API di produzione.",
|
||||
"opensign-drive-1": "Fai clic sui collegamenti breadcrumb per navigare facilmente attraverso la gerarchia delle cartelle e visualizzare i documenti in ciascuna cartella.",
|
||||
"opensign-drive-2": "Fai clic sul pulsante aggiungi per creare una nuova cartella o documento.",
|
||||
@@ -700,19 +689,19 @@
|
||||
"download-pdf": "Scarica Pdf",
|
||||
"pdf-certificate": "Scarica Pdf + Certificato",
|
||||
"document-logs": "Log del documento",
|
||||
"server-down": "Impossibile connettersi al server {{appName}}. Se stai ospitando {{appName}} autonomamente, assicurati che tutti i passaggi nella documentazione siano stati seguiti correttamente. Se stai eseguendo {{appName}} localmente, potresti accedervi tramite un numero di porta errato.",
|
||||
"server-down": "Impossibile connettersi al server OpenSign. Se stai ospitando OpenSign autonomamente, assicurati che tutti i passaggi nella documentazione siano stati seguiti correttamente. Se stai eseguendo OpenSign localmente, potresti accedervi tramite un numero di porta errato.",
|
||||
"admin-exists": "L'amministratore esiste già. Accedi all'applicazione utilizzando le credenziali di amministratore per gestire gli utenti.",
|
||||
"enable-tour": "Abilita tour",
|
||||
"istourenabled-help": {
|
||||
"p1": "Questo abiliterà un tour guidato per i firmatari, fornendo istruzioni durante il processo di firma.",
|
||||
"p2": "Questo disabiliterà il tour guidato, garantendo un'esperienza di firma più veloce e senza interruzioni.",
|
||||
"p3": "Suggerimento: Se i tuoi firmatari sono familiari con {{appName}} e lo usano frequentemente, potresti voler disabilitare il tour guidato per un'esperienza più fluida. Scegli l'opzione che meglio si adatta alle tue esigenze di firma dei documenti."
|
||||
"p3": "Suggerimento: Se i tuoi firmatari sono familiari con OpenSign e lo usano frequentemente, potresti voler disabilitare il tour guidato per un'esperienza più fluida. Scegli l'opzione che meglio si adatta alle tue esigenze di firma dei documenti."
|
||||
},
|
||||
"form-title-1": "Impostazioni del flusso del documento",
|
||||
"form-title-2": "Impostazioni di sicurezza",
|
||||
"public-tour-message": "Il modello deve essere pubblico prima di poter generare un link condivisibile.",
|
||||
"add-user-template": "Devi aggiungere un ruolo prima di poter aggiungere i campi per esso.",
|
||||
"pdf-uncompatible": "Questo PDF non è compatibile, contatta {{appName}}",
|
||||
"pdf-uncompatible": "Questo PDF non è compatibile con OpenSign, contatta <support@opensignlabs.com>",
|
||||
"text-field-tour": "I campi di tipo 'Testo' devono essere compilati in anticipo prima che il documento venga inviato. Se hai bisogno che i firmatari forniscano un input, usa invece il campo 'Testo di input'.",
|
||||
"attach-signer-tour": "Devi allegare un firmatario a ogni ruolo. Puoi farlo cliccando su questa icona. Una volta selezionato un firmatario, sarà associato a tutti i campi associati a quel ruolo che appariranno dello stesso colore.",
|
||||
"allowed-signature-types": "Tipi di firma consentiti",
|
||||
@@ -752,7 +741,7 @@
|
||||
"delete-folder-alert": "Sei sicuro di voler eliminare questa cartella?",
|
||||
"delete-folder-alert-1": "Impossibile eliminare: la cartella deve essere vuota.",
|
||||
"defaultSign-alert": "I widget {{widgetsType}} non sono disponibili per la firma automatica.",
|
||||
"embed-heading": "Incorpora modelli {{appName}}",
|
||||
"embed-heading": "Incorpora modelli OpenSign",
|
||||
"public-template-edit-title": "Modifica Modello Pubblico",
|
||||
"public-template-edit-mssg": "Non puoi modificare direttamente un modello pubblico. Per apportare modifiche, il modello sarà impostato come privato e dovrai renderlo pubblico di nuovo successivamente. Vuoi continuare?",
|
||||
"agree-p1": "Confermo di aver letto e compreso il",
|
||||
@@ -761,46 +750,46 @@
|
||||
"agrre-button": "Accetta e Continua",
|
||||
"term-cond-title": "Termini e Condizioni",
|
||||
"term-cond-h": "DIVULGAZIONE SULLE REGISTRAZIONI E FIRME ELETTRONICHE",
|
||||
"term-cond-p1": "Questa Divulgazione sulle Registrazioni e Firme Elettroniche ('Divulgazione') è un accordo tra il Creatore del Documento ('Mittente') e il Firmatario ('Tu'), facilitato tramite la piattaforma {{appName}} (Piattaforma). Firmando documenti tramite {{appName}}, accetti i termini descritti in questa Divulgazione. Ti preghiamo di leggerla attentamente prima di procedere.",
|
||||
"term-cond-p1": "Questa Divulgazione sulle Registrazioni e Firme Elettroniche ('Divulgazione') è un accordo tra il Creatore del Documento ('Mittente') e il Firmatario ('Tu'), facilitato tramite la piattaforma OpenSign ('Piattaforma'). Firmando documenti tramite OpenSign, accetti i termini descritti in questa Divulgazione. Ti preghiamo di leggerla attentamente prima di procedere.",
|
||||
"term-cond-h1": "1. Scopo e ambito",
|
||||
"term-cond-p2": "Questa Divulgazione regola l'uso di registrazioni e firme elettroniche per i documenti inviati dal Mittente e firmati da Te tramite la piattaforma {{appName}}. Accettando, riconosci che:",
|
||||
"term-cond-p3": "Riceverai e firmerai documenti elettronicamente tramite {{appName}}.",
|
||||
"term-cond-p2": "Questa Divulgazione regola l'uso di registrazioni e firme elettroniche per i documenti inviati dal Mittente e firmati da Te tramite la piattaforma OpenSign. Accettando, riconosci che:",
|
||||
"term-cond-p3": "Riceverai e firmerai documenti elettronicamente tramite OpenSign.",
|
||||
"term-cond-p4": "La tua firma elettronica è legalmente vincolante ed equivalente a una firma manoscritta.",
|
||||
"term-cond-h2": "2. Consenso all'uso di registrazioni e firme elettroniche",
|
||||
"term-cond-p5": "Accettando questa Divulgazione:",
|
||||
"term-cond-p6": "Consenti di effettuare transazioni elettroniche con il Mittente utilizzando {{appName}} e comprendi che questo consenso è valido fino a revoca.",
|
||||
"term-cond-p7": "Accetti di rivedere, firmare e restituire documenti elettronicamente utilizzando {{appName}}.",
|
||||
"term-cond-p6": "Consenti di effettuare transazioni elettroniche con il Mittente utilizzando OpenSign e comprendi che questo consenso è valido fino a revoca.",
|
||||
"term-cond-p7": "Accetti di rivedere, firmare e restituire documenti elettronicamente utilizzando OpenSign.",
|
||||
"term-cond-p8": "Questo consenso si applica solo ai documenti specifici forniti dal Mittente.",
|
||||
"term-cond-h3": "3. Diritto di revoca del consenso",
|
||||
"term-cond-p9": "Hai il diritto di ritirare il tuo consenso all'uso di registrazioni elettroniche e firme contattando direttamente il mittente tramite le informazioni di contatto fornite nella loro comunicazione.",
|
||||
"term-cond-p10": "Contattando il mittente direttamente utilizzando le informazioni di contatto fornite nella loro comunicazione.",
|
||||
"term-cond-p11": "Notificando il mittente prima di completare il processo di firma.",
|
||||
"term-cond-h4": "4. Requisiti hardware e software",
|
||||
"term-cond-p12": "Per firmare documenti utilizzando {{appName}}, devi avere:",
|
||||
"term-cond-p12": "Per firmare documenti utilizzando OpenSign, devi avere:",
|
||||
"term-cond-p13": "Un dispositivo con accesso a Internet.",
|
||||
"term-cond-p14": "Un browser web compatibile con JavaScript abilitato.",
|
||||
"term-cond-p15": "Un account email per ricevere notifiche e documenti firmati.",
|
||||
"term-cond-p16": "Se questi requisiti cambiano, il mittente o {{appName}} ti notificheranno gli aggiornamenti.",
|
||||
"term-cond-p16": "Se questi requisiti cambiano, il mittente o OpenSign ti notificheranno gli aggiornamenti.",
|
||||
"term-cond-h5": "5. Conservazione dei documenti e richiesta di copie cartacee",
|
||||
"term-cond-p17": "Sei responsabile di assicurarti di poter accedere e conservare il documento(i) firmato(i) elettronicamente. {{appName}} fornisce strumenti per scaricare o stampare il documento firmato subito dopo che il processo di firma è completo.",
|
||||
"term-cond-p17": "Sei responsabile di assicurarti di poter accedere e conservare il documento(i) firmato(i) elettronicamente. OpenSign fornisce strumenti per scaricare o stampare il documento firmato subito dopo che il processo di firma è completo.",
|
||||
"term-cond-p18": "Se preferisci una copia cartacea di qualsiasi documento firmato elettronicamente, puoi richiederla direttamente al mittente. Il mittente può addebitare una tariffa ragionevole per fornire copie cartacee, salvo quanto vietato dalla legge applicabile.",
|
||||
"term-cond-h6": "6. Riconoscimento e Accordo",
|
||||
"term-cond-p19": "Procedendo, confermi che:",
|
||||
"term-cond-p20": "Confermi di poter accedere e rivedere i documenti elettronici come descritto in questa divulgazione.",
|
||||
"term-cond-p21": "Accetti di utilizzare registrazioni elettroniche e firme per le transazioni specificate con il mittente.",
|
||||
"term-cond-p22": "Comprendi che {{appName}} è una piattaforma che facilita la transazione e non è parte dell'accordo.",
|
||||
"term-cond-p22": "Comprendi che OpenSign è una piattaforma che facilita la transazione e non è parte dell'accordo.",
|
||||
"term-cond-h7": "7. Effetto Legale",
|
||||
"term-cond-p23": "La tua firma elettronica facilitata tramite {{appName}}:",
|
||||
"term-cond-p23": "La tua firma elettronica facilitata tramite OpenSign:",
|
||||
"term-cond-p24": "Rispetta le leggi applicabili sulle firme elettroniche, inclusa, ma non limitata alla Legge E-SIGN negli Stati Uniti, al Regolamento eIDAS dell'UE e alla Legge sull'Information Technology in India.",
|
||||
"term-cond-p25": "È legalmente vincolante tra te e il mittente per il/i documento(i) firmato(i).",
|
||||
"term-cond-h8": "8. Ruolo della piattaforma e limitazione di responsabilità",
|
||||
"term-cond-p26": "{{appName}} funge da piattaforma per facilitare le transazioni elettroniche. Non è responsabile del contenuto, della validità o dell'applicabilità dei documenti inviati dal mittente. Eventuali controversie o problemi relativi al documento o alla sua firma devono essere risolti direttamente tra te e il mittente.",
|
||||
"term-cond-p26": "OpenSign funge da piattaforma per facilitare le transazioni elettroniche. Non è responsabile del contenuto, della validità o dell'applicabilità dei documenti inviati dal mittente. Eventuali controversie o problemi relativi al documento o alla sua firma devono essere risolti direttamente tra te e il mittente.",
|
||||
"term-cond-h9": "9. Risoluzione dell'accordo",
|
||||
"term-cond-p27": "Il tuo consenso si applica solo alla transazione corrente, salvo diverso accordo da parte del mittente. {{appName}} si riserva il diritto di terminare l'accesso alla sua piattaforma per violazioni dei suoi Termini di servizio o delle politiche.",
|
||||
"term-cond-p28": "Selezionando 'Accetto', confermi di aver compreso e accettato i termini di questa divulgazione delle registrazioni elettroniche e delle firme e acconsenti a firmare elettronicamente il/i documento(i) fornito(i) dal mittente tramite {{appName}}.",
|
||||
"term-cond-p29": "Se hai domande su questa divulgazione, contatta direttamente il mittente. Per supporto tecnico con {{appName}}, visita ",
|
||||
"term-cond-p30": " o invia una email a",
|
||||
"js-snippet-msg": "Per integrare i modelli {{appName}} nel tuo sito web HTML o nelle tue pagine di destinazione, puoi usare il codice qui sotto:",
|
||||
"term-cond-p27": "Il tuo consenso si applica solo alla transazione corrente, salvo diverso accordo da parte del mittente. OpenSign si riserva il diritto di terminare l'accesso alla sua piattaforma per violazioni dei suoi Termini di servizio o delle politiche.",
|
||||
"term-cond-p28": "Selezionando 'Accetto', confermi di aver compreso e accettato i termini di questa divulgazione delle registrazioni elettroniche e delle firme e acconsenti a firmare elettronicamente il/i documento(i) fornito(i) dal mittente tramite OpenSign.",
|
||||
"term-cond-p29": "Se hai domande su questa divulgazione, contatta direttamente il mittente. Per supporto tecnico con OpenSign, visita",
|
||||
"term-cond-p30": "o invia una email a",
|
||||
"js-snippet-msg": "Per integrare i modelli OpenSign nel tuo sito web HTML o nelle tue pagine di destinazione, puoi usare il codice qui sotto:",
|
||||
"js-snippet-msg-1": "Puoi ottenere il TemplateId dalla",
|
||||
"js-snippet-msg-2": "pagina di gestione modelli",
|
||||
"js-snippet-msg-3": "pagina.",
|
||||
@@ -825,8 +814,8 @@
|
||||
},
|
||||
"signature-setting": "Impostazioni Firma",
|
||||
"activation-key": "Chiave di attivazione",
|
||||
"paid-selfhost-help": "Si prega di contattare {{appName}} per ulteriori informazioni all'indirizzo ",
|
||||
"remaining-credits-selfhost-help": "Utilizza i crediti premium per la firma di documenti tramite API, l'invio in massa e l'integrazione di {{appName}} sul tuo sito web. Hai {{allowedcredits}} crediti inclusi e {{addoncredits}} crediti aggiuntivi acquistati rimanenti.",
|
||||
"paid-selfhost-help": "Si prega di contattare OpenSign per ulteriori informazioni all'indirizzo ",
|
||||
"remaining-credits-selfhost-help": "Utilizza i crediti premium per la firma di documenti tramite API, l'invio in massa e l'integrazione di OpenSign sul tuo sito web. Hai {{allowedcredits}} crediti inclusi e {{addoncredits}} crediti aggiuntivi acquistati rimanenti.",
|
||||
"signature-type": "La tua firma",
|
||||
"initial-type": "Le tue iniziali",
|
||||
"redirect-url": "URL di reindirizzamento",
|
||||
@@ -845,16 +834,5 @@
|
||||
"send-to-sign": "ha richiesto la tua firma",
|
||||
"use-template": "Usa modello",
|
||||
"contact-already-exists": "Il contatto esiste già.",
|
||||
"docx-error": "Stiamo riscontrando alcuni problemi con l'elaborazione dei file DOCX. Per favore, carica il file PDF",
|
||||
"docx-error-contact": "o contattaci a support@opensignlabs.com",
|
||||
"agreement-note": "Nota: Accettare questo non significa che stai firmando immediatamente il documento. Questo ti consente solo di esaminare il documento elettronicamente. Avrai l'opportunità di leggerlo per intero e decidere successivamente se firmarlo.",
|
||||
"draft-template-info-p1": "Per rendere il tuo modello pubblico, deve contenere un solo ruolo oppure, se include più ruoli, tutti i ruoli aggiuntivi devono essere già assegnati ai firmatari. Il ruolo pubblico non assegnato deve rimanere vuoto e deve essere posizionato per primo.",
|
||||
"visit-below-link": "Visita il link qui sotto per saperne di più -",
|
||||
"storage-help": "Abilitare BYOC ti consente di collegare il tuo archivio S3 in modo che i tuoi file rimangano completamente sotto il tuo controllo, senza copie esterne conservate. Se l'autonomia dei dati è importante per te, considera l'upgrade a Teams per sbloccare questa funzionalità.",
|
||||
"daily-quota-reached": "Hai raggiunto la tua quota giornaliera. Per assistenza, contatta quotas@opensignlabs.com.",
|
||||
"enabled-signature-type": "Tipi di firma abilitati",
|
||||
"enabled-signature-type-help": "L'impostazione 'Tipi di firma abilitati' determina quali opzioni di firma sono disponibili nella tua organizzazione. Ad esempio, se disabiliti l'opzione 'Disegna', i membri della tua organizzazione non la vedranno nel widget della firma, mentre le altre tre opzioni resteranno accessibili.",
|
||||
"indexing-public-profile": "Consenti l'indicizzazione del profilo pubblico dai motori di ricerca",
|
||||
"user-created-successfully": "Utente creato con successo.",
|
||||
"only-15-reminder-allowed": "Puoi impostare fino a 15 promemoria automatici. Ad esempio, se 'TimeToComplete' è di 15 giorni e 'RemindOnceInEvery' è di 1 giorno, raggiungerai il limite massimo di 15 promemoria. Regola le tue impostazioni di conseguenza."
|
||||
"agreement-note": "Nota: Accettare questo non significa che stai firmando immediatamente il documento. Questo ti consente solo di esaminare il documento elettronicamente. Avrai l'opportunità di leggerlo per intero e decidere successivamente se firmarlo."
|
||||
}
|
||||
|
||||
@@ -19,7 +19,6 @@ import Loader from "./primitives/Loader";
|
||||
import UserList from "./pages/UserList";
|
||||
import { serverUrl_fn } from "./constant/appinfo";
|
||||
import DocSuccessPage from "./pages/DocSuccessPage";
|
||||
import ValidateSession from "./primitives/ValidateSession";
|
||||
const DebugPdf = lazy(() => import("./pages/DebugPdf"));
|
||||
const ForgetPassword = lazy(() => import("./pages/ForgetPassword"));
|
||||
const GuestLogin = lazy(() => import("./pages/GuestLogin"));
|
||||
@@ -30,7 +29,6 @@ const ManageSign = lazy(() => import("./pages/Managesign"));
|
||||
const AddAdmin = lazy(() => import("./pages/AddAdmin"));
|
||||
const UpdateExistUserAdmin = lazy(() => import("./pages/UpdateExistUserAdmin"));
|
||||
const Preferences = lazy(() => import("./pages/Preferences"));
|
||||
|
||||
pdfjs.GlobalWorkerOptions.workerSrc = `//unpkg.com/pdfjs-dist@${pdfjs.version}/legacy/build/pdf.worker.min.mjs`;
|
||||
const AppLoader = () => {
|
||||
return (
|
||||
@@ -110,13 +108,7 @@ function App() {
|
||||
path="/forgetpassword"
|
||||
element={<LazyPage Page={ForgetPassword} />}
|
||||
/>
|
||||
<Route
|
||||
element={
|
||||
<ValidateSession>
|
||||
<HomeLayout />
|
||||
</ValidateSession>
|
||||
}
|
||||
>
|
||||
<Route element={<HomeLayout />}>
|
||||
<Route
|
||||
path="/changepassword"
|
||||
element={<LazyPage Page={ChangePassword} />}
|
||||
@@ -129,7 +121,7 @@ function App() {
|
||||
element={<LazyPage Page={UserProfile} />}
|
||||
/>
|
||||
<Route
|
||||
path="/drive"
|
||||
path="/opensigndrive"
|
||||
element={<LazyPage Page={Opensigndrive} />}
|
||||
/>
|
||||
<Route
|
||||
|
||||
@@ -2,8 +2,13 @@ import React, { useEffect, useState } from "react";
|
||||
import Parse from "parse";
|
||||
import Title from "./Title";
|
||||
import Loader from "../primitives/Loader";
|
||||
import { copytoData, usertimezone } from "../constant/Utils";
|
||||
import { emailRegex } from "../constant/const";
|
||||
import {
|
||||
copytoData,
|
||||
usertimezone
|
||||
} from "../constant/Utils";
|
||||
import {
|
||||
emailRegex,
|
||||
} from "../constant/const";
|
||||
import { useTranslation } from "react-i18next";
|
||||
function generatePassword(length) {
|
||||
const characters =
|
||||
@@ -41,9 +46,9 @@ const AddUser = (props) => {
|
||||
if (teamRes.length > 0) {
|
||||
const _teamRes = JSON.parse(JSON.stringify(teamRes));
|
||||
setTeamList(_teamRes);
|
||||
const allUserId =
|
||||
_teamRes.find((x) => x.Name === "All Users")?.objectId || "";
|
||||
setFormdata((prev) => ({ ...prev, team: allUserId }));
|
||||
const allUserId =
|
||||
_teamRes.find((x) => x.Name === "All Users")?.objectId || "";
|
||||
setFormdata((prev) => ({ ...prev, team: allUserId }));
|
||||
}
|
||||
};
|
||||
const checkUserExist = async () => {
|
||||
@@ -71,167 +76,167 @@ const AddUser = (props) => {
|
||||
setIsFormLoader(true);
|
||||
const res = await checkUserExist();
|
||||
if (res) {
|
||||
props.showAlert("danger", t("user-already-exist"));
|
||||
props.setIsAlert({ type: "danger", msg: t("user-already-exist") });
|
||||
setIsFormLoader(false);
|
||||
setTimeout(() => props.setIsAlert({ type: "success", msg: "" }), 1000);
|
||||
} else {
|
||||
if (localStorage.getItem("TenantId")) {
|
||||
try {
|
||||
const extUser = new Parse.Object("contracts_Users");
|
||||
extUser.set("Name", formdata.name);
|
||||
if (formdata.phone) {
|
||||
extUser.set("Phone", formdata.phone);
|
||||
}
|
||||
extUser.set("Email", formdata.email);
|
||||
extUser.set("UserRole", `contracts_${formdata.role}`);
|
||||
if (formdata?.team) {
|
||||
extUser.set("TeamIds", [
|
||||
{
|
||||
__type: "Pointer",
|
||||
className: "contracts_Teams",
|
||||
objectId: formdata.team
|
||||
}
|
||||
]);
|
||||
}
|
||||
if (localUser && localUser.OrganizationId) {
|
||||
extUser.set("OrganizationId", {
|
||||
__type: "Pointer",
|
||||
className: "contracts_Organizations",
|
||||
objectId: localUser.OrganizationId.objectId
|
||||
});
|
||||
}
|
||||
if (localUser && localUser.Company) {
|
||||
extUser.set("Company", localUser.Company);
|
||||
}
|
||||
|
||||
if (localStorage.getItem("TenantId")) {
|
||||
extUser.set("TenantId", {
|
||||
__type: "Pointer",
|
||||
className: "partners_Tenant",
|
||||
objectId: localStorage.getItem("TenantId")
|
||||
});
|
||||
}
|
||||
const timezone = usertimezone;
|
||||
if (timezone) {
|
||||
extUser.set("Timezone", timezone);
|
||||
}
|
||||
try {
|
||||
const extUser = new Parse.Object("contracts_Users");
|
||||
extUser.set("Name", formdata.name);
|
||||
const _users = Parse.Object.extend("User");
|
||||
const _user = new _users();
|
||||
_user.set("name", formdata.name);
|
||||
_user.set("username", formdata.email);
|
||||
_user.set("email", formdata.email);
|
||||
_user.set("password", formdata.password);
|
||||
if (formdata.phone) {
|
||||
extUser.set("Phone", formdata.phone);
|
||||
_user.set("phone", formdata.phone);
|
||||
}
|
||||
extUser.set("Email", formdata.email);
|
||||
extUser.set("UserRole", `contracts_${formdata.role}`);
|
||||
if (formdata?.team) {
|
||||
extUser.set("TeamIds", [
|
||||
{
|
||||
__type: "Pointer",
|
||||
className: "contracts_Teams",
|
||||
objectId: formdata.team
|
||||
|
||||
const user = await _user.save();
|
||||
if (user) {
|
||||
const currentUser = Parse.User.current();
|
||||
extUser.set(
|
||||
"CreatedBy",
|
||||
Parse.User.createWithoutData(currentUser.id)
|
||||
);
|
||||
|
||||
extUser.set("UserId", user);
|
||||
const acl = new Parse.ACL();
|
||||
acl.setPublicReadAccess(true);
|
||||
acl.setPublicWriteAccess(true);
|
||||
acl.setReadAccess(currentUser.id, true);
|
||||
acl.setWriteAccess(currentUser.id, true);
|
||||
|
||||
extUser.setACL(acl);
|
||||
|
||||
const res = await extUser.save();
|
||||
|
||||
const parseData = JSON.parse(JSON.stringify(res));
|
||||
|
||||
if (props.closePopup) {
|
||||
props.closePopup();
|
||||
}
|
||||
if (props.handleUserData) {
|
||||
if (formdata?.team) {
|
||||
const team = teamList.find(
|
||||
(x) => x.objectId === formdata.team
|
||||
);
|
||||
parseData.TeamIds = parseData.TeamIds.map((y) =>
|
||||
y.objectId === team.objectId ? team : y
|
||||
);
|
||||
}
|
||||
]);
|
||||
}
|
||||
if (localUser && localUser.OrganizationId) {
|
||||
extUser.set("OrganizationId", {
|
||||
__type: "Pointer",
|
||||
className: "contracts_Organizations",
|
||||
objectId: localUser.OrganizationId.objectId
|
||||
props.handleUserData(parseData);
|
||||
}
|
||||
|
||||
setIsFormLoader(false);
|
||||
setFormdata({
|
||||
name: "",
|
||||
email: "",
|
||||
phone: "",
|
||||
team: "",
|
||||
role: ""
|
||||
});
|
||||
}
|
||||
if (localUser && localUser.Company) {
|
||||
extUser.set("Company", localUser.Company);
|
||||
}
|
||||
|
||||
if (localStorage.getItem("TenantId")) {
|
||||
extUser.set("TenantId", {
|
||||
__type: "Pointer",
|
||||
className: "partners_Tenant",
|
||||
objectId: localStorage.getItem("TenantId")
|
||||
});
|
||||
}
|
||||
const timezone = usertimezone;
|
||||
if (timezone) {
|
||||
extUser.set("Timezone", timezone);
|
||||
}
|
||||
try {
|
||||
const _users = Parse.Object.extend("User");
|
||||
const _user = new _users();
|
||||
_user.set("name", formdata.name);
|
||||
_user.set("username", formdata.email);
|
||||
_user.set("email", formdata.email);
|
||||
_user.set("password", formdata.password);
|
||||
if (formdata.phone) {
|
||||
_user.set("phone", formdata.phone);
|
||||
}
|
||||
|
||||
const user = await _user.save();
|
||||
if (user) {
|
||||
const currentUser = Parse.User.current();
|
||||
extUser.set(
|
||||
"CreatedBy",
|
||||
Parse.User.createWithoutData(currentUser.id)
|
||||
);
|
||||
|
||||
extUser.set("UserId", user);
|
||||
const acl = new Parse.ACL();
|
||||
acl.setPublicReadAccess(true);
|
||||
acl.setPublicWriteAccess(true);
|
||||
acl.setReadAccess(currentUser.id, true);
|
||||
acl.setWriteAccess(currentUser.id, true);
|
||||
|
||||
extUser.setACL(acl);
|
||||
|
||||
const res = await extUser.save();
|
||||
|
||||
const parseData = JSON.parse(JSON.stringify(res));
|
||||
|
||||
if (props.closePopup) {
|
||||
props.closePopup();
|
||||
}
|
||||
if (props.handleUserData) {
|
||||
if (formdata?.team) {
|
||||
const team = teamList.find(
|
||||
(x) => x.objectId === formdata.team
|
||||
);
|
||||
parseData.TeamIds = parseData.TeamIds.map((y) =>
|
||||
y.objectId === team.objectId ? team : y
|
||||
);
|
||||
}
|
||||
props.handleUserData(parseData);
|
||||
}
|
||||
|
||||
setIsFormLoader(false);
|
||||
setFormdata({
|
||||
name: "",
|
||||
email: "",
|
||||
phone: "",
|
||||
team: "",
|
||||
role: ""
|
||||
});
|
||||
props.showAlert("success", t("user-created-successfully"));
|
||||
}
|
||||
} catch (err) {
|
||||
console.log("err ", err);
|
||||
if (err.code === 202) {
|
||||
const params = { email: formdata.email };
|
||||
const userRes = await Parse.Cloud.run("getUserId", params);
|
||||
const currentUser = Parse.User.current();
|
||||
extUser.set(
|
||||
"CreatedBy",
|
||||
Parse.User.createWithoutData(currentUser.id)
|
||||
);
|
||||
|
||||
extUser.set("UserId", {
|
||||
__type: "Pointer",
|
||||
className: "_User",
|
||||
objectId: userRes.id
|
||||
});
|
||||
const acl = new Parse.ACL();
|
||||
acl.setPublicReadAccess(true);
|
||||
acl.setPublicWriteAccess(true);
|
||||
acl.setReadAccess(currentUser.id, true);
|
||||
acl.setWriteAccess(currentUser.id, true);
|
||||
|
||||
extUser.setACL(acl);
|
||||
const res = await extUser.save();
|
||||
|
||||
const parseData = JSON.parse(JSON.stringify(res));
|
||||
if (props.closePopup) {
|
||||
props.closePopup();
|
||||
}
|
||||
if (props.handleUserData) {
|
||||
if (formdata?.team) {
|
||||
const team = teamList.find(
|
||||
(x) => x.objectId === formdata.team
|
||||
);
|
||||
parseData.TeamIds = parseData.TeamIds.map((y) =>
|
||||
y.objectId === team.objectId ? team : y
|
||||
);
|
||||
}
|
||||
props.handleUserData(parseData);
|
||||
}
|
||||
setIsFormLoader(false);
|
||||
setFormdata({
|
||||
name: "",
|
||||
email: "",
|
||||
phone: "",
|
||||
team: "",
|
||||
role: ""
|
||||
});
|
||||
props.showAlert("success", t("user-created-successfully"));
|
||||
} else {
|
||||
setIsFormLoader(false);
|
||||
props.showAlert("danger", t("something-went-wrong-mssg"));
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
console.log("err", err);
|
||||
setIsFormLoader(false);
|
||||
props.showAlert("danger", t("something-went-wrong-mssg"));
|
||||
console.log("err ", err);
|
||||
if (err.code === 202) {
|
||||
const params = { email: formdata.email };
|
||||
const userRes = await Parse.Cloud.run("getUserId", params);
|
||||
const currentUser = Parse.User.current();
|
||||
extUser.set(
|
||||
"CreatedBy",
|
||||
Parse.User.createWithoutData(currentUser.id)
|
||||
);
|
||||
|
||||
extUser.set("UserId", {
|
||||
__type: "Pointer",
|
||||
className: "_User",
|
||||
objectId: userRes.id
|
||||
});
|
||||
const acl = new Parse.ACL();
|
||||
acl.setPublicReadAccess(true);
|
||||
acl.setPublicWriteAccess(true);
|
||||
acl.setReadAccess(currentUser.id, true);
|
||||
acl.setWriteAccess(currentUser.id, true);
|
||||
|
||||
extUser.setACL(acl);
|
||||
const res = await extUser.save();
|
||||
|
||||
const parseData = JSON.parse(JSON.stringify(res));
|
||||
if (props.closePopup) {
|
||||
props.closePopup();
|
||||
}
|
||||
if (props.handleUserData) {
|
||||
if (formdata?.team) {
|
||||
const team = teamList.find(
|
||||
(x) => x.objectId === formdata.team
|
||||
);
|
||||
parseData.TeamIds = parseData.TeamIds.map((y) =>
|
||||
y.objectId === team.objectId ? team : y
|
||||
);
|
||||
}
|
||||
props.handleUserData(parseData);
|
||||
}
|
||||
setIsFormLoader(false);
|
||||
setFormdata({
|
||||
name: "",
|
||||
email: "",
|
||||
phone: "",
|
||||
team: "",
|
||||
role: ""
|
||||
});
|
||||
}
|
||||
}
|
||||
} else {
|
||||
props.showAlert("danger", t("something-went-wrong-mssg"));
|
||||
} catch (err) {
|
||||
console.log("err", err);
|
||||
setIsFormLoader(false);
|
||||
props.setIsAlert({
|
||||
type: "danger",
|
||||
msg: t("something-went-wrong-mssg")
|
||||
});
|
||||
} finally {
|
||||
setTimeout(
|
||||
() => props.setIsAlert({ type: "success", msg: "" }),
|
||||
1500
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -254,7 +259,8 @@ const AddUser = (props) => {
|
||||
|
||||
const copytoclipboard = (text) => {
|
||||
copytoData(text);
|
||||
props.showAlert("success", t("copied"));
|
||||
props.setIsAlert({ type: "success", msg: t("copied") });
|
||||
setTimeout(() => props.setIsAlert({ type: "success", msg: "" }), 1500); // Reset copied state after 1.5 seconds
|
||||
};
|
||||
return (
|
||||
<div className="shadow-md rounded-box my-[1px] p-3 bg-base-100 relative">
|
||||
@@ -264,120 +270,126 @@ const AddUser = (props) => {
|
||||
<Loader />
|
||||
</div>
|
||||
)}
|
||||
<div className="w-full mx-auto">
|
||||
<form onSubmit={handleSubmit}>
|
||||
<div className="mb-3">
|
||||
<label
|
||||
htmlFor="name"
|
||||
className="block text-xs text-gray-700 font-semibold"
|
||||
>
|
||||
{t("name")}
|
||||
<span className="text-[red] text-[13px]"> *</span>
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
name="name"
|
||||
value={formdata.name}
|
||||
onChange={(e) => handleChange(e)}
|
||||
onInvalid={(e) => e.target.setCustomValidity(t("input-required"))}
|
||||
onInput={(e) => e.target.setCustomValidity("")}
|
||||
required
|
||||
className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs"
|
||||
/>
|
||||
</div>
|
||||
<div className="mb-3">
|
||||
<label
|
||||
htmlFor="email"
|
||||
className="block text-xs text-gray-700 font-semibold"
|
||||
>
|
||||
{t("email")}
|
||||
<span className="text-[red] text-[13px]"> *</span>
|
||||
</label>
|
||||
<input
|
||||
type="email"
|
||||
name="email"
|
||||
value={formdata.email}
|
||||
onChange={(e) => handleChange(e)}
|
||||
required
|
||||
onInvalid={(e) => e.target.setCustomValidity(t("input-required"))}
|
||||
onInput={(e) => e.target.setCustomValidity("")}
|
||||
className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs"
|
||||
/>
|
||||
</div>
|
||||
<div className="mb-3">
|
||||
<label className="block text-xs text-gray-700 font-semibold">
|
||||
{t("password")}
|
||||
</label>
|
||||
<div className="flex justify-between items-center op-input op-input-bordered op-input-sm text-base-content w-full h-full text-[13px]">
|
||||
<div className="break-all">{formdata?.password}</div>
|
||||
<i
|
||||
onClick={() => copytoclipboard(formdata?.password)}
|
||||
className="fa-light fa-copy rounded-full hover:bg-base-300 p-[8px] cursor-pointer "
|
||||
></i>
|
||||
</div>
|
||||
<div className="text-[12px] ml-2 mb-0 text-[red] select-none">
|
||||
{t("password-generateed")}
|
||||
</div>
|
||||
</div>
|
||||
<div className="mb-3">
|
||||
<label
|
||||
htmlFor="phone"
|
||||
className="block text-xs text-gray-700 font-semibold"
|
||||
>
|
||||
{t("phone")}
|
||||
{/* <span className="text-[red] text-[13px]"> *</span> */}
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
name="phone"
|
||||
placeholder={t("phone-optional")}
|
||||
value={formdata.phone}
|
||||
onChange={(e) => handleChange(e)}
|
||||
className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs"
|
||||
/>
|
||||
</div>
|
||||
<div className="mb-3">
|
||||
<label
|
||||
htmlFor="phone"
|
||||
className="block text-xs text-gray-700 font-semibold"
|
||||
>
|
||||
{t("Role")}
|
||||
<span className="text-[red] text-[13px]"> *</span>
|
||||
</label>
|
||||
<select
|
||||
value={formdata.role}
|
||||
onChange={(e) => handleChange(e)}
|
||||
name="role"
|
||||
className="op-select op-select-bordered op-select-sm focus:outline-none hover:border-base-content w-full text-xs"
|
||||
onInvalid={(e) => e.target.setCustomValidity(t("input-required"))}
|
||||
onInput={(e) => e.target.setCustomValidity("")}
|
||||
required
|
||||
>
|
||||
<option defaultValue={""} value={""}>
|
||||
{t("Select")}
|
||||
</option>
|
||||
{role.length > 0 &&
|
||||
role.map((x) => (
|
||||
<option key={x} value={x}>
|
||||
{x}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
<div className="flex items-center mt-3 gap-2 text-white">
|
||||
<button type="submit" className="op-btn op-btn-primary">
|
||||
{t("submit")}
|
||||
</button>
|
||||
<div
|
||||
type="button"
|
||||
onClick={() => handleReset()}
|
||||
className="op-btn op-btn-secondary"
|
||||
>
|
||||
{t("cancel")}
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div className="w-full mx-auto">
|
||||
<form onSubmit={handleSubmit}>
|
||||
<div className="mb-3">
|
||||
<label
|
||||
htmlFor="name"
|
||||
className="block text-xs text-gray-700 font-semibold"
|
||||
>
|
||||
{t("name")}
|
||||
<span className="text-[red] text-[13px]"> *</span>
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
name="name"
|
||||
value={formdata.name}
|
||||
onChange={(e) => handleChange(e)}
|
||||
onInvalid={(e) =>
|
||||
e.target.setCustomValidity(t("input-required"))
|
||||
}
|
||||
onInput={(e) => e.target.setCustomValidity("")}
|
||||
required
|
||||
className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs"
|
||||
/>
|
||||
</div>
|
||||
<div className="mb-3">
|
||||
<label
|
||||
htmlFor="email"
|
||||
className="block text-xs text-gray-700 font-semibold"
|
||||
>
|
||||
{t("email")}
|
||||
<span className="text-[red] text-[13px]"> *</span>
|
||||
</label>
|
||||
<input
|
||||
type="email"
|
||||
name="email"
|
||||
value={formdata.email}
|
||||
onChange={(e) => handleChange(e)}
|
||||
required
|
||||
onInvalid={(e) =>
|
||||
e.target.setCustomValidity(t("input-required"))
|
||||
}
|
||||
onInput={(e) => e.target.setCustomValidity("")}
|
||||
className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs"
|
||||
/>
|
||||
</div>
|
||||
<div className="mb-3">
|
||||
<label className="block text-xs text-gray-700 font-semibold">
|
||||
{t("password")}
|
||||
</label>
|
||||
<div className="flex justify-between items-center op-input op-input-bordered op-input-sm text-base-content w-full h-full text-[13px]">
|
||||
<div className="break-all">{formdata?.password}</div>
|
||||
<i
|
||||
onClick={() => copytoclipboard(formdata?.password)}
|
||||
className="fa-light fa-copy rounded-full hover:bg-base-300 p-[8px] cursor-pointer "
|
||||
></i>
|
||||
</div>
|
||||
<div className="text-[12px] ml-2 mb-0 text-[red] select-none">
|
||||
{t("password-generateed")}
|
||||
</div>
|
||||
</div>
|
||||
<div className="mb-3">
|
||||
<label
|
||||
htmlFor="phone"
|
||||
className="block text-xs text-gray-700 font-semibold"
|
||||
>
|
||||
{t("phone")}
|
||||
{/* <span className="text-[red] text-[13px]"> *</span> */}
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
name="phone"
|
||||
placeholder={t("phone-optional")}
|
||||
value={formdata.phone}
|
||||
onChange={(e) => handleChange(e)}
|
||||
className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs"
|
||||
/>
|
||||
</div>
|
||||
<div className="mb-3">
|
||||
<label
|
||||
htmlFor="phone"
|
||||
className="block text-xs text-gray-700 font-semibold"
|
||||
>
|
||||
{t("Role")}
|
||||
<span className="text-[red] text-[13px]"> *</span>
|
||||
</label>
|
||||
<select
|
||||
value={formdata.role}
|
||||
onChange={(e) => handleChange(e)}
|
||||
name="role"
|
||||
className="op-select op-select-bordered op-select-sm focus:outline-none hover:border-base-content w-full text-xs"
|
||||
onInvalid={(e) =>
|
||||
e.target.setCustomValidity(t("input-required"))
|
||||
}
|
||||
onInput={(e) => e.target.setCustomValidity("")}
|
||||
required
|
||||
>
|
||||
<option defaultValue={""} value={""}>
|
||||
{t("Select")}
|
||||
</option>
|
||||
{role.length > 0 &&
|
||||
role.map((x) => (
|
||||
<option key={x} value={x}>
|
||||
{x}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
<div className="flex items-center mt-3 gap-2 text-white">
|
||||
<button type="submit" className="op-btn op-btn-primary">
|
||||
{t("submit")}
|
||||
</button>
|
||||
<div
|
||||
type="button"
|
||||
onClick={() => handleReset()}
|
||||
className="op-btn op-btn-secondary"
|
||||
>
|
||||
{t("cancel")}
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -4,7 +4,6 @@ import axios from "axios";
|
||||
import { openInNewTab } from "../constant/Utils";
|
||||
import { useTranslation } from "react-i18next";
|
||||
const Footer = () => {
|
||||
const appName = "OpenSign™";
|
||||
const { t } = useTranslation();
|
||||
const [showButton, setShowButton] = useState(false);
|
||||
const [version, setVersion] = useState("");
|
||||
@@ -40,6 +39,7 @@ const Footer = () => {
|
||||
};
|
||||
}, []);
|
||||
|
||||
const appName = "OpenSign™";
|
||||
const openUrl = () => {
|
||||
openInNewTab(
|
||||
"https://github.com/OpenSignLabs/OpenSign/releases/tag/" + version
|
||||
|
||||
@@ -10,16 +10,16 @@ import {
|
||||
saveLanguageInLocal
|
||||
} from "../constant/Utils";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { appInfo } from "../constant/appinfo";
|
||||
|
||||
const Header = ({ showSidebar, setIsMenu, isConsole }) => {
|
||||
const Header = ({ showSidebar, setIsMenu }) => {
|
||||
const { t, i18n } = useTranslation();
|
||||
const navigate = useNavigate();
|
||||
const { width } = useWindowSize();
|
||||
const username = localStorage.getItem("username") || "";
|
||||
const image = localStorage.getItem("profileImg") || dp;
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const [applogo, setAppLogo] = useState("");
|
||||
const [applogo, setAppLogo] = useState(
|
||||
localStorage.getItem("appLogo") || " "
|
||||
);
|
||||
|
||||
const toggleDropdown = () => {
|
||||
setIsOpen(!isOpen);
|
||||
@@ -36,8 +36,7 @@ const Header = ({ showSidebar, setIsMenu, isConsole }) => {
|
||||
if (applogo?.logo) {
|
||||
setAppLogo(applogo?.logo);
|
||||
} else {
|
||||
const logo = localStorage.getItem("appLogo") || appInfo.applogo;
|
||||
setAppLogo(logo);
|
||||
setAppLogo(localStorage.getItem("appLogo") || "");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -96,13 +95,11 @@ const Header = ({ showSidebar, setIsMenu, isConsole }) => {
|
||||
</div>
|
||||
<div className="flex-1 ml-2">
|
||||
<div className="h-[25px] md:h-[40px] w-auto overflow-hidden">
|
||||
{applogo && (
|
||||
<img
|
||||
className="object-contain h-full w-auto"
|
||||
src={applogo}
|
||||
alt="logo"
|
||||
/>
|
||||
)}
|
||||
<img
|
||||
className="object-contain h-full w-auto"
|
||||
src={applogo}
|
||||
alt="img"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div id="profile-menu" className="flex-none gap-2">
|
||||
@@ -124,65 +121,55 @@ const Header = ({ showSidebar, setIsMenu, isConsole }) => {
|
||||
{width >= 768 && (
|
||||
<div
|
||||
onClick={toggleDropdown}
|
||||
role="button"
|
||||
tabIndex="0"
|
||||
className="cursor-pointer text-base-content text-sm"
|
||||
>
|
||||
{username && username}
|
||||
</div>
|
||||
)}
|
||||
<div
|
||||
className="op-dropdown op-dropdown-open op-dropdown-end"
|
||||
id="profile-menu"
|
||||
>
|
||||
<div className="op-dropdown op-dropdown-end" id="profile-menu">
|
||||
<div
|
||||
tabIndex={0}
|
||||
role="button"
|
||||
onClick={toggleDropdown}
|
||||
className="op-btn op-btn-ghost op-btn-xs w-[10px] h-[20px] hover:bg-transparent"
|
||||
>
|
||||
<i className="fa-light fa-angle-down text-base-content"></i>
|
||||
<i
|
||||
tabIndex={0}
|
||||
role="button"
|
||||
onClick={toggleDropdown}
|
||||
className="fa-light fa-angle-down text-base-content"
|
||||
></i>
|
||||
</div>
|
||||
<ul
|
||||
tabIndex={0}
|
||||
className={`mt-3 z-[1] p-2 shadow op-dropdown-open op-menu op-menu-sm op-dropdown-content text-base-content bg-base-100 rounded-box w-52 ${
|
||||
className={`mt-3 z-[1] p-2 shadow op-menu op-menu-sm op-dropdown-content text-base-content bg-base-100 rounded-box w-52 ${
|
||||
isOpen ? "" : "hidden"
|
||||
}`}
|
||||
>
|
||||
{!isConsole && (
|
||||
<>
|
||||
<li
|
||||
onClick={() =>
|
||||
openInNewTab("https://docs.opensignlabs.com")
|
||||
}
|
||||
>
|
||||
<span>
|
||||
<i className="fa-light fa-book"></i> {t("docs")}
|
||||
</span>
|
||||
</li>
|
||||
<li
|
||||
onClick={() => {
|
||||
setIsOpen(false);
|
||||
navigate("/profile");
|
||||
}}
|
||||
>
|
||||
<span>
|
||||
<i className="fa-light fa-user"></i> {t("profile")}
|
||||
</span>
|
||||
</li>
|
||||
<li
|
||||
onClick={() => {
|
||||
setIsOpen(false);
|
||||
navigate("/changepassword");
|
||||
}}
|
||||
>
|
||||
<span>
|
||||
<i className="fa-light fa-lock"></i>{" "}
|
||||
{t("change-password")}
|
||||
</span>
|
||||
</li>
|
||||
</>
|
||||
)}
|
||||
<li onClick={() => openInNewTab("https://docs.opensignlabs.com")}>
|
||||
<span>
|
||||
<i className="fa-light fa-book"></i> {t("docs")}
|
||||
</span>
|
||||
</li>
|
||||
<li
|
||||
onClick={() => {
|
||||
setIsOpen(false);
|
||||
navigate("/profile");
|
||||
}}
|
||||
>
|
||||
<span>
|
||||
<i className="fa-light fa-user"></i> {t("profile")}
|
||||
</span>
|
||||
</li>
|
||||
<li
|
||||
onClick={() => {
|
||||
setIsOpen(false);
|
||||
navigate("/changepassword");
|
||||
}}
|
||||
>
|
||||
<span>
|
||||
<i className="fa-light fa-lock"></i> {t("change-password")}
|
||||
</span>
|
||||
</li>
|
||||
<li onClick={closeDropdown}>
|
||||
<span>
|
||||
<i className="fa-light fa-arrow-right-from-bracket"></i>{" "}
|
||||
|
||||
@@ -2,12 +2,10 @@ import React from "react";
|
||||
import { Helmet } from "react-helmet";
|
||||
|
||||
function Title({ title, drive }) {
|
||||
const appName =
|
||||
"OpenSign™";
|
||||
return (
|
||||
<Helmet>
|
||||
<title>{drive ? title : `${title} - ${appName}`}</title>
|
||||
<meta name="description" content={`${title} - ${appName}`} />
|
||||
<title>{drive ? title : `${title} - OpenSign™`}</title>
|
||||
<meta name="description" content={`${title} - OpenSign™`} />
|
||||
<link
|
||||
rel="icon"
|
||||
type="image/png"
|
||||
|
||||
@@ -346,6 +346,7 @@ const DashboardCard = (props) => {
|
||||
id={props.Label}
|
||||
iconColor={"white"}
|
||||
message={t(`tour-mssg.${props.Label}`)}
|
||||
// {props?.Data?.tourMessage}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -347,14 +347,12 @@ function DriveBody(props) {
|
||||
}
|
||||
|
||||
const signersName = () => {
|
||||
const getSignersName =
|
||||
signerExist?.length > 0 && signerExist?.map((data) => data?.Name || "");
|
||||
const signerName =
|
||||
getSignersName?.length > 0 ? getSignersName?.join(", ") : "";
|
||||
const getSignersName = signerExist.map((data) => data.Name);
|
||||
const signerName = getSignersName.join(", ");
|
||||
|
||||
return (
|
||||
<span className="text-[12px] font-medium w-[90%] break-words">
|
||||
{signerName && signerName}
|
||||
{signerName}
|
||||
</span>
|
||||
);
|
||||
};
|
||||
@@ -628,7 +626,7 @@ function DriveBody(props) {
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{props?.pdfData?.map((data, ind) => {
|
||||
{props.pdfData.map((data, ind) => {
|
||||
return (
|
||||
<React.Fragment key={ind}>
|
||||
{handleFolderData(data, ind, "table")}
|
||||
|
||||
@@ -4,8 +4,6 @@ import ModalUi from "../../primitives/ModalUi";
|
||||
|
||||
function AgreementContent(props) {
|
||||
const { t } = useTranslation();
|
||||
const appName =
|
||||
"OpenSign™";
|
||||
const h2Style = "text-base-content font-medium text-lg";
|
||||
const ulStyle = "list-disc px-4 py-3";
|
||||
const handleOnclick = () => {
|
||||
@@ -23,94 +21,78 @@ function AgreementContent(props) {
|
||||
>
|
||||
<div className="h-[100%] p-[20px]">
|
||||
<h2 className={h2Style}>{t("term-cond-h")}</h2>
|
||||
<span className="mt-2">
|
||||
{t("term-cond-p1", { appName: appName })}
|
||||
</span>
|
||||
<hr className="bg-[#9f9f9f] w-full my-[15px]" />
|
||||
<span className="mt-2">{t("term-cond-p1")}</span>
|
||||
<div className="h-[1px] bg-[#9f9f9f] w-full my-[15px]"></div>
|
||||
<h2 className={h2Style}>{t("term-cond-h1")}</h2>
|
||||
<span className="mt-2">
|
||||
{t("term-cond-p2", { appName: appName })}
|
||||
</span>
|
||||
<span className="mt-2">{t("term-cond-p2")}</span>
|
||||
<ul className={ulStyle}>
|
||||
<li>{t("term-cond-p3", { appName: appName })}</li>
|
||||
<li>{t("term-cond-p3")}</li>
|
||||
<li>{t("term-cond-p4")}</li>
|
||||
</ul>
|
||||
<hr className="bg-[#9f9f9f] w-full my-[15px]" />
|
||||
<div className="h-[1px] bg-[#9f9f9f] w-full my-[15px]"></div>
|
||||
<h2 className={h2Style}>{t("term-cond-h2")}</h2>
|
||||
<span className="mt-2">{t("term-cond-p5")}</span>
|
||||
<ul className={ulStyle}>
|
||||
<li>{t("term-cond-p6", { appName: appName })}</li>
|
||||
<li>{t("term-cond-p7", { appName: appName })}</li>
|
||||
<li>{t("term-cond-p6")}</li>
|
||||
<li>{t("term-cond-p7")}</li>
|
||||
<li>{t("term-cond-p8")}</li>
|
||||
</ul>
|
||||
<hr className="bg-[#9f9f9f] w-full my-[15px]" />
|
||||
<div className="h-[1px] bg-[#9f9f9f] w-full my-[15px]"></div>
|
||||
<h2 className={h2Style}>{t("term-cond-h3")}</h2>
|
||||
<span className="mt-2">{t("term-cond-p9")}</span>
|
||||
<ul className={ulStyle}>
|
||||
<li>{t("term-cond-p10")}</li>
|
||||
<li>{t("term-cond-p11")}</li>
|
||||
</ul>
|
||||
<hr className="bg-[#9f9f9f] w-full my-[15px]" />
|
||||
<div className="h-[1px] bg-[#9f9f9f] w-full my-[15px]"></div>
|
||||
<h2 className={h2Style}>{t("term-cond-h4")}</h2>
|
||||
<span className="mt-2">
|
||||
{t("term-cond-p12", { appName: appName })}
|
||||
</span>
|
||||
<span className="mt-2">{t("term-cond-p12")}</span>
|
||||
<ul className={ulStyle}>
|
||||
<li>{t("term-cond-p13")}</li>
|
||||
<li>{t("term-cond-p14")}</li>
|
||||
<li>{t("term-cond-p15")}</li>
|
||||
</ul>
|
||||
<span>{t("term-cond-p16", { appName: appName })}</span>
|
||||
<hr className="bg-[#9f9f9f] w-full my-[15px]" />
|
||||
<span>{t("term-cond-p16")}</span>
|
||||
<div className="h-[1px] bg-[#9f9f9f] w-full my-[15px]"></div>
|
||||
<h2 className={h2Style}>{t("term-cond-h5")}</h2>
|
||||
<p>{t("term-cond-p17", { appName: appName })}</p>
|
||||
<p>{t("term-cond-p17")}</p>
|
||||
<p className="mt-2">{t("term-cond-p18")}</p>
|
||||
<hr className="bg-[#9f9f9f] w-full my-[15px]" />
|
||||
<div className="h-[1px] bg-[#9f9f9f] w-full my-[15px]"></div>
|
||||
<h2 className={h2Style}>{t("term-cond-h6")}</h2>
|
||||
<span className="mt-2">{t("term-cond-p19")}</span>
|
||||
<ul className={ulStyle}>
|
||||
<li>{t("term-cond-p20")}</li>
|
||||
<li>{t("term-cond-p21")}</li>
|
||||
<li>{t("term-cond-p22", { appName: appName })}</li>
|
||||
<li>{t("term-cond-p22")}</li>
|
||||
</ul>
|
||||
<hr className="bg-[#9f9f9f] w-full my-[15px]" />
|
||||
<div className="h-[1px] bg-[#9f9f9f] w-full my-[15px]"></div>
|
||||
<h2 className={h2Style}>{t("term-cond-h7")}</h2>
|
||||
<span className="mt-2">
|
||||
{t("term-cond-p23", { appName: appName })}
|
||||
</span>
|
||||
<span className="mt-2">{t("term-cond-p23")}</span>
|
||||
<ul className={ulStyle}>
|
||||
<li>{t("term-cond-p24")}</li>
|
||||
<li>{t("term-cond-p25")}</li>
|
||||
</ul>
|
||||
<hr className="bg-[#9f9f9f] w-full my-[15px]" />
|
||||
<div className="h-[1px] bg-[#9f9f9f] w-full my-[15px]"></div>
|
||||
<h2 className={h2Style}>{t("term-cond-h8")}</h2>
|
||||
<span className="mt-2">
|
||||
{t("term-cond-p26", { appName: appName })}
|
||||
</span>
|
||||
<hr className="bg-[#9f9f9f] w-full my-[15px]" />
|
||||
<span className="mt-2">{t("term-cond-p26")}</span>
|
||||
<div className="h-[1px] bg-[#9f9f9f] w-full my-[15px]"></div>
|
||||
<h2 className={h2Style}>{t("term-cond-h9")}</h2>
|
||||
<span className="mt-2">
|
||||
{t("term-cond-p27", { appName: appName })}
|
||||
</span>
|
||||
<hr className="bg-[#9f9f9f] w-full my-[15px]" />
|
||||
<span className="mt-2 font-medium">
|
||||
{t("term-cond-p28", { appName: appName })}
|
||||
</span>
|
||||
<hr className="bg-[#9f9f9f] w-full my-[15px]" />
|
||||
<span className="mt-2">
|
||||
{t("term-cond-p29", { appName: appName })}
|
||||
</span>
|
||||
<a
|
||||
href="www.opensignlabs.com"
|
||||
target="_blank"
|
||||
className="text-blue-700 cursor-pointer"
|
||||
>
|
||||
www.opensignlabs.com
|
||||
</a>
|
||||
|
||||
<span>{t("term-cond-p30")}</span>
|
||||
<span className="font-medium"> support@opensignlabs.com </span>
|
||||
<hr className="bg-[#9f9f9f] w-full my-[15px]" />
|
||||
<span className="mt-2">{t("term-cond-p27")}</span>
|
||||
<div className="h-[1px] bg-[#9f9f9f] w-full my-[15px]"></div>
|
||||
<span className="mt-2 font-medium">{t("term-cond-p28")}</span>
|
||||
<div className="h-[1px] bg-[#9f9f9f] w-full my-[15px]"></div>
|
||||
<span className="mt-2">{t("term-cond-p29")}</span>
|
||||
<a
|
||||
href="www.opensignlabs.com"
|
||||
target="_blank"
|
||||
className="text-blue-700 cursor-pointer"
|
||||
>
|
||||
{" "}
|
||||
www.opensignlabs.com{" "}
|
||||
</a>
|
||||
<span>{t("term-cond-p30")}</span>
|
||||
<span className="font-medium"> support@opensignlabs.com </span>
|
||||
<div className="h-[1px] bg-[#9f9f9f] w-full my-[15px]"></div>
|
||||
<div className="mt-6 flex justify-start gap-2">
|
||||
<button
|
||||
onClick={() => handleOnclick()}
|
||||
|
||||
@@ -1,11 +1,17 @@
|
||||
import React, { useState } from "react";
|
||||
import { getFileName } from "../../constant/Utils";
|
||||
import React, {
|
||||
useState,
|
||||
} from "react";
|
||||
import {
|
||||
getFileName
|
||||
} from "../../constant/Utils";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Tooltip } from "react-tooltip";
|
||||
import SignersInput from "../shared/fields/SignersInput";
|
||||
|
||||
const EditTemplate = ({ template, onSuccess }) => {
|
||||
const appName = "OpenSign™";
|
||||
const EditTemplate = ({
|
||||
template,
|
||||
onSuccess,
|
||||
}) => {
|
||||
const { t } = useTranslation();
|
||||
const [formData, setFormData] = useState({
|
||||
Name: template?.Name || "",
|
||||
@@ -56,13 +62,6 @@ const EditTemplate = ({ template, onSuccess }) => {
|
||||
const IsEnableOTP = formData.IsEnableOTP === "true" ? true : false;
|
||||
const allowModify = formData?.AllowModifications || false;
|
||||
let reminderDate = {};
|
||||
const remindOnceInEvery = formData?.RemindOnceInEvery;
|
||||
const TimeToCompleteDays = parseInt(formData?.TimeToCompleteDays);
|
||||
const reminderCount = TimeToCompleteDays / remindOnceInEvery;
|
||||
if (AutoReminder && reminderCount > 15) {
|
||||
alert(t("only-15-reminder-allowed"));
|
||||
return;
|
||||
}
|
||||
if (AutoReminder) {
|
||||
const RemindOnceInEvery = parseInt(formData?.RemindOnceInEvery);
|
||||
const ReminderDate = new Date(template?.createdAt);
|
||||
@@ -200,7 +199,7 @@ const EditTemplate = ({ template, onSuccess }) => {
|
||||
</li>
|
||||
</ol>
|
||||
</p>
|
||||
<p>{t("istourenabled-help.p3", { appName: appName })}</p>
|
||||
<p>{t("istourenabled-help.p3")}</p>
|
||||
</div>
|
||||
</Tooltip>
|
||||
</label>
|
||||
@@ -246,7 +245,11 @@ const EditTemplate = ({ template, onSuccess }) => {
|
||||
</Tooltip>
|
||||
</label>
|
||||
<div className="flex flex-col md:flex-row md:gap-4">
|
||||
<div className={`flex items-center gap-2 ml-2 mb-1`}>
|
||||
<div
|
||||
className={
|
||||
`flex items-center gap-2 ml-2 mb-1`
|
||||
}
|
||||
>
|
||||
<input
|
||||
className="mr-[2px] op-radio op-radio-xs"
|
||||
type="radio"
|
||||
@@ -255,7 +258,11 @@ const EditTemplate = ({ template, onSuccess }) => {
|
||||
/>
|
||||
<div className="text-center">{t("yes")}</div>
|
||||
</div>
|
||||
<div className={`flex items-center gap-2 ml-2 mb-1`}>
|
||||
<div
|
||||
className={
|
||||
`flex items-center gap-2 ml-2 mb-1`
|
||||
}
|
||||
>
|
||||
<input
|
||||
className="mr-[2px] op-radio op-radio-xs"
|
||||
type="radio"
|
||||
|
||||
@@ -1,16 +1,20 @@
|
||||
import React, { useState } from "react";
|
||||
import axios from "axios";
|
||||
import { handleToPrint } from "../../constant/Utils";
|
||||
import { emailRegex } from "../../constant/const";
|
||||
import { themeColor, emailRegex } from "../../constant/const";
|
||||
import Loader from "../../primitives/Loader";
|
||||
import ModalUi from "../../primitives/ModalUi";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import Parse from "parse";
|
||||
|
||||
function EmailComponent({
|
||||
isEmail,
|
||||
pdfUrl,
|
||||
setIsEmail,
|
||||
setSuccessEmail,
|
||||
pdfDetails,
|
||||
sender,
|
||||
setIsAlert,
|
||||
extUserId,
|
||||
setIsDownloadModal
|
||||
}) {
|
||||
const { t } = useTranslation();
|
||||
@@ -22,11 +26,79 @@ function EmailComponent({
|
||||
const isAndroid = /Android/i.test(navigator.userAgent);
|
||||
//function for send email
|
||||
const sendEmail = async () => {
|
||||
const pdfName = pdfDetails[0]?.Name;
|
||||
setIsLoading(true);
|
||||
const params = { docId: pdfDetails?.[0]?.objectId, recipients: emailList };
|
||||
const sendmail = await Parse.Cloud.run("forwarddoc", params);
|
||||
console.log("sendmail ", sendmail);
|
||||
if (sendmail?.status === "success") {
|
||||
let sendMail;
|
||||
const docId = pdfDetails?.[0]?.objectId || "";
|
||||
let presignedUrl = pdfUrl;
|
||||
try {
|
||||
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++) {
|
||||
try {
|
||||
const imgPng =
|
||||
"https://qikinnovation.ams3.digitaloceanspaces.com/logo.png";
|
||||
|
||||
let url = `${localStorage.getItem("baseUrl")}functions/sendmailv3`;
|
||||
const headers = {
|
||||
"Content-Type": "application/json",
|
||||
"X-Parse-Application-Id": localStorage.getItem("parseAppId"),
|
||||
sessionToken: localStorage.getItem("accesstoken")
|
||||
};
|
||||
const openSignUrl = "https://www.opensignlabs.com/contact-us";
|
||||
const themeBGcolor = themeColor;
|
||||
let params = {
|
||||
extUserId: extUserId,
|
||||
pdfName: pdfName,
|
||||
url: presignedUrl,
|
||||
recipient: emailList[i],
|
||||
subject: `${sender.name} has signed the doc - ${pdfName}`,
|
||||
replyto:
|
||||
pdfDetails?.[0]?.ExtUserPtr?.Email ||
|
||||
"",
|
||||
from:
|
||||
sender.email,
|
||||
html:
|
||||
"<html><head><meta http-equiv='Content-Type' content='text/html; charset=UTF-8' /></head><body> <div style='background-color:#f5f5f5;padding:20px'> <div style='box-shadow: rgba(0, 0, 0, 0.1) 0px 4px 12px;background-color:white;'> <div><img src=" +
|
||||
imgPng +
|
||||
" height='50' style='padding:20px,width:170px,height:40px'/> </div><div style='padding:2px;font-family:system-ui; background-color:" +
|
||||
themeBGcolor +
|
||||
";'> <p style='font-size:20px;font-weight:400;color:white;padding-left:20px',> Document Copy</p></div><div><p style='padding:20px;font-family:system-ui;font-size:14px'>A copy of the document <strong>" +
|
||||
pdfName +
|
||||
" </strong>is attached to this email. Kindly download the document from the attachment.</p></div> </div><div><p>This is an automated email from OpenSign™. For any queries regarding this email, please contact the sender " +
|
||||
sender.email +
|
||||
" directly. If you think this email is inappropriate or spam, you may file a complaint with OpenSign™ <a href= " +
|
||||
openSignUrl +
|
||||
" target=_blank>here</a> </p></div></div></body></html>"
|
||||
};
|
||||
sendMail = await axios.post(url, params, { headers: headers });
|
||||
} catch (error) {
|
||||
console.log("error", error);
|
||||
setIsLoading(false);
|
||||
setIsEmail(false);
|
||||
setIsAlert({
|
||||
isShow: true,
|
||||
alertMessage: t("something-went-wrong-mssg")
|
||||
});
|
||||
}
|
||||
}
|
||||
if (sendMail?.data?.result?.status === "success") {
|
||||
setSuccessEmail(true);
|
||||
setIsEmail(false);
|
||||
setTimeout(() => {
|
||||
|
||||
@@ -74,24 +74,25 @@ const changeDateToMomentFormat = (format) => {
|
||||
return "L";
|
||||
}
|
||||
};
|
||||
|
||||
//function to get default date
|
||||
const getDefaultdate = (selectedDate, format = "dd-MM-yyyy") => {
|
||||
let date;
|
||||
if (format && format === "dd-MM-yyyy") {
|
||||
const newdate = selectedDate
|
||||
? selectedDate
|
||||
: moment(new Date()).format(changeDateToMomentFormat(format));
|
||||
const [day, month, year] = newdate.split("-");
|
||||
date = new Date(`${year}-${month}-${day}`);
|
||||
} else {
|
||||
date = new Date(selectedDate);
|
||||
}
|
||||
const value = date;
|
||||
return value;
|
||||
};
|
||||
//function to get default format
|
||||
const getDefaultFormat = (dateFormat) => dateFormat || "MM/dd/yyyy";
|
||||
|
||||
//function to convert formated date to new Date() format
|
||||
const getDefaultDate = (dateStr, format) => {
|
||||
//get valid date format for moment to convert formated date to new Date() format
|
||||
const formats = changeDateToMomentFormat(format);
|
||||
const parsedDate = moment(dateStr, formats);
|
||||
let date;
|
||||
if (parsedDate.isValid()) {
|
||||
date = new Date(parsedDate.toISOString());
|
||||
return date;
|
||||
} else {
|
||||
date = new Date();
|
||||
return date;
|
||||
}
|
||||
};
|
||||
|
||||
function Placeholder(props) {
|
||||
//'isTouchDevice' is used to detect whether a device has a touchscreen or is mouse-based
|
||||
const isTouchDevice = navigator.maxTouchPoints > 0;
|
||||
@@ -103,16 +104,28 @@ function Placeholder(props) {
|
||||
const holdTimeout = useRef(null);
|
||||
const startTime = useRef(null); // Track when the user starts holdings
|
||||
const [isDisableDragging, setIsDisableDragging] = useState(true);
|
||||
const [selectDate, setSelectDate] = useState({});
|
||||
const [selectDate, setSelectDate] = useState({
|
||||
date:
|
||||
props.pos.type === "date"
|
||||
? moment(
|
||||
getDefaultdate(
|
||||
props?.pos?.options?.response,
|
||||
props.pos?.options?.validation?.format
|
||||
).getTime()
|
||||
).format(
|
||||
changeDateToMomentFormat(props.pos?.options?.validation?.format)
|
||||
)
|
||||
: "",
|
||||
format:
|
||||
props.pos.type === "date"
|
||||
? getDefaultFormat(props.pos?.options?.validation?.format)
|
||||
: ""
|
||||
});
|
||||
const [dateFormat, setDateFormat] = useState([]);
|
||||
const [clickonWidget, setClickonWidget] = useState({});
|
||||
const [startDate, setStartDate] = useState(
|
||||
props?.pos?.options?.response
|
||||
? getDefaultDate(
|
||||
props?.pos?.options?.response,
|
||||
props.pos?.options?.validation?.format
|
||||
)
|
||||
: new Date()
|
||||
props.pos.type === "date" &&
|
||||
getDefaultdate(new Date(), props.pos?.options?.validation?.format)
|
||||
);
|
||||
const [getCheckboxRenderWidth, setGetCheckboxRenderWidth] = useState({
|
||||
width: null,
|
||||
@@ -151,6 +164,7 @@ function Placeholder(props) {
|
||||
|
||||
return () => clearTimeout(timer);
|
||||
}, [props.pos]);
|
||||
|
||||
useEffect(() => {
|
||||
const onOutsideClick = () => {
|
||||
if (!isDraggingEnabled) {
|
||||
@@ -439,9 +453,7 @@ function Placeholder(props) {
|
||||
|
||||
//checking widget's type and open widget copy modal for required widgets
|
||||
if (
|
||||
["signature", textInputWidget, textWidget, "stamp", "initials"].includes(
|
||||
props.pos.type
|
||||
)
|
||||
["signature", textWidget, "stamp", "initials"].includes(props.pos.type)
|
||||
) {
|
||||
props.setIsPageCopy(true);
|
||||
props.setSignKey(props.pos.key);
|
||||
@@ -464,7 +476,7 @@ function Placeholder(props) {
|
||||
const isDateChange = true;
|
||||
const dateObj = {
|
||||
date: startDate,
|
||||
format: getDefaultFormat(props.pos?.options?.validation?.format)
|
||||
format: selectDate.format
|
||||
};
|
||||
handleSaveDate(dateObj, isDateChange); //function to save date and format in local array
|
||||
}
|
||||
@@ -473,18 +485,19 @@ function Placeholder(props) {
|
||||
//function to save date and format on local array onchange date and onclick format
|
||||
const handleSaveDate = (data, isDateChange) => {
|
||||
let updateDate = data.date;
|
||||
let date;
|
||||
if (data?.format === "dd-MM-yyyy") {
|
||||
date = isDateChange
|
||||
? moment(updateDate).format(changeDateToMomentFormat(data.format))
|
||||
: updateDate;
|
||||
} else {
|
||||
//using moment package is used to change date as per the format provided in selectDate obj e.g. - MM/dd/yyyy -> 03/12/2024
|
||||
const newDate = new Date(updateDate);
|
||||
date = moment(newDate.getTime()).format(
|
||||
changeDateToMomentFormat(data?.format)
|
||||
//check if date change by user
|
||||
if (isDateChange) {
|
||||
//`changeDateToMomentFormat` is used to convert date as per required to moment package
|
||||
updateDate = moment(data.date).format(
|
||||
changeDateToMomentFormat(data.format)
|
||||
);
|
||||
}
|
||||
//using moment package is used to change date as per the format provided in selectDate obj e.g. - MM/dd/yyyy -> 03/12/2024
|
||||
//`getDefaultdate` is used to convert update date in new Date() format
|
||||
const date = moment(
|
||||
getDefaultdate(updateDate, data?.format).getTime()
|
||||
).format(changeDateToMomentFormat(data?.format));
|
||||
|
||||
//`onChangeInput` is used to save data related to date in a placeholder field
|
||||
onChangeInput(
|
||||
date,
|
||||
@@ -769,8 +782,7 @@ function Placeholder(props) {
|
||||
//enable dragging functionality only if isAlllowModify true on tab that widget and hold 1sec
|
||||
if (
|
||||
props.isAlllowModify &&
|
||||
props?.assignedWidgetId.includes(props.pos.key) &&
|
||||
props.data?.signerObjId === props.signerObjId
|
||||
props?.assignedWidgetId.includes(props.pos.key)
|
||||
) {
|
||||
//if 'isTouchDevice' then handle dragging functionality conditionaly
|
||||
if (isTouchDevice) {
|
||||
@@ -782,8 +794,7 @@ function Placeholder(props) {
|
||||
} else if (
|
||||
//condition when 'isAlllowModify' is true and user add new widgets then handle dragging functionality like signyourself flow
|
||||
props.isAlllowModify &&
|
||||
!props?.assignedWidgetId.includes(props.pos.key) &&
|
||||
props.data?.signerObjId === props.signerObjId
|
||||
!props?.assignedWidgetId.includes(props.pos.key)
|
||||
) {
|
||||
return !isDraggingEnabled;
|
||||
} else {
|
||||
@@ -1087,7 +1098,7 @@ function Placeholder(props) {
|
||||
isSignYourself={props.isSignYourself}
|
||||
isSelfSign={props.isSelfSign}
|
||||
signerObjId={props.signerObjId}
|
||||
calculateFontsize={props.calculateFontsize}
|
||||
handleUserName={props.handleUserName}
|
||||
pdfDetails={props?.pdfDetails && props?.pdfDetails[0]}
|
||||
isNeedSign={props.isNeedSign}
|
||||
setSelectDate={setSelectDate}
|
||||
|
||||
@@ -30,7 +30,6 @@ function PlaceholderType(props) {
|
||||
const inputRef = useRef(null);
|
||||
const [textValue, setTextValue] = useState();
|
||||
const [selectedCheckbox, setSelectedCheckbox] = useState([]);
|
||||
const [hint, setHint] = useState("");
|
||||
const years = range(1950, getYear(new Date()) + 16, 1);
|
||||
const fontSize = props.calculateFont(props.pos.options?.fontSize);
|
||||
const fontColor = props.pos.options?.fontColor || "black";
|
||||
@@ -151,11 +150,6 @@ function PlaceholderType(props) {
|
||||
if (defaultData) {
|
||||
setTextValue(defaultData);
|
||||
}
|
||||
if (props.pos?.options?.hint) {
|
||||
setHint(props.pos?.options.hint);
|
||||
} else {
|
||||
setHint(props.pos?.type);
|
||||
}
|
||||
} else if ([textInputWidget].includes(props.pos?.type)) {
|
||||
const defaultData = props.pos?.options?.defaultValue;
|
||||
if (defaultData) {
|
||||
@@ -164,6 +158,7 @@ function PlaceholderType(props) {
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [props.pos?.options?.defaultValue]);
|
||||
|
||||
const ExampleCustomInput = forwardRef(({ value, onClick }, ref) => (
|
||||
<div
|
||||
style={{
|
||||
@@ -332,20 +327,13 @@ function PlaceholderType(props) {
|
||||
/>
|
||||
) : (
|
||||
<div className={widgetCls}>
|
||||
{props.pos.type && (
|
||||
<div
|
||||
style={{
|
||||
fontSize: props.pos
|
||||
? props.calculateFontsize(props.pos)
|
||||
: "11px"
|
||||
}}
|
||||
className="font-medium"
|
||||
>
|
||||
{props.isNeedSign
|
||||
? props.pos?.options?.hint || widgetTypeTraslation
|
||||
: widgetTypeTraslation}
|
||||
</div>
|
||||
)}
|
||||
{props?.handleUserName &&
|
||||
props?.handleUserName(
|
||||
props?.data?.Id,
|
||||
props?.data?.Role,
|
||||
widgetTypeTraslation,
|
||||
props.pos
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
case "stamp":
|
||||
@@ -358,20 +346,13 @@ function PlaceholderType(props) {
|
||||
/>
|
||||
) : (
|
||||
<div className={widgetCls}>
|
||||
{props.pos.type && (
|
||||
<div
|
||||
style={{
|
||||
fontSize: props.pos
|
||||
? props.calculateFontsize(props.pos)
|
||||
: "11px"
|
||||
}}
|
||||
className="font-medium"
|
||||
>
|
||||
{props.isNeedSign
|
||||
? props.pos?.options?.hint || widgetTypeTraslation
|
||||
: widgetTypeTraslation}
|
||||
</div>
|
||||
)}
|
||||
{props?.handleUserName &&
|
||||
props?.handleUserName(
|
||||
props?.data?.Id,
|
||||
props?.data?.Role,
|
||||
widgetTypeTraslation,
|
||||
props.pos
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
case "checkbox":
|
||||
@@ -552,20 +533,13 @@ function PlaceholderType(props) {
|
||||
/>
|
||||
) : (
|
||||
<div className={widgetCls}>
|
||||
{props.pos.type && (
|
||||
<div
|
||||
style={{
|
||||
fontSize: props.pos
|
||||
? props.calculateFontsize(props.pos)
|
||||
: "11px"
|
||||
}}
|
||||
className="font-medium text-center"
|
||||
>
|
||||
{props.isNeedSign
|
||||
? props.pos?.options?.hint || widgetTypeTraslation
|
||||
: widgetTypeTraslation}
|
||||
</div>
|
||||
)}
|
||||
{props?.handleUserName &&
|
||||
props?.handleUserName(
|
||||
props?.data?.Id,
|
||||
props?.data?.Role,
|
||||
widgetTypeTraslation,
|
||||
props.pos
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
case "name":
|
||||
@@ -574,7 +548,7 @@ function PlaceholderType(props) {
|
||||
(props.isNeedSign && props.data?.signerObjId === props.signerObjId) ? (
|
||||
<textarea
|
||||
ref={inputRef}
|
||||
placeholder={hint}
|
||||
placeholder={t("widgets-name.name")}
|
||||
rows={1}
|
||||
onKeyDown={handleEnterPress}
|
||||
value={textValue}
|
||||
@@ -606,7 +580,7 @@ function PlaceholderType(props) {
|
||||
(props.isNeedSign && props.data?.signerObjId === props.signerObjId) ? (
|
||||
<textarea
|
||||
ref={inputRef}
|
||||
placeholder={hint}
|
||||
placeholder={t("widgets-name.company")}
|
||||
rows={1}
|
||||
onKeyDown={handleEnterPress}
|
||||
value={textValue}
|
||||
@@ -637,7 +611,7 @@ function PlaceholderType(props) {
|
||||
(props.isNeedSign && props.data?.signerObjId === props.signerObjId) ? (
|
||||
<textarea
|
||||
ref={inputRef}
|
||||
placeholder={hint}
|
||||
placeholder={t("widgets-name.job title")}
|
||||
rows={1}
|
||||
onKeyDown={handleEnterPress}
|
||||
value={textValue}
|
||||
@@ -738,20 +712,13 @@ function PlaceholderType(props) {
|
||||
/>
|
||||
) : (
|
||||
<div className={widgetCls}>
|
||||
{props.pos.type && (
|
||||
<div
|
||||
style={{
|
||||
fontSize: props.pos
|
||||
? props.calculateFontsize(props.pos)
|
||||
: "11px"
|
||||
}}
|
||||
className="font-medium text-center"
|
||||
>
|
||||
{props.isNeedSign
|
||||
? props.pos?.options?.hint || widgetTypeTraslation
|
||||
: widgetTypeTraslation}
|
||||
</div>
|
||||
)}
|
||||
{props?.handleUserName &&
|
||||
props?.handleUserName(
|
||||
props?.data?.Id,
|
||||
props?.data?.Role,
|
||||
widgetTypeTraslation,
|
||||
props.pos
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
case "email":
|
||||
@@ -760,7 +727,7 @@ function PlaceholderType(props) {
|
||||
(props.isNeedSign && props.data?.signerObjId === props.signerObjId) ? (
|
||||
<textarea
|
||||
ref={inputRef}
|
||||
placeholder={hint}
|
||||
placeholder={t("widgets-name.email")}
|
||||
rows={1}
|
||||
onKeyDown={(e) => {
|
||||
// Prevent new line on Enter key press
|
||||
@@ -881,20 +848,13 @@ function PlaceholderType(props) {
|
||||
) : (
|
||||
<div className={widgetCls}>
|
||||
{props.pos.isStamp ? <div>stamp</div> : <div>signature</div>}
|
||||
{props.pos.type && (
|
||||
<div
|
||||
style={{
|
||||
fontSize: props.pos
|
||||
? props.calculateFontsize(props.pos)
|
||||
: "11px"
|
||||
}}
|
||||
className="font-medium"
|
||||
>
|
||||
{props.isNeedSign
|
||||
? props.pos?.options?.hint || widgetTypeTraslation
|
||||
: widgetTypeTraslation}
|
||||
</div>
|
||||
)}
|
||||
{props?.handleUserName &&
|
||||
props?.handleUserName(
|
||||
props?.data?.Id,
|
||||
props?.data?.Role,
|
||||
null,
|
||||
props.pos
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -89,6 +89,35 @@ function RenderPdf(props) {
|
||||
sign?.Id === data?.Id || sign?.objectId === data?.signerObjId
|
||||
)
|
||||
: [];
|
||||
const handleAllUserName = (Id, Role, type, pos) => {
|
||||
return (
|
||||
<React.Fragment>
|
||||
<div className="text-black text-[8px] font-bold">
|
||||
{
|
||||
props.pdfDetails[0].Signers?.find(
|
||||
(signer) => signer.objectId === data.signerObjId
|
||||
)?.Name
|
||||
}
|
||||
</div>
|
||||
{type && (
|
||||
<div
|
||||
style={{ fontSize: pos ? calculateFontsize(pos) : "11px" }}
|
||||
className="font-bold"
|
||||
>
|
||||
{type}
|
||||
</div>
|
||||
)}
|
||||
{Role && (
|
||||
<div
|
||||
style={{ fontSize: pos ? calculateFontsize(pos) : "8px" }}
|
||||
className="text-black font-medium"
|
||||
>
|
||||
{`(${Role})`}
|
||||
</div>
|
||||
)}
|
||||
</React.Fragment>
|
||||
);
|
||||
};
|
||||
return (
|
||||
checkSign.length === 0 &&
|
||||
data?.placeHolder?.map((placeData, key) => {
|
||||
@@ -119,6 +148,7 @@ function RenderPdf(props) {
|
||||
isSignYourself={false}
|
||||
posWidth={posWidth}
|
||||
posHeight={posHeight}
|
||||
handleUserName={handleAllUserName}
|
||||
isDragging={props.isDragging}
|
||||
pdfDetails={props.pdfDetails}
|
||||
setIsInitial={props.setIsInitial}
|
||||
@@ -155,7 +185,6 @@ function RenderPdf(props) {
|
||||
fontColor={props.fontColor}
|
||||
setFontColor={props.setFontColor}
|
||||
setRequestSignTour={props.setRequestSignTour}
|
||||
calculateFontsize={calculateFontsize}
|
||||
/>
|
||||
</React.Fragment>
|
||||
)
|
||||
@@ -177,6 +206,73 @@ function RenderPdf(props) {
|
||||
return `${width / 10}px`;
|
||||
}
|
||||
};
|
||||
//function for render placeholder block over pdf document
|
||||
|
||||
const handleUserName = (Id, Role, type, pos) => {
|
||||
if (Id) {
|
||||
const checkSign = props.signersdata.find((sign) => sign.Id === Id);
|
||||
if (checkSign?.Name) {
|
||||
return (
|
||||
<>
|
||||
<div
|
||||
style={{
|
||||
fontSize: pos ? calculateFontsize(pos) : "8px"
|
||||
}}
|
||||
className="text-black font-medium"
|
||||
>
|
||||
{checkSign?.Name}
|
||||
</div>
|
||||
{type && (
|
||||
<div
|
||||
style={{
|
||||
fontSize: pos ? calculateFontsize(pos) : "11px"
|
||||
}}
|
||||
className=" font-bold"
|
||||
>
|
||||
{type}
|
||||
</div>
|
||||
)}
|
||||
{Role && (
|
||||
<div
|
||||
style={{
|
||||
fontSize: pos ? calculateFontsize(pos) : "8px"
|
||||
}}
|
||||
className="text-black text-[8px] font-medium"
|
||||
>
|
||||
{`(${Role})`}
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
} else {
|
||||
return (
|
||||
<>
|
||||
{type && (
|
||||
<div
|
||||
style={{ fontSize: pos ? calculateFontsize(pos) : "11px" }}
|
||||
className=" font-bold"
|
||||
>
|
||||
{type}
|
||||
</div>
|
||||
)}
|
||||
<div
|
||||
style={{ fontSize: pos ? calculateFontsize(pos) : "8px" }}
|
||||
className="text-black font-medium"
|
||||
>
|
||||
{Role}
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
} else {
|
||||
return (
|
||||
<>
|
||||
{type && <div className="text-[11px] font-bold">{type}</div>}
|
||||
<div className="text-black text-[8px] font-medium">{Role}</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
};
|
||||
const pdfDataBase64 = `data:application/pdf;base64,${props.pdfBase64Url}`;
|
||||
//calculate render height of pdf in mobile view
|
||||
const handlePageLoadSuccess = (page) => {
|
||||
@@ -265,6 +361,7 @@ function RenderPdf(props) {
|
||||
handleLinkUser={
|
||||
props.handleLinkUser
|
||||
}
|
||||
handleUserName={handleUserName}
|
||||
isSignYourself={false}
|
||||
posWidth={posWidth}
|
||||
posHeight={posHeight}
|
||||
@@ -306,9 +403,6 @@ function RenderPdf(props) {
|
||||
props.unSignedWidgetId
|
||||
}
|
||||
isFreeResize={true}
|
||||
calculateFontsize={
|
||||
calculateFontsize
|
||||
}
|
||||
/>
|
||||
</React.Fragment>
|
||||
);
|
||||
@@ -354,6 +448,7 @@ function RenderPdf(props) {
|
||||
setWidgetType={props.setWidgetType}
|
||||
setSelectWidgetId={props.setSelectWidgetId}
|
||||
selectWidgetId={props.selectWidgetId}
|
||||
handleUserName={handleUserName}
|
||||
setIsCheckbox={props.setIsCheckbox}
|
||||
setValidateAlert={props.setValidateAlert}
|
||||
setCurrWidgetsDetails={
|
||||
@@ -373,7 +468,6 @@ function RenderPdf(props) {
|
||||
setIsResize={props.setIsResize}
|
||||
isFreeResize={false}
|
||||
isOpenSignPad={true}
|
||||
calculateFontsize={calculateFontsize}
|
||||
/>
|
||||
)
|
||||
);
|
||||
@@ -479,6 +573,7 @@ function RenderPdf(props) {
|
||||
handleLinkUser={
|
||||
props.handleLinkUser
|
||||
}
|
||||
handleUserName={handleUserName}
|
||||
isSignYourself={false}
|
||||
posWidth={posWidth}
|
||||
posHeight={posHeight}
|
||||
@@ -520,9 +615,6 @@ function RenderPdf(props) {
|
||||
props.unSignedWidgetId
|
||||
}
|
||||
isFreeResize={true}
|
||||
calculateFontsize={
|
||||
calculateFontsize
|
||||
}
|
||||
/>
|
||||
</React.Fragment>
|
||||
);
|
||||
@@ -573,6 +665,7 @@ function RenderPdf(props) {
|
||||
setWidgetType={props.setWidgetType}
|
||||
setSelectWidgetId={props.setSelectWidgetId}
|
||||
selectWidgetId={props.selectWidgetId}
|
||||
handleUserName={handleUserName}
|
||||
setIsCheckbox={props.setIsCheckbox}
|
||||
setValidateAlert={props.setValidateAlert}
|
||||
setCurrWidgetsDetails={
|
||||
@@ -593,7 +686,6 @@ function RenderPdf(props) {
|
||||
setIsResize={props.setIsResize}
|
||||
isFreeResize={false}
|
||||
isOpenSignPad={true}
|
||||
calculateFontsize={calculateFontsize}
|
||||
/>
|
||||
</React.Fragment>
|
||||
);
|
||||
|
||||
@@ -31,11 +31,7 @@ const WidgetNameModal = (props) => {
|
||||
name: props.defaultdata?.options?.name || "",
|
||||
defaultValue: props.defaultdata?.options?.defaultValue || "",
|
||||
status: props.defaultdata?.options?.status || "required",
|
||||
hint:
|
||||
props.defaultdata?.options?.hint ||
|
||||
(props.defaultdata?.type === textInputWidget
|
||||
? "Enter text"
|
||||
: `Enter ${props.defaultdata?.options?.name}`),
|
||||
hint: props.defaultdata?.options?.hint || "",
|
||||
textvalidate:
|
||||
props.defaultdata?.options?.validation?.type === "regex"
|
||||
? props.defaultdata?.options?.validation?.pattern
|
||||
@@ -117,6 +113,7 @@ const WidgetNameModal = (props) => {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const handleCheckboxChange = (index) => {
|
||||
// Update the state with the modified array
|
||||
setSignatureType((prev) =>
|
||||
@@ -275,13 +272,12 @@ const WidgetNameModal = (props) => {
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
{props.defaultdata?.type !== textWidget && (
|
||||
{props.defaultdata?.type === textInputWidget && (
|
||||
<div className="mb-[0.75rem]">
|
||||
<label htmlFor="hint" className="text-[13px]">
|
||||
{t("hint")}
|
||||
</label>
|
||||
<input
|
||||
maxLength={40}
|
||||
className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs"
|
||||
name="hint"
|
||||
value={formdata.hint}
|
||||
@@ -299,7 +295,7 @@ const WidgetNameModal = (props) => {
|
||||
].includes(props.defaultdata?.type) && (
|
||||
<div className="flex flex-col md:flex-row md:items-center gap-3 mb-3">
|
||||
<div className="flex items-center gap-2 ">
|
||||
<span className="whitespace-nowrap">{t("font-size")}: </span>
|
||||
<span>{t("font-size")}:</span>
|
||||
<select
|
||||
className="ml-[7px] w-[60%] op-select op-select-bordered op-select-sm focus:outline-none hover:border-base-content text-xs"
|
||||
value={
|
||||
|
||||
@@ -6,9 +6,6 @@ import { useTranslation } from "react-i18next";
|
||||
|
||||
const FolderModal = (props) => {
|
||||
const { t } = useTranslation();
|
||||
const appName =
|
||||
"OpenSign™";
|
||||
const drivename = appName === "OpenSign™" ? "OpenSign™" : "";
|
||||
const [clickFolder, setClickFolder] = useState("");
|
||||
const [folderList, setFolderList] = useState([]);
|
||||
const [tabList, setTabList] = useState([]);
|
||||
@@ -82,7 +79,7 @@ const FolderModal = (props) => {
|
||||
|
||||
// `handleSubmit` is used to pass folderPtr to parent component
|
||||
const handleSubmit = () => {
|
||||
let url = drivename + " Drive";
|
||||
let url = "OpenSign™ Drive";
|
||||
tabList.forEach((t) => {
|
||||
url = url + " / " + t.Name;
|
||||
});
|
||||
@@ -160,10 +157,10 @@ const FolderModal = (props) => {
|
||||
<div className="pt-1 text-[#ac4848] text-[14px] font-[500]">
|
||||
<span
|
||||
className="cursor-pointer"
|
||||
title={`${drivename} Drive`}
|
||||
title="OpenSign™ Drive"
|
||||
onClick={(e) => removeTabListItem(e)}
|
||||
>
|
||||
{t("OpenSign-drive", { appName: drivename })} /{" "}
|
||||
{t("OpenSign-drive")} /{" "}
|
||||
</span>
|
||||
{tabList &&
|
||||
tabList.map((tab, i) => (
|
||||
|
||||
@@ -6,9 +6,6 @@ import Tooltip from "../../../primitives/Tooltip";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
const SelectFolder = ({ required, onSuccess, folderCls, isReset }) => {
|
||||
const appName =
|
||||
"OpenSign™";
|
||||
const drivename = appName === "OpenSign™" ? "OpenSign™" : "";
|
||||
const { t } = useTranslation();
|
||||
const [isOpen, SetIsOpen] = useState(false);
|
||||
const [clickFolder, setClickFolder] = useState("");
|
||||
@@ -102,7 +99,7 @@ const SelectFolder = ({ required, onSuccess, folderCls, isReset }) => {
|
||||
|
||||
// `handleSubmit` is used to pass folderPtr to parent component
|
||||
const handleSubmit = () => {
|
||||
let url = drivename + " Drive";
|
||||
let url = "OpenSign™ Drive";
|
||||
tabList.forEach((t) => {
|
||||
url = url + " / " + t.Name;
|
||||
});
|
||||
@@ -197,7 +194,7 @@ const SelectFolder = ({ required, onSuccess, folderCls, isReset }) => {
|
||||
<p>
|
||||
{selectFolder && selectFolder.Name
|
||||
? selectFolder.Name
|
||||
: t("OpenSign-drive", { appName: drivename })}
|
||||
: t("OpenSign-drive")}
|
||||
</p>
|
||||
<div className="text-black text-sm">
|
||||
<i
|
||||
@@ -213,7 +210,7 @@ const SelectFolder = ({ required, onSuccess, folderCls, isReset }) => {
|
||||
</div>
|
||||
</div>
|
||||
<div className="absolute top-2 right-1 cursor-pointer">
|
||||
<Tooltip message={t("select-folder-help", { appName: drivename })} />
|
||||
<Tooltip message={t("select-folder-help")} />
|
||||
</div>
|
||||
</div>
|
||||
<ModalUi
|
||||
@@ -225,10 +222,10 @@ const SelectFolder = ({ required, onSuccess, folderCls, isReset }) => {
|
||||
<div className="pt-1 text-[#ac4848] text-[14px] font-[500]">
|
||||
<span
|
||||
className="cursor-pointer"
|
||||
title={`${drivename} Drive`}
|
||||
title="OpenSign™ Drive"
|
||||
onClick={(e) => removeTabListItem(e)}
|
||||
>
|
||||
{t("OpenSign-drive", { appName: drivename })} /{" "}
|
||||
{t("OpenSign-drive")} /{" "}
|
||||
</span>
|
||||
{tabList &&
|
||||
tabList.map((tab, i) => (
|
||||
|
||||
@@ -54,10 +54,16 @@ const TimezoneSelector = (props) => {
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<div className="mt-[12px] ml-[10px] text-[13px]">
|
||||
<strong>
|
||||
{formatDate(new Date(), selectedTimezone?.value || selectedTimezone)}
|
||||
</strong>{" "}
|
||||
<div className="mt-[20px] text-[13px]">
|
||||
<p>
|
||||
{t("current-time")}:{" "}
|
||||
<strong>
|
||||
{formatDate(
|
||||
new Date(),
|
||||
selectedTimezone?.value || selectedTimezone
|
||||
)}
|
||||
</strong>{" "}
|
||||
</p>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
|
||||
@@ -3,9 +3,6 @@ import { useTranslation } from "react-i18next";
|
||||
import { NavLink } from "react-router";
|
||||
|
||||
const Menu = ({ item, isOpen, closeSidebar }) => {
|
||||
const appName =
|
||||
"OpenSign™";
|
||||
const drivename = appName === "OpenSign™" ? "OpenSign™" : "";
|
||||
const { t } = useTranslation();
|
||||
return (
|
||||
<li key={item.title} role="none" className="my-0.5">
|
||||
@@ -25,9 +22,7 @@ const Menu = ({ item, isOpen, closeSidebar }) => {
|
||||
role="menuitem"
|
||||
>
|
||||
<i className={`${item.icon} text-[18px]`} aria-hidden="true"></i>
|
||||
<span className="ml-3 lg:ml-4">
|
||||
{t(`sidebar.${item.title}`, { appName: drivename })}
|
||||
</span>
|
||||
<span className="ml-3 lg:ml-4">{t(`sidebar.${item.title}`)}</span>
|
||||
</NavLink>
|
||||
</li>
|
||||
);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import React, { useState, useEffect } from "react";
|
||||
import Menu from "./Menu";
|
||||
import Submenu from "./SubMenu";
|
||||
import SocialMedia from "../SocialMedia";
|
||||
import SocialMedia from "./SocialMedia";
|
||||
import dp from "../../assets/images/dp.png";
|
||||
import sidebarList, { subSetting } from "../../json/menuJson";
|
||||
import { useNavigate } from "react-router";
|
||||
@@ -140,9 +140,9 @@ const Sidebar = ({ isOpen, closeSidebar }) => {
|
||||
)}
|
||||
</ul>
|
||||
</nav>
|
||||
<footer className="mt-4 flex justify-center items-center text-[25px] text-base-content gap-3">
|
||||
<SocialMedia />
|
||||
</footer>
|
||||
<footer className="mt-4 flex justify-center items-center text-[25px] text-base-content gap-3">
|
||||
<SocialMedia />
|
||||
</footer>
|
||||
</aside>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -3,9 +3,6 @@ import { useTranslation } from "react-i18next";
|
||||
import { NavLink } from "react-router";
|
||||
|
||||
const Submenu = ({ item, closeSidebar, toggleSubmenu, submenuOpen }) => {
|
||||
const appName =
|
||||
"OpenSign™";
|
||||
const drivename = appName === "OpenSign™" ? "OpenSign™" : "";
|
||||
const { t } = useTranslation();
|
||||
const { title, icon, children } = item;
|
||||
return (
|
||||
@@ -19,9 +16,7 @@ const Submenu = ({ item, closeSidebar, toggleSubmenu, submenuOpen }) => {
|
||||
>
|
||||
<i className={`${icon} text-[18px]`}></i>
|
||||
<div className="flex justify-between items-center w-full">
|
||||
<span className="ml-3 lg:ml-4">
|
||||
{t(`sidebar.${item.title}`, { appName })}
|
||||
</span>
|
||||
<span className="ml-3 lg:ml-4">{t(`sidebar.${item.title}`)}</span>
|
||||
<i
|
||||
className={`${
|
||||
submenuOpen[item.title]
|
||||
@@ -56,9 +51,7 @@ const Submenu = ({ item, closeSidebar, toggleSubmenu, submenuOpen }) => {
|
||||
aria-hidden="true"
|
||||
></i>
|
||||
<span className="ml-3 lg:ml-4">
|
||||
{t(`sidebar.${item.title}-Children.${childItem.title}`, {
|
||||
appName: drivename
|
||||
})}
|
||||
{t(`sidebar.${item.title}-Children.${childItem.title}`)}
|
||||
</span>
|
||||
</NavLink>
|
||||
</li>
|
||||
|
||||
@@ -7,7 +7,6 @@ import { appInfo } from "./appinfo";
|
||||
import { saveAs } from "file-saver";
|
||||
import printModule from "print-js";
|
||||
import fontkit from "@pdf-lib/fontkit";
|
||||
import { themeColor } from "./const";
|
||||
|
||||
export const fontsizeArr = [2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28];
|
||||
export const fontColorArr = ["red", "black", "blue", "yellow"];
|
||||
@@ -18,7 +17,6 @@ export const isTabAndMobile = window.innerWidth < 1023;
|
||||
export const textInputWidget = "text input";
|
||||
export const textWidget = "text";
|
||||
export const radioButtonWidget = "radio button";
|
||||
|
||||
export const fileasbytes = async (filepath) => {
|
||||
const response = await fetch(filepath); // Adjust the path accordingly
|
||||
const arrayBuffer = await response.arrayBuffer();
|
||||
@@ -134,12 +132,14 @@ export const pdfNewWidthFun = (divRef) => {
|
||||
};
|
||||
|
||||
//`contractUsers` function is used to get contract_User details
|
||||
export const contractUsers = async () => {
|
||||
export const contractUsers = async (
|
||||
) => {
|
||||
try {
|
||||
const url = `${localStorage.getItem("baseUrl")}functions/getUserDetails`;
|
||||
const parseAppId = localStorage.getItem("parseAppId");
|
||||
const accesstoken = localStorage.getItem("accesstoken");
|
||||
const token = { "X-Parse-Session-Token": accesstoken };
|
||||
const token =
|
||||
{ "X-Parse-Session-Token": accesstoken };
|
||||
const headers = {
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
@@ -491,7 +491,7 @@ export const signPdfFun = async (
|
||||
documentId,
|
||||
signerObjectId,
|
||||
objectId,
|
||||
widgets
|
||||
widgets,
|
||||
) => {
|
||||
let isCustomCompletionMail = false;
|
||||
try {
|
||||
@@ -500,7 +500,10 @@ export const signPdfFun = async (
|
||||
if (tenantDetails && tenantDetails === "user does not exist!") {
|
||||
return { status: "error", message: "User does not exist." };
|
||||
} else {
|
||||
if (tenantDetails?.CompletionBody && tenantDetails?.CompletionSubject) {
|
||||
if (
|
||||
tenantDetails?.CompletionBody &&
|
||||
tenantDetails?.CompletionSubject
|
||||
) {
|
||||
isCustomCompletionMail = true;
|
||||
}
|
||||
}
|
||||
@@ -635,13 +638,7 @@ export const createDocument = async (
|
||||
...Bcc,
|
||||
...RedirectUrl
|
||||
};
|
||||
const remindOnceInEvery = Doc?.RemindOnceInEvery;
|
||||
const TimeToCompleteDays = parseInt(Doc?.TimeToCompleteDays);
|
||||
const reminderCount = TimeToCompleteDays / remindOnceInEvery;
|
||||
const AutomaticReminders = Doc.autoreminder;
|
||||
if (AutomaticReminders && reminderCount > 15) {
|
||||
return { status: "error", id: "only-15-reminder-allowed" };
|
||||
}
|
||||
|
||||
try {
|
||||
const res = await axios.post(
|
||||
`${localStorage.getItem("baseUrl")}classes/contracts_Document`,
|
||||
@@ -659,7 +656,7 @@ export const createDocument = async (
|
||||
}
|
||||
} catch (err) {
|
||||
console.log("axois err ", err);
|
||||
return { status: "error", id: "something-went-wrong-mssg" };
|
||||
return { status: "error", id: "Something Went Wrong!" };
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -984,7 +981,7 @@ export const addInitialData = (signerPos, setXyPosition, value, userId) => {
|
||||
...item,
|
||||
options: {
|
||||
...item.options,
|
||||
defaultValue: item?.options?.defaultValue || widgetData
|
||||
defaultValue: widgetData
|
||||
}
|
||||
// Width:
|
||||
// calculateInitialWidthHeight(item.type, widgetData).getWidth ||
|
||||
@@ -1004,7 +1001,6 @@ export const addInitialData = (signerPos, setXyPosition, value, userId) => {
|
||||
|
||||
//function for embed document id
|
||||
export const embedDocId = async (pdfDoc, documentId, allPages) => {
|
||||
const appName = "OpenSign™";
|
||||
// `fontBytes` is used to embed custom font in pdf
|
||||
const fontBytes = await fileasbytes(
|
||||
"https://cdn.opensignlabs.com/webfonts/times.ttf"
|
||||
@@ -1013,7 +1009,7 @@ export const embedDocId = async (pdfDoc, documentId, allPages) => {
|
||||
const font = await pdfDoc.embedFont(fontBytes, { subset: true });
|
||||
for (let i = 0; i < allPages; i++) {
|
||||
const fontSize = 10;
|
||||
const textContent = documentId && `${appName} DocumentId: ${documentId} `;
|
||||
const textContent = documentId && `OpenSign™ DocumentId: ${documentId} `;
|
||||
const pages = pdfDoc.getPages();
|
||||
const page = pages[i];
|
||||
try {
|
||||
@@ -1866,9 +1862,12 @@ export const contactBook = async (objectId) => {
|
||||
};
|
||||
|
||||
//function for getting document details from contract_Documents class
|
||||
export const contractDocument = async (documentId) => {
|
||||
export const contractDocument = async (
|
||||
documentId,
|
||||
) => {
|
||||
const data = { docId: documentId };
|
||||
const token = { sessionToken: localStorage.getItem("accesstoken") };
|
||||
const token =
|
||||
{ sessionToken: localStorage.getItem("accesstoken") };
|
||||
const documentDeatils = await axios
|
||||
.post(`${localStorage.getItem("baseUrl")}functions/getDocument`, data, {
|
||||
headers: {
|
||||
@@ -2052,31 +2051,35 @@ export const getFileName = (fileUrl) => {
|
||||
|
||||
//fetch tenant app logo from `partners_Tenant` class by domain name
|
||||
export const getAppLogo = async () => {
|
||||
const domain = window.location.host;
|
||||
try {
|
||||
const tenant = await Parse.Cloud.run("getlogobydomain", {
|
||||
domain: domain
|
||||
});
|
||||
if (tenant) {
|
||||
localStorage.setItem("appname", "OpenSign™");
|
||||
return { logo: tenant?.logo, user: tenant?.user };
|
||||
const domain = window.location.host;
|
||||
try {
|
||||
const tenant = await Parse.Cloud.run("getlogobydomain", {
|
||||
domain: domain
|
||||
});
|
||||
if (tenant) {
|
||||
return { logo: tenant?.logo, user: tenant?.user };
|
||||
}
|
||||
} catch (err) {
|
||||
console.log("err in getlogo ", err);
|
||||
if (err?.message?.includes("valid JSON")) {
|
||||
return { logo: appInfo.applogo, user: "exist", error: "invalid_json" };
|
||||
} else {
|
||||
return { logo: appInfo.applogo, user: "exist" };
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
console.log("err in getlogo ", err);
|
||||
if (err?.message?.includes("valid JSON")) {
|
||||
return { logo: appInfo.applogo, user: "exist", error: "invalid_json" };
|
||||
} else {
|
||||
return { logo: appInfo.applogo, user: "exist" };
|
||||
}
|
||||
}
|
||||
};
|
||||
export const getTenantDetails = async (objectId, contactId) => {
|
||||
export const getTenantDetails = async (
|
||||
objectId,
|
||||
contactId
|
||||
) => {
|
||||
try {
|
||||
const url = `${localStorage.getItem("baseUrl")}functions/gettenant`;
|
||||
const parseAppId = localStorage.getItem("parseAppId");
|
||||
const accesstoken = localStorage.getItem("accesstoken");
|
||||
const token = { "X-Parse-Session-Token": accesstoken };
|
||||
const data = { userId: objectId, contactId: contactId };
|
||||
const token =
|
||||
{ "X-Parse-Session-Token": accesstoken };
|
||||
const data =
|
||||
{ userId: objectId, contactId: contactId };
|
||||
const res = await axios.post(url, data, {
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
@@ -2163,7 +2166,6 @@ export const handleSendOTP = async (email) => {
|
||||
}
|
||||
};
|
||||
export const fetchUrl = async (url, pdfName) => {
|
||||
const appName = "OpenSign™";
|
||||
try {
|
||||
const response = await fetch(url);
|
||||
if (!response.ok) {
|
||||
@@ -2171,13 +2173,17 @@ export const fetchUrl = async (url, pdfName) => {
|
||||
throw new Error("Network response was not ok");
|
||||
}
|
||||
const blob = await response.blob();
|
||||
saveAs(blob, `${sanitizeFileName(pdfName)}_signed_by_${appName}.pdf`);
|
||||
saveAs(blob, `${sanitizeFileName(pdfName)}_signed_by_OpenSign™.pdf`);
|
||||
} catch (error) {
|
||||
alert("something went wrong, please try again later.");
|
||||
console.error("Error downloading the file:", error);
|
||||
}
|
||||
};
|
||||
export const getSignedUrl = async (pdfUrl, docId, templateId) => {
|
||||
export const getSignedUrl = async (
|
||||
pdfUrl,
|
||||
docId,
|
||||
templateId
|
||||
) => {
|
||||
//use only axios here due to public template sign
|
||||
const axiosRes = await axios.post(
|
||||
`${localStorage.getItem("baseUrl")}/functions/getsignedurl`,
|
||||
@@ -2238,7 +2244,10 @@ export const handleDownloadPdf = async (
|
||||
setIsDownloading && setIsDownloading("pdf");
|
||||
const docId = pdfDetails?.[0]?.objectId || "";
|
||||
try {
|
||||
const url = await getSignedUrl(pdfUrl, docId);
|
||||
const url = await getSignedUrl(
|
||||
pdfUrl,
|
||||
docId,
|
||||
);
|
||||
await fetchUrl(url, pdfName);
|
||||
setIsDownloading && setIsDownloading("");
|
||||
} catch (err) {
|
||||
@@ -2268,7 +2277,7 @@ export const handleToPrint = async (event, setIsDownloading, pdfDetails) => {
|
||||
`${localStorage.getItem("baseUrl")}/functions/getsignedurl`,
|
||||
{
|
||||
url: pdfUrl,
|
||||
docId: docId
|
||||
docId: docId,
|
||||
},
|
||||
{
|
||||
headers: {
|
||||
@@ -2312,7 +2321,6 @@ export const handleDownloadCertificate = async (
|
||||
setIsDownloading,
|
||||
isZip
|
||||
) => {
|
||||
const appName = "OpenSign™";
|
||||
if (pdfDetails?.length > 0 && pdfDetails[0]?.CertificateUrl) {
|
||||
try {
|
||||
await fetch(pdfDetails[0] && pdfDetails[0]?.CertificateUrl);
|
||||
@@ -2320,7 +2328,7 @@ export const handleDownloadCertificate = async (
|
||||
if (isZip) {
|
||||
return certificateUrl;
|
||||
} else {
|
||||
saveAs(certificateUrl, `Certificate_signed_by_${appName}.pdf`);
|
||||
saveAs(certificateUrl, `Certificate_signed_by_OpenSign™.pdf`);
|
||||
}
|
||||
} catch (err) {
|
||||
console.log("err in download in certificate", err);
|
||||
@@ -2349,7 +2357,7 @@ export const handleDownloadCertificate = async (
|
||||
setIsDownloading("");
|
||||
return certificateUrl;
|
||||
} else {
|
||||
saveAs(certificateUrl, `Certificate_signed_by_${appName}.pdf`);
|
||||
saveAs(certificateUrl, `Certificate_signed_by_OpenSign™.pdf`);
|
||||
setIsDownloading("");
|
||||
}
|
||||
} else {
|
||||
@@ -2374,7 +2382,7 @@ export const handleDownloadCertificate = async (
|
||||
// Convert the response into a Blob
|
||||
const certificateBlob = await fetchCertificate.blob();
|
||||
setIsDownloading("");
|
||||
saveAs(certificateBlob, `Certificate_signed_by_${appName}.pdf`);
|
||||
saveAs(certificateBlob, `Certificate_signed_by_OpenSign™.pdf`);
|
||||
}
|
||||
} catch (err) {
|
||||
console.log("err in download in certificate", err);
|
||||
@@ -2396,13 +2404,14 @@ export const handleDownloadCertificate = async (
|
||||
export function escapeRegExp(string) {
|
||||
return string.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); // Escape special characters
|
||||
}
|
||||
export async function findContact(value) {
|
||||
export async function findContact(
|
||||
value,
|
||||
) {
|
||||
try {
|
||||
const baseURL = localStorage.getItem("baseUrl");
|
||||
const url = `${baseURL}functions/getsigners`;
|
||||
const token = {
|
||||
"X-Parse-Session-Token": localStorage.getItem("accesstoken")
|
||||
};
|
||||
const token =
|
||||
{ "X-Parse-Session-Token": localStorage.getItem("accesstoken") };
|
||||
const headers = {
|
||||
"Content-Type": "application/json",
|
||||
"X-Parse-Application-Id": localStorage.getItem("parseAppId"),
|
||||
@@ -2614,20 +2623,23 @@ export function base64ToArrayBuffer(base64) {
|
||||
return bytes.buffer;
|
||||
}
|
||||
|
||||
export const convertBase64ToFile = async (pdfName, pdfBase64) => {
|
||||
export const convertBase64ToFile = async (
|
||||
pdfName,
|
||||
pdfBase64,
|
||||
) => {
|
||||
const fileName = sanitizeFileName(pdfName) + ".pdf";
|
||||
try {
|
||||
const pdfFile = new Parse.File(fileName, { base64: pdfBase64 });
|
||||
// Save the Parse File if needed
|
||||
const pdfData = await pdfFile.save();
|
||||
const pdfUrl = pdfData.url();
|
||||
const fileRes = await getSecureUrl(pdfUrl);
|
||||
if (fileRes?.url) {
|
||||
return fileRes.url;
|
||||
try {
|
||||
const pdfFile = new Parse.File(fileName, { base64: pdfBase64 });
|
||||
// Save the Parse File if needed
|
||||
const pdfData = await pdfFile.save();
|
||||
const pdfUrl = pdfData.url();
|
||||
const fileRes = await getSecureUrl(pdfUrl);
|
||||
if (fileRes?.url) {
|
||||
return fileRes.url;
|
||||
}
|
||||
} catch (e) {
|
||||
console.log("error in convertbase64tofile", e);
|
||||
}
|
||||
} catch (e) {
|
||||
console.log("error in convertbase64tofile", e);
|
||||
}
|
||||
};
|
||||
export const onClickZoomIn = (scale, zoomPercent, setScale, setZoomPercent) => {
|
||||
setScale(scale + 0.1 * scale);
|
||||
@@ -2924,36 +2936,3 @@ export const flattenPdf = async (pdfFile) => {
|
||||
const flatPdf = await pdfDoc.save({ useObjectStreams: false });
|
||||
return flatPdf;
|
||||
};
|
||||
|
||||
export const mailTemplate = (param) => {
|
||||
const appName = "OpenSign™";
|
||||
const logo = `<div style='padding:10px'><img src='https://qikinnovation.ams3.digitaloceanspaces.com/logo.png' height='50' /></div>`;
|
||||
|
||||
const opurl = ` <a href='https://www.opensignlabs.com' target=_blank>here</a>.</p></div></div></body></html>`;
|
||||
|
||||
const subject = `${param.senderName} has requested you to sign "${param.title}"`;
|
||||
const body =
|
||||
"<html><head><meta http-equiv='Content-Type' content='text/html;charset=UTF-8' /></head><body><div style='background-color:#f5f5f5;padding:20px'><div style='background:white;padding-bottom:20px'>" +
|
||||
logo +
|
||||
`<div style='padding:2px;font-family:system-ui;background-color:${themeColor}'><p style='font-size:20px;font-weight:400;color:white;padding-left:20px'>Digital Signature Request</p></div><div><p style='padding:20px;font-size:14px;margin-bottom:10px'>` +
|
||||
param.senderName +
|
||||
" has requested you to review and sign <strong>" +
|
||||
param.title +
|
||||
"</strong>.</p><div style='padding: 5px 0px 5px 25px;display:flex;flex-direction:row;justify-content:space-around'><table><tr><td style='font-weight:bold;font-family:sans-serif;font-size:15px'>Sender</td><td></td><td style='color:#626363;font-weight:bold'>" +
|
||||
param.senderMail +
|
||||
"</td></tr><tr><td style='font-weight:bold;font-family:sans-serif;font-size:15px'>Organization</td><td></td><td style='color:#626363;font-weight:bold'> " +
|
||||
param.organization +
|
||||
"</td></tr><tr><td style='font-weight:bold;font-family:sans-serif;font-size:15px'>Expire on</td><td></td><td style='color:#626363;font-weight:bold'>" +
|
||||
param.localExpireDate +
|
||||
"</td></tr><tr><td></td><td></td></tr></table></div> <div style='margin-left:70px'><a target=_blank href=" +
|
||||
param.sigingUrl +
|
||||
"><button style='padding:12px;background-color:#d46b0f;color:white;border:0px;font-weight:bold;margin-top:30px'>Sign here</button></a></div><div style='display:flex;justify-content:center;margin-top:10px'></div></div></div><div><p> This is an automated email from " +
|
||||
appName +
|
||||
". For any queries regarding this email, please contact the sender " +
|
||||
param.senderMail +
|
||||
" directly. If you think this email is inappropriate or spam, you may file a complaint with " +
|
||||
appName +
|
||||
opurl;
|
||||
|
||||
return { subject, body };
|
||||
};
|
||||
|
||||
@@ -4,7 +4,7 @@ export function serverUrl_fn() {
|
||||
let baseUrl;
|
||||
baseUrl = process.env.REACT_APP_SERVERURL
|
||||
? process.env.REACT_APP_SERVERURL
|
||||
: window.location.origin + "/api/app";
|
||||
: window.location.origin + "/app";
|
||||
|
||||
return baseUrl;
|
||||
}
|
||||
|
||||
@@ -74,7 +74,7 @@ const sidebarList = [
|
||||
target: "_self",
|
||||
pageType: "",
|
||||
description: "",
|
||||
objectId: "drive"
|
||||
objectId: "opensigndrive"
|
||||
},
|
||||
{
|
||||
icon: "fa-light fa-address-card",
|
||||
|
||||
@@ -15,8 +15,6 @@ import { showHeader } from "../redux/reducers/showHeader";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
const HomeLayout = () => {
|
||||
const appName =
|
||||
"OpenSign™";
|
||||
const { t, i18n } = useTranslation();
|
||||
const navigate = useNavigate();
|
||||
const location = useLocation();
|
||||
@@ -151,7 +149,7 @@ const HomeLayout = () => {
|
||||
...resArr,
|
||||
{
|
||||
selector: '[data-tut="reactourLast"]',
|
||||
content: t("tour-mssg.home-layout-3", { appName }),
|
||||
content: t("tour-mssg.home-layout-3"),
|
||||
position: "top"
|
||||
// style: { backgroundColor: "#abd4d2" },
|
||||
}
|
||||
|
||||
@@ -16,8 +16,6 @@ import { useTranslation } from "react-i18next";
|
||||
import { emailRegex } from "../constant/const";
|
||||
|
||||
const AddAdmin = () => {
|
||||
const appName =
|
||||
"OpenSign™";
|
||||
const { t, i18n } = useTranslation();
|
||||
const navigate = useNavigate();
|
||||
const dispatch = useDispatch();
|
||||
@@ -50,7 +48,7 @@ const AddAdmin = () => {
|
||||
try {
|
||||
const app = await getAppLogo();
|
||||
if (app?.error === "invalid_json") {
|
||||
setErrMsg(t("server-down", { appName: appName }));
|
||||
setErrMsg(t("server-down"));
|
||||
} else if (app?.user === "exist") {
|
||||
setErrMsg(t("admin-exists"));
|
||||
}
|
||||
@@ -282,7 +280,7 @@ const AddAdmin = () => {
|
||||
<form onSubmit={handleSubmit}>
|
||||
<div className="w-full my-4 op-card bg-base-100 shadow-md outline outline-1 outline-slate-300/50">
|
||||
<h2 className="text-[30px] text-center mt-3 font-medium">
|
||||
{t("opensign-setup", { appName })}
|
||||
{t("opensign-setup")}
|
||||
</h2>
|
||||
<NavLink
|
||||
to="https://discord.com/invite/xe9TDuyAyj"
|
||||
|
||||
@@ -9,7 +9,6 @@ import {
|
||||
import ModalUi from "../primitives/ModalUi";
|
||||
import Loader from "../primitives/Loader";
|
||||
import DownloadPdfZip from "../primitives/DownloadPdfZip";
|
||||
import Title from "../components/Title";
|
||||
|
||||
const DocSuccessPage = () => {
|
||||
const signed = window.location?.search?.includes("docid");
|
||||
@@ -53,7 +52,6 @@ const DocSuccessPage = () => {
|
||||
};
|
||||
return (
|
||||
<div className="flex h-screen justify-center items-center text-sm md:text-base">
|
||||
<Title title="Success" />
|
||||
{sent ? (
|
||||
<div>{t("doc-sent")}</div>
|
||||
) : signed ? (
|
||||
|
||||
@@ -75,7 +75,7 @@ function ForgotPassword() {
|
||||
};
|
||||
return (
|
||||
<div>
|
||||
<Title title="Forgot password" />
|
||||
<Title title="Forgot password page" />
|
||||
{sentStatus === "success" && (
|
||||
<Alert type="success">{t("reset-password-alert-1")}</Alert>
|
||||
)}
|
||||
|
||||
+215
-228
@@ -36,7 +36,6 @@ function Form() {
|
||||
}
|
||||
|
||||
const Forms = (props) => {
|
||||
const appName = "OpenSign™";
|
||||
const { t } = useTranslation();
|
||||
const maxFileSize = 20;
|
||||
const abortController = new AbortController();
|
||||
@@ -80,15 +79,6 @@ const Forms = (props) => {
|
||||
const extUserData =
|
||||
localStorage.getItem("Extand_Class") &&
|
||||
JSON.parse(localStorage.getItem("Extand_Class"))?.[0];
|
||||
const sendinorder =
|
||||
extUserData?.SendinOrder !== undefined && extUserData?.SendinOrder === false
|
||||
? "false"
|
||||
: "true";
|
||||
const istourenabled =
|
||||
extUserData?.IsTourEnabled !== undefined &&
|
||||
extUserData?.IsTourEnabled === false
|
||||
? "false"
|
||||
: "true";
|
||||
useEffect(() => {
|
||||
handleReset();
|
||||
return () => abortController.abort();
|
||||
@@ -100,12 +90,7 @@ const Forms = (props) => {
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, []);
|
||||
const initializeValues = async () => {
|
||||
setFormData((obj) => ({
|
||||
...obj,
|
||||
NotifyOnSignatures: true,
|
||||
SendinOrder: sendinorder,
|
||||
IsTourEnabled: istourenabled
|
||||
}));
|
||||
setFormData((obj) => ({ ...obj, NotifyOnSignatures: true }));
|
||||
};
|
||||
|
||||
function getFileAsArrayBuffer(file) {
|
||||
@@ -143,88 +128,17 @@ const Forms = (props) => {
|
||||
const name = generatePdfName(16);
|
||||
const pdfName = `${name?.split(".")[0]}.pdf`;
|
||||
setfileload(true);
|
||||
try {
|
||||
const res = await getFileAsArrayBuffer(files[0]);
|
||||
const flatPdf = await flattenPdf(res);
|
||||
const parseFile = new Parse.File(
|
||||
pdfName,
|
||||
[...flatPdf],
|
||||
"application/pdf"
|
||||
);
|
||||
|
||||
try {
|
||||
const response = await parseFile.save({
|
||||
progress: (progressValue, loaded, total, { type }) => {
|
||||
if (type === "upload" && progressValue !== null) {
|
||||
const percentCompleted = Math.round(
|
||||
(loaded * 100) / total
|
||||
);
|
||||
setpercentage(percentCompleted);
|
||||
}
|
||||
}
|
||||
});
|
||||
// The response object will contain information about the uploaded file
|
||||
// You can access the URL of the uploaded file using response.url()
|
||||
if (response.url()) {
|
||||
const fileRes = await getSecureUrl(response.url());
|
||||
if (fileRes.url) {
|
||||
setFileUpload(fileRes.url);
|
||||
setfileload(false);
|
||||
const tenantId = localStorage.getItem("TenantId");
|
||||
const title = generateTitleFromFilename(files?.[0]?.name);
|
||||
setFormData((obj) => ({ ...obj, Name: title }));
|
||||
SaveFileSize(size, fileRes.url, tenantId);
|
||||
return fileRes.url;
|
||||
} else {
|
||||
removeFile(e);
|
||||
}
|
||||
} else {
|
||||
removeFile(e);
|
||||
}
|
||||
} catch (error) {
|
||||
removeFile(e);
|
||||
console.error("Error uploading file:", error);
|
||||
}
|
||||
} catch (err) {
|
||||
if (err?.message?.includes("is encrypted")) {
|
||||
try {
|
||||
await Parse.Cloud.run("encryptedpdf", {
|
||||
email: Parse.User.current().getEmail()
|
||||
});
|
||||
} catch (err) {
|
||||
console.log("err in sending posthog encryptedpdf", err);
|
||||
}
|
||||
try {
|
||||
setIsDecrypting(true);
|
||||
const size = files?.[0].size;
|
||||
const name = generatePdfName(16);
|
||||
const url = "https://ai.nxglabs.in/decryptpdf"; //
|
||||
let formData = new FormData();
|
||||
formData.append("file", files[0]);
|
||||
formData.append("password", "");
|
||||
const config = {
|
||||
headers: { "content-type": "multipart/form-data" },
|
||||
responseType: "blob"
|
||||
};
|
||||
const response = await axios.post(url, formData, config);
|
||||
const pdfBlob = new Blob([response.data], {
|
||||
type: "application/pdf"
|
||||
});
|
||||
const pdfFile = new File([pdfBlob], name, {
|
||||
type: "application/pdf"
|
||||
});
|
||||
setIsDecrypting(false);
|
||||
setfileload(true);
|
||||
const res = await getFileAsArrayBuffer(pdfFile);
|
||||
const flatPdf = await flattenPdf(res);
|
||||
// Upload the file to Parse Server
|
||||
const parseFile = new Parse.File(
|
||||
name,
|
||||
[...flatPdf],
|
||||
"application/pdf"
|
||||
);
|
||||
const res = await getFileAsArrayBuffer(files[0]);
|
||||
const flatPdf = await flattenPdf(res);
|
||||
const parseFile = new Parse.File(
|
||||
pdfName,
|
||||
[...flatPdf],
|
||||
"application/pdf"
|
||||
);
|
||||
|
||||
await parseFile.save({
|
||||
try {
|
||||
const response = await parseFile.save({
|
||||
progress: (progressValue, loaded, total, { type }) => {
|
||||
if (type === "upload" && progressValue !== null) {
|
||||
const percentCompleted = Math.round(
|
||||
@@ -234,16 +148,16 @@ const Forms = (props) => {
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Retrieve the URL of the uploaded file
|
||||
if (parseFile.url()) {
|
||||
const fileRes = await getSecureUrl(parseFile.url());
|
||||
// The response object will contain information about the uploaded file
|
||||
// You can access the URL of the uploaded file using response.url()
|
||||
if (response.url()) {
|
||||
const fileRes = await getSecureUrl(response.url());
|
||||
if (fileRes.url) {
|
||||
setFileUpload(fileRes.url);
|
||||
removeFile();
|
||||
setfileload(false);
|
||||
const tenantId = localStorage.getItem("TenantId");
|
||||
const title = generateTitleFromFilename(files?.[0]?.name);
|
||||
setFormData((obj) => ({ ...obj, Name: title }));
|
||||
const tenantId = localStorage.getItem("TenantId");
|
||||
SaveFileSize(size, fileRes.url, tenantId);
|
||||
return fileRes.url;
|
||||
} else {
|
||||
@@ -252,22 +166,95 @@ const Forms = (props) => {
|
||||
} else {
|
||||
removeFile(e);
|
||||
}
|
||||
} catch (err) {
|
||||
removeFile();
|
||||
if (err?.response?.status === 401) {
|
||||
setIsPassword(true);
|
||||
} else {
|
||||
console.log("Error uploading file: ", err?.response);
|
||||
setIsDecrypting(false);
|
||||
e.target.value = "";
|
||||
}
|
||||
} catch (error) {
|
||||
removeFile(e);
|
||||
console.error("Error uploading file:", error);
|
||||
}
|
||||
} catch (err) {
|
||||
if (err?.message?.includes("is encrypted")) {
|
||||
try {
|
||||
await Parse.Cloud.run("encryptedpdf", {
|
||||
email: Parse.User.current().getEmail()
|
||||
});
|
||||
} catch (err) {
|
||||
console.log("err in sending posthog encryptedpdf", err);
|
||||
}
|
||||
try {
|
||||
setIsDecrypting(true);
|
||||
const size = files?.[0].size;
|
||||
const name = generatePdfName(16);
|
||||
const url = "https://ai.nxglabs.in/decryptpdf"; //
|
||||
let formData = new FormData();
|
||||
formData.append("file", files[0]);
|
||||
formData.append("password", "");
|
||||
const config = {
|
||||
headers: { "content-type": "multipart/form-data" },
|
||||
responseType: "blob"
|
||||
};
|
||||
const response = await axios.post(url, formData, config);
|
||||
const pdfBlob = new Blob([response.data], {
|
||||
type: "application/pdf"
|
||||
});
|
||||
const pdfFile = new File([pdfBlob], name, {
|
||||
type: "application/pdf"
|
||||
});
|
||||
setIsDecrypting(false);
|
||||
setfileload(true);
|
||||
const res = await getFileAsArrayBuffer(pdfFile);
|
||||
const flatPdf = await flattenPdf(res);
|
||||
// Upload the file to Parse Server
|
||||
const parseFile = new Parse.File(
|
||||
name,
|
||||
[...flatPdf],
|
||||
"application/pdf"
|
||||
);
|
||||
|
||||
await parseFile.save({
|
||||
progress: (progressValue, loaded, total, { type }) => {
|
||||
if (type === "upload" && progressValue !== null) {
|
||||
const percentCompleted = Math.round(
|
||||
(loaded * 100) / total
|
||||
);
|
||||
setpercentage(percentCompleted);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Retrieve the URL of the uploaded file
|
||||
if (parseFile.url()) {
|
||||
const fileRes = await getSecureUrl(parseFile.url());
|
||||
if (fileRes.url) {
|
||||
setFileUpload(fileRes.url);
|
||||
removeFile();
|
||||
const title = generateTitleFromFilename(
|
||||
files?.[0]?.name
|
||||
);
|
||||
setFormData((obj) => ({ ...obj, Name: title }));
|
||||
const tenantId = localStorage.getItem("TenantId");
|
||||
SaveFileSize(size, fileRes.url, tenantId);
|
||||
return fileRes.url;
|
||||
} else {
|
||||
removeFile(e);
|
||||
}
|
||||
} else {
|
||||
removeFile(e);
|
||||
}
|
||||
} catch (err) {
|
||||
removeFile();
|
||||
if (err?.response?.status === 401) {
|
||||
setIsPassword(true);
|
||||
} else {
|
||||
console.log("Error uploading file: ", err?.response);
|
||||
setIsDecrypting(false);
|
||||
e.target.value = "";
|
||||
}
|
||||
}
|
||||
} else {
|
||||
console.log("err ", err);
|
||||
setFileUpload("");
|
||||
removeFile(e);
|
||||
}
|
||||
} else {
|
||||
console.log("err ", err);
|
||||
setFileUpload("");
|
||||
removeFile(e);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
const isImage = files?.[0]?.type.includes("image/");
|
||||
if (isImage) {
|
||||
@@ -292,50 +279,50 @@ const Forms = (props) => {
|
||||
});
|
||||
const size = files?.[0]?.size;
|
||||
const name = generatePdfName(16);
|
||||
const getFile = await pdfDoc.save({
|
||||
useObjectStreams: false
|
||||
});
|
||||
setfileload(true);
|
||||
const pdfName = `${name?.split(".")[0]}.pdf`;
|
||||
const parseFile = new Parse.File(
|
||||
pdfName,
|
||||
[...getFile],
|
||||
"application/pdf"
|
||||
);
|
||||
|
||||
try {
|
||||
const response = await parseFile.save({
|
||||
progress: (progressValue, loaded, total, { type }) => {
|
||||
if (type === "upload" && progressValue !== null) {
|
||||
const percentCompleted = Math.round(
|
||||
(loaded * 100) / total
|
||||
);
|
||||
setpercentage(percentCompleted);
|
||||
}
|
||||
}
|
||||
const getFile = await pdfDoc.save({
|
||||
useObjectStreams: false
|
||||
});
|
||||
// The response object will contain information about the uploaded file
|
||||
// You can access the URL of the uploaded file using response.url()
|
||||
if (response.url()) {
|
||||
const fileRes = await getSecureUrl(response.url());
|
||||
if (fileRes.url) {
|
||||
setFileUpload(fileRes.url);
|
||||
setfileload(false);
|
||||
const tenantId = localStorage.getItem("TenantId");
|
||||
const title = generateTitleFromFilename(files?.[0]?.name);
|
||||
setFormData((obj) => ({ ...obj, Name: title }));
|
||||
SaveFileSize(size, fileRes.url, tenantId);
|
||||
return fileRes.url;
|
||||
setfileload(true);
|
||||
const pdfName = `${name?.split(".")[0]}.pdf`;
|
||||
const parseFile = new Parse.File(
|
||||
pdfName,
|
||||
[...getFile],
|
||||
"application/pdf"
|
||||
);
|
||||
|
||||
try {
|
||||
const response = await parseFile.save({
|
||||
progress: (progressValue, loaded, total, { type }) => {
|
||||
if (type === "upload" && progressValue !== null) {
|
||||
const percentCompleted = Math.round(
|
||||
(loaded * 100) / total
|
||||
);
|
||||
setpercentage(percentCompleted);
|
||||
}
|
||||
}
|
||||
});
|
||||
// The response object will contain information about the uploaded file
|
||||
// You can access the URL of the uploaded file using response.url()
|
||||
if (response.url()) {
|
||||
const fileRes = await getSecureUrl(response.url());
|
||||
if (fileRes.url) {
|
||||
setFileUpload(fileRes.url);
|
||||
setfileload(false);
|
||||
const tenantId = localStorage.getItem("TenantId");
|
||||
const title = generateTitleFromFilename(files?.[0]?.name);
|
||||
setFormData((obj) => ({ ...obj, Name: title }));
|
||||
SaveFileSize(size, fileRes.url, tenantId);
|
||||
return fileRes.url;
|
||||
} else {
|
||||
removeFile(e);
|
||||
}
|
||||
} else {
|
||||
removeFile(e);
|
||||
}
|
||||
} else {
|
||||
} catch (error) {
|
||||
removeFile(e);
|
||||
console.error("Error uploading file:", error);
|
||||
}
|
||||
} catch (error) {
|
||||
removeFile(e);
|
||||
console.error("Error uploading file:", error);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -385,24 +372,19 @@ const Forms = (props) => {
|
||||
const isChecked = formData.SendinOrder === "false" ? false : true;
|
||||
const isTourEnabled =
|
||||
formData?.IsTourEnabled === "false" ? false : true;
|
||||
const remindOnceInEvery = parseInt(formData.remindOnceInEvery);
|
||||
const TimeToCompleteDays = parseInt(formData?.TimeToCompleteDays);
|
||||
const AutomaticReminders = formData.autoreminder;
|
||||
const reminderCount = TimeToCompleteDays / remindOnceInEvery;
|
||||
if (AutomaticReminders && reminderCount > 15) {
|
||||
alert(t("only-15-reminder-allowed"));
|
||||
return;
|
||||
}
|
||||
object.set("SendinOrder", isChecked);
|
||||
object.set("AutomaticReminders", AutomaticReminders);
|
||||
object.set("RemindOnceInEvery", remindOnceInEvery);
|
||||
object.set("AutomaticReminders", formData.autoreminder);
|
||||
object.set("RemindOnceInEvery", parseInt(formData.remindOnceInEvery));
|
||||
object.set("IsTourEnabled", isTourEnabled);
|
||||
object.set("TimeToCompleteDays", TimeToCompleteDays);
|
||||
object.set("AllowModifications", false);
|
||||
object.set("IsEnableOTP", false);
|
||||
if (formData.NotifyOnSignatures !== undefined) {
|
||||
object.set("NotifyOnSignatures", formData.NotifyOnSignatures);
|
||||
}
|
||||
object.set(
|
||||
"TimeToCompleteDays",
|
||||
parseInt(formData?.TimeToCompleteDays)
|
||||
);
|
||||
object.set("AllowModifications", false);
|
||||
object.set("IsEnableOTP", false);
|
||||
if (formData.NotifyOnSignatures !== undefined) {
|
||||
object.set("NotifyOnSignatures", formData.NotifyOnSignatures);
|
||||
}
|
||||
if (formData?.RedirectUrl) {
|
||||
object.set("RedirectUrl", formData.RedirectUrl);
|
||||
}
|
||||
@@ -441,9 +423,10 @@ const Forms = (props) => {
|
||||
setSigners([]);
|
||||
setBcc([]);
|
||||
setFolder({ ObjectId: "", Name: "" });
|
||||
const notifySign = extUserData?.NotifyOnSignatures
|
||||
? extUserData?.NotifyOnSignatures
|
||||
: true;
|
||||
const notifySign =
|
||||
extUserData?.NotifyOnSignatures
|
||||
? extUserData?.NotifyOnSignatures
|
||||
: true;
|
||||
setFormData({
|
||||
Name: "",
|
||||
Description: "",
|
||||
@@ -452,14 +435,14 @@ const Forms = (props) => {
|
||||
? "Note to myself"
|
||||
: "Please review and sign this document",
|
||||
TimeToCompleteDays: 15,
|
||||
SendinOrder: sendinorder,
|
||||
SendinOrder: "true",
|
||||
password: "",
|
||||
file: "",
|
||||
NotifyOnSignatures: notifySign,
|
||||
remindOnceInEvery: 5,
|
||||
autoreminder: false,
|
||||
IsEnableOTP: "false",
|
||||
IsTourEnabled: istourenabled,
|
||||
IsTourEnabled: "true",
|
||||
RedirectUrl: "",
|
||||
AllowModifications: false
|
||||
});
|
||||
@@ -469,17 +452,7 @@ const Forms = (props) => {
|
||||
}
|
||||
} catch (err) {
|
||||
console.log("err ", err);
|
||||
if (err.message === "only 15 reminder allowed") {
|
||||
setIsAlert({
|
||||
type: "danger",
|
||||
message: t("only-15-reminder-allowed")
|
||||
});
|
||||
} else {
|
||||
setIsAlert({
|
||||
type: "danger",
|
||||
message: t("something-went-wrong-mssg")
|
||||
});
|
||||
}
|
||||
setIsAlert({ type: "danger", message: t("something-went-wrong-mssg") });
|
||||
} finally {
|
||||
setTimeout(() => setIsAlert({ type: "success", message: "" }), 1000);
|
||||
setIsSubmit(false);
|
||||
@@ -519,9 +492,10 @@ const Forms = (props) => {
|
||||
setSigners([]);
|
||||
setBcc([]);
|
||||
setFolder({ ObjectId: "", Name: "" });
|
||||
const notifySign = extUserData?.NotifyOnSignatures
|
||||
? extUserData?.NotifyOnSignatures
|
||||
: true;
|
||||
const notifySign =
|
||||
extUserData?.NotifyOnSignatures
|
||||
? extUserData?.NotifyOnSignatures
|
||||
: true;
|
||||
let obj = {
|
||||
Name: "",
|
||||
Description: "",
|
||||
@@ -530,13 +504,13 @@ const Forms = (props) => {
|
||||
? "Note to myself"
|
||||
: "Please review and sign this document",
|
||||
TimeToCompleteDays: 15,
|
||||
SendinOrder: sendinorder,
|
||||
SendinOrder: "true",
|
||||
password: "",
|
||||
file: "",
|
||||
remindOnceInEvery: 5,
|
||||
autoreminder: false,
|
||||
IsEnableOTP: "false",
|
||||
IsTourEnabled: istourenabled,
|
||||
IsTourEnabled: "true",
|
||||
NotifyOnSignatures: notifySign,
|
||||
RedirectUrl: "",
|
||||
AllowModifications: false
|
||||
@@ -575,28 +549,36 @@ const Forms = (props) => {
|
||||
type: "application/pdf"
|
||||
});
|
||||
setIsDecrypting(false);
|
||||
const res = await getFileAsArrayBuffer(pdfFile);
|
||||
const flatPdf = await flattenPdf(res);
|
||||
const parseFile = new Parse.File(name, [...flatPdf], "application/pdf");
|
||||
await parseFile.save({
|
||||
progress: (progressValue, loaded, total, { type }) => {
|
||||
if (type === "upload" && progressValue !== null) {
|
||||
const percentCompleted = Math.round((loaded * 100) / total);
|
||||
setpercentage(percentCompleted);
|
||||
const res = await getFileAsArrayBuffer(pdfFile);
|
||||
const flatPdf = await flattenPdf(res);
|
||||
const parseFile = new Parse.File(name, [...flatPdf], "application/pdf");
|
||||
await parseFile.save({
|
||||
progress: (progressValue, loaded, total, { type }) => {
|
||||
if (type === "upload" && progressValue !== null) {
|
||||
const percentCompleted = Math.round((loaded * 100) / total);
|
||||
setpercentage(percentCompleted);
|
||||
}
|
||||
}
|
||||
});
|
||||
// Retrieve the URL of the uploaded file
|
||||
if (parseFile.url()) {
|
||||
const fileRes = await getSecureUrl(parseFile.url());
|
||||
if (fileRes.url) {
|
||||
setFileUpload(fileRes.url);
|
||||
removeFile();
|
||||
const title = generateTitleFromFilename(formData?.file?.name);
|
||||
setFormData((obj) => ({ ...obj, password: "", Name: title }));
|
||||
const tenantId = localStorage.getItem("TenantId");
|
||||
SaveFileSize(size, fileRes.url, tenantId);
|
||||
return fileRes.url;
|
||||
} else {
|
||||
removeFile();
|
||||
setFormData((prev) => ({ ...prev, password: "" }));
|
||||
setIsDecrypting(false);
|
||||
if (inputFileRef.current) {
|
||||
inputFileRef.current.value = ""; // Set file input value to empty string
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
// Retrieve the URL of the uploaded file
|
||||
if (parseFile.url()) {
|
||||
const fileRes = await getSecureUrl(parseFile.url());
|
||||
if (fileRes.url) {
|
||||
setFileUpload(fileRes.url);
|
||||
removeFile();
|
||||
const title = generateTitleFromFilename(formData?.file?.name);
|
||||
setFormData((obj) => ({ ...obj, password: "", Name: title }));
|
||||
const tenantId = localStorage.getItem("TenantId");
|
||||
SaveFileSize(size, fileRes.url, tenantId);
|
||||
return fileRes.url;
|
||||
} else {
|
||||
removeFile();
|
||||
setFormData((prev) => ({ ...prev, password: "" }));
|
||||
@@ -605,14 +587,6 @@ const Forms = (props) => {
|
||||
inputFileRef.current.value = ""; // Set file input value to empty string
|
||||
}
|
||||
}
|
||||
} else {
|
||||
removeFile();
|
||||
setFormData((prev) => ({ ...prev, password: "" }));
|
||||
setIsDecrypting(false);
|
||||
if (inputFileRef.current) {
|
||||
inputFileRef.current.value = ""; // Set file input value to empty string
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
removeFile();
|
||||
if (err?.response?.status === 401) {
|
||||
@@ -734,7 +708,9 @@ const Forms = (props) => {
|
||||
)}
|
||||
<div className="text-xs">
|
||||
<label className="block">
|
||||
{`${`${t("report-heading.File")} (${t("file-type")}`}${")"}`}
|
||||
{`${`${t("report-heading.File")} (${t("file-type")}`}${
|
||||
")"
|
||||
}`}
|
||||
<span className="text-red-500 text-[13px]">*</span>
|
||||
</label>
|
||||
{fileupload.length > 0 ? (
|
||||
@@ -758,7 +734,9 @@ const Forms = (props) => {
|
||||
className="op-file-input op-file-input-bordered op-file-input-sm focus:outline-none hover:border-base-content w-full text-xs"
|
||||
onChange={(e) => handleFileInput(e)}
|
||||
ref={inputFileRef}
|
||||
accept={"application/pdf,image/png,image/jpeg"}
|
||||
accept={
|
||||
"application/pdf,image/png,image/jpeg"
|
||||
}
|
||||
onInvalid={(e) =>
|
||||
e.target.setCustomValidity(t("input-required"))
|
||||
}
|
||||
@@ -1048,7 +1026,10 @@ const Forms = (props) => {
|
||||
{isAdvanceOpt && (
|
||||
<div
|
||||
style={{
|
||||
height: props.title === "New Template" ? "100px" : "280px"
|
||||
height:
|
||||
props.title === "New Template"
|
||||
? "100px"
|
||||
: "280px"
|
||||
}}
|
||||
className="w-[1px] bg-gray-300 m-auto hidden md:inline-block"
|
||||
></div>
|
||||
@@ -1107,9 +1088,7 @@ const Forms = (props) => {
|
||||
</li>
|
||||
</ol>
|
||||
</p>
|
||||
<p>
|
||||
{t("istourenabled-help.p3", { appName: appName })}
|
||||
</p>
|
||||
<p>{t("istourenabled-help.p3")}</p>
|
||||
</div>
|
||||
</Tooltip>
|
||||
</label>
|
||||
@@ -1157,7 +1136,11 @@ const Forms = (props) => {
|
||||
</Tooltip>
|
||||
</label>
|
||||
<div className="flex flex-col md:flex-row md:gap-4">
|
||||
<div className={`flex items-center gap-2 ml-2 mb-1`}>
|
||||
<div
|
||||
className={
|
||||
`flex items-center gap-2 ml-2 mb-1`
|
||||
}
|
||||
>
|
||||
<input
|
||||
className="mr-[2px] op-radio op-radio-xs"
|
||||
type="radio"
|
||||
@@ -1166,7 +1149,11 @@ const Forms = (props) => {
|
||||
/>
|
||||
<div className="text-center">{t("yes")}</div>
|
||||
</div>
|
||||
<div className={`flex items-center gap-2 ml-2 mb-1`}>
|
||||
<div
|
||||
className={
|
||||
`flex items-center gap-2 ml-2 mb-1`
|
||||
}
|
||||
>
|
||||
<input
|
||||
className="mr-[2px] op-radio op-radio-xs"
|
||||
type="radio"
|
||||
|
||||
@@ -14,7 +14,6 @@ import Parse from "parse";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import SelectLanguage from "../components/pdf/SelectLanguage";
|
||||
import LoaderWithMsg from "../primitives/LoaderWithMsg";
|
||||
import Title from "../components/Title";
|
||||
|
||||
function GuestLogin() {
|
||||
const { t, i18n } = useTranslation();
|
||||
@@ -65,11 +64,7 @@ function GuestLogin() {
|
||||
const handleServerUrl = async () => {
|
||||
setAppLogo(logo);
|
||||
|
||||
localStorage.clear(); // Clears everything
|
||||
localStorage.setItem(
|
||||
"appname",
|
||||
"OpenSign™"
|
||||
);
|
||||
localStorage.clear();
|
||||
//save isGuestSigner true in local to handle login flow header in mobile view
|
||||
localStorage.setItem("isGuestSigner", true);
|
||||
saveLanguageInLocal(i18n);
|
||||
@@ -220,19 +215,14 @@ function GuestLogin() {
|
||||
};
|
||||
return (
|
||||
<div>
|
||||
<Title title="Request Sign" />
|
||||
{isLoading.isLoad ? (
|
||||
<LoaderWithMsg isLoading={isLoading} />
|
||||
) : (
|
||||
<div className="pb-1 md:pb-4 pt-10 md:px-10 lg:px-16">
|
||||
<div className="md:p-4 lg:p-10 p-4 text-base-content bg-base-100 op-card shadow-md">
|
||||
<div className="w-[250px] h-[66px] inline-block overflow-hidden mb-6">
|
||||
<div className="p-14 h">
|
||||
<div className="m-1 md:m-2 p-[30px] text-base-content bg-base-100 op-card shadow-md">
|
||||
<div className="md:w-[250px] md:h-[66px] inline-block overflow-hidden mt-2 mb-11">
|
||||
{appLogo && (
|
||||
<img
|
||||
src={appLogo}
|
||||
className="object-contain h-full"
|
||||
alt="logo"
|
||||
/>
|
||||
<img src={appLogo} className="object-contain" alt="logo" />
|
||||
)}
|
||||
</div>
|
||||
{contactId ? (
|
||||
|
||||
@@ -24,8 +24,6 @@ import { useTranslation } from "react-i18next";
|
||||
import SelectLanguage from "../components/pdf/SelectLanguage";
|
||||
|
||||
function Login() {
|
||||
const appName =
|
||||
"OpenSign™";
|
||||
const { t, i18n } = useTranslation();
|
||||
const navigate = useNavigate();
|
||||
const location = useLocation();
|
||||
@@ -60,7 +58,7 @@ function Login() {
|
||||
const checkUserExt = async () => {
|
||||
const app = await getAppLogo();
|
||||
if (app?.error === "invalid_json") {
|
||||
setErrMsg(t("server-down", { appName: appName }));
|
||||
setErrMsg(t("server-down"));
|
||||
} else if (
|
||||
app?.user === "not_exist"
|
||||
) {
|
||||
@@ -508,7 +506,7 @@ function Login() {
|
||||
</div>
|
||||
) : (
|
||||
<div>
|
||||
<Title title="Login" />
|
||||
<Title title={"Login Page"} />
|
||||
{state.loading && (
|
||||
<div
|
||||
aria-live="assertive"
|
||||
|
||||
@@ -13,7 +13,6 @@ import Alert from "../primitives/Alert";
|
||||
import Loader from "../primitives/Loader";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import sanitizeFileName from "../primitives/sanitizeFileName";
|
||||
import Title from "../components/Title";
|
||||
const ManageSign = () => {
|
||||
const { t } = useTranslation();
|
||||
const [penColor, setPenColor] = useState("blue");
|
||||
@@ -298,7 +297,6 @@ const ManageSign = () => {
|
||||
};
|
||||
return (
|
||||
<div className="relative h-full bg-base-100 text-base-content flex shadow-md rounded-box overflow-auto">
|
||||
<Title title="My signature" />
|
||||
{isLoader && (
|
||||
<div className="absolute bg-black bg-opacity-30 z-50 w-full h-full flex justify-center items-center">
|
||||
<Loader />
|
||||
|
||||
@@ -3,9 +3,7 @@ import "../styles/opensigndrive.css";
|
||||
import {
|
||||
iconColor,
|
||||
} from "../constant/const";
|
||||
import {
|
||||
getDrive
|
||||
} from "../constant/Utils";
|
||||
import { getDrive } from "../constant/Utils";
|
||||
import { useNavigate } from "react-router";
|
||||
import Title from "../components/Title";
|
||||
import Parse from "parse";
|
||||
@@ -15,7 +13,6 @@ import Tour from "reactour";
|
||||
import axios from "axios";
|
||||
import Loader from "../primitives/Loader";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
const DriveBody = React.lazy(
|
||||
() => import("../components/opensigndrive/DriveBody")
|
||||
);
|
||||
@@ -29,9 +26,6 @@ const AppLoader = () => {
|
||||
);
|
||||
};
|
||||
function Opensigndrive() {
|
||||
const appName =
|
||||
"OpenSign™";
|
||||
const drivename = appName === "OpenSign™" ? "OpenSign™" : "";
|
||||
const { t } = useTranslation();
|
||||
const navigate = useNavigate();
|
||||
const scrollRef = useRef(null);
|
||||
@@ -79,7 +73,8 @@ function Opensigndrive() {
|
||||
const jsonCurrentUser = JSON.parse(currentUser);
|
||||
|
||||
useEffect(() => {
|
||||
getDetails();
|
||||
getPdfDocumentList();
|
||||
|
||||
// eslint-disable-next-line
|
||||
}, [docId]);
|
||||
|
||||
@@ -129,9 +124,6 @@ function Opensigndrive() {
|
||||
style: { fontSize: "13px" }
|
||||
}
|
||||
];
|
||||
const getDetails = async () => {
|
||||
getPdfDocumentList();
|
||||
};
|
||||
//function for get all pdf document list
|
||||
const getPdfDocumentList = async (disbaleLoading) => {
|
||||
setLoading(true);
|
||||
@@ -203,9 +195,7 @@ function Opensigndrive() {
|
||||
setTourData(tourConfigs);
|
||||
}
|
||||
if (!docId) {
|
||||
setFolderName([
|
||||
{ name: t("OpenSign-drive", { appName: drivename }), objectId: "" }
|
||||
]);
|
||||
setFolderName([{ name: t("OpenSign-drive"), objectId: "" }]);
|
||||
}
|
||||
} catch (e) {
|
||||
setIsAlert({
|
||||
@@ -524,7 +514,7 @@ function Opensigndrive() {
|
||||
}
|
||||
return (
|
||||
<div className="bg-base-100 text-base-content rounded-box w-full shadow-md">
|
||||
<Title title={`${drivename} Drive`} drive={true} />
|
||||
<Title title={"OpenSign™ Drive"} drive={true} />
|
||||
<ModalUi
|
||||
isOpen={isAlert.isShow}
|
||||
title={t("alert")}
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
import React, { useState, useRef, useEffect } from "react";
|
||||
import {
|
||||
themeColor
|
||||
} from "../constant/const";
|
||||
import { PDFDocument } from "pdf-lib";
|
||||
import "../styles/signature.css";
|
||||
import Parse from "parse";
|
||||
@@ -40,8 +43,7 @@ import {
|
||||
defaultWidthHeight,
|
||||
addWidgetOptions,
|
||||
textWidget,
|
||||
compressedFileSize,
|
||||
mailTemplate
|
||||
compressedFileSize
|
||||
} from "../constant/Utils";
|
||||
import Header from "../components/pdf/PdfHeader";
|
||||
import RenderPdf from "../components/pdf/RenderPdf";
|
||||
@@ -67,8 +69,6 @@ import TextFontSetting from "../components/pdf/TextFontSetting";
|
||||
function PdfRequestFiles(
|
||||
) {
|
||||
const { t } = useTranslation();
|
||||
const appName =
|
||||
"OpenSign™";
|
||||
const [pdfDetails, setPdfDetails] = useState([]);
|
||||
const [signedSigners, setSignedSigners] = useState([]);
|
||||
const [unsignedSigners, setUnSignedSigners] = useState([]);
|
||||
@@ -833,13 +833,13 @@ function PdfRequestFiles(
|
||||
"en-US",
|
||||
{ day: "numeric", month: "long", year: "numeric" }
|
||||
);
|
||||
let senderEmail =
|
||||
pdfDetails?.[0]?.ExtUserPtr?.Email;
|
||||
let senderEmail = pdfDetails?.[0].ExtUserPtr.Email;
|
||||
let senderPhone = pdfDetails?.[0]?.ExtUserPtr?.Phone;
|
||||
const senderName =
|
||||
pdfDetails?.[0].ExtUserPtr.Name;
|
||||
const documentName = pdfDetails?.[0].Name;
|
||||
const senderName = `${pdfDetails?.[0].ExtUserPtr.Name}`;
|
||||
|
||||
try {
|
||||
const imgPng =
|
||||
"https://qikinnovation.ams3.digitaloceanspaces.com/logo.png";
|
||||
let url = `${localStorage.getItem("baseUrl")}functions/sendmailv3`;
|
||||
const headers = {
|
||||
"Content-Type": "application/json",
|
||||
@@ -862,9 +862,12 @@ function PdfRequestFiles(
|
||||
}
|
||||
let signPdf =
|
||||
`${hostUrl}/login/${encodeBase64}`;
|
||||
const openSignUrl =
|
||||
"https://www.opensignlabs.com/contact-us";
|
||||
const orgName = pdfDetails[0]?.ExtUserPtr.Company
|
||||
? pdfDetails[0].ExtUserPtr.Company
|
||||
: "";
|
||||
const themeBGcolor = themeColor;
|
||||
let replaceVar;
|
||||
if (
|
||||
requestBody &&
|
||||
@@ -880,9 +883,11 @@ function PdfRequestFiles(
|
||||
"</body> </html>";
|
||||
|
||||
const variables = {
|
||||
document_title: documentName,
|
||||
sender_name: senderName,
|
||||
sender_mail: senderEmail,
|
||||
document_title: pdfDetails?.[0].Name,
|
||||
sender_name:
|
||||
senderName,
|
||||
sender_mail:
|
||||
senderEmail,
|
||||
sender_phone: senderPhone,
|
||||
receiver_name: user?.Name || "",
|
||||
receiver_email: user.Email,
|
||||
@@ -897,26 +902,41 @@ function PdfRequestFiles(
|
||||
variables
|
||||
);
|
||||
}
|
||||
const mailparam = {
|
||||
senderName: senderName,
|
||||
senderMail: senderEmail,
|
||||
title: documentName,
|
||||
organization: orgName,
|
||||
localExpireDate: localExpireDate,
|
||||
sigingUrl: signPdf
|
||||
};
|
||||
|
||||
let params = {
|
||||
replyto: senderEmail || "",
|
||||
replyto:
|
||||
senderEmail ||
|
||||
"",
|
||||
extUserId: extUserId,
|
||||
recipient: user.Email,
|
||||
subject: replaceVar?.subject
|
||||
? replaceVar?.subject
|
||||
: mailTemplate(mailparam).subject,
|
||||
: `${pdfDetails?.[0].ExtUserPtr.Name} has requested you to sign "${pdfDetails?.[0].Name}"`,
|
||||
from:
|
||||
senderEmail,
|
||||
html: replaceVar?.body
|
||||
? replaceVar?.body
|
||||
: mailTemplate(mailparam).body
|
||||
: "<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: white;padding-bottom: 20px;'> <div style='padding:10px 10px 0 10px'><img src=" +
|
||||
imgPng +
|
||||
" height='50' style='padding: 20px,width:170px,height:40px' /></div> <div style=' padding: 2px;font-family: system-ui;background-color:" +
|
||||
themeBGcolor +
|
||||
";'><p style='font-size: 20px;font-weight: 400;color: white;padding-left: 20px;' > Digital Signature Request</p></div><div><p style='padding: 20px;font-family: system-ui;font-size: 14px; margin-bottom: 10px;'> " +
|
||||
pdfDetails?.[0].ExtUserPtr.Name +
|
||||
" has requested you to review and sign <strong> " +
|
||||
pdfDetails?.[0].Name +
|
||||
"</strong>.</p><div style='padding: 5px 0px 5px 25px;display: flex;flex-direction: row;justify-content: space-around;'><table> <tr> <td style='font-weight:bold;font-family:sans-serif;font-size:15px'>Sender</td> <td> </td> <td style='color:#626363;font-weight:bold'>" +
|
||||
senderEmail +
|
||||
"</td></tr><tr><td style='font-weight:bold;font-family:sans-serif;font-size:15px'>Organization</td> <td> </td><td style='color:#626363;font-weight:bold'> " +
|
||||
orgName +
|
||||
"</td></tr> <tr> <td style='font-weight:bold;font-family:sans-serif;font-size:15px'>Expires on</td><td> </td> <td style='color:#626363;font-weight:bold'>" +
|
||||
localExpireDate +
|
||||
"</td></tr><tr> <td></td> <td> </td></tr></table> </div> <div style='margin-left:70px'><a target=_blank href=" +
|
||||
signPdf +
|
||||
"> <button style='padding: 12px 12px 12px 12px;background-color: #d46b0f;color: white; border: 0px;box-shadow: rgba(0, 0, 0, 0.05) 0px 6px 24px 0px,rgba(0, 0, 0, 0.08) 0px 0px 0px 1px;font-weight:bold;margin-top:30px'>Sign here</button></a> </div> <div style='display: flex; justify-content: center;margin-top: 10px;'> </div></div></div><div><p> This is an automated email from OpenSign™. For any queries regarding this email, please contact the sender " +
|
||||
senderEmail +
|
||||
" directly.If you think this email is inappropriate or spam, you may file a complaint with OpenSign™ <a href= " +
|
||||
openSignUrl +
|
||||
" target=_blank>here</a>.</p> </div></div></body> </html>"
|
||||
};
|
||||
await axios.post(url, params, { headers: headers });
|
||||
} catch (error) {
|
||||
@@ -950,7 +970,7 @@ function PdfRequestFiles(
|
||||
setIsAlert({
|
||||
title: "Error",
|
||||
isShow: true,
|
||||
alertMessage: t("pdf-uncompatible", { appName: appName })
|
||||
alertMessage: t("pdf-uncompatible")
|
||||
});
|
||||
}
|
||||
} catch (err) {
|
||||
|
||||
@@ -3,6 +3,9 @@ import axios from "axios";
|
||||
import Parse from "parse";
|
||||
import "../styles/signature.css";
|
||||
import { PDFDocument } from "pdf-lib";
|
||||
import {
|
||||
themeColor
|
||||
} from "../constant/const";
|
||||
import { DndProvider } from "react-dnd";
|
||||
import { HTML5Backend } from "react-dnd-html5-backend";
|
||||
import { useDrop } from "react-dnd";
|
||||
@@ -40,8 +43,7 @@ import {
|
||||
signatureTypes,
|
||||
handleSignatureType,
|
||||
getBase64FromUrl,
|
||||
generatePdfName,
|
||||
mailTemplate
|
||||
generatePdfName
|
||||
} from "../constant/Utils";
|
||||
import RenderPdf from "../components/pdf/RenderPdf";
|
||||
import { useNavigate } from "react-router";
|
||||
@@ -68,8 +70,6 @@ import AddContact from "../primitives/AddContact";
|
||||
|
||||
function PlaceHolderSign() {
|
||||
const { t } = useTranslation();
|
||||
const copyUrlRef = useRef(null);
|
||||
const appName = "OpenSign™";
|
||||
const editorRef = useRef();
|
||||
const { state } = useLocation();
|
||||
const navigate = useNavigate();
|
||||
@@ -188,7 +188,7 @@ function PlaceHolderSign() {
|
||||
);
|
||||
if (user) {
|
||||
try {
|
||||
const defaultRequestBody = `<p>Hi {{receiver_name}},</p><br><p>We hope this email finds you well. {{sender_name}} has requested you to review and sign {{document_title}}.</p><p>Your signature is crucial to proceed with the next steps as it signifies your agreement and authorization.</p><br><p>{{signing_url}}</p><br><p>If you have any questions or need further clarification regarding the document or the signing process, please contact the sender.</p><br><p>Thanks</p><p> Team ${appName}</p><br>`;
|
||||
const defaultRequestBody = `<p>Hi {{receiver_name}},</p><br><p>We hope this email finds you well. {{sender_name}} has requested you to review and sign {{document_title}}.</p><p>Your signature is crucial to proceed with the next steps as it signifies your agreement and authorization.</p><br><p>{{signing_url}}</p><br><p>If you have any questions or need further clarification regarding the document or the signing process, please contact the sender.</p><br><p>Thanks</p><p> Team OpenSign™</p><br>`;
|
||||
const defaultSubject = `{{sender_name}} has requested you to sign {{document_title}}`;
|
||||
setDefaultBody(defaultRequestBody);
|
||||
setDefaultSubject(defaultSubject);
|
||||
@@ -863,7 +863,11 @@ function PlaceHolderSign() {
|
||||
scale
|
||||
);
|
||||
const pdfName = generatePdfName(16);
|
||||
const pdfUrl = await convertBase64ToFile(pdfName, pdfBase64, "");
|
||||
const pdfUrl = await convertBase64ToFile(
|
||||
pdfName,
|
||||
pdfBase64,
|
||||
"",
|
||||
);
|
||||
const tenantId = localStorage.getItem("TenantId");
|
||||
const buffer = atob(pdfBase64);
|
||||
SaveFileSize(buffer.length, pdfUrl, tenantId);
|
||||
@@ -875,7 +879,11 @@ function PlaceHolderSign() {
|
||||
} else if (pdfBase64Url) {
|
||||
try {
|
||||
const pdfName = generatePdfName(16);
|
||||
const pdfUrl = await convertBase64ToFile(pdfName, pdfBase64Url, "");
|
||||
const pdfUrl = await convertBase64ToFile(
|
||||
pdfName,
|
||||
pdfBase64Url,
|
||||
"",
|
||||
);
|
||||
return pdfUrl;
|
||||
} catch (err) {
|
||||
console.log("error to convertBase64ToFile in placeholder flow", err);
|
||||
@@ -981,7 +989,11 @@ function PlaceHolderSign() {
|
||||
let pdfUrl;
|
||||
if (isUploadPdf) {
|
||||
const pdfName = generatePdfName(16);
|
||||
pdfUrl = await convertBase64ToFile(pdfName, pdfBase64Url, "");
|
||||
pdfUrl = await convertBase64ToFile(
|
||||
pdfName,
|
||||
pdfBase64Url,
|
||||
"",
|
||||
);
|
||||
}
|
||||
try {
|
||||
const docCls = new Parse.Object("contracts_Document");
|
||||
@@ -1079,9 +1091,6 @@ function PlaceHolderSign() {
|
||||
|
||||
const copytoclipboard = (text) => {
|
||||
copytoData(text);
|
||||
if (copyUrlRef.current) {
|
||||
copyUrlRef.current.textContent = text; // Update text safely
|
||||
}
|
||||
setCopied(true);
|
||||
setTimeout(() => setCopied(false), 1500); // Reset copied state after 1.5 seconds
|
||||
};
|
||||
@@ -1150,6 +1159,8 @@ function PlaceHolderSign() {
|
||||
|
||||
for (let i = 0; i < signerMail.length; i++) {
|
||||
try {
|
||||
const imgPng =
|
||||
"https://qikinnovation.ams3.digitaloceanspaces.com/logo.png";
|
||||
let url = `${localStorage.getItem("baseUrl")}functions/sendmailv3`;
|
||||
const headers = {
|
||||
"Content-Type": "application/json",
|
||||
@@ -1163,14 +1174,20 @@ function PlaceHolderSign() {
|
||||
`${pdfDetails?.[0].objectId}/${signerMail[i].Email}/${objectId}`
|
||||
);
|
||||
let signPdf = `${hostUrl}/login/${encodeBase64}`;
|
||||
const openSignUrl = "https://www.opensignlabs.com/";
|
||||
const orgName = pdfDetails[0]?.ExtUserPtr.Company
|
||||
? pdfDetails[0].ExtUserPtr.Company
|
||||
: "";
|
||||
const senderName = pdfDetails?.[0].ExtUserPtr.Name;
|
||||
const themeBGcolor = themeColor;
|
||||
const senderName = `${pdfDetails?.[0].ExtUserPtr.Name}`;
|
||||
const documentName = `${pdfDetails?.[0].Name}`;
|
||||
let replaceVar;
|
||||
|
||||
if (requestBody && requestSubject && isCustomize) {
|
||||
if (
|
||||
requestBody &&
|
||||
requestSubject &&
|
||||
isCustomize
|
||||
) {
|
||||
const replacedRequestBody = requestBody.replace(/"/g, "'");
|
||||
htmlReqBody =
|
||||
"<html><head><meta http-equiv='Content-Type' content='text/html; charset=UTF-8' /></head><body>" +
|
||||
@@ -1179,8 +1196,10 @@ function PlaceHolderSign() {
|
||||
|
||||
const variables = {
|
||||
document_title: documentName,
|
||||
sender_name: senderName,
|
||||
sender_mail: senderEmail,
|
||||
sender_name:
|
||||
senderName,
|
||||
sender_mail:
|
||||
senderEmail,
|
||||
sender_phone: senderPhone || "",
|
||||
receiver_name: signerMail[i]?.Name || "",
|
||||
receiver_email: signerMail[i].Email,
|
||||
@@ -1194,7 +1213,10 @@ function PlaceHolderSign() {
|
||||
htmlReqBody,
|
||||
variables
|
||||
);
|
||||
} else if (tenantMailTemplate?.body && tenantMailTemplate?.subject) {
|
||||
} else if (
|
||||
tenantMailTemplate?.body &&
|
||||
tenantMailTemplate?.subject
|
||||
) {
|
||||
const mailBody = tenantMailTemplate?.body;
|
||||
const mailSubject = tenantMailTemplate?.subject;
|
||||
const replacedRequestBody = mailBody.replace(/"/g, "'");
|
||||
@@ -1204,8 +1226,10 @@ function PlaceHolderSign() {
|
||||
"</body> </html>";
|
||||
const variables = {
|
||||
document_title: documentName,
|
||||
sender_name: senderName,
|
||||
sender_mail: senderEmail,
|
||||
sender_name:
|
||||
senderName,
|
||||
sender_mail:
|
||||
senderEmail,
|
||||
sender_phone: senderPhone || "",
|
||||
receiver_name: signerMail[i]?.Name || "",
|
||||
receiver_email: signerMail[i].Email,
|
||||
@@ -1216,25 +1240,40 @@ function PlaceHolderSign() {
|
||||
};
|
||||
replaceVar = replaceMailVaribles(mailSubject, htmlReqBody, variables);
|
||||
}
|
||||
const mailparam = {
|
||||
senderName: senderName,
|
||||
senderMail: senderEmail,
|
||||
title: documentName,
|
||||
organization: orgName,
|
||||
localExpireDate: localExpireDate,
|
||||
sigingUrl: signPdf
|
||||
};
|
||||
let params = {
|
||||
extUserId: extUserId,
|
||||
recipient: signerMail[i].Email,
|
||||
subject: replaceVar?.subject
|
||||
? replaceVar?.subject
|
||||
: mailTemplate(mailparam).subject,
|
||||
replyto: senderEmail,
|
||||
from: senderEmail,
|
||||
: `${senderName} has requested you to sign "${documentName}"`,
|
||||
replyto:
|
||||
senderEmail ||
|
||||
"",
|
||||
from:
|
||||
senderEmail,
|
||||
html: replaceVar?.body
|
||||
? replaceVar?.body
|
||||
: mailTemplate(mailparam).body
|
||||
: "<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:white;padding-bottom:20px;'><div style='padding:10px 10px 0 10px'><img src=" +
|
||||
imgPng +
|
||||
" height='50' style='padding:20px,width:170px,height:40px' /></div><div style='padding:2px;font-family:system-ui;background-color:" +
|
||||
themeBGcolor +
|
||||
";'><p style='font-size:20px;font-weight:400;color:white;padding-left:20px;' > Digital Signature Request</p></div><div><p style='padding:20px;font-family:system-ui;font-size:14px;margin-bottom:10px;'> " +
|
||||
pdfDetails?.[0].ExtUserPtr.Name +
|
||||
" has requested you to review and sign <strong> " +
|
||||
pdfDetails?.[0].Name +
|
||||
"</strong>.</p><div style='padding: 5px 0px 5px 25px;display:flex;flex-direction:row;justify-content:space-around;'><table><tr><td style='font-weight:bold;font-family:sans-serif;font-size:15px'>Sender</td><td></td><td style='color:#626363;font-weight:bold;'>" +
|
||||
senderEmail +
|
||||
"</td></tr><tr><td style='font-weight:bold;font-family:sans-serif;font-size:15px'>Organization</td><td></td><td style='color:#626363;font-weight:bold'> " +
|
||||
orgName +
|
||||
"</td></tr><tr><td style='font-weight:bold;font-family:sans-serif;font-size:15px'>Expire on</td><td></td><td style='color:#626363;font-weight:bold'>" +
|
||||
localExpireDate +
|
||||
"</td></tr><tr><td></td><td></td></tr></table></div> <div style='margin-left:70px'><a target=_blank href=" +
|
||||
signPdf +
|
||||
"><button style='padding: 12px 12px 12px 12px;background-color:#d46b0f;color:white;border:0px;box-shadow: rgba(0, 0, 0, 0.05) 0px 6px 24px 0px,rgba(0, 0, 0, 0.08) 0px 0px 0px 1px;font-weight:bold;margin-top:30px'>Sign here</button></a></div><div style='display: flex; justify-content: center;margin-top: 10px;'></div></div></div><div><p> This is an automated email from OpenSign™. For any queries regarding this email, please contact the sender " +
|
||||
senderEmail +
|
||||
" directly.If you think this email is inappropriate or spam, you may file a complaint with OpenSign™ <a href= " +
|
||||
openSignUrl +
|
||||
" target=_blank>here</a>.</p></div></div></body></html>"
|
||||
};
|
||||
|
||||
sendMail = await axios.post(url, params, { headers: headers });
|
||||
@@ -1246,13 +1285,20 @@ function PlaceHolderSign() {
|
||||
setMailStatus("success");
|
||||
try {
|
||||
let data;
|
||||
if (requestBody && requestSubject && isCustomize) {
|
||||
if (
|
||||
requestBody &&
|
||||
requestSubject &&
|
||||
isCustomize
|
||||
) {
|
||||
data = {
|
||||
RequestBody: htmlReqBody,
|
||||
RequestSubject: requestSubject,
|
||||
SendMail: true
|
||||
};
|
||||
} else if (tenantMailTemplate?.body && tenantMailTemplate?.subject) {
|
||||
} else if (
|
||||
tenantMailTemplate?.body &&
|
||||
tenantMailTemplate?.subject
|
||||
) {
|
||||
data = {
|
||||
RequestBody: tenantMailTemplate?.body,
|
||||
RequestSubject: tenantMailTemplate?.subject,
|
||||
@@ -1531,7 +1577,8 @@ function PlaceHolderSign() {
|
||||
status: defaultdata?.status || "required",
|
||||
hint: defaultdata?.hint || "",
|
||||
defaultValue: defaultdata?.defaultValue || "",
|
||||
validation: {},
|
||||
validation:
|
||||
{},
|
||||
fontSize:
|
||||
fontSize || currWidgetsDetails?.options?.fontSize || 12,
|
||||
fontColor:
|
||||
@@ -1541,15 +1588,6 @@ function PlaceHolderSign() {
|
||||
isReadOnly: defaultdata?.isReadOnly || false
|
||||
}
|
||||
};
|
||||
} else if (["signature"].includes(position.type)) {
|
||||
return {
|
||||
...position,
|
||||
options: {
|
||||
...position.options,
|
||||
name: defaultdata.name,
|
||||
hint: defaultdata?.hint || ""
|
||||
}
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
...position,
|
||||
@@ -1558,7 +1596,6 @@ function PlaceHolderSign() {
|
||||
name: defaultdata.name,
|
||||
status: defaultdata.status,
|
||||
defaultValue: defaultdata.defaultValue,
|
||||
hint: defaultdata?.hint || "",
|
||||
fontSize:
|
||||
fontSize || currWidgetsDetails?.options?.fontSize || 12,
|
||||
fontColor:
|
||||
@@ -2006,26 +2043,30 @@ function PlaceHolderSign() {
|
||||
{!isCustomize && (
|
||||
<span>{t("placeholder-alert-3")}</span>
|
||||
)}
|
||||
{isCustomize && (
|
||||
<>
|
||||
<EmailBody
|
||||
editorRef={editorRef}
|
||||
requestBody={requestBody}
|
||||
requestSubject={requestSubject}
|
||||
handleOnchangeRequest={handleOnchangeRequest}
|
||||
setRequestSubject={setRequestSubject}
|
||||
/>
|
||||
<div
|
||||
className="flex justify-end items-center gap-1 mt-2 op-link op-link-primary"
|
||||
onClick={() => {
|
||||
setRequestBody(defaultBody);
|
||||
setRequestSubject(defaultSubject);
|
||||
}}
|
||||
>
|
||||
<span>{t("reset-to-default")}</span>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
{
|
||||
isCustomize && (
|
||||
<>
|
||||
<EmailBody
|
||||
editorRef={editorRef}
|
||||
requestBody={requestBody}
|
||||
requestSubject={requestSubject}
|
||||
handleOnchangeRequest={
|
||||
handleOnchangeRequest
|
||||
}
|
||||
setRequestSubject={setRequestSubject}
|
||||
/>
|
||||
<div
|
||||
className="flex justify-end items-center gap-1 mt-2 op-link op-link-primary"
|
||||
onClick={() => {
|
||||
setRequestBody(defaultBody);
|
||||
setRequestSubject(defaultSubject);
|
||||
}}
|
||||
>
|
||||
<span>{t("reset-to-default")}</span>
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
<div className="flex flex-row items-center gap-2 md:gap-6 mt-2">
|
||||
<div className="flex flex-row gap-2">
|
||||
<button
|
||||
@@ -2043,14 +2084,16 @@ function PlaceHolderSign() {
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
{!isCustomize && (
|
||||
<span
|
||||
className="op-link op-link-accent text-sm"
|
||||
onClick={() => setIsCustomize(!isCustomize)}
|
||||
>
|
||||
{t("cutomize-email")}
|
||||
</span>
|
||||
)}
|
||||
{
|
||||
!isCustomize && (
|
||||
<span
|
||||
className="op-link op-link-accent text-sm"
|
||||
onClick={() => setIsCustomize(!isCustomize)}
|
||||
>
|
||||
{t("cutomize-email")}
|
||||
</span>
|
||||
)
|
||||
}
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
@@ -2062,11 +2105,6 @@ function PlaceHolderSign() {
|
||||
<span className="h-[1px] w-[20%] bg-[#ccc]"></span>
|
||||
</div>
|
||||
<div className="my-3">{handleShareList()}</div>
|
||||
<p
|
||||
id="copyUrl"
|
||||
ref={copyUrlRef}
|
||||
className="hidden"
|
||||
></p>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
@@ -2108,11 +2146,7 @@ function PlaceHolderSign() {
|
||||
</div>
|
||||
) : (
|
||||
<div className="mb-[10px]">
|
||||
{mailStatus === "dailyquotareached" ? (
|
||||
<p>{t("daily-quota-reached")}</p>
|
||||
) : (
|
||||
<p>{t("placeholder-alert-6")}</p>
|
||||
)}
|
||||
<p>{t("placeholder-alert-6")}</p>
|
||||
{isCurrUser && (
|
||||
<p className="mt-1">{t("placeholder-alert-5")}</p>
|
||||
)}
|
||||
|
||||
@@ -22,7 +22,6 @@ import EditorToolbar, {
|
||||
} from "../components/pdf/EditorToolbar";
|
||||
|
||||
const Preferences = () => {
|
||||
const appName = "OpenSign™";
|
||||
const { t } = useTranslation();
|
||||
const editorRef = useRef();
|
||||
const editorRefCom = useRef();
|
||||
@@ -45,8 +44,6 @@ const Preferences = () => {
|
||||
const [activeTab, setactiveTab] = useState(0);
|
||||
const generaltab = { title: t("general"), icon: "fa-light fa-gears" };
|
||||
const [tab, setTab] = useState([generaltab]);
|
||||
const [sendinOrder, setSendinOrder] = useState(true);
|
||||
const [isTourEnabled, setIsTourEnabled] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
fetchSignType();
|
||||
@@ -91,14 +88,6 @@ const Preferences = () => {
|
||||
const SignatureType = _getUser?.SignatureType || signatureTypes;
|
||||
setSignatureType(SignatureType);
|
||||
}
|
||||
const sendinorder =
|
||||
_getUser?.SendinOrder !== undefined ? _getUser?.SendinOrder : true;
|
||||
setSendinOrder(sendinorder);
|
||||
const istourenabled =
|
||||
_getUser?.IsTourEnabled !== undefined
|
||||
? _getUser?.IsTourEnabled
|
||||
: true;
|
||||
setIsTourEnabled(istourenabled);
|
||||
}
|
||||
} catch (err) {
|
||||
console.log("err while getting user details", err);
|
||||
@@ -151,11 +140,6 @@ const Preferences = () => {
|
||||
params = { ...params, NotifyOnSignatures: isNotifyOnSignatures };
|
||||
}
|
||||
try {
|
||||
params = {
|
||||
...params,
|
||||
SendinOrder: sendinOrder,
|
||||
IsTourEnabled: isTourEnabled
|
||||
};
|
||||
const updateRes = await Parse.Cloud.run("updatepreferences", params);
|
||||
if (updateRes) {
|
||||
setIsAlert({ type: "success", msg: "Saved successfully." });
|
||||
@@ -164,8 +148,6 @@ const Preferences = () => {
|
||||
JSON.parse(localStorage.getItem("Extand_Class"))?.[0];
|
||||
if (extUser && extUser?.objectId) {
|
||||
extUser.NotifyOnSignatures = isNotifyOnSignatures;
|
||||
extUser.SendinOrder = sendinOrder;
|
||||
extUser.IsTourEnabled = isTourEnabled;
|
||||
const _extUser = JSON.parse(JSON.stringify(extUser));
|
||||
localStorage.setItem("Extand_Class", JSON.stringify([_extUser]));
|
||||
}
|
||||
@@ -191,7 +173,7 @@ const Preferences = () => {
|
||||
setIsLoader(true);
|
||||
const updateRes = tenantRes;
|
||||
setTenantId(updateRes?.objectId);
|
||||
const defaultRequestBody = `<p>Hi {{receiver_name}},</p><br><p>We hope this email finds you well. {{sender_name}} has requested you to review and sign {{document_title}}.</p><p>Your signature is crucial to proceed with the next steps as it signifies your agreement and authorization.</p><br><p>{{signing_url}}</p><br><p>If you have any questions or need further clarification regarding the document or the signing process, please contact the sender.</p><br><p>Thanks</p><p> Team ${appName}</p><br>`;
|
||||
const defaultRequestBody = `<p>Hi {{receiver_name}},</p><br><p>We hope this email finds you well. {{sender_name}} has requested you to review and sign {{document_title}}.</p><p>Your signature is crucial to proceed with the next steps as it signifies your agreement and authorization.</p><br><p>{{signing_url}}</p><br><p>If you have any questions or need further clarification regarding the document or the signing process, please contact the sender.</p><br><p>Thanks</p><p> Team OpenSign™</p><br>`;
|
||||
if (updateRes?.RequestBody) {
|
||||
setRequestBody(updateRes?.RequestBody);
|
||||
setRequestSubject(updateRes?.RequestSubject);
|
||||
@@ -205,7 +187,7 @@ const Preferences = () => {
|
||||
body: defaultRequestBody,
|
||||
subject: `{{sender_name}} has requested you to sign {{document_title}}`
|
||||
});
|
||||
const defaultCompletionBody = `<p>Hi {{sender_name}},</p><br><p>All parties have successfully signed the document {{document_title}}. Kindly download the document from the attachment.</p><br><p>Thanks</p><p> Team ${appName}</p><br>`;
|
||||
const defaultCompletionBody = `<p>Hi {{sender_name}},</p><br><p>All parties have successfully signed the document {{document_title}}. Kindly download the document from the attachment.</p><br><p>Thanks</p><p> Team OpenSign™</p><br>`;
|
||||
if (updateRes?.CompletionBody) {
|
||||
SetCompletionBody(updateRes?.CompletionBody);
|
||||
setCompletionSubject(updateRes?.CompletionSubject);
|
||||
@@ -301,9 +283,6 @@ const Preferences = () => {
|
||||
}
|
||||
};
|
||||
|
||||
const handleTourInput = () => setIsTourEnabled(!isTourEnabled);
|
||||
const handleSendinOrderInput = () => setSendinOrder(!sendinOrder);
|
||||
|
||||
return (
|
||||
<React.Fragment>
|
||||
<Title title={t("Preferences")} />
|
||||
@@ -321,14 +300,14 @@ const Preferences = () => {
|
||||
) : (
|
||||
<div className="relative bg-base-100 text-base-content flex flex-col justify-center shadow-md rounded-box mb-3">
|
||||
{isLoader && (
|
||||
<div className="flex z-[100] justify-center items-center absolute w-full h-full rounded-box bg-black/30">
|
||||
<div className="flex justify-center items-center absolute w-full h-full rounded-box bg-black/30">
|
||||
<Loader />
|
||||
</div>
|
||||
)}
|
||||
<h1 className="ml-4 mt-3 mb-2 font-semibold">
|
||||
{appName} {t("Preferences")}{" "}
|
||||
OpenSign™ {t("Preferences")}{" "}
|
||||
<span>
|
||||
<Tooltip message={`${appName} ${t("Preferences")}`} />
|
||||
<Tooltip message={`OpenSign™ ${t("Preferences")}`} />
|
||||
</span>
|
||||
</h1>
|
||||
<div className="flex justify-center items-center mt-2">
|
||||
@@ -341,9 +320,7 @@ const Preferences = () => {
|
||||
onClick={() => setactiveTab(ind)}
|
||||
key={ind}
|
||||
role="tab"
|
||||
className={`${
|
||||
activeTab === ind ? "op-tab-active" : ""
|
||||
} op-tab text-xs md:text-base pb-2 md:pb-0 }`}
|
||||
className={`${activeTab === ind ? "op-tab-active" : ""} op-tab text-xs md:text-base pb-2 md:pb-0 }`}
|
||||
>
|
||||
<i className={tabData.icon}></i>
|
||||
<span className="ml-1 md:ml-2">{tabData.title}</span>
|
||||
@@ -353,272 +330,154 @@ const Preferences = () => {
|
||||
</div>
|
||||
<div className="flex justify-center md:justify-start mt-3 md:mt-4 break-all">
|
||||
{activeTab === 0 ? (
|
||||
<div className="ml-4 mt-1 mb-2 flex flex-col">
|
||||
<div className="mb-[0.75rem]">
|
||||
<label
|
||||
className="mb-[0.7rem] text-[12px]"
|
||||
htmlFor="signaturetype"
|
||||
>
|
||||
<span className="font-medium text-[14px]">
|
||||
{t("allowed-signature-types")}
|
||||
</span>
|
||||
<a data-tooltip-id="signtypes-tooltip" className="ml-1">
|
||||
<sup>
|
||||
<i className="fa-light fa-question rounded-full border-[#33bbff] text-[#33bbff] text-[13px] border-[1px] py-[1.5px] px-[4px]"></i>
|
||||
</sup>
|
||||
</a>
|
||||
<ReactTooltip
|
||||
id="signtypes-tooltip"
|
||||
className="z-[999]"
|
||||
<>
|
||||
<div className="ml-4 mt-1 mb-2 flex flex-col">
|
||||
<div className="mb-[0.75rem]">
|
||||
<label
|
||||
htmlFor="signaturetype"
|
||||
className="text-[14px] mb-[0.7rem] font-medium"
|
||||
>
|
||||
<div className="max-w-[200px] md:max-w-[450px]">
|
||||
<p className="font-bold">
|
||||
{t("allowed-signature-types")}
|
||||
</p>
|
||||
<p>{t("allowed-signature-types-help.p1")}</p>
|
||||
<p className="p-[5px] ml-2">
|
||||
<ol className="list-disc">
|
||||
<li>
|
||||
<span className="font-bold">Draw: </span>
|
||||
<span>
|
||||
{t("allowed-signature-types-help.l1")}
|
||||
</span>
|
||||
</li>
|
||||
<li>
|
||||
<span className="font-bold">Type: </span>
|
||||
<span>
|
||||
{t("allowed-signature-types-help.l2")}
|
||||
</span>
|
||||
</li>
|
||||
<li>
|
||||
<span className="font-bold">Upload: </span>
|
||||
<span>
|
||||
{t("allowed-signature-types-help.l3")}
|
||||
</span>
|
||||
</li>
|
||||
<li>
|
||||
<span className="font-bold">Default: </span>
|
||||
<span>
|
||||
{t("allowed-signature-types-help.l4")}
|
||||
</span>
|
||||
</li>
|
||||
</ol>
|
||||
</p>
|
||||
</div>
|
||||
</ReactTooltip>
|
||||
</label>
|
||||
<div className="ml-[7px] flex flex-col md:flex-row gap-[10px] mb-[0.7rem]">
|
||||
{signatureType.map((type, i) => (
|
||||
{t("allowed-signature-types")}
|
||||
<a
|
||||
data-tooltip-id="signtypes-tooltip"
|
||||
className="ml-1"
|
||||
>
|
||||
<sup>
|
||||
<i className="fa-light fa-question rounded-full border-[#33bbff] text-[#33bbff] text-[13px] border-[1px] py-[1.5px] px-[4px]"></i>
|
||||
</sup>
|
||||
</a>
|
||||
<ReactTooltip
|
||||
id="signtypes-tooltip"
|
||||
className="z-[999]"
|
||||
>
|
||||
<div className="max-w-[200px] md:max-w-[450px] text-[11px]">
|
||||
<p className="font-bold">
|
||||
{t("allowed-signature-types")}
|
||||
</p>
|
||||
<p>{t("allowed-signature-types-help.p1")}</p>
|
||||
<p className="p-[5px] ml-2">
|
||||
<ol className="list-disc">
|
||||
<li>
|
||||
<span className="font-bold">Draw: </span>
|
||||
<span>
|
||||
{t("allowed-signature-types-help.l1")}
|
||||
</span>
|
||||
</li>
|
||||
<li>
|
||||
<span className="font-bold">Type: </span>
|
||||
<span>
|
||||
{t("allowed-signature-types-help.l2")}
|
||||
</span>
|
||||
</li>
|
||||
<li>
|
||||
<span className="font-bold">Upload: </span>
|
||||
<span>
|
||||
{t("allowed-signature-types-help.l3")}
|
||||
</span>
|
||||
</li>
|
||||
<li>
|
||||
<span className="font-bold">Default: </span>
|
||||
<span>
|
||||
{t("allowed-signature-types-help.l4")}
|
||||
</span>
|
||||
</li>
|
||||
</ol>
|
||||
</p>
|
||||
</div>
|
||||
</ReactTooltip>
|
||||
</label>
|
||||
<div className=" ml-[7px] flex flex-col md:flex-row gap-[10px] mb-[0.7rem]">
|
||||
{signatureType.map((type, i) => (
|
||||
<div
|
||||
key={i}
|
||||
className="flex flex-row gap-[5px] items-center"
|
||||
>
|
||||
<input
|
||||
className="mr-[2px] op-checkbox op-checkbox-xs"
|
||||
type="checkbox"
|
||||
name="signaturetype"
|
||||
onChange={() => handleCheckboxChange(i)}
|
||||
checked={type.enabled}
|
||||
/>
|
||||
<div
|
||||
className="text-[13px] font-medium hover:underline underline-offset-2 cursor-default capitalize"
|
||||
title={`Enabling this allow signers to ${type.name} signature`}
|
||||
>
|
||||
{type?.name === "typed" ? "type" : type?.name}
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
<div className="mb-[0.75rem]">
|
||||
<label className="text-[14px] mb-[0.7rem] font-medium">
|
||||
{t("notify-on-signatures")}
|
||||
<a data-tooltip-id="nos-tooltip" className="ml-1">
|
||||
<sup>
|
||||
<i className="fa-light fa-question rounded-full border-[#33bbff] text-[#33bbff] text-[13px] border-[1px] py-[1.5px] px-[4px]"></i>
|
||||
</sup>
|
||||
</a>
|
||||
<ReactTooltip id="nos-tooltip" className="z-[999]">
|
||||
<div className="max-w-[200px] md:max-w-[450px] text-[11px]">
|
||||
<p className="font-bold">
|
||||
{t("notify-on-signatures")}
|
||||
</p>
|
||||
<p>{t("notify-on-signatures-help.p1")}</p>
|
||||
<p>{t("notify-on-signatures-help.note")}</p>
|
||||
</div>
|
||||
</ReactTooltip>
|
||||
</label>
|
||||
<div className="flex flex-col md:flex-row md:gap-4">
|
||||
<div
|
||||
key={i}
|
||||
className="flex flex-row gap-[5px] items-center"
|
||||
className={
|
||||
"flex items-center gap-2 ml-2 mb-1"
|
||||
}
|
||||
>
|
||||
<input
|
||||
className="mr-[2px] op-checkbox op-checkbox-xs"
|
||||
type="checkbox"
|
||||
name="signaturetype"
|
||||
onChange={() => handleCheckboxChange(i)}
|
||||
checked={type.enabled}
|
||||
className="mr-[2px] op-radio op-radio-xs"
|
||||
type="radio"
|
||||
onChange={() => handleNotifySignChange(true)}
|
||||
checked={isNotifyOnSignatures === true}
|
||||
/>
|
||||
<div
|
||||
className="text-[13px] font-medium hover:underline underline-offset-2 cursor-default capitalize"
|
||||
title={`Enabling this allow signers to ${type.name} signature`}
|
||||
>
|
||||
{type?.name === "typed" ? "type" : type?.name}
|
||||
<div className="text-[13px] font-medium cursor-default capitalize">
|
||||
{t("yes")}
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
<div className="mb-[0.75rem]">
|
||||
<label className="mb-[0.7rem] text-[12px]">
|
||||
<span className="text-[14px] font-medium">
|
||||
{t("notify-on-signatures")}
|
||||
</span>
|
||||
<a data-tooltip-id="nos-tooltip" className="ml-1">
|
||||
<sup>
|
||||
<i className="fa-light fa-question rounded-full border-[#33bbff] text-[#33bbff] text-[13px] border-[1px] py-[1.5px] px-[4px]"></i>
|
||||
</sup>
|
||||
</a>
|
||||
<ReactTooltip id="nos-tooltip" className="z-[999]">
|
||||
<div className="max-w-[200px] md:max-w-[450px]">
|
||||
<p className="font-bold">
|
||||
{t("notify-on-signatures")}
|
||||
</p>
|
||||
<p>{t("notify-on-signatures-help.p1")}</p>
|
||||
<p>{t("notify-on-signatures-help.note")}</p>
|
||||
</div>
|
||||
</ReactTooltip>
|
||||
</label>
|
||||
<div className="flex flex-col md:flex-row md:gap-4">
|
||||
<div className={"flex items-center gap-2 ml-2 mb-1"}>
|
||||
<input
|
||||
className="mr-[2px] op-radio op-radio-xs"
|
||||
type="radio"
|
||||
onChange={() => handleNotifySignChange(true)}
|
||||
checked={isNotifyOnSignatures === true}
|
||||
/>
|
||||
<div className="text-[13px] cursor-default capitalize">
|
||||
{t("yes")}
|
||||
</div>
|
||||
</div>
|
||||
<div className={"flex items-center gap-2 ml-2 mb-1"}>
|
||||
<input
|
||||
className="mr-[2px] op-radio op-radio-xs"
|
||||
type="radio"
|
||||
onChange={() => handleNotifySignChange(false)}
|
||||
checked={isNotifyOnSignatures === false}
|
||||
/>
|
||||
<div className="text-[13px] cursor-default capitalize">
|
||||
{t("no")}
|
||||
<div className="flex flex-col md:flex-row md:gap-4">
|
||||
<div
|
||||
className={
|
||||
"flex items-center gap-2 ml-2 mb-1"
|
||||
}
|
||||
>
|
||||
<input
|
||||
className="mr-[2px] op-radio op-radio-xs"
|
||||
type="radio"
|
||||
onChange={() => handleNotifySignChange(false)}
|
||||
checked={isNotifyOnSignatures === false}
|
||||
/>
|
||||
<div className="text-[13px] font-medium cursor-default capitalize">
|
||||
{t("no")}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="mb-[0.75rem]">
|
||||
<TimezoneSelector
|
||||
timezone={timezone}
|
||||
setTimezone={setTimezone}
|
||||
/>
|
||||
</div>
|
||||
<div className="mb-[0.75rem] text-[12px]">
|
||||
<label className="block mb-[0.7rem]">
|
||||
<span className="text-[14px] font-medium">
|
||||
{t("send-in-order")}
|
||||
</span>
|
||||
<a
|
||||
data-tooltip-id="sendInOrder-tooltip"
|
||||
className="ml-1"
|
||||
<div className="mb-[0.75rem]">
|
||||
<TimezoneSelector
|
||||
timezone={timezone}
|
||||
setTimezone={setTimezone}
|
||||
/>
|
||||
</div>
|
||||
<div className="mb-[0.75rem]">
|
||||
<button
|
||||
className="op-btn op-btn-primary"
|
||||
onClick={handleSave}
|
||||
>
|
||||
<sup>
|
||||
<i className="fa-light fa-question rounded-full border-[#33bbff] text-[#33bbff] text-[13px] border-[1px] py-[1.5px] px-[4px]"></i>
|
||||
</sup>
|
||||
</a>
|
||||
<ReactTooltip
|
||||
id="sendInOrder-tooltip"
|
||||
className="z-[999]"
|
||||
>
|
||||
<div className="max-w-[200px] md:max-w-[450px]">
|
||||
<p className="font-bold">{t("send-in-order")}</p>
|
||||
<p>{t("send-in-order-help.p1")}</p>
|
||||
<p className="p-[5px]">
|
||||
<ol className="list-disc">
|
||||
<li>
|
||||
<span className="font-bold">
|
||||
{t("yes")}:{" "}
|
||||
</span>
|
||||
<span>{t("send-in-order-help.p2")}</span>
|
||||
</li>
|
||||
<li>
|
||||
<span className="font-bold">{t("no")}: </span>
|
||||
<span>{t("send-in-order-help.p3")}</span>
|
||||
</li>
|
||||
</ol>
|
||||
</p>
|
||||
<p>{t("send-in-order-help.p4")}</p>
|
||||
</div>
|
||||
</ReactTooltip>
|
||||
</label>
|
||||
<div className="flex flex-col md:flex-row md:gap-4">
|
||||
<div className="flex items-center gap-2 ml-2 mb-1">
|
||||
<input
|
||||
type="radio"
|
||||
value={true}
|
||||
className="op-radio op-radio-xs"
|
||||
name="SendinOrder"
|
||||
checked={sendinOrder}
|
||||
onChange={handleSendinOrderInput}
|
||||
/>
|
||||
<div className="text-center">{t("yes")}</div>
|
||||
</div>
|
||||
<div className="flex items-center gap-2 ml-2 mb-1">
|
||||
<input
|
||||
type="radio"
|
||||
value={false}
|
||||
name="SendinOrder"
|
||||
className="op-radio op-radio-xs"
|
||||
checked={!sendinOrder}
|
||||
onChange={handleSendinOrderInput}
|
||||
/>
|
||||
<div className="text-center">{t("no")}</div>
|
||||
</div>
|
||||
{t("save")}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div className="mb-[0.75rem] text-[12px]">
|
||||
<label className="block mb-[0.7rem]">
|
||||
<span className="text-[14px] font-medium">
|
||||
{t("enable-tour")}
|
||||
</span>
|
||||
<a
|
||||
data-tooltip-id="istourenabled-tooltip"
|
||||
className="ml-1"
|
||||
>
|
||||
<sup>
|
||||
<i className="fa-light fa-question rounded-full border-[#33bbff] text-[#33bbff] text-[13px] border-[1px] py-[1.5px] px-[4px]"></i>
|
||||
</sup>
|
||||
</a>
|
||||
<ReactTooltip
|
||||
id="istourenabled-tooltip"
|
||||
className="z-[999]"
|
||||
>
|
||||
<div className="max-w-[200px] md:max-w-[450px]">
|
||||
<p className="font-bold">{t("enable-tour")}</p>
|
||||
<p className="p-[5px]">
|
||||
<ol className="list-disc">
|
||||
<li>
|
||||
<span className="font-bold">
|
||||
{t("yes")}:{" "}
|
||||
</span>
|
||||
<span>{t("istourenabled-help.p1")}</span>
|
||||
</li>
|
||||
<li>
|
||||
<span className="font-bold">{t("no")}: </span>
|
||||
<span>{t("istourenabled-help.p2")}</span>
|
||||
</li>
|
||||
</ol>
|
||||
</p>
|
||||
<p>
|
||||
{t("istourenabled-help.p3", {
|
||||
appName: appName
|
||||
})}
|
||||
</p>
|
||||
</div>
|
||||
</ReactTooltip>
|
||||
</label>
|
||||
<div className="flex flex-col md:flex-row md:gap-4">
|
||||
<div className="flex items-center gap-2 ml-2 mb-1">
|
||||
<input
|
||||
type="radio"
|
||||
value={true}
|
||||
className="op-radio op-radio-xs"
|
||||
name="IsTourEnabled"
|
||||
checked={isTourEnabled}
|
||||
onChange={handleTourInput}
|
||||
/>
|
||||
<div className="text-center">{t("yes")}</div>
|
||||
</div>
|
||||
<div className="flex items-center gap-2 ml-2 mb-1">
|
||||
<input
|
||||
type="radio"
|
||||
value={false}
|
||||
name="IsTourEnabled"
|
||||
className="op-radio op-radio-xs"
|
||||
checked={!isTourEnabled}
|
||||
onChange={handleTourInput}
|
||||
/>
|
||||
<div className="text-center">{t("no")}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="mb-[0.75rem]">
|
||||
<button
|
||||
className="op-btn op-btn-primary w-[110px]"
|
||||
onClick={handleSave}
|
||||
>
|
||||
{t("save")}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
) : (
|
||||
<div className="flex flex-col mx-4 mb-4">
|
||||
<div className="flex flex-col">
|
||||
@@ -635,9 +494,7 @@ const Preferences = () => {
|
||||
{t("subject")}
|
||||
<Tooltip
|
||||
id={"request-sub-tooltip"}
|
||||
message={`${t(
|
||||
"variables-use"
|
||||
)}: {{sender_name}} {{document_title}}`}
|
||||
message={`${t("variables-use")}: {{sender_name}} {{document_title}}`}
|
||||
/>
|
||||
</label>
|
||||
<input
|
||||
@@ -646,9 +503,7 @@ const Preferences = () => {
|
||||
onChange={(e) =>
|
||||
setRequestSubject(e.target.value)
|
||||
}
|
||||
placeholder={`{{sender_name}} ${t(
|
||||
"send-to-sign"
|
||||
)} {{document_title}}`}
|
||||
placeholder={`{{sender_name}} ${t("send-to-sign")} {{document_title}}`}
|
||||
className="w-full op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content text-xs"
|
||||
/>
|
||||
</div>
|
||||
@@ -657,9 +512,7 @@ const Preferences = () => {
|
||||
{t("body")}
|
||||
<Tooltip
|
||||
id={"request-body-tooltip"}
|
||||
message={`${t(
|
||||
"variables-use"
|
||||
)}: {{sender_name}} {{document_title}}`}
|
||||
message={`${t("variables-use")}: {{sender_name}} {{document_title}}`}
|
||||
/>
|
||||
</label>
|
||||
<EditorToolbar containerId="toolbar1" />
|
||||
@@ -705,9 +558,7 @@ const Preferences = () => {
|
||||
{t("subject")}
|
||||
<Tooltip
|
||||
id={"complete-sub-tooltip"}
|
||||
message={`${t(
|
||||
"variables-use"
|
||||
)}:{{sender_name}} {{document_title}}`}
|
||||
message={`${t("variables-use")}:{{sender_name}} {{document_title}}`}
|
||||
/>
|
||||
</label>
|
||||
<input
|
||||
@@ -716,9 +567,7 @@ const Preferences = () => {
|
||||
onChange={(e) =>
|
||||
setCompletionSubject(e.target.value)
|
||||
}
|
||||
placeholder={`{{sender_name}} ${t(
|
||||
"send-to-sign"
|
||||
)} {{document_title}}`}
|
||||
placeholder={`{{sender_name}} ${t("send-to-sign")} {{document_title}}`}
|
||||
className="w-full op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content text-xs"
|
||||
/>
|
||||
</div>
|
||||
@@ -727,9 +576,7 @@ const Preferences = () => {
|
||||
{t("body")}
|
||||
<Tooltip
|
||||
id={"complete-body-tooltip"}
|
||||
message={`${t(
|
||||
"variables-use"
|
||||
)}:{{sender_name}} {{document_title}} {{signing_url}}`}
|
||||
message={`${t("variables-use")}:{{sender_name}} {{document_title}} {{signing_url}}`}
|
||||
/>
|
||||
</label>
|
||||
<EditorToolbar containerId="toolbar2" />
|
||||
|
||||
@@ -66,7 +66,6 @@ import LoaderWithMsg from "../primitives/LoaderWithMsg";
|
||||
function SignYourSelf() {
|
||||
const { t } = useTranslation();
|
||||
const { docId } = useParams();
|
||||
const appName = "OpenSign™";
|
||||
const divRef = useRef(null);
|
||||
const nodeRef = useRef(null);
|
||||
const imageRef = useRef(null);
|
||||
@@ -123,6 +122,7 @@ function SignYourSelf() {
|
||||
const [pdfLoad, setPdfLoad] = useState(false);
|
||||
const [isAlert, setIsAlert] = useState({ isShow: false, alertMessage: "" });
|
||||
const [isDontShow, setIsDontShow] = useState(false);
|
||||
const [extUserId, setExtUserId] = useState("");
|
||||
const [isCompleted, setIsCompleted] = useState(false);
|
||||
const [isCelebration, setIsCelebration] = useState(false);
|
||||
const [pdfArrayBuffer, setPdfArrayBuffer] = useState("");
|
||||
@@ -205,6 +205,7 @@ function SignYourSelf() {
|
||||
|
||||
if (documentData && documentData.length > 0) {
|
||||
setPdfDetails(documentData);
|
||||
setExtUserId(documentData[0]?.ExtUserPtr?.objectId);
|
||||
const placeholders =
|
||||
documentData[0]?.Placeholders?.length > 0
|
||||
? documentData[0]?.Placeholders
|
||||
@@ -561,7 +562,11 @@ function SignYourSelf() {
|
||||
let pdfUrl;
|
||||
if (isUploadPdf) {
|
||||
const pdfName = generatePdfName(16);
|
||||
pdfUrl = await convertBase64ToFile(pdfName, pdfBase64Url, "");
|
||||
pdfUrl = await convertBase64ToFile(
|
||||
pdfName,
|
||||
pdfBase64Url,
|
||||
"",
|
||||
);
|
||||
}
|
||||
const widgetsType = ["signature", "stamp", "image", "initials"];
|
||||
let updatedXYPosition;
|
||||
@@ -700,7 +705,7 @@ function SignYourSelf() {
|
||||
setIsAlert({
|
||||
header: t("error"),
|
||||
isShow: true,
|
||||
alertMessage: t("pdf-uncompatible", { appName: appName })
|
||||
alertMessage: t("pdf-uncompatible")
|
||||
});
|
||||
}
|
||||
} catch (err) {
|
||||
@@ -747,7 +752,10 @@ function SignYourSelf() {
|
||||
if (tenantDetails && tenantDetails === "user does not exist!") {
|
||||
alert(t("user-not-exist"));
|
||||
} else {
|
||||
if (tenantDetails?.CompletionBody && tenantDetails?.CompletionSubject) {
|
||||
if (
|
||||
tenantDetails?.CompletionBody &&
|
||||
tenantDetails?.CompletionSubject
|
||||
) {
|
||||
isCustomCompletionMail = true;
|
||||
}
|
||||
}
|
||||
@@ -783,7 +791,7 @@ function SignYourSelf() {
|
||||
pdfFile: base64Url,
|
||||
docId: documentId,
|
||||
isCustomCompletionMail: isCustomCompletionMail,
|
||||
signature: suffixbase64
|
||||
signature: suffixbase64,
|
||||
};
|
||||
const resSignPdf = await Parse.Cloud.run("signPdf", params);
|
||||
if (resSignPdf) {
|
||||
@@ -1189,7 +1197,7 @@ function SignYourSelf() {
|
||||
};
|
||||
return (
|
||||
<DndProvider backend={HTML5Backend}>
|
||||
<Title title={"Signyourself"} />
|
||||
<Title title={"signyourself"} />
|
||||
{isLoading.isLoad ? (
|
||||
<LoaderWithMsg isLoading={isLoading} />
|
||||
) : handleError ? (
|
||||
@@ -1361,10 +1369,13 @@ function SignYourSelf() {
|
||||
{/*render email component to send email after finish signature on document */}
|
||||
<EmailComponent
|
||||
isEmail={isEmail}
|
||||
pdfUrl={pdfUrl}
|
||||
setIsEmail={setIsEmail}
|
||||
setSuccessEmail={setSuccessEmail}
|
||||
pdfDetails={pdfDetails}
|
||||
setSuccessEmail={setSuccessEmail}
|
||||
sender={jsonSender}
|
||||
setIsAlert={setIsAlert}
|
||||
extUserId={extUserId}
|
||||
setIsDownloadModal={setIsDownloadModal}
|
||||
/>
|
||||
{/* pdf header which contain funish back button */}
|
||||
|
||||
@@ -165,6 +165,7 @@ const TemplatePlaceholder = () => {
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [divRef.current, isHeader]);
|
||||
|
||||
|
||||
//function to fetch tenant Details
|
||||
const fetchTenantDetails = async () => {
|
||||
const user = JSON.parse(
|
||||
@@ -777,7 +778,11 @@ const TemplatePlaceholder = () => {
|
||||
let pdfUrl;
|
||||
if (isUploadPdf) {
|
||||
const pdfName = generatePdfName(16);
|
||||
pdfUrl = await convertBase64ToFile(pdfName, pdfBase64Url, "");
|
||||
pdfUrl = await convertBase64ToFile(
|
||||
pdfName,
|
||||
pdfBase64Url,
|
||||
"",
|
||||
);
|
||||
}
|
||||
if (signersdata?.length > 0) {
|
||||
signersdata.forEach((x) => {
|
||||
@@ -844,7 +849,11 @@ const TemplatePlaceholder = () => {
|
||||
scale
|
||||
);
|
||||
const pdfName = generatePdfName(16);
|
||||
const pdfUrl = await convertBase64ToFile(pdfName, pdfBase64, "");
|
||||
const pdfUrl = await convertBase64ToFile(
|
||||
pdfName,
|
||||
pdfBase64,
|
||||
"",
|
||||
);
|
||||
const tenantId = localStorage.getItem("TenantId");
|
||||
const buffer = atob(pdfBase64);
|
||||
SaveFileSize(buffer.length, pdfUrl, tenantId);
|
||||
@@ -856,7 +865,11 @@ const TemplatePlaceholder = () => {
|
||||
} else if (pdfBase64Url) {
|
||||
try {
|
||||
const pdfName = generatePdfName(16);
|
||||
const pdfUrl = await convertBase64ToFile(pdfName, pdfBase64Url, "");
|
||||
const pdfUrl = await convertBase64ToFile(
|
||||
pdfName,
|
||||
pdfBase64Url,
|
||||
"",
|
||||
);
|
||||
return pdfUrl;
|
||||
} catch (err) {
|
||||
console.log("error to convertBase64ToFile in placeholder flow", err);
|
||||
@@ -868,14 +881,6 @@ const TemplatePlaceholder = () => {
|
||||
};
|
||||
const handleSaveTemplate = async () => {
|
||||
if (signersdata?.length) {
|
||||
const remindOnceInEvery = parseInt(pdfDetails[0]?.RemindOnceInEvery);
|
||||
const TimeToCompleteDays = parseInt(pdfDetails[0]?.TimeToCompleteDays);
|
||||
const AutomaticReminders = pdfDetails[0]?.AutomaticReminders;
|
||||
const reminderCount = TimeToCompleteDays / remindOnceInEvery;
|
||||
if (AutomaticReminders && reminderCount > 15) {
|
||||
alert(t("only-15-reminder-allowed"));
|
||||
return;
|
||||
}
|
||||
setIsLoading({ isLoad: true, message: t("loading-mssg") });
|
||||
setIsSendAlert(false);
|
||||
let signers = [],
|
||||
@@ -1081,7 +1086,7 @@ const TemplatePlaceholder = () => {
|
||||
});
|
||||
setIsCreateDoc(false);
|
||||
} else {
|
||||
setHandleError(t(res.id));
|
||||
setHandleError(t("something-went-wrong-mssg"));
|
||||
setIsCreateDoc(false);
|
||||
}
|
||||
};
|
||||
@@ -1456,7 +1461,8 @@ const TemplatePlaceholder = () => {
|
||||
status: defaultdata?.status || "required",
|
||||
hint: defaultdata?.hint || "",
|
||||
defaultValue: defaultdata?.defaultValue || "",
|
||||
validation: {},
|
||||
validation:
|
||||
{},
|
||||
fontSize:
|
||||
fontSize || currWidgetsDetails?.options?.fontSize || 12,
|
||||
fontColor:
|
||||
@@ -1465,15 +1471,6 @@ const TemplatePlaceholder = () => {
|
||||
"black"
|
||||
}
|
||||
};
|
||||
} else if (["signature"].includes(position.type)) {
|
||||
return {
|
||||
...position,
|
||||
options: {
|
||||
...position.options,
|
||||
name: defaultdata.name,
|
||||
hint: defaultdata?.hint || ""
|
||||
}
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
...position,
|
||||
@@ -1482,7 +1479,6 @@ const TemplatePlaceholder = () => {
|
||||
name: defaultdata.name,
|
||||
status: defaultdata.status,
|
||||
defaultValue: defaultdata.defaultValue,
|
||||
hint: defaultdata?.hint || "",
|
||||
fontSize:
|
||||
fontSize || currWidgetsDetails?.options?.fontSize || 12,
|
||||
fontColor:
|
||||
|
||||
@@ -7,8 +7,6 @@ import Title from "../components/Title";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { emailRegex } from "../constant/const";
|
||||
const UpdateExistUserAdmin = () => {
|
||||
const appName =
|
||||
"OpenSign™";
|
||||
const { t } = useTranslation();
|
||||
const navigate = useNavigate();
|
||||
const [formdata, setFormdata] = useState({ email: "", masterkey: "" });
|
||||
@@ -95,7 +93,7 @@ const UpdateExistUserAdmin = () => {
|
||||
</div>
|
||||
)}
|
||||
<h2 className="text-[30px] text-center mt-3 font-medium">
|
||||
{t("opensign-setup", { appName })}
|
||||
{t("opensign-Setup")}
|
||||
</h2>
|
||||
<NavLink
|
||||
to="https://discord.com/invite/xe9TDuyAyj"
|
||||
|
||||
+194
-185
@@ -10,6 +10,7 @@ import AddUser from "../components/AddUser";
|
||||
import Title from "../components/Title";
|
||||
import { useTranslation } from "react-i18next";
|
||||
const heading = ["Sr.No", "Name", "Email", "Phone", "Role", "Team", "Active"];
|
||||
// const actions = [];
|
||||
const UserList = () => {
|
||||
const { t } = useTranslation();
|
||||
const [userList, setUserList] = useState([]);
|
||||
@@ -113,8 +114,9 @@ const UserList = () => {
|
||||
setUserList(_userRes);
|
||||
} catch (err) {
|
||||
console.log("Err in fetch userlist", err);
|
||||
showAlert("danger", t("something-went-wrong-mssg"));
|
||||
setIsAlert({ type: "danger", msg: t("something-went-wrong-mssg") });
|
||||
} finally {
|
||||
setTimeout(() => setIsAlert({ type: "success", msg: "" }), 1500);
|
||||
setIsLoader(false);
|
||||
}
|
||||
}
|
||||
@@ -171,15 +173,17 @@ const UserList = () => {
|
||||
extUser.id = user.objectId;
|
||||
extUser.set("IsDisabled", !IsDisabled);
|
||||
await extUser.save();
|
||||
showAlert(
|
||||
!IsDisabled === true ? "danger" : "success",
|
||||
!IsDisabled === true ? t("user-deactivated") : t("user-activated")
|
||||
);
|
||||
setIsAlert({
|
||||
type: !IsDisabled === true ? "danger" : "success",
|
||||
msg:
|
||||
!IsDisabled === true ? t("user-deactivated") : t("user-activated")
|
||||
});
|
||||
} catch (err) {
|
||||
showAlert("danger", t("something-went-wrong-mssg"));
|
||||
setIsAlert({ type: "danger", msg: t("something-went-wrong-mssg") });
|
||||
console.log("err in disable team", err);
|
||||
} finally {
|
||||
setIsActLoader({});
|
||||
setTimeout(() => setIsAlert({ type: "success", msg: "" }), 1500);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -187,11 +191,6 @@ const UserList = () => {
|
||||
setIsActiveModal({ [user.objectId]: true });
|
||||
};
|
||||
|
||||
// `showAlert` handle show/hide alert
|
||||
const showAlert = (type, msg) => {
|
||||
setIsAlert({ type, msg });
|
||||
setTimeout(() => setIsAlert({ type: "success", msg: "" }), 1500);
|
||||
};
|
||||
return (
|
||||
<div className="relative">
|
||||
<Title title={isAdmin ? "Users" : "Page not found"} />
|
||||
@@ -206,187 +205,197 @@ const UserList = () => {
|
||||
</div>
|
||||
)}
|
||||
|
||||
{!isLoader && (
|
||||
<>
|
||||
{isAdmin ? (
|
||||
<div className="p-2 w-full bg-base-100 text-base-content op-card shadow-lg">
|
||||
{isAlert.msg && <Alert type={isAlert.type}>{isAlert.msg}</Alert>}
|
||||
<div className="flex flex-row items-center justify-between my-2 mx-3 text-[20px] md:text-[23px]">
|
||||
<div className="font-light">
|
||||
{t("report-name.Users")}{" "}
|
||||
<span className="text-xs md:text-[13px] font-normal">
|
||||
<Tooltip message={t("users-from-teams")} />
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex flex-row gap-2 items-center">
|
||||
<div
|
||||
className="cursor-pointer"
|
||||
onClick={() => handleModal("form")}
|
||||
>
|
||||
<i className="fa-light fa-square-plus text-accent text-[30px] md:text-[40px]"></i>
|
||||
{
|
||||
!isLoader && (
|
||||
<>
|
||||
{isAdmin ? (
|
||||
<div className="p-2 w-full bg-base-100 text-base-content op-card shadow-lg">
|
||||
{isAlert.msg && (
|
||||
<Alert type={isAlert.type}>{isAlert.msg}</Alert>
|
||||
)}
|
||||
<div className="flex flex-row items-center justify-between my-2 mx-3 text-[20px] md:text-[23px]">
|
||||
<div className="font-light">
|
||||
{t("report-name.Users")}{" "}
|
||||
<span className="text-xs md:text-[13px] font-normal">
|
||||
<Tooltip message={t("users-from-teams")} />
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex flex-row gap-2 items-center">
|
||||
<div
|
||||
className="cursor-pointer"
|
||||
onClick={() => handleModal("form")}
|
||||
>
|
||||
<i className="fa-light fa-square-plus text-accent text-[30px] md:text-[40px]"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="w-full overflow-x-auto">
|
||||
<table className="op-table border-collapse w-full mb-[50px]">
|
||||
<thead className="text-[14px]">
|
||||
<tr className="border-y-[1px]">
|
||||
{heading?.map((item, index) => (
|
||||
<th key={index} className="px-4 py-2">
|
||||
{t(`report-heading.${item}`)}
|
||||
</th>
|
||||
))}
|
||||
</tr>
|
||||
</thead>
|
||||
{userList?.length > 0 && (
|
||||
<tbody className="text-[12px]">
|
||||
{currentList.map((item, index) => (
|
||||
<tr className="border-y-[1px]" key={index}>
|
||||
{heading.includes("Sr.No") && (
|
||||
<th className="px-4 py-2">
|
||||
{startIndex + index + 1}
|
||||
<div className="overflow-x-auto w-full">
|
||||
<table className="op-table border-collapse w-full">
|
||||
<thead className="text-[14px]">
|
||||
<tr className="border-y-[1px]">
|
||||
{heading?.map((item, index) => (
|
||||
<th key={index} className="px-4 py-2">
|
||||
{t(`report-heading.${item}`)}
|
||||
</th>
|
||||
)}
|
||||
<td className="px-4 py-2 font-semibold">
|
||||
{item?.Name}{" "}
|
||||
</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?.UserRole?.split("_").pop() || "-"}
|
||||
</td>
|
||||
<td className="px-4 py-2">
|
||||
{formatRow(item.TeamIds)}
|
||||
</td>
|
||||
{item.UserRole !== "contracts_Admin" ? (
|
||||
<td className="px-4 py-2 font-semibold">
|
||||
<label className="cursor-pointer relative block items-center mb-0">
|
||||
<input
|
||||
type="checkbox"
|
||||
className="op-toggle transition-all op-toggle-secondary"
|
||||
checked={item?.IsDisabled !== true}
|
||||
onChange={() => handleToggleBtn(item)}
|
||||
/>
|
||||
</label>
|
||||
{isActiveModal[item.objectId] && (
|
||||
<ModalUi
|
||||
isOpen
|
||||
title={t("user-status")}
|
||||
handleClose={handleClose}
|
||||
>
|
||||
<div className="m-[20px]">
|
||||
<div className="text-lg font-normal text-black">
|
||||
{t("are-you-sure")}{" "}
|
||||
{item?.IsDisabled
|
||||
? t("activate")
|
||||
: t("deactivate")}{" "}
|
||||
{t("this-user")}?
|
||||
</div>
|
||||
<hr className="bg-[#ccc] mt-4 " />
|
||||
<div className="flex items-center mt-3 gap-2 text-white">
|
||||
<button
|
||||
onClick={() => handleToggleSubmit(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 className="px-4 py-2 font-semibold"></td>
|
||||
)}
|
||||
))}
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
)}
|
||||
</table>
|
||||
</div>
|
||||
<div className="flex flex-row justify-between items-center text-xs font-medium">
|
||||
<div className="op-join flex flex-wrap items-center p-2">
|
||||
{userList.length > recordperPage && (
|
||||
<button
|
||||
onClick={() => paginateBack()}
|
||||
className="op-join-item op-btn op-btn-sm"
|
||||
>
|
||||
{t("prev")}
|
||||
</button>
|
||||
)}
|
||||
{pageNumbers.map((x, i) => (
|
||||
<button
|
||||
key={i}
|
||||
onClick={() => setCurrentPage(x)}
|
||||
disabled={x === "..."}
|
||||
className={`${
|
||||
x === currentPage ? "op-btn-active" : ""
|
||||
} op-join-item op-btn op-btn-sm`}
|
||||
>
|
||||
{x}
|
||||
</button>
|
||||
))}
|
||||
{userList.length > recordperPage && (
|
||||
<button
|
||||
onClick={() => paginateFront()}
|
||||
className="op-join-item op-btn op-btn-sm"
|
||||
>
|
||||
{t("next")}
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
{userList?.length <= 0 && (
|
||||
<div
|
||||
className={`${
|
||||
isDashboard ? "h-[317px]" : ""
|
||||
} flex flex-col items-center justify-center w-ful bg-base-100 text-base-content rounded-xl py-4`}
|
||||
>
|
||||
<div className="w-[60px] h-[60px] overflow-hidden">
|
||||
<img
|
||||
className="w-full h-full object-contain"
|
||||
src={pad}
|
||||
alt="img"
|
||||
/>
|
||||
</thead>
|
||||
<tbody className="text-[12px]">
|
||||
{userList?.length > 0 && (
|
||||
<>
|
||||
{currentList.map((item, index) => (
|
||||
<tr className="border-y-[1px]" key={index}>
|
||||
{heading.includes("Sr.No") && (
|
||||
<th className="px-4 py-2">
|
||||
{startIndex + index + 1}
|
||||
</th>
|
||||
)}
|
||||
<td className="px-4 py-2 font-semibold">
|
||||
{item?.Name}{" "}
|
||||
</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?.UserRole?.split("_").pop() || "-"}
|
||||
</td>
|
||||
<td className="px-4 py-2">
|
||||
{formatRow(item.TeamIds)}
|
||||
</td>
|
||||
{item.UserRole !== "contracts_Admin" && (
|
||||
<td className="px-4 py-2 font-semibold">
|
||||
<label className="cursor-pointer relative block items-center mb-0">
|
||||
<input
|
||||
type="checkbox"
|
||||
className="op-toggle transition-all op-toggle-secondary"
|
||||
checked={item?.IsDisabled !== true}
|
||||
onChange={() => handleToggleBtn(item)}
|
||||
/>
|
||||
</label>
|
||||
{isActiveModal[item.objectId] && (
|
||||
<ModalUi
|
||||
isOpen
|
||||
title={t("user-status")}
|
||||
handleClose={handleClose}
|
||||
>
|
||||
<div className="m-[20px]">
|
||||
<div className="text-lg font-normal text-black">
|
||||
{t("are-you-sure")}{" "}
|
||||
{item?.IsDisabled
|
||||
? t("activate")
|
||||
: t("deactivate")}{" "}
|
||||
{t("this-user")}?
|
||||
</div>
|
||||
<hr className="bg-[#ccc] mt-4 " />
|
||||
<div className="flex items-center mt-3 gap-2 text-white">
|
||||
<button
|
||||
onClick={() =>
|
||||
handleToggleSubmit(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>
|
||||
)}
|
||||
</tr>
|
||||
))}
|
||||
</>
|
||||
)}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div className="text-sm font-semibold">
|
||||
{t("no-data-avaliable")}
|
||||
<div className="flex flex-row justify-between items-center text-xs font-medium">
|
||||
<div className="op-join flex flex-wrap items-center p-2">
|
||||
{userList.length > recordperPage && (
|
||||
<button
|
||||
onClick={() => paginateBack()}
|
||||
className="op-join-item op-btn op-btn-sm"
|
||||
>
|
||||
{t("prev")}
|
||||
</button>
|
||||
)}
|
||||
{pageNumbers.map((x, i) => (
|
||||
<button
|
||||
key={i}
|
||||
onClick={() => setCurrentPage(x)}
|
||||
disabled={x === "..."}
|
||||
className={`${
|
||||
x === currentPage ? "op-btn-active" : ""
|
||||
} op-join-item op-btn op-btn-sm`}
|
||||
>
|
||||
{x}
|
||||
</button>
|
||||
))}
|
||||
{userList.length > recordperPage && (
|
||||
<button
|
||||
onClick={() => paginateFront()}
|
||||
className="op-join-item op-btn op-btn-sm"
|
||||
>
|
||||
{t("next")}
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
{userList?.length <= 0 && (
|
||||
<div
|
||||
className={`${
|
||||
isDashboard ? "h-[317px]" : ""
|
||||
} flex flex-col items-center justify-center w-ful bg-base-100 text-base-content rounded-xl py-4`}
|
||||
>
|
||||
<div className="w-[60px] h-[60px] overflow-hidden">
|
||||
<img
|
||||
className="w-full h-full object-contain"
|
||||
src={pad}
|
||||
alt="img"
|
||||
/>
|
||||
</div>
|
||||
<div className="text-sm font-semibold">
|
||||
{t("no-data-avaliable")}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
<ModalUi
|
||||
isOpen={isModal.form}
|
||||
title={formHeader}
|
||||
handleClose={() => handleModal("form")}
|
||||
>
|
||||
<AddUser
|
||||
setIsAlert={setIsAlert}
|
||||
handleUserData={handleUserData}
|
||||
closePopup={() => handleModal("form")}
|
||||
setFormHeader={setFormHeader}
|
||||
/>
|
||||
</ModalUi>
|
||||
</div>
|
||||
) : (
|
||||
<div className="flex items-center justify-center h-screen w-full bg-base-100 text-base-content rounded-box">
|
||||
<div className="text-center">
|
||||
<h1 className="text-[60px] lg:text-[120px] font-semibold">
|
||||
404
|
||||
</h1>
|
||||
<p className="text-[30px] lg:text-[50px]">
|
||||
{t("page-not-found")}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
<ModalUi
|
||||
isOpen={isModal.form}
|
||||
title={formHeader}
|
||||
handleClose={() => handleModal("form")}
|
||||
>
|
||||
<AddUser
|
||||
showAlert={showAlert}
|
||||
handleUserData={handleUserData}
|
||||
closePopup={() => handleModal("form")}
|
||||
setFormHeader={setFormHeader}
|
||||
/>
|
||||
</ModalUi>
|
||||
</div>
|
||||
) : (
|
||||
<div className="flex items-center justify-center h-screen w-full bg-base-100 text-base-content rounded-box">
|
||||
<div className="text-center">
|
||||
<h1 className="text-[60px] lg:text-[120px] font-semibold">
|
||||
404
|
||||
</h1>
|
||||
<p className="text-[30px] lg:text-[50px]">
|
||||
{t("page-not-found")}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
)
|
||||
}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -12,8 +12,6 @@ import JSZip from "jszip";
|
||||
import { saveAs } from "file-saver";
|
||||
|
||||
function DownloadPdfZip(props) {
|
||||
const appName =
|
||||
"OpenSign™";
|
||||
const { t } = useTranslation();
|
||||
const [selectType, setSelectType] = useState(1);
|
||||
const [isDownloading, setIsDownloading] = useState(false);
|
||||
@@ -65,18 +63,19 @@ function DownloadPdfZip(props) {
|
||||
throw new Error(`Failed to fetch certificate PDF: ${certificateUrl}`);
|
||||
}
|
||||
const pdf2Blob = await pdf2Response.blob();
|
||||
// Add files to ZIP
|
||||
zip.file(
|
||||
`${sanitizeFileName(pdfName)}_signed_by_${appName}.pdf`,
|
||||
pdf1Blob
|
||||
);
|
||||
zip.file(`Certificate_signed_by_${appName}.pdf`, pdf2Blob);
|
||||
// Generate the ZIP and trigger download
|
||||
const zipBlob = await zip.generateAsync({ type: "blob" });
|
||||
saveAs(
|
||||
zipBlob,
|
||||
`${sanitizeFileName(pdfName)}_signed_by_${appName}.zip`
|
||||
);
|
||||
// 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("");
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
import React, { useState, useEffect, useRef } from "react";
|
||||
import React, { useState, useEffect } from "react";
|
||||
import pad from "../assets/images/pad.svg";
|
||||
import { useLocation, useNavigate } from "react-router";
|
||||
import axios from "axios";
|
||||
import ModalUi from "./ModalUi";
|
||||
import AddSigner from "../components/AddSigner";
|
||||
import { emailRegex } from "../constant/const";
|
||||
import {
|
||||
emailRegex,
|
||||
} from "../constant/const";
|
||||
import Alert from "./Alert";
|
||||
import Tooltip from "./Tooltip";
|
||||
import { RWebShare } from "react-web-share";
|
||||
@@ -36,9 +38,6 @@ import * as XLSX from "xlsx";
|
||||
import EditContactForm from "../components/EditContactForm";
|
||||
|
||||
const ReportTable = (props) => {
|
||||
const copyUrlRef = useRef(null);
|
||||
const appName = "OpenSign™";
|
||||
const drivename = appName === "OpenSign™" ? "OpenSign™" : "";
|
||||
const { t } = useTranslation();
|
||||
const navigate = useNavigate();
|
||||
const location = useLocation();
|
||||
@@ -154,14 +153,14 @@ const ReportTable = (props) => {
|
||||
const teamtRes = await Parse.Cloud.run("getteams", { active: true });
|
||||
if (teamtRes.length > 0) {
|
||||
const _teamRes = JSON.parse(JSON.stringify(teamtRes));
|
||||
const selected = _teamRes.map(
|
||||
(x) =>
|
||||
x.Name === "All Users" && {
|
||||
label: x.Name,
|
||||
value: x.objectId
|
||||
}
|
||||
);
|
||||
setSelectedTeam(selected);
|
||||
const selected = _teamRes.map(
|
||||
(x) =>
|
||||
x.Name === "All Users" && {
|
||||
label: x.Name,
|
||||
value: x.objectId
|
||||
}
|
||||
);
|
||||
setSelectedTeam(selected);
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
@@ -222,7 +221,7 @@ const ReportTable = (props) => {
|
||||
const handleURL = async (item, act) => {
|
||||
if (props.ReportName === "Templates") {
|
||||
if (act.hoverLabel === "Edit") {
|
||||
navigate(`/${act.redirectUrl}/${item.objectId}`);
|
||||
navigate(`/${act.redirectUrl}/${item.objectId}`);
|
||||
} else {
|
||||
setActLoader({ [`${item.objectId}_${act.btnId}`]: true });
|
||||
try {
|
||||
@@ -408,7 +407,8 @@ const ReportTable = (props) => {
|
||||
setSelectedTeam(formatedList);
|
||||
}
|
||||
setIsShareWith({ [item.objectId]: true });
|
||||
} else if (act.action === "duplicate") {
|
||||
}
|
||||
else if (act.action === "duplicate") {
|
||||
setIsModal({ [`duplicate_${item.objectId}`]: true });
|
||||
} else if (act.action === "rename") {
|
||||
setIsModal({ [`rename_${item.objectId}`]: true });
|
||||
@@ -492,7 +492,8 @@ const ReportTable = (props) => {
|
||||
setActLoader({});
|
||||
}
|
||||
};
|
||||
const handleClose = () => {
|
||||
const handleClose = (
|
||||
) => {
|
||||
setIsRevoke({});
|
||||
setIsDeleteModal({});
|
||||
setReason("");
|
||||
@@ -523,9 +524,6 @@ const ReportTable = (props) => {
|
||||
|
||||
const copytoclipboard = (share) => {
|
||||
copytoData(share.url);
|
||||
if (copyUrlRef.current) {
|
||||
copyUrlRef.current.textContent = share.url; // Update text safely
|
||||
}
|
||||
setCopied({ ...copied, [share.email]: true });
|
||||
};
|
||||
//function to handle revoke/decline docment
|
||||
@@ -651,7 +649,11 @@ const ReportTable = (props) => {
|
||||
if (isCompleted) {
|
||||
setIsDownloadModal({ [item.objectId]: true });
|
||||
} else {
|
||||
const signedUrl = await getSignedUrl(url, docId, templateId);
|
||||
const signedUrl = await getSignedUrl(
|
||||
url,
|
||||
docId,
|
||||
templateId
|
||||
);
|
||||
await fetchUrl(signedUrl, pdfName);
|
||||
}
|
||||
setActLoader({});
|
||||
@@ -678,8 +680,10 @@ const ReportTable = (props) => {
|
||||
const signPdf = `${window.location.origin}/login/${encodeBase64}`;
|
||||
const variables = {
|
||||
document_title: doc.Name,
|
||||
sender_name: doc.ExtUserPtr.Name,
|
||||
sender_mail: doc.ExtUserPtr.Email,
|
||||
sender_name:
|
||||
doc.ExtUserPtr.Name,
|
||||
sender_mail:
|
||||
doc.ExtUserPtr.Email,
|
||||
sender_phone: doc.ExtUserPtr?.Phone || "",
|
||||
receiver_name: userDetails?.Name || "",
|
||||
receiver_email: userDetails?.Email,
|
||||
@@ -707,8 +711,10 @@ const ReportTable = (props) => {
|
||||
const signPdf = `${window.location.origin}/login/${encodeBase64}`;
|
||||
const variables = {
|
||||
document_title: doc.Name,
|
||||
sender_name: doc.ExtUserPtr.Name,
|
||||
sender_mail: doc.ExtUserPtr.Email,
|
||||
sender_name:
|
||||
doc.ExtUserPtr.Name,
|
||||
sender_mail:
|
||||
doc.ExtUserPtr.Email,
|
||||
sender_phone: doc.ExtUserPtr?.Phone || "",
|
||||
receiver_name: userDetails?.Name || "",
|
||||
receiver_email: userDetails?.Email || "",
|
||||
@@ -748,8 +754,10 @@ const ReportTable = (props) => {
|
||||
const signPdf = `${window.location.origin}/login/${encodeBase64}`;
|
||||
const variables = {
|
||||
document_title: doc.Name,
|
||||
sender_name: doc.ExtUserPtr.Name,
|
||||
sender_mail: doc.ExtUserPtr.Email,
|
||||
sender_name:
|
||||
doc.ExtUserPtr.Name,
|
||||
sender_mail:
|
||||
doc.ExtUserPtr.Email,
|
||||
sender_phone: doc.ExtUserPtr?.Phone || "",
|
||||
receiver_name: user?.signerPtr?.Name || "",
|
||||
receiver_email: user?.email ? user?.email : user?.signerPtr?.Email,
|
||||
@@ -764,7 +772,7 @@ const ReportTable = (props) => {
|
||||
`{{sender_name}} has requested you to sign "{{document_title}}"`;
|
||||
const body =
|
||||
doc?.RequestBody ||
|
||||
`<html><head><meta http-equiv='Content-Type' content='text/html; charset=UTF-8' /></head><body><p>Hi {{receiver_name}},</p><br><p>We hope this email finds you well. {{sender_name}} has requested you to review and sign <b>"{{document_title}}"</b>.</p><p>Your signature is crucial to proceed with the next steps as it signifies your agreement and authorization.</p><br><p>{{signing_url}}</p><br><p>If you have any questions or need further clarification regarding the document or the signing process, please contact the sender.</p><br><p>Thanks</p><p> Team ${appName}</p><br></body> </html>`;
|
||||
`<html><head><meta http-equiv='Content-Type' content='text/html; charset=UTF-8' /></head><body><p>Hi {{receiver_name}},</p><br><p>We hope this email finds you well. {{sender_name}} has requested you to review and sign <b>"{{document_title}}"</b>.</p><p>Your signature is crucial to proceed with the next steps as it signifies your agreement and authorization.</p><br><p>{{signing_url}}</p><br><p>If you have any questions or need further clarification regarding the document or the signing process, please contact the sender.</p><br><p>Thanks</p><p> Team OpenSign™</p><br></body> </html>`;
|
||||
const res = replaceMailVaribles(subject, body, variables);
|
||||
setMail((prev) => ({ ...prev, subject: res.subject, body: res.body }));
|
||||
setIsNextStep({ [user.Id]: true });
|
||||
@@ -779,11 +787,14 @@ const ReportTable = (props) => {
|
||||
sessionToken: localStorage.getItem("accesstoken")
|
||||
};
|
||||
let params = {
|
||||
replyto: doc?.ExtUserPtr?.Email || "",
|
||||
replyto:
|
||||
doc?.ExtUserPtr?.Email ||
|
||||
"",
|
||||
extUserId: doc?.ExtUserPtr?.objectId,
|
||||
recipient: userDetails?.Email,
|
||||
subject: mail.subject,
|
||||
from: doc?.ExtUserPtr?.Email,
|
||||
from:
|
||||
doc?.ExtUserPtr?.Email,
|
||||
html: mail.body
|
||||
};
|
||||
try {
|
||||
@@ -1409,13 +1420,10 @@ const ReportTable = (props) => {
|
||||
)}
|
||||
<div className="flex flex-row items-center justify-between my-2 mx-3 text-[20px] md:text-[23px]">
|
||||
<div className="font-light">
|
||||
{t(`report-name.${props.ReportName}`)}{" "}
|
||||
{t(`report-name.${props.ReportName}`)}
|
||||
{props.report_help && (
|
||||
<span className="text-xs md:text-[13px] font-normal">
|
||||
<Tooltip
|
||||
id="report_help"
|
||||
message={t(`report-help.${props.ReportName}`)}
|
||||
/>
|
||||
<span className="text-xs md:text-[13px] font-normal ml-[2px]">
|
||||
<Tooltip message={t(`report-help.${props.ReportName}`)} />
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
@@ -1656,9 +1664,7 @@ const ReportTable = (props) => {
|
||||
{props.heading.includes("Folder") && (
|
||||
<td className="p-2 text-center">
|
||||
{item?.Folder?.Name ||
|
||||
t("sidebar.OpenSign™ Drive", {
|
||||
appName: drivename
|
||||
})}
|
||||
t("sidebar.OpenSign™ Drive")}
|
||||
</td>
|
||||
)}
|
||||
<td className="p-2 text-center">
|
||||
@@ -1726,7 +1732,11 @@ const ReportTable = (props) => {
|
||||
<i className={act.btnIcon}></i>
|
||||
{act.btnLabel && (
|
||||
<span className="uppercase font-medium">
|
||||
{`${t(`btnLabel.${act.btnLabel}`)}`}
|
||||
{
|
||||
`${t(
|
||||
`btnLabel.${act.btnLabel}`
|
||||
)}`
|
||||
}
|
||||
</span>
|
||||
)}
|
||||
{/* template report */}
|
||||
@@ -1806,9 +1816,7 @@ const ReportTable = (props) => {
|
||||
title={t(`btnLabel.${act.hoverLabel}`)}
|
||||
className={
|
||||
act.action !== "option"
|
||||
? `${
|
||||
act?.btnColor || ""
|
||||
} op-btn op-btn-sm mr-1`
|
||||
? `${act?.btnColor || ""} op-btn op-btn-sm mr-1`
|
||||
: "text-base-content focus:outline-none text-lg mr-2 relative"
|
||||
}
|
||||
>
|
||||
@@ -1895,26 +1903,28 @@ const ReportTable = (props) => {
|
||||
{isShareWith[item.objectId] && (
|
||||
<div className="op-modal op-modal-open">
|
||||
<div className="max-h-90 bg-base-100 w-[95%] md:max-w-[500px] rounded-box relative">
|
||||
<h3 className="text-base-content font-bold text-lg pt-[15px] px-[20px]">
|
||||
{t("share-with")}
|
||||
</h3>
|
||||
<div
|
||||
className="op-btn op-btn-sm op-btn-circle op-btn-ghost text-base-content absolute right-2 top-2 z-40"
|
||||
onClick={() => setIsShareWith({})}
|
||||
>
|
||||
✕
|
||||
</div>
|
||||
<div className="px-2 mt-3 w-full h-full">
|
||||
<div className="op-input op-input-bordered op-input-sm w-full h-full text-[13px] break-all">
|
||||
{selectedTeam?.[0]?.label}
|
||||
</div>
|
||||
</div>
|
||||
<button
|
||||
onClick={(e) => handleShareWith(e, item)}
|
||||
className="op-btn op-btn-primary ml-[10px] my-3"
|
||||
>
|
||||
{t("submit")}
|
||||
</button>
|
||||
<h3 className="text-base-content font-bold text-lg pt-[15px] px-[20px]">
|
||||
{t("share-with")}
|
||||
</h3>
|
||||
<div
|
||||
className="op-btn op-btn-sm op-btn-circle op-btn-ghost text-base-content absolute right-2 top-2 z-40"
|
||||
onClick={() => setIsShareWith({})}
|
||||
>
|
||||
✕
|
||||
</div>
|
||||
<div className="px-2 mt-3 w-full h-full">
|
||||
<div className="op-input op-input-bordered op-input-sm w-full h-full text-[13px] break-all">
|
||||
{selectedTeam?.[0]?.label}
|
||||
</div>
|
||||
</div>
|
||||
<button
|
||||
onClick={(e) =>
|
||||
handleShareWith(e, item)
|
||||
}
|
||||
className="op-btn op-btn-primary ml-[10px] my-3"
|
||||
>
|
||||
{t("submit")}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
@@ -2007,7 +2017,9 @@ const ReportTable = (props) => {
|
||||
{isBulkSend[item.objectId] && (
|
||||
<ModalUi
|
||||
isOpen
|
||||
title={t("quick-send")}
|
||||
title={
|
||||
t("quick-send")
|
||||
}
|
||||
handleClose={() => setIsBulkSend({})}
|
||||
>
|
||||
{isLoader[item.objectId] ? (
|
||||
@@ -2067,11 +2079,6 @@ const ReportTable = (props) => {
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
<p
|
||||
id="copyUrl"
|
||||
ref={copyUrlRef}
|
||||
className="hidden"
|
||||
></p>
|
||||
</div>
|
||||
</ModalUi>
|
||||
)}
|
||||
|
||||
@@ -45,7 +45,7 @@ const Tooltip = ({
|
||||
</a>
|
||||
<ReactTooltip
|
||||
id={id ? id : "my-tooltip"}
|
||||
className={`${maxWidth ? maxWidth : "max-w-[200px]"} z-[200]`}
|
||||
className={`${maxWidth ? maxWidth : "max-w-[200px]"} z-[200]`}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
import React from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import ModalUi from "./ModalUi";
|
||||
import { useNavigate } from "react-router";
|
||||
import Parse from "parse";
|
||||
|
||||
const ValidateSession = ({ children }) => {
|
||||
const { t } = useTranslation();
|
||||
const navigate = useNavigate();
|
||||
|
||||
const handleLoginBtn = async () => {
|
||||
try {
|
||||
await Parse?.User?.logOut();
|
||||
} catch (err) {
|
||||
console.log("err ", err);
|
||||
} finally {
|
||||
localStorage.removeItem("accesstoken");
|
||||
navigate("/", { replace: true });
|
||||
}
|
||||
};
|
||||
return localStorage.getItem("accesstoken") ? (
|
||||
children
|
||||
) : (
|
||||
<ModalUi showHeader={false} isOpen={true} showClose={false}>
|
||||
<div className="flex flex-col justify-center items-center py-4 md:py-5 gap-5">
|
||||
<p className="text-xl font-medium">Your session has expired.</p>
|
||||
<button onClick={handleLoginBtn} className="op-btn op-btn-neutral">
|
||||
{t("login")}
|
||||
</button>
|
||||
</div>
|
||||
</ModalUi>
|
||||
);
|
||||
};
|
||||
|
||||
export default ValidateSession;
|
||||
@@ -1,9 +1,5 @@
|
||||
# Use an official Node runtime as the base image
|
||||
FROM node:22.14.0
|
||||
|
||||
# install java
|
||||
RUN wget https://download.oracle.com/java/23/latest/jdk-23_linux-x64_bin.deb \
|
||||
&& dpkg -i jdk-23_linux-x64_bin.deb
|
||||
FROM node:20
|
||||
|
||||
# Set the working directory inside the container
|
||||
WORKDIR /usr/src/app
|
||||
|
||||
Binary file not shown.
+130
-44
@@ -5,7 +5,7 @@ import { PDFDocument } from 'pdf-lib';
|
||||
dotenv.config();
|
||||
|
||||
export const cloudServerUrl = 'http://localhost:8080/app';
|
||||
export const appName = 'OpenSign™';
|
||||
export const appName = process.env.APP_NAME || 'OpenSign™';
|
||||
export function customAPIurl() {
|
||||
const url = new URL(cloudServerUrl);
|
||||
return url.pathname === '/api/app' ? url.origin + '/api' : url.origin;
|
||||
@@ -105,29 +105,20 @@ export const updateMailCount = async (extUserId, plan, monthchange) => {
|
||||
try {
|
||||
const contractUser = await query.first({ useMasterKey: true });
|
||||
if (contractUser) {
|
||||
const _extRes = JSON.parse(JSON.stringify(contractUser));
|
||||
let updateDate = new Date();
|
||||
if (_extRes?.LastEmailCountReset?.iso) {
|
||||
updateDate = new Date(_extRes?.LastEmailCountReset?.iso);
|
||||
const newDate = new Date();
|
||||
// Update the month while keeping the same day and year
|
||||
updateDate.setMonth(newDate.getMonth());
|
||||
updateDate.setFullYear(newDate.getFullYear());
|
||||
}
|
||||
contractUser.increment('EmailCount', 1);
|
||||
if (plan === 'freeplan') {
|
||||
if (monthchange) {
|
||||
contractUser.set('LastEmailCountReset', updateDate);
|
||||
contractUser.set('LastEmailCountReset', new Date());
|
||||
contractUser.set('MonthlyFreeEmails', 1);
|
||||
} else {
|
||||
if (contractUser?.get('MonthlyFreeEmails')) {
|
||||
contractUser.increment('MonthlyFreeEmails', 1);
|
||||
if (contractUser?.get('LastEmailCountReset')) {
|
||||
contractUser.set('LastEmailCountReset', updateDate);
|
||||
contractUser.set('LastEmailCountReset', new Date());
|
||||
}
|
||||
} else {
|
||||
contractUser.set('MonthlyFreeEmails', 1);
|
||||
contractUser.set('LastEmailCountReset', updateDate);
|
||||
contractUser.set('LastEmailCountReset', new Date());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -138,6 +129,131 @@ export const updateMailCount = async (extUserId, plan, monthchange) => {
|
||||
}
|
||||
};
|
||||
|
||||
export function formatWidgetOptions(type, options) {
|
||||
const colorsArr = ['red', 'black', 'blue', 'yellow'];
|
||||
const fontSizes = [2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28];
|
||||
const status = options?.required === true ? 'required' : 'optional' || 'required';
|
||||
const defaultValue = options?.default || '';
|
||||
const values = options?.values || [];
|
||||
const color = options?.color ? options.color : 'black';
|
||||
const fontColor = colorsArr.includes(color) ? color : 'black';
|
||||
const size = options?.fontsize ? parseInt(options.fontsize) : 12;
|
||||
const fontSize = fontSizes.includes(size) ? size : 12;
|
||||
switch (type) {
|
||||
case 'signature':
|
||||
return { name: 'signature', status: 'required' };
|
||||
case 'stamp':
|
||||
return { status: status, name: 'stamp' };
|
||||
case 'initials':
|
||||
return { status: status, name: options.name || 'initials' };
|
||||
case 'image':
|
||||
return { status: status, name: options.name || 'image' };
|
||||
case 'email':
|
||||
return {
|
||||
status: status,
|
||||
name: options.name || 'email',
|
||||
validation: { type: 'email' },
|
||||
fontColor: fontColor,
|
||||
fontSize: fontSize,
|
||||
};
|
||||
case 'name':
|
||||
return {
|
||||
status: status,
|
||||
name: options.name || 'name',
|
||||
fontColor: fontColor,
|
||||
fontSize: fontSize,
|
||||
};
|
||||
case 'job title':
|
||||
return {
|
||||
status: status,
|
||||
name: options.name || 'job title',
|
||||
fontColor: fontColor,
|
||||
fontSize: fontSize,
|
||||
};
|
||||
case 'company':
|
||||
return {
|
||||
status: status,
|
||||
name: options.name || 'company',
|
||||
fontColor: fontColor,
|
||||
fontSize: fontSize,
|
||||
};
|
||||
case 'date': {
|
||||
let today = new Date();
|
||||
let dd = String(today.getDate()).padStart(2, '0');
|
||||
let mm = String(today.getMonth() + 1).padStart(2, '0'); // January is 0!
|
||||
let yyyy = today.getFullYear();
|
||||
today = dd + '-' + mm + '-' + yyyy;
|
||||
let dateFormat = options?.format;
|
||||
dateFormat = dateFormat.replace(/m/g, 'M');
|
||||
return {
|
||||
status: status,
|
||||
name: options.name || 'date',
|
||||
response: defaultValue || today,
|
||||
validation: { format: dateFormat || 'dd-MM-yyyy', type: 'date-format' },
|
||||
fontColor: fontColor,
|
||||
fontSize: fontSize,
|
||||
};
|
||||
}
|
||||
case 'textbox':
|
||||
return {
|
||||
status: status,
|
||||
name: 'textbox',
|
||||
defaultValue: defaultValue,
|
||||
hint: options.hint,
|
||||
validation: { type: 'regex', pattern: options?.regularexpression || '/^[a-zA-Z0-9s]+$/' },
|
||||
fontColor: fontColor,
|
||||
fontSize: fontSize,
|
||||
isReadOnly: options?.readonly || false,
|
||||
};
|
||||
case 'checkbox': {
|
||||
const arr = options?.values;
|
||||
let selectedvalues = [];
|
||||
for (const obj of options.selectedvalues) {
|
||||
const index = arr.indexOf(obj);
|
||||
selectedvalues.push(index);
|
||||
}
|
||||
return {
|
||||
status: status,
|
||||
name: options.name || 'checkbox',
|
||||
values: values,
|
||||
isReadOnly: options?.readonly || false,
|
||||
isHideLabel: options?.hidelabel || false,
|
||||
validation: {
|
||||
minRequiredCount: options?.validation?.minselections || 0,
|
||||
maxRequiredCount: options?.validation?.maxselections || 0,
|
||||
},
|
||||
defaultValue: selectedvalues || [],
|
||||
fontColor: fontColor,
|
||||
fontSize: fontSize,
|
||||
};
|
||||
}
|
||||
case 'radio button': {
|
||||
return {
|
||||
status: status,
|
||||
name: options.name || 'radio',
|
||||
values: values,
|
||||
isReadOnly: options?.readonly || false,
|
||||
isHideLabel: options?.hidelabel || false,
|
||||
defaultValue: defaultValue,
|
||||
fontColor: fontColor,
|
||||
fontSize: fontSize,
|
||||
};
|
||||
}
|
||||
case 'dropdown':
|
||||
return {
|
||||
status: status,
|
||||
name: options.name || 'dropdown',
|
||||
values: values,
|
||||
defaultValue: defaultValue,
|
||||
fontColor: fontColor,
|
||||
fontSize: fontSize,
|
||||
isReadOnly: options?.readonly || false,
|
||||
};
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
export function sanitizeFileName(fileName) {
|
||||
// Remove spaces and invalid characters
|
||||
const file = fileName.replace(/[^a-zA-Z0-9._-]/g, '');
|
||||
@@ -150,6 +266,7 @@ export const smtpsecure = process.env.SMTP_PORT && process.env.SMTP_PORT !== '46
|
||||
export const smtpenable =
|
||||
process.env.SMTP_ENABLE && process.env.SMTP_ENABLE.toLowerCase() === 'true' ? true : false;
|
||||
|
||||
|
||||
// `generateId` is used to unique Id for fileAdapter
|
||||
export function generateId(length) {
|
||||
const characters = 'abcdefghijklmnopqrstuvwxyz0123456789';
|
||||
@@ -225,34 +342,3 @@ export const flattenPdf = async pdfFile => {
|
||||
throw new Error('error in pdf');
|
||||
}
|
||||
};
|
||||
|
||||
export const mailTemplate = param => {
|
||||
const themeColor = '#47a3ad';
|
||||
const subject = `${param.senderName} has requested you to sign "${param.title}"`;
|
||||
const logo = `<img src='https://qikinnovation.ams3.digitaloceanspaces.com/logo.png' height='50' />`;
|
||||
|
||||
const opurl = ` <a href='www.opensignlabs.com' target=_blank>here</a>`;
|
||||
|
||||
const body =
|
||||
"<html><head><meta http-equiv='Content-Type' content='text/html;charset=UTF-8' /></head><body><div style='background-color:#f5f5f5;padding:20px'><div style='background:white;padding-bottom:20px'><div style='padding:10px'>" +
|
||||
logo +
|
||||
`</div><div style='padding:2px;font-family:system-ui;background-color:${themeColor}'><p style='font-size:20px;font-weight:400;color:white;padding-left:20px'>Digital Signature Request</p></div><div><p style='padding:20px;font-size:14px;margin-bottom:10px'>` +
|
||||
param.senderName +
|
||||
' has requested you to review and sign <strong>' +
|
||||
param.title +
|
||||
"</strong>.</p><div style='padding: 5px 0px 5px 25px;display:flex;flex-direction:row;justify-content:space-around'><table><tr><td style='font-weight:bold;font-family:sans-serif;font-size:15px'>Sender</td><td></td><td style='color:#626363;font-weight:bold'>" +
|
||||
param.senderMail +
|
||||
"</td></tr><tr><td style='font-weight:bold;font-family:sans-serif;font-size:15px'>Organization</td><td></td><td style='color:#626363;font-weight:bold'> " +
|
||||
param.organization +
|
||||
"</td></tr><tr><td style='font-weight:bold;font-family:sans-serif;font-size:15px'>Expire on</td><td></td><td style='color:#626363;font-weight:bold'>" +
|
||||
param.localExpireDate +
|
||||
"</td></tr><tr><td></td><td></td></tr></table></div> <div style='margin-left:70px'><a target=_blank href=" +
|
||||
param.sigingUrl +
|
||||
"><button style='padding:12px;background-color:#d46b0f;color:white;border:0px;font-weight:bold;margin-top:30px'>Sign here</button></a></div><div style='display:flex;justify-content:center;margin-top:10px'></div></div></div><div><p> This is an automated email from " +
|
||||
appName +
|
||||
'. For any queries regarding this email, please contact the sender ' +
|
||||
param.senderMail +
|
||||
` directly. If you think this email is inappropriate or spam, you may file a complaint with ${appName}${opurl}.</p></div></div></body></html>`;
|
||||
|
||||
return { subject, body };
|
||||
};
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
|
||||
import PDF from './parsefunction/pdf/PDF.js';
|
||||
import sendmailv3 from './parsefunction/sendMailv3.js';
|
||||
import usersignup from './parsefunction/usersignup.js';
|
||||
@@ -50,7 +51,7 @@ import generateCertificatebydocId from './parsefunction/generateCertificatebydoc
|
||||
import fileUpload from './parsefunction/fileUpload.js';
|
||||
import getUserListByOrg from './parsefunction/getUserListByOrg.js';
|
||||
import editContact from './parsefunction/editContact.js';
|
||||
import forwardDoc from './parsefunction/ForwardDoc.js';
|
||||
|
||||
|
||||
// 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);
|
||||
@@ -111,4 +112,3 @@ Parse.Cloud.define('generatecertificate', generateCertificatebydocId);
|
||||
Parse.Cloud.define('fileupload', fileUpload);
|
||||
Parse.Cloud.define('getuserlistbyorg', getUserListByOrg);
|
||||
Parse.Cloud.define('editcontact', editContact);
|
||||
Parse.Cloud.define('forwarddoc', forwardDoc);
|
||||
|
||||
@@ -1,13 +1,4 @@
|
||||
async function DocumentBeforesave(request) {
|
||||
if (!request.original) {
|
||||
const TimeToCompleteDays = request.object.get('TimeToCompleteDays') || 15;
|
||||
const RemindOnceInEvery = request?.object?.get('RemindOnceInEvery') || 5;
|
||||
const AutoReminder = request?.object?.get('AutomaticReminders') || false;
|
||||
const reminderCount = TimeToCompleteDays / RemindOnceInEvery;
|
||||
if (AutoReminder && reminderCount > 15) {
|
||||
throw new Parse.Error(Parse.Error.INVALID_QUERY, 'only 15 reminder allowed');
|
||||
}
|
||||
}
|
||||
try {
|
||||
// below code is used to update document when user sent document or self signed
|
||||
const document = request.object;
|
||||
|
||||
@@ -1,81 +0,0 @@
|
||||
import axios from 'axios';
|
||||
import { appName, cloudServerUrl } from '../../Utils.js';
|
||||
|
||||
export default async function forwardDoc(request) {
|
||||
try {
|
||||
if (!request.user) {
|
||||
throw new Parse.Error(Parse.Error.INVALID_SESSION_TOKEN, 'unauthorized.');
|
||||
}
|
||||
const { docId, recipients } = request.params;
|
||||
const isReceipents = recipients?.length > 0 && recipients?.length <= 10;
|
||||
if (docId && isReceipents) {
|
||||
const userPtr = { __type: 'Pointer', className: '_User', objectId: request.user.id };
|
||||
const docQuery = new Parse.Query('contracts_Document');
|
||||
docQuery
|
||||
.equalTo('objectId', docId)
|
||||
.equalTo('CreatedBy', userPtr)
|
||||
.notEqualTo('IsArchive', true)
|
||||
.notEqualTo('IsDeclined', true)
|
||||
.include('Signers')
|
||||
.include('ExtUserPtr')
|
||||
.include('Placeholders.signerPtr')
|
||||
.include('ExtUserPtr.TenantId');
|
||||
const docRes = await docQuery.first({ useMasterKey: true });
|
||||
if (!docRes) {
|
||||
throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'Document not found.');
|
||||
}
|
||||
const _docRes = docRes?.toJSON();
|
||||
const docName = _docRes.Name;
|
||||
const fileAdapterId = _docRes?.FileAdapterId || '';
|
||||
const extUserId = _docRes?.ExtUserPtr?.objectId;
|
||||
const from = _docRes?.ExtUserPtr?.Email;
|
||||
const replyTo = _docRes?.ExtUserPtr?.Email;
|
||||
const senderName = _docRes?.ExtUserPtr?.Name;
|
||||
|
||||
try {
|
||||
let mailRes;
|
||||
for (let i = 0; i < recipients.length; i++) {
|
||||
const logo = `<img src='https://qikinnovation.ams3.digitaloceanspaces.com/logo.png' height='50' style='padding:20px'/>`;
|
||||
const opurl = ` <a href='www.opensignlabs.com' target=_blank>here</a>`;
|
||||
const themeColor = '#47a3ad';
|
||||
|
||||
let params = {
|
||||
extUserId: extUserId,
|
||||
pdfName: docName,
|
||||
url: _docRes?.SignedUrl || '',
|
||||
recipient: recipients[i],
|
||||
subject: `${senderName} has signed the doc - ${docName}`,
|
||||
replyto: replyTo || '',
|
||||
from: from,
|
||||
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='background-color:white'><div>` +
|
||||
`${logo}</div><div style='padding:2px;font-family:system-ui;background-color:${themeColor}'><p style='font-size:20px;font-weight:400;color:white;padding-left:20px'>Document Copy</p></div><div>` +
|
||||
`<p style='padding:20px;font-family:system-ui;font-size:14px'>A copy of the document <strong>${docName}</strong> is attached to this email. Kindly download the document from the attachment.</p>` +
|
||||
`</div></div><div><p>This is an automated email from ${appName}. For any queries regarding this email, please contact the sender ${replyTo} directly. ` +
|
||||
`If you think this email is inappropriate or spam, you may file a complaint with ${appName}${opurl}.</p></div></div></body></html>`,
|
||||
};
|
||||
mailRes = await axios.post(`${cloudServerUrl}/functions/sendmailv3`, params, {
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'X-Parse-Application-Id': process.env.APP_ID,
|
||||
'X-Parse-Master-Key': process.env.MASTER_KEY,
|
||||
},
|
||||
});
|
||||
}
|
||||
return mailRes.data?.result;
|
||||
} catch (error) {
|
||||
const msg =
|
||||
error?.response?.data?.error ||
|
||||
error?.response?.data ||
|
||||
error?.message ||
|
||||
'Something went wrong.';
|
||||
throw new Parse.Error(400, msg);
|
||||
}
|
||||
} else {
|
||||
throw new Parse.Error(Parse.Error.INVALID_QUERY, 'please provide parameters.');
|
||||
}
|
||||
} catch (err) {
|
||||
console.log('Err in forwardDoc', err);
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,3 @@
|
||||
import { appName } from '../../Utils.js';
|
||||
|
||||
// `GetLogoByDomain` is used to get logo by domain as well as check any tenant exist or not in db
|
||||
export default async function GetLogoByDomain(request) {
|
||||
const domain = request.params.domain;
|
||||
@@ -9,14 +7,14 @@ export default async function GetLogoByDomain(request) {
|
||||
const res = await tenantCreditsQuery.first();
|
||||
if (res) {
|
||||
const updateRes = JSON.parse(JSON.stringify(res));
|
||||
return { logo: updateRes?.Logo, appname: appName, user: 'exist' };
|
||||
return { logo: updateRes?.Logo, user: 'exist' };
|
||||
} else {
|
||||
const tenantCreditsQuery = new Parse.Query('partners_Tenant');
|
||||
const tenantRes = await tenantCreditsQuery.first();
|
||||
if (tenantRes) {
|
||||
return { logo: '', appname: appName, user: 'exist' };
|
||||
return { logo: '', user: 'exist' };
|
||||
} else {
|
||||
return { logo: '', appname: appName, user: 'not_exist' };
|
||||
return { logo: '', user: 'not_exist' };
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
|
||||
@@ -4,7 +4,7 @@ export default async function Newsletter(request) {
|
||||
const email = request.params.email;
|
||||
const domain = request.params.domain;
|
||||
try {
|
||||
const envAppId = process.env.REACT_APP_APPID || 'opensign';
|
||||
const envAppId = process.env.REACT_APP_APPID || 'legadranaxn';
|
||||
const headers = { 'Content-Type': 'application/json', 'X-Parse-Application-Id': envAppId };
|
||||
const envProdServer = process.env.REACT_APP_SERVERURL || 'https://app.opensignlabs.com/api/app';
|
||||
const newsletter = await axios.post(
|
||||
|
||||
@@ -11,7 +11,7 @@ async function getDocument(docId) {
|
||||
query.include('Placeholders');
|
||||
query.notEqualTo('IsArchive', true);
|
||||
const res = await query.first({ useMasterKey: true });
|
||||
const _res = res?.toJSON();
|
||||
const _res = res.toJSON();
|
||||
return _res?.ExtUserPtr?.objectId;
|
||||
} catch (err) {
|
||||
console.log('err ', err);
|
||||
|
||||
@@ -1,13 +1,4 @@
|
||||
async function TemplateBeforeSave(request) {
|
||||
if (!request.original) {
|
||||
const TimeToCompleteDays = request.object.get('TimeToCompleteDays') || 15;
|
||||
const RemindOnceInEvery = request?.object?.get('RemindOnceInEvery') || 5;
|
||||
const AutoReminder = request?.object?.get('AutomaticReminders') || false;
|
||||
const reminderCount = TimeToCompleteDays / RemindOnceInEvery;
|
||||
if (AutoReminder && reminderCount > 15) {
|
||||
throw new Parse.Error(Parse.Error.INVALID_QUERY, 'only 15 reminder allowed');
|
||||
}
|
||||
}
|
||||
try {
|
||||
if (!request.original) {
|
||||
// below code is used to update template when user sent template or self signed
|
||||
|
||||
@@ -32,11 +32,8 @@ async function sendMail(document) {
|
||||
month: 'long',
|
||||
year: 'numeric',
|
||||
});
|
||||
const sender = document.ExtUserPtr.Email;
|
||||
let signerMail = document.Placeholders;
|
||||
const senderName =
|
||||
document.ExtUserPtr.Name;
|
||||
const senderEmail =
|
||||
document.ExtUserPtr.Email;
|
||||
|
||||
if (document.SendinOrder) {
|
||||
signerMail = signerMail.slice();
|
||||
@@ -44,6 +41,7 @@ async function sendMail(document) {
|
||||
}
|
||||
for (let i = 0; i < signerMail.length; i++) {
|
||||
try {
|
||||
const imgPng = 'https://qikinnovation.ams3.digitaloceanspaces.com/logo.png';
|
||||
let url = `${serverUrl}/functions/sendmailv3`;
|
||||
const headers = { 'Content-Type': 'application/json', 'X-Parse-Application-Id': appId };
|
||||
const objectId = signerMail[i]?.signerObjId;
|
||||
@@ -57,7 +55,9 @@ async function sendMail(document) {
|
||||
encodeBase64 = btoa(`${document.objectId}/${signerMail[i].email}`);
|
||||
}
|
||||
let signPdf = `${hostUrl}/login/${encodeBase64}`;
|
||||
const openSignUrl = 'https://www.opensignlabs.com/';
|
||||
const orgName = document.ExtUserPtr.Company ? document.ExtUserPtr.Company : '';
|
||||
const themeBGcolor = '#47a3ad';
|
||||
const senderObj = document?.ExtUserPtr;
|
||||
const mailBody = document?.ExtUserPtr?.TenantId?.RequestBody || '';
|
||||
const mailSubject = document?.ExtUserPtr?.TenantId?.RequestSubject || '';
|
||||
@@ -70,8 +70,10 @@ async function sendMail(document) {
|
||||
'</body></html>';
|
||||
const variables = {
|
||||
document_title: document?.Name,
|
||||
sender_name: senderName,
|
||||
sender_mail: senderEmail,
|
||||
sender_name:
|
||||
senderObj?.Name,
|
||||
sender_mail:
|
||||
senderObj?.Email,
|
||||
sender_phone: senderObj?.Phone || '',
|
||||
receiver_name: existSigner?.Name || '',
|
||||
receiver_email: existSigner?.Email || signerMail[i].email,
|
||||
@@ -82,22 +84,41 @@ async function sendMail(document) {
|
||||
};
|
||||
replaceVar = replaceMailVaribles(mailSubject, htmlReqBody, variables);
|
||||
}
|
||||
const mailparam = {
|
||||
senderName: senderName,
|
||||
senderMail: senderEmail,
|
||||
title: document.Name,
|
||||
organization: orgName,
|
||||
localExpireDate: localExpireDate,
|
||||
sigingUrl: signPdf,
|
||||
};
|
||||
|
||||
let params = {
|
||||
extUserId: document.ExtUserPtr.objectId,
|
||||
recipient: objectId ? existSigner?.Email : signerMail[i].email,
|
||||
subject: replaceVar?.subject ? replaceVar?.subject : mailTemplate(mailparam).subject,
|
||||
subject: replaceVar?.subject
|
||||
? replaceVar?.subject
|
||||
: `${document.ExtUserPtr.Name} has requested you to sign "${document.Name}"`,
|
||||
from:
|
||||
document.ExtUserPtr.Email,
|
||||
replyto: senderEmail || '',
|
||||
html: replaceVar?.body ? replaceVar?.body : mailTemplate(mailparam).body,
|
||||
sender,
|
||||
replyto:
|
||||
sender ||
|
||||
'',
|
||||
html: replaceVar?.body
|
||||
? replaceVar?.body
|
||||
: "<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:white;padding-bottom:20px;'><div style='padding:10px 10px 0 10px'><img src=" +
|
||||
imgPng +
|
||||
" height='50' style='padding:20px;width:170px;height:40px;' /></div><div style='padding:2px;font-family:system-ui;background-color:" +
|
||||
themeBGcolor +
|
||||
";'><p style='font-size:20px;font-weight:400;color:white;padding-left:20px;' > Digital Signature Request</p></div><div><p style='padding:20px;font-family:system-ui;font-size:14px;margin-bottom:10px;'> " +
|
||||
document.ExtUserPtr.Name +
|
||||
' has requested you to review and sign <strong> ' +
|
||||
document.Name +
|
||||
"</strong>.</p><div style='padding: 5px 0px 5px 25px;display:flex;flex-direction:row;justify-content:space-around;'><table><tr><td style='font-weight:bold;font-family:sans-serif;font-size:15px'>Sender</td><td></td><td style='color:#626363;font-weight:bold'>" +
|
||||
sender +
|
||||
"</td></tr><tr><td style='font-weight:bold;font-family:sans-serif;font-size:15px'>Organization</td><td></td><td style='color:#626363;font-weight:bold'> " +
|
||||
orgName +
|
||||
"</td></tr><tr><td style='font-weight:bold;font-family:sans-serif;font-size:15px'>Expires on</td><td></td><td style='color:#626363;font-weight:bold'>" +
|
||||
localExpireDate +
|
||||
"</td></tr><tr><td></td><td></td></tr></table></div><div style='margin-left:70px;'><a target=_blank href=" +
|
||||
signPdf +
|
||||
"><button style='padding:12px 12px 12px 12px;background-color:#d46b0f;color:white;border:0px;box-shadow:rgba(0, 0, 0, 0.05) 0px 6px 24px 0px,rgba(0, 0, 0, 0.08) 0px 0px 0px 1px;font-weight:bold;margin-top:30px;'>Sign here</button></a></div><div style='display:flex;justify-content:center;margin-top:10px;'></div></div></div><div><p> This is an automated email from OpenSign™. For any queries regarding this email, please contact the sender " +
|
||||
sender +
|
||||
' directly.If you think this email is inappropriate or spam, you may file a complaint with OpenSign™ <a href=' +
|
||||
openSignUrl +
|
||||
' target=_blank>here</a>.</p></div></div></body></html>',
|
||||
};
|
||||
const sendMail = await axios.post(url, params, { headers: headers });
|
||||
// if (sendMail.data.result.status === 'success') {
|
||||
|
||||
@@ -8,22 +8,25 @@ import dotenv from 'dotenv';
|
||||
import GenerateCertificate from './pdf/GenerateCertificate.js';
|
||||
import { getSecureUrl } from '../../Utils.js';
|
||||
dotenv.config();
|
||||
const eSignName = 'OpenSign';
|
||||
const eSignName = 'opensign';
|
||||
const eSigncontact = 'hello@opensignlabs.com';
|
||||
|
||||
// `uploadFile` is used to create url in from pdfFile
|
||||
async function uploadFile(pdfName, filepath) {
|
||||
async function uploadFile(
|
||||
pdfName,
|
||||
filepath,
|
||||
) {
|
||||
try {
|
||||
const filedata = fs.readFileSync(filepath);
|
||||
let fileUrl;
|
||||
const file = new Parse.File(pdfName, [...filedata], 'application/pdf');
|
||||
await file.save({ useMasterKey: true });
|
||||
const fileRes = getSecureUrl(file.url());
|
||||
fileUrl = fileRes.url;
|
||||
const file = new Parse.File(pdfName, [...filedata], 'application/pdf');
|
||||
await file.save({ useMasterKey: true });
|
||||
const fileRes = getSecureUrl(file.url());
|
||||
fileUrl = fileRes.url;
|
||||
return { imageUrl: fileUrl };
|
||||
} catch (err) {
|
||||
console.log('Err ', err);
|
||||
// `unlinkCertificate` is used to remove exported certificate file from exports folder
|
||||
// `unlinkCertificate` is used to remove exported signed pdf file from exports folder
|
||||
unlinkCertificate(filepath);
|
||||
}
|
||||
}
|
||||
@@ -68,7 +71,7 @@ export default async function generateCertificatebydocId(req) {
|
||||
// `pdflibAddPlaceholder` is used to add code of only digitial sign in certificate
|
||||
pdflibAddPlaceholder({
|
||||
pdfDoc: certificatePdf,
|
||||
reason: `Digitally signed by ${eSignName}.`,
|
||||
reason: 'Digitally signed by OpenSign.',
|
||||
location: 'n/a',
|
||||
name: eSignName,
|
||||
contactInfo: eSigncontact,
|
||||
@@ -83,7 +86,10 @@ export default async function generateCertificatebydocId(req) {
|
||||
|
||||
//below is used to save signed certificate in exports folder
|
||||
fs.writeFileSync(certificatePath, signedCertificate);
|
||||
const file = await uploadFile('certificate.pdf', certificatePath);
|
||||
const file = await uploadFile(
|
||||
'certificate.pdf',
|
||||
certificatePath,
|
||||
);
|
||||
const updateDoc = new Parse.Object('contracts_Document');
|
||||
updateDoc.id = doc.objectId;
|
||||
updateDoc.set('CertificateUrl', file.imageUrl);
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
import { exec } from 'child_process';
|
||||
|
||||
export default function DigitalSign(pdf, pfx, details) {
|
||||
const signcmd = `java -jar PDFDigitalSigner.jar "${pdf}" "${pfx.name}" "${pfx.passphrase}" "${details.name}" "${details.location}" "${details.reason}"`;
|
||||
// const signcmd = `java -jar PDFDigitalSigner.jar "${pdf}" keystore.pfx opensign "${details.name}" "${details.location}" "${details.reason}"`;
|
||||
return new Promise((resolve, reject) => {
|
||||
exec(signcmd, (error, stdout, stderr) => {
|
||||
if (error) {
|
||||
reject(`Error: ${error.message}`);
|
||||
}
|
||||
if (stderr) {
|
||||
reject(`stderr: ${stderr}`);
|
||||
}
|
||||
// Resolve the promise with the output
|
||||
resolve(stdout.trim());
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
export async function retryAsync(fn, args = [], retries = 3, delay = 2000) {
|
||||
for (let attempt = 1; attempt <= retries; attempt++) {
|
||||
try {
|
||||
const response = await fn(...args); // Try executing the async function
|
||||
if (response) return { response, attempt }; // Stop retrying if response is received
|
||||
} catch (error) {
|
||||
if (attempt < retries) {
|
||||
console.log(`Attempt ${attempt} failed. Retrying in ${delay / 1000} seconds...\n`);
|
||||
await new Promise(resolve => setTimeout(resolve, delay)); // Wait before retrying
|
||||
} else {
|
||||
return { error, attempt };
|
||||
// throw new Error(error);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,7 @@
|
||||
import { PDFDocument, rgb } from 'pdf-lib';
|
||||
import { PDFDocument, StandardFonts, rgb } from 'pdf-lib';
|
||||
import fs from 'node:fs';
|
||||
import fontkit from '@pdf-lib/fontkit';
|
||||
import {
|
||||
formatTimeInTimezone,
|
||||
} from '../../../Utils.js';
|
||||
import { formatTimeInTimezone } from '../../../Utils.js';
|
||||
|
||||
export default async function GenerateCertificate(docDetails) {
|
||||
const timezone = docDetails?.ExtUserPtr?.Timezone || '';
|
||||
@@ -75,12 +73,12 @@ export default async function GenerateCertificate(docDetails) {
|
||||
borderColor: borderColor,
|
||||
borderWidth: 1,
|
||||
});
|
||||
page.drawImage(pngImage, {
|
||||
x: 30,
|
||||
y: 790,
|
||||
width: 100,
|
||||
height: 25,
|
||||
});
|
||||
page.drawImage(pngImage, {
|
||||
x: 30,
|
||||
y: 790,
|
||||
width: 100,
|
||||
height: 25,
|
||||
});
|
||||
|
||||
page.drawText(generatedOn, {
|
||||
x: 320,
|
||||
|
||||
@@ -1,37 +1,34 @@
|
||||
import fs from 'node:fs';
|
||||
import axios from 'axios';
|
||||
import { SignPdf } from '@signpdf/signpdf';
|
||||
import { P12Signer } from '@signpdf/signer-p12';
|
||||
import { pdflibAddPlaceholder } from '@signpdf/placeholder-pdf-lib';
|
||||
import { PDFDocument } from 'pdf-lib';
|
||||
import {
|
||||
cloudServerUrl,
|
||||
replaceMailVaribles,
|
||||
saveFileUsage,
|
||||
getSecureUrl,
|
||||
appName,
|
||||
} from '../../../Utils.js';
|
||||
import GenerateCertificate from './GenerateCertificate.js';
|
||||
import { pdflibAddPlaceholder } from '@signpdf/placeholder-pdf-lib';
|
||||
import { Placeholder } from './Placeholder.js';
|
||||
import { SignPdf } from '@signpdf/signpdf';
|
||||
import { P12Signer } from '@signpdf/signer-p12';
|
||||
|
||||
const serverUrl = cloudServerUrl; // process.env.SERVER_URL;
|
||||
const APPID = process.env.APP_ID;
|
||||
const masterKEY = process.env.MASTER_KEY;
|
||||
const eSignName = 'OpenSign';
|
||||
const eSignName = 'opensign';
|
||||
const eSigncontact = 'hello@opensignlabs.com';
|
||||
const logo =
|
||||
"<img src='https://qikinnovation.ams3.digitaloceanspaces.com/logo.png' height='50' style='padding:20px'/>";
|
||||
const opurl = ` <a href=www.opensignlabs.com target=_blank>here</a>`;
|
||||
|
||||
// `updateDoc` is used to create url in from pdfFile
|
||||
async function uploadFile(pdfName, filepath) {
|
||||
async function uploadFile(
|
||||
pdfName,
|
||||
filepath,
|
||||
) {
|
||||
try {
|
||||
const filedata = fs.readFileSync(filepath);
|
||||
let fileUrl;
|
||||
const file = new Parse.File(pdfName, [...filedata], 'application/pdf');
|
||||
await file.save({ useMasterKey: true });
|
||||
const fileRes = getSecureUrl(file.url());
|
||||
fileUrl = fileRes.url;
|
||||
const file = new Parse.File(pdfName, [...filedata], 'application/pdf');
|
||||
await file.save({ useMasterKey: true });
|
||||
const fileRes = getSecureUrl(file.url());
|
||||
fileUrl = fileRes.url;
|
||||
|
||||
return { imageUrl: fileUrl };
|
||||
} catch (err) {
|
||||
@@ -105,18 +102,21 @@ async function sendNotifyMail(doc, signUser, mailProvider) {
|
||||
const creatorEmail = doc.ExtUserPtr.Email;
|
||||
const signerName = signUser.Name;
|
||||
const signerEmail = signUser.Email;
|
||||
const mailLogo = 'https://qikinnovation.ams3.digitaloceanspaces.com/logo.png';
|
||||
const viewDocUrl = `${process.env.PUBLIC_URL}/recipientSignPdf/${doc.objectId}`;
|
||||
const subject = `Document "${pdfName}" has been signed by ${signerName}`;
|
||||
const body =
|
||||
"<html><head><meta http-equiv='Content-Type' content='text/html; charset=UTF-8'/></head><body><div style='background-color:#f5f5f5;padding:20px'><div style='background-color:white'>" +
|
||||
`<div>${logo}</div><div style='padding:2px;font-family:system-ui;background-color:#47a3ad'><p style='font-size:20px;font-weight:400;color:white;padding-left:20px'>Document signed by ${signerName}</p>` +
|
||||
`</div><div style='padding:20px;font-family:system-ui;font-size:14px'><p>Dear ${creatorName},</p><p>${pdfName} has been signed by ${signerName} "${signerEmail}" successfully</p>` +
|
||||
`<p><a href=${viewDocUrl} target=_blank>View Document</a></p></div></div><div><p>This is an automated email from ${appName}. For any queries regarding this email, ` +
|
||||
`please contact the sender ${creatorEmail} directly. If you think this email is inappropriate or spam, you may file a complaint with ${appName}${opurl}.</p></div></div></body></html>`;
|
||||
"<html><head><meta http-equiv='Content-Type' content='text/html; charset=UTF-8' /></head><body><div style='background-color:#f5f5f5;padding:20px'><div style='box-shadow:rgba(0, 0, 0, 0.1) 0px 4px 12px;background-color:white;'>" +
|
||||
`<div><img src=${mailLogo} height='50' style='padding:20px' /></div><div style='padding:2px;font-family:system-ui;background-color:#47a3ad;'>` +
|
||||
`<p style='font-size:20px;font-weight:400;color:white;padding-left:20px'>Document signed by ${signerName}</p>` +
|
||||
`</div><div style='padding:20px;font-family:system-ui;font-size:14px'><p>Dear ${creatorName},</p>` +
|
||||
`<p>${pdfName} has been signed by ${signerName} "${signerEmail}" successfully</p>` +
|
||||
`<p><a href=${viewDocUrl} target=_blank>View Document</a></p>` +
|
||||
`</div></div><div><p>This is an automated email from OpenSign™. For any queries regarding this email, please contact the sender ${creatorEmail} directly. If you think this email is inappropriate or spam, you may file a complaint with OpenSign™ <a href=www.opensignlabs.com target=_blank>here</a>.</p></div></div></body></html>`;
|
||||
|
||||
const params = {
|
||||
extUserId: sender.objectId,
|
||||
from: appName,
|
||||
from: 'OpenSign™',
|
||||
recipient: creatorEmail,
|
||||
subject: subject,
|
||||
pdfName: pdfName,
|
||||
@@ -142,6 +142,7 @@ async function sendCompletedMail(obj) {
|
||||
const doc = obj.doc;
|
||||
const sender = obj.doc.ExtUserPtr;
|
||||
const pdfName = doc.Name;
|
||||
const mailLogo = 'https://qikinnovation.ams3.digitaloceanspaces.com/logo.png';
|
||||
let signersMail;
|
||||
if (doc?.Signers?.length > 0) {
|
||||
const isOwnerExistsinSigners = doc?.Signers?.find(x => x.Email === sender.Email);
|
||||
@@ -154,11 +155,12 @@ async function sendCompletedMail(obj) {
|
||||
const recipient = signersMail;
|
||||
let subject = `Document "${pdfName}" has been signed by all parties`;
|
||||
let body =
|
||||
"<html><head><meta http-equiv='Content-Type' content='text/html; charset=UTF-8' /></head><body><div style='background-color:#f5f5f5;padding:20px'><div style='background-color:white'>" +
|
||||
`<div>${logo}</div><div style='padding:2px;font-family:system-ui;background-color:#47a3ad'><p style='font-size:20px;font-weight:400;color:white;padding-left:20px'>Document signed successfully</p></div><div>` +
|
||||
`<p style='padding:20px;font-family:system-ui;font-size:14px'>All parties have successfully signed the document <b>"${pdfName}"</b>. Kindly download the document from the attachment.</p>` +
|
||||
`</div></div><div><p>This is an automated email from ${appName}. For any queries regarding this email, please contact the sender ${sender.Email} directly.` +
|
||||
`If you think this email is inappropriate or spam, you may file a complaint with ${appName}${opurl}.</p></div></div></body></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='background-color:white;'>" +
|
||||
`<div><img src=${mailLogo} height='50' style='padding:20px'/></div><div style='padding:2px;font-family:system-ui; background-color: #47a3ad;'>` +
|
||||
`<p style='font-size:20px;font-weight:400;color:white;padding-left:20px;'>Document signed successfully</p></div><div>` +
|
||||
`<p style='padding:20px;font-family:system-ui;font-size:14px;'>All parties have successfully signed the document <b>"${pdfName}"</b>. Kindly download the document from the attachment.</p>` +
|
||||
`</div> </div><div><p>This is an automated email from OpenSign™. For any queries regarding this email, please contact the sender ${sender.Email} directly.` +
|
||||
'If you think this email is inappropriate or spam, you may file a complaint with OpenSign™ <a href=www.opensignlabs.com target=_blank>here</a>.</p></div></div></body></html>';
|
||||
|
||||
if (obj?.isCustomMail) {
|
||||
const tenant = sender?.TenantId;
|
||||
@@ -196,7 +198,8 @@ async function sendCompletedMail(obj) {
|
||||
|
||||
const variables = {
|
||||
document_title: pdfName,
|
||||
sender_name: sender.Name,
|
||||
sender_name:
|
||||
sender.Name,
|
||||
sender_mail: doc?.SenderMail || sender.Email,
|
||||
sender_phone: sender?.Phone || '',
|
||||
receiver_name: sender.Name,
|
||||
@@ -213,44 +216,49 @@ async function sendCompletedMail(obj) {
|
||||
const params = {
|
||||
extUserId: sender.objectId,
|
||||
url: url,
|
||||
from: appName,
|
||||
replyto: doc?.ExtUserPtr?.Email || '',
|
||||
from:
|
||||
'OpenSign™',
|
||||
replyto:
|
||||
doc?.ExtUserPtr?.Email ||
|
||||
'',
|
||||
recipient: recipient,
|
||||
subject: subject,
|
||||
pdfName: pdfName,
|
||||
html: body,
|
||||
mailProvider: obj.mailProvider,
|
||||
bcc: Bcc,
|
||||
certificatePath: `./exports/signed_certificate_${doc.objectId}.pdf`,
|
||||
certificatePath: `./exports/certificate_${doc.objectId}.pdf`,
|
||||
filename: obj?.filename,
|
||||
};
|
||||
try {
|
||||
const res = await axios.post(serverUrl + '/functions/sendmailv3', params, {
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'X-Parse-Application-Id': APPID,
|
||||
'X-Parse-Master-Key': masterKEY,
|
||||
},
|
||||
});
|
||||
// console.log('res', res.data.result);
|
||||
if (res.data?.result?.status !== 'success') {
|
||||
fs.unlinkSync(`./exports/signed_certificate_${doc.objectId}.pdf`);
|
||||
}
|
||||
} catch (err) {
|
||||
fs.unlinkSync(`./exports/signed_certificate_${doc.objectId}.pdf`);
|
||||
}
|
||||
const res = await axios.post(serverUrl + '/functions/sendmailv3', params, {
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'X-Parse-Application-Id': APPID,
|
||||
'X-Parse-Master-Key': masterKEY,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// `sendMailsaveCertifcate` is used send completion mail and update complete status of document
|
||||
async function sendMailsaveCertifcate(doc, pfx, isCustomMail, mailProvider, filename) {
|
||||
async function sendMailsaveCertifcate(
|
||||
doc,
|
||||
P12Buffer,
|
||||
isCustomMail,
|
||||
mailProvider,
|
||||
filename,
|
||||
) {
|
||||
const certificate = await GenerateCertificate(doc);
|
||||
const certificatePdf = await PDFDocument.load(certificate);
|
||||
const P12Buffer = fs.readFileSync(pfx.name);
|
||||
const p12 = new P12Signer(P12Buffer, { passphrase: pfx.passphrase || null });
|
||||
let passphrase = process.env.PASS_PHRASE;
|
||||
if (doc?.ExtUserPtr?.TenantId?.PfxFile?.password) {
|
||||
passphrase = doc?.ExtUserPtr?.TenantId?.PfxFile?.password;
|
||||
}
|
||||
const p12 = new P12Signer(P12Buffer, { passphrase: passphrase || null });
|
||||
// `pdflibAddPlaceholder` is used to add code of only digitial sign in certificate
|
||||
pdflibAddPlaceholder({
|
||||
pdfDoc: certificatePdf,
|
||||
reason: `Digitally signed by ${eSignName}.`,
|
||||
reason: 'Digitally signed by OpenSign.',
|
||||
location: 'n/a',
|
||||
name: eSignName,
|
||||
contactInfo: eSigncontact,
|
||||
@@ -262,11 +270,13 @@ async function sendMailsaveCertifcate(doc, pfx, isCustomMail, mailProvider, file
|
||||
const certificateOBJ = new SignPdf();
|
||||
// `signedCertificate` is used to sign certificate digitally
|
||||
const signedCertificate = await certificateOBJ.sign(CertificateBuffer, p12);
|
||||
const certificatePath = `./exports/signed_certificate_${doc.objectId}.pdf`;
|
||||
|
||||
const certificatePath = `./exports/certificate_${doc.objectId}.pdf`;
|
||||
//below is used to save signed certificate in exports folder
|
||||
fs.writeFileSync(certificatePath, signedCertificate);
|
||||
const file = await uploadFile('certificate.pdf', certificatePath);
|
||||
const file = await uploadFile(
|
||||
'certificate.pdf',
|
||||
certificatePath,
|
||||
);
|
||||
const body = { CertificateUrl: file.imageUrl };
|
||||
await axios.put(serverUrl + '/classes/contracts_Document/' + doc.objectId, body, {
|
||||
headers: {
|
||||
@@ -282,7 +292,6 @@ async function sendMailsaveCertifcate(doc, pfx, isCustomMail, mailProvider, file
|
||||
sendCompletedMail({ isCustomMail, doc, mailProvider, filename });
|
||||
}
|
||||
saveFileUsage(CertificateBuffer.length, file.imageUrl, doc?.CreatedBy?.objectId);
|
||||
fs.unlinkSync(pfx.name);
|
||||
}
|
||||
/**
|
||||
*
|
||||
@@ -291,11 +300,9 @@ async function sendMailsaveCertifcate(doc, pfx, isCustomMail, mailProvider, file
|
||||
* @returns if success {status, data} else {status, message}
|
||||
*/
|
||||
async function PDF(req) {
|
||||
const docId = req.params.docId;
|
||||
const randomNumber = Math.floor(Math.random() * 5000);
|
||||
const pfxname = `keystore_${randomNumber}.pfx`;
|
||||
try {
|
||||
const userIP = req.headers['x-real-ip']; // client IPaddress
|
||||
const docId = req.params.docId;
|
||||
const reqUserId = req.params.userId;
|
||||
const isCustomMail = req.params.isCustomCompletionMail || false;
|
||||
const mailProvider = req.params.mailProvider || '';
|
||||
@@ -343,9 +350,9 @@ async function PDF(req) {
|
||||
pfxFile = _resDoc?.ExtUserPtr?.TenantId?.PfxFile?.base64;
|
||||
passphrase = _resDoc?.ExtUserPtr?.TenantId?.PfxFile?.password;
|
||||
}
|
||||
const pfx = { name: pfxname, passphrase: passphrase };
|
||||
// const P12Buffer = fs.readFileSync();
|
||||
const P12Buffer = Buffer.from(pfxFile, 'base64');
|
||||
fs.writeFileSync(pfxname, P12Buffer);
|
||||
const p12Cert = new P12Signer(P12Buffer, { passphrase: passphrase || null });
|
||||
const UserPtr = { __type: 'Pointer', className: className, objectId: signUser.objectId };
|
||||
const obj = { UserPtr: UserPtr, SignedUrl: '', Activity: 'Signed', ipAddress: userIP };
|
||||
let updateAuditTrail;
|
||||
@@ -364,12 +371,12 @@ async function PDF(req) {
|
||||
} else {
|
||||
isCompleted = true;
|
||||
}
|
||||
const randomNumber = Math.floor(Math.random() * 5000);
|
||||
// below regex is used to replace all word with "_" except A to Z, a to z, numbers
|
||||
const docName = _resDoc?.Name?.replace(/[^a-zA-Z0-9._-]/g, '_')?.toLowerCase();
|
||||
const filename = docName?.length > 100 ? docName?.slice(0, 100) : docName;
|
||||
const name = `${filename}_${randomNumber}.pdf`;
|
||||
let filePath = `./exports/${name}`;
|
||||
let signedFilePath = `./exports/signed_${name}`;
|
||||
const name = `signed_${filename}_${randomNumber}.pdf`;
|
||||
const filePath = `./exports/${name}`;
|
||||
let pdfSize = PdfBuffer.length;
|
||||
if (isCompleted) {
|
||||
const signersName = _resDoc.Signers?.map(x => x.Name + ' <' + x.Email + '>');
|
||||
@@ -383,11 +390,9 @@ async function PDF(req) {
|
||||
form.updateFieldAppearances();
|
||||
// Flattens the form, converting all form fields into non-editable, static content
|
||||
form.flatten();
|
||||
const p12Cert = new P12Signer(P12Buffer, { passphrase: passphrase || null });
|
||||
signedFilePath = `./exports/signed_${name}`;
|
||||
Placeholder({
|
||||
pdfDoc: pdfDoc,
|
||||
reason: `Digitally signed by ${eSignName} for ${reason}`,
|
||||
reason: 'Digitally signed by OpenSign for ' + reason,
|
||||
location: 'n/a',
|
||||
name: eSignName,
|
||||
contactInfo: eSigncontact,
|
||||
@@ -401,18 +406,19 @@ async function PDF(req) {
|
||||
const signedDocs = await OBJ.sign(PdfBuffer, p12Cert);
|
||||
|
||||
//`saveUrl` is used to save signed pdf in exports folder
|
||||
fs.writeFileSync(signedFilePath, signedDocs);
|
||||
fs.writeFileSync(filePath, signedDocs);
|
||||
pdfSize = signedDocs.length;
|
||||
console.log(`✅ PDF digitally signed created: ${signedFilePath} \n`);
|
||||
} else {
|
||||
//`saveUrl` is used to save signed pdf in exports folder
|
||||
fs.writeFileSync(signedFilePath, PdfBuffer);
|
||||
fs.writeFileSync(filePath, PdfBuffer);
|
||||
pdfSize = PdfBuffer.length;
|
||||
console.log(`New Signed PDF created called: ${signedFilePath}`);
|
||||
}
|
||||
|
||||
// `uploadFile` is used to upload pdf to aws s3 and get it's url
|
||||
const data = await uploadFile(`signed_${name}`, signedFilePath);
|
||||
const data = await uploadFile(
|
||||
name,
|
||||
filePath,
|
||||
);
|
||||
|
||||
if (data && data.imageUrl) {
|
||||
// `axios` is used to update signed pdf url in contracts_Document classes for given DocId
|
||||
@@ -429,13 +435,17 @@ async function PDF(req) {
|
||||
saveFileUsage(pdfSize, data.imageUrl, _resDoc?.CreatedBy?.objectId);
|
||||
if (updatedDoc && updatedDoc.isCompleted) {
|
||||
const doc = { ..._resDoc, AuditTrail: updatedDoc.AuditTrail, SignedUrl: data.imageUrl };
|
||||
sendMailsaveCertifcate(doc, pfx, isCustomMail, mailProvider, `signed_${name}`);
|
||||
} else {
|
||||
fs.unlinkSync(pfxname);
|
||||
sendMailsaveCertifcate(
|
||||
doc,
|
||||
P12Buffer,
|
||||
isCustomMail,
|
||||
mailProvider,
|
||||
name,
|
||||
);
|
||||
}
|
||||
// `fs.unlinkSync` is used to remove exported signed pdf file from exports folder
|
||||
fs.unlinkSync(signedFilePath);
|
||||
// console.log(`New Signed PDF created called: ${filePath}`);
|
||||
fs.unlinkSync(filePath);
|
||||
console.log(`New Signed PDF created called: ${filePath}`);
|
||||
if (updatedDoc.message === 'success') {
|
||||
return { status: 'success', data: data.imageUrl };
|
||||
} else {
|
||||
@@ -451,15 +461,6 @@ async function PDF(req) {
|
||||
}
|
||||
} catch (err) {
|
||||
console.log('Err in signpdf', err);
|
||||
const body = { DebugginLog: err?.message };
|
||||
try {
|
||||
await axios.put(serverUrl + '/classes/contracts_Document/' + docId, body, {
|
||||
headers: { 'X-Parse-Application-Id': APPID, 'X-Parse-Master-Key': masterKEY },
|
||||
});
|
||||
} catch (err) {
|
||||
console.log('err in saving debugginglog', err);
|
||||
}
|
||||
fs.unlinkSync(pfxname);
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,8 +35,7 @@ const makeEmail = async (
|
||||
bcc,
|
||||
filename,
|
||||
certificatePath,
|
||||
replyto,
|
||||
testPdf
|
||||
replyto
|
||||
) => {
|
||||
const publicUrl = new URL(process.env.SERVER_URL);
|
||||
const htmlContent = html;
|
||||
@@ -47,7 +46,7 @@ const makeEmail = async (
|
||||
let str;
|
||||
if (url) {
|
||||
let attachments;
|
||||
let Pdf = fs.createWriteStream(testPdf);
|
||||
let Pdf = fs.createWriteStream('test.pdf');
|
||||
const writeToLocalDisk = () => {
|
||||
return new Promise((resolve, reject) => {
|
||||
const isSecure =
|
||||
@@ -162,8 +161,6 @@ export default async function sendMailGmailProvider(_extRes, template) {
|
||||
// Construct email message
|
||||
const from = sender || _extRes.Email || 'me';
|
||||
const to = receiver;
|
||||
const randomNumber = Math.floor(Math.random() * 5000);
|
||||
const testPdf = `test_${randomNumber}.pdf`;
|
||||
const email = await makeEmail(
|
||||
to,
|
||||
from,
|
||||
@@ -174,8 +171,7 @@ export default async function sendMailGmailProvider(_extRes, template) {
|
||||
bcc,
|
||||
filename,
|
||||
certificatePath,
|
||||
replyto,
|
||||
testPdf
|
||||
replyto
|
||||
);
|
||||
// Update Gmail client with new access token
|
||||
const newGmail = createGmailClient(access_token);
|
||||
@@ -193,13 +189,6 @@ export default async function sendMailGmailProvider(_extRes, template) {
|
||||
console.log('Err in unlink certificate sendmailgmail provider');
|
||||
}
|
||||
}
|
||||
if (fs.existsSync(testPdf)) {
|
||||
try {
|
||||
fs.unlinkSync(testPdf);
|
||||
} catch (err) {
|
||||
console.log('Err in unlink pdf sendmailv3');
|
||||
}
|
||||
}
|
||||
return { code: 200, message: 'Email sent successfully' };
|
||||
} catch (error) {
|
||||
console.error('Error sending email:', error);
|
||||
|
||||
@@ -29,9 +29,7 @@ async function sendMailProvider(req, plan, monthchange) {
|
||||
}
|
||||
}
|
||||
if (req.params.url) {
|
||||
const randomNumber = Math.floor(Math.random() * 5000);
|
||||
const testPdf = `test_${randomNumber}.pdf`;
|
||||
let Pdf = fs.createWriteStream(testPdf);
|
||||
let Pdf = fs.createWriteStream('test.pdf');
|
||||
const writeToLocalDisk = () => {
|
||||
return new Promise((resolve, reject) => {
|
||||
const isSecure =
|
||||
@@ -131,13 +129,6 @@ async function sendMailProvider(req, plan, monthchange) {
|
||||
console.log('Err in unlink certificate sendmailv3');
|
||||
}
|
||||
}
|
||||
if (fs.existsSync(testPdf)) {
|
||||
try {
|
||||
fs.unlinkSync(testPdf);
|
||||
} catch (err) {
|
||||
console.log('Err in unlink pdf sendmailv3');
|
||||
}
|
||||
}
|
||||
return { status: 'success' };
|
||||
}
|
||||
} else {
|
||||
@@ -155,13 +146,6 @@ async function sendMailProvider(req, plan, monthchange) {
|
||||
console.log('Err in unlink certificate sendmailv3');
|
||||
}
|
||||
}
|
||||
if (fs.existsSync(testPdf)) {
|
||||
try {
|
||||
fs.unlinkSync(testPdf);
|
||||
} catch (err) {
|
||||
console.log('Err in unlink pdf sendmailv3');
|
||||
}
|
||||
}
|
||||
return { status: 'success' };
|
||||
}
|
||||
} else {
|
||||
@@ -172,13 +156,6 @@ async function sendMailProvider(req, plan, monthchange) {
|
||||
console.log('Err in unlink certificate sendmailv3');
|
||||
}
|
||||
}
|
||||
if (fs.existsSync(testPdf)) {
|
||||
try {
|
||||
fs.unlinkSync(testPdf);
|
||||
} catch (err) {
|
||||
console.log('Err in unlink pdf sendmailv3');
|
||||
}
|
||||
}
|
||||
return { status: 'error' };
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,12 +42,6 @@ export default async function updatePreferences(request) {
|
||||
newOrg.set('SignatureType', SignatureType);
|
||||
}
|
||||
}
|
||||
if (request.params.SendinOrder !== undefined) {
|
||||
newOrg.set('SendinOrder', request.params.SendinOrder);
|
||||
}
|
||||
if (request.params.IsTourEnabled !== undefined) {
|
||||
newOrg.set('IsTourEnabled', request.params.IsTourEnabled);
|
||||
}
|
||||
const updateUserRes = await newOrg.save(null, { useMasterKey: true });
|
||||
if (updateUserRes) {
|
||||
const _updateUserRes = JSON.parse(JSON.stringify(updateUserRes));
|
||||
|
||||
Binary file not shown.
@@ -10,7 +10,7 @@
|
||||
<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>
|
||||
<br />
|
||||
<p>{{appName}}</p>
|
||||
<p><a href="https://www.opensignlabs.com">{{appName}}</a></p>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
|
||||
@@ -4,4 +4,4 @@ Click the link below to verify your email address:
|
||||
|
||||
{{{link}}}
|
||||
|
||||
{{appName}}
|
||||
ExampleApp
|
||||
@@ -148,8 +148,6 @@ export const config = {
|
||||
: {}),
|
||||
filesAdapter: fsAdapter,
|
||||
auth: { google: { enabled: true }, sso: SSOAuth },
|
||||
// for fix Adapter prototype don't match expected prototype
|
||||
push: { queueOptions: { disablePushWorker: true } },
|
||||
};
|
||||
// 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:
|
||||
|
||||
Binary file not shown.
Binary file not shown.
+1
-2
@@ -11,8 +11,7 @@ services:
|
||||
env_file: .env.prod
|
||||
environment:
|
||||
- NODE_ENV=production
|
||||
- SERVER_URL=${HOST_URL:-https://localhost:3001}/api/app
|
||||
- PUBLIC_URL=${HOST_URL:-https://localhost:3001}
|
||||
- SERVER_URL=${HOST_URL:-https://localhost:3001}/app
|
||||
networks:
|
||||
- app-network
|
||||
mongo:
|
||||
|
||||
Reference in New Issue
Block a user