Compare commits

...
Author SHA1 Message Date
AmolandGitHub 7ef22eb220 Update uploadFiletoS3.js 2024-12-04 21:47:28 +05:30
AmolandGitHub 2237358d8a Update getSignedUrl.js 2024-12-04 21:46:32 +05:30
AmolandGitHub 0275762e20 Merge pull request #1492 from OpenSignLabs/fix_uncaught 2024-11-28 18:32:56 +05:30
prafull-opensignlabs 618b4fa2fb fix: handle uncaught server error 2024-11-28 18:20:48 +05:30
AndrewandGitHub 37b41fca93 Merge pull request #1491 from OpenSignLabs/prafull-opensignlabs-patch-3 2024-11-28 16:07:53 +05:30
prafull-opensignlabsandGitHub 470ed8970a fix: get owner subscription is expired in guest login flow 2024-11-28 16:02:39 +05:30
AmolandGitHub bb80324c35 Update CONTRIBUTING.md 2024-11-22 11:08:08 +05:30
AmolandGitHub a460b62233 Create LICENSE 2024-11-21 18:37:36 +05:30
AmolandGitHub 412901b839 Update LICENSE 2024-11-21 18:36:46 +05:30
prafull-opensignlabsandGitHub 9b322913f6 Merge pull request #1475 from OpenSignLabs/raktima-main-patch-1
fix: resolved text widget data embedding issue after sending the document
2024-11-20 16:30:36 +05:30
RaktimaandGitHub 248bb71ceb Update PlaceHolderSign.js 2024-11-20 16:13:53 +05:30
RaktimaNXG f62b241270 fix: resolved text widget data embedding issue after sending the document 2024-11-20 13:38:25 +05:30
prafull-opensignlabsandGitHub d95da53757 Merge pull request #1457 from OpenSignLabs/staging
fix: otp auth must be disable in certificate if OTP verification is off
2024-11-13 18:46:48 +05:30
prafull-opensignlabsandGitHub 66323f9347 Merge pull request #1456 from OpenSignLabs/uncompatible_pdf
fix: otp auth must be disable in certificate if OTP verification is off
2024-11-13 16:22:16 +05:30
prafull-opensignlabs c65f17a216 fix: otp auth must be disable in certificate if OTP verfication is off 2024-11-13 16:20:17 +05:30
prafull-opensignlabsandGitHub 277cc34e65 Merge pull request #1455 from OpenSignLabs/staging
fix: incompatible pdf error while signing pdf
2024-11-13 14:18:50 +05:30
prafull-opensignlabsandGitHub 9bf93fb231 Merge pull request #1454 from OpenSignLabs/uncompatible_pdf
fix: incompatible pdf error while signing pdf
2024-11-13 14:13:43 +05:30
prafull-opensignlabs f418e02270 fix: uncompatible pdf error while signing pdf 2024-11-13 14:11:11 +05:30
prafull-opensignlabsandGitHub 1ca33c0b76 Merge pull request #1453 from OpenSignLabs/staging
fix: server get crash in self-hosting
2024-11-13 10:11:42 +05:30
prafull-opensignlabsandGitHub 403254a5c6 Merge pull request #1451 from OpenSignLabs/validation
fix: server get crash in self-hosting
2024-11-13 10:09:14 +05:30
prafull-opensignlabs c893d96ad3 fix: server get crash in self-hosting 2024-11-13 00:33:46 +05:30
AndrewandGitHub d8131a6199 Merge pull request #1450 from OpenSignLabs/staging 2024-11-12 17:11:09 +05:30
AndrewandGitHub 3971118af8 Merge pull request #1449 from OpenSignLabs/validation 2024-11-12 17:04:04 +05:30
prafull-opensignlabs 4db0d93f41 refactor: update news from header 2024-11-12 16:24:50 +05:30
AndrewandGitHub affbfc5061 Merge pull request #1448 from OpenSignLabs/validation
refactor: change parameter from size to fontsize
2024-11-12 15:18:21 +05:30
prafull-opensignlabs 886ede2007 refactor: change parameter from size to fontsize 2024-11-12 15:17:34 +05:30
prafull-opensignlabsandGitHub a3936c66aa Merge pull request #1447 from OpenSignLabs/validation
fix: resolve spacing issue for text-type widgets in mobile view using draft template
2024-11-12 10:11:14 +05:30
prafull-opensignlabs d98453ffc2 fix: resolve spacing issue for text-type widgets in mobile view using draft template 2024-11-12 10:08:13 +05:30
AndrewandGitHub 7424912455 Merge pull request #1446 from OpenSignLabs/validation 2024-11-11 21:33:35 +05:30
prafull-opensignlabs e095495081 fix: handle invalid email validation in quick send 2024-11-11 21:24:56 +05:30
AndrewandGitHub eb4ce5544f Merge pull request #1445 from OpenSignLabs/validation 2024-11-11 20:29:33 +05:30
prafull-opensignlabs 8eef17834d fix: correct email validation in forms 2024-11-11 20:11:38 +05:30
prafull-opensignlabsandGitHub 40ed5e2353 Merge pull request #1443 from OpenSignLabs/raktima-patch-11
fix: resolve spacing issue for text-type widgets in mobile view using template flow
2024-11-11 16:54:31 +05:30
RaktimaNXG 2aa4c8c361 fix: resolve spacing issue for text-type widgets in mobile view using template flow 2024-11-11 15:50:17 +05:30
ZathielandGitHub e5b120fa36 Merge pull request #1437 from OpenSignLabs/dependabot/npm_and_yarn/apps/OpenSign/tailwindcss-3.4.14
build(deps-dev): bump tailwindcss from 3.4.13 to 3.4.14 in /apps/OpenSign
2024-11-11 02:09:07 +01:00
ZathielandGitHub 1e026f8ebd Merge pull request #1438 from OpenSignLabs/dependabot/npm_and_yarn/apps/OpenSign/i18next-23.16.5
build(deps): bump i18next from 23.16.2 to 23.16.5 in /apps/OpenSign
2024-11-11 02:08:40 +01:00
ZathielandGitHub e5c7da0847 Merge pull request #1439 from OpenSignLabs/dependabot/npm_and_yarn/apps/OpenSign/daisyui-4.12.14
build(deps-dev): bump daisyui from 4.12.13 to 4.12.14 in /apps/OpenSign
2024-11-11 02:06:46 +01:00
dependabot[bot]andGitHub 2e67002768 build(deps-dev): bump tailwindcss in /apps/OpenSign
Bumps [tailwindcss](https://github.com/tailwindlabs/tailwindcss) from 3.4.13 to 3.4.14.
- [Release notes](https://github.com/tailwindlabs/tailwindcss/releases)
- [Changelog](https://github.com/tailwindlabs/tailwindcss/blob/v3.4.14/CHANGELOG.md)
- [Commits](https://github.com/tailwindlabs/tailwindcss/compare/v3.4.13...v3.4.14)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-11-11 01:06:23 +00:00
ZathielandGitHub 9c03649d48 Merge pull request #1441 from OpenSignLabs/dependabot/npm_and_yarn/apps/OpenSign/lottiefiles/dotlottie-react-0.9.3
build(deps): bump @lottiefiles/dotlottie-react from 0.9.1 to 0.9.3 in /apps/OpenSign
2024-11-11 02:05:57 +01:00
ZathielandGitHub df436b3b20 Merge pull request #1442 from OpenSignLabs/dependabot/npm_and_yarn/apps/OpenSign/npm_and_yarn-1b75c58f89
build(deps): bump the npm_and_yarn group in /apps/OpenSign with 2 updates
2024-11-11 02:04:07 +01:00
ZathielandGitHub 34acf4170e Merge pull request #1440 from OpenSignLabs/dependabot/npm_and_yarn/apps/OpenSign/react-select-5.8.3
build(deps): bump react-select from 5.8.1 to 5.8.3 in /apps/OpenSign
2024-11-11 02:02:58 +01:00
dependabot[bot]andGitHub f9a13c880a build(deps): bump the npm_and_yarn group
Bumps the npm_and_yarn group in /apps/OpenSign with 2 updates: [postcss](https://github.com/postcss/postcss) and [http-proxy-middleware](https://github.com/chimurai/http-proxy-middleware).


Updates `postcss` from 8.4.47 to 8.4.48
- [Release notes](https://github.com/postcss/postcss/releases)
- [Changelog](https://github.com/postcss/postcss/blob/main/CHANGELOG.md)
- [Commits](https://github.com/postcss/postcss/compare/8.4.47...8.4.48)

Updates `http-proxy-middleware` from 2.0.6 to 2.0.7
- [Release notes](https://github.com/chimurai/http-proxy-middleware/releases)
- [Changelog](https://github.com/chimurai/http-proxy-middleware/blob/v2.0.7/CHANGELOG.md)
- [Commits](https://github.com/chimurai/http-proxy-middleware/compare/v2.0.6...v2.0.7)

---
updated-dependencies:
- dependency-name: postcss
  dependency-type: direct:development
  dependency-group: npm_and_yarn
- dependency-name: http-proxy-middleware
  dependency-type: indirect
  dependency-group: npm_and_yarn
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-11-11 01:01:45 +00:00
ZathielandGitHub df7cd45be6 Merge pull request #1434 from OpenSignLabs/dependabot/npm_and_yarn/apps/OpenSignServer/eslint-9.14.0
build(deps-dev): bump eslint from 9.13.0 to 9.14.0 in /apps/OpenSignServer
2024-11-11 01:58:59 +01:00
dependabot[bot]andGitHub b22d70c833 build(deps): bump @lottiefiles/dotlottie-react in /apps/OpenSign
Bumps [@lottiefiles/dotlottie-react](https://github.com/LottieFiles/dotlottie-web/tree/HEAD/packages/react) from 0.9.1 to 0.9.3.
- [Release notes](https://github.com/LottieFiles/dotlottie-web/releases)
- [Changelog](https://github.com/LottieFiles/dotlottie-web/blob/main/packages/react/CHANGELOG.md)
- [Commits](https://github.com/LottieFiles/dotlottie-web/commits/HEAD/packages/react)

---
updated-dependencies:
- dependency-name: "@lottiefiles/dotlottie-react"
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-11-11 00:58:58 +00:00
dependabot[bot]andGitHub 1ef8e8aa6a build(deps): bump react-select from 5.8.1 to 5.8.3 in /apps/OpenSign
Bumps [react-select](https://github.com/JedWatson/react-select) from 5.8.1 to 5.8.3.
- [Release notes](https://github.com/JedWatson/react-select/releases)
- [Changelog](https://github.com/JedWatson/react-select/blob/master/docs/CHANGELOG.md)
- [Commits](https://github.com/JedWatson/react-select/compare/react-select@5.8.1...react-select@5.8.3)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-11-11 00:58:47 +00:00
dependabot[bot]andGitHub 2aa58b7eb3 build(deps-dev): bump daisyui from 4.12.13 to 4.12.14 in /apps/OpenSign
Bumps [daisyui](https://github.com/saadeghi/daisyui) from 4.12.13 to 4.12.14.
- [Release notes](https://github.com/saadeghi/daisyui/releases)
- [Changelog](https://github.com/saadeghi/daisyui/blob/master/CHANGELOG.md)
- [Commits](https://github.com/saadeghi/daisyui/compare/v4.12.13...v4.12.14)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-11-11 00:58:36 +00:00
dependabot[bot]andGitHub 9fb61509c4 build(deps): bump i18next from 23.16.2 to 23.16.5 in /apps/OpenSign
Bumps [i18next](https://github.com/i18next/i18next) from 23.16.2 to 23.16.5.
- [Release notes](https://github.com/i18next/i18next/releases)
- [Changelog](https://github.com/i18next/i18next/blob/master/CHANGELOG.md)
- [Commits](https://github.com/i18next/i18next/compare/v23.16.2...v23.16.5)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-11-11 00:58:25 +00:00
ZathielandGitHub b99dc875ed Merge pull request #1432 from OpenSignLabs/dependabot/npm_and_yarn/apps/OpenSignServer/aws-sdk/s3-request-presigner-3.688.0
build(deps): bump @aws-sdk/s3-request-presigner from 3.685.0 to 3.688.0 in /apps/OpenSignServer
2024-11-11 01:58:01 +01:00
dependabot[bot]andGitHub 7da31f00c3 build(deps-dev): bump eslint in /apps/OpenSignServer
Bumps [eslint](https://github.com/eslint/eslint) from 9.13.0 to 9.14.0.
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/compare/v9.13.0...v9.14.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-11-11 00:57:28 +00:00
ZathielandGitHub 894ccd1244 Merge pull request #1433 from OpenSignLabs/dependabot/npm_and_yarn/apps/OpenSignServer/nodemailer-6.9.16
build(deps): bump nodemailer from 6.9.15 to 6.9.16 in /apps/OpenSignServer
2024-11-11 01:56:36 +01:00
ZathielandGitHub 8d90e6e808 Merge pull request #1435 from OpenSignLabs/dependabot/npm_and_yarn/apps/OpenSignServer/babel/eslint-parser-7.25.9
build(deps-dev): bump @babel/eslint-parser from 7.25.8 to 7.25.9 in /apps/OpenSignServer
2024-11-11 01:55:18 +01:00
dependabot[bot]andGitHub 79771f725e build(deps-dev): bump @babel/eslint-parser in /apps/OpenSignServer
Bumps [@babel/eslint-parser](https://github.com/babel/babel/tree/HEAD/eslint/babel-eslint-parser) from 7.25.8 to 7.25.9.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.25.9/eslint/babel-eslint-parser)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-11-11 00:53:16 +00:00
ZathielandGitHub 786f56941a Merge pull request #1436 from OpenSignLabs/dependabot/npm_and_yarn/apps/OpenSignServer/mongodb-runner-5.7.1
build(deps-dev): bump mongodb-runner from 5.7.0 to 5.7.1 in /apps/OpenSignServer
2024-11-11 01:51:59 +01:00
dependabot[bot]andGitHub 8fae910d46 build(deps-dev): bump mongodb-runner in /apps/OpenSignServer
Bumps [mongodb-runner](https://github.com/mongodb-js/devtools-shared) from 5.7.0 to 5.7.1.
- [Commits](https://github.com/mongodb-js/devtools-shared/compare/mongodb-runner@5.7.0...mongodb-runner@5.7.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-11-11 00:15:02 +00:00
dependabot[bot]andGitHub 8b5920bba3 build(deps): bump nodemailer in /apps/OpenSignServer
Bumps [nodemailer](https://github.com/nodemailer/nodemailer) from 6.9.15 to 6.9.16.
- [Release notes](https://github.com/nodemailer/nodemailer/releases)
- [Changelog](https://github.com/nodemailer/nodemailer/blob/master/CHANGELOG.md)
- [Commits](https://github.com/nodemailer/nodemailer/compare/v6.9.15...v6.9.16)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-11-11 00:14:33 +00:00
dependabot[bot]andGitHub 03f1451e64 build(deps): bump @aws-sdk/s3-request-presigner in /apps/OpenSignServer
Bumps [@aws-sdk/s3-request-presigner](https://github.com/aws/aws-sdk-js-v3/tree/HEAD/packages/s3-request-presigner) from 3.685.0 to 3.688.0.
- [Release notes](https://github.com/aws/aws-sdk-js-v3/releases)
- [Changelog](https://github.com/aws/aws-sdk-js-v3/blob/main/packages/s3-request-presigner/CHANGELOG.md)
- [Commits](https://github.com/aws/aws-sdk-js-v3/commits/v3.688.0/packages/s3-request-presigner)

---
updated-dependencies:
- dependency-name: "@aws-sdk/s3-request-presigner"
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-11-11 00:14:24 +00:00
AndrewandGitHub 1d2a975b5f Merge pull request #1431 from OpenSignLabs/validation 2024-11-08 21:12:00 +05:30
prafull-opensignlabs 3db32979dc refacotr: add translation message for warning 2024-11-08 21:05:39 +05:30
AndrewandGitHub 110431dae2 Merge pull request #1430 from OpenSignLabs/validation 2024-11-08 20:10:03 +05:30
prafull-opensignlabs ade228f756 fix: user does not exist error while signing 2024-11-08 20:08:44 +05:30
AndrewandGitHub 9b18a66f22 Merge pull request #1429 from OpenSignLabs/validation
fix: signature types issues in public template while creating through drafttemplate
2024-11-08 18:39:33 +05:30
prafull-opensignlabs c88de90a24 fix: signature types issues in public template while creating through drafttemplate 2024-11-08 18:33:29 +05:30
RaktimaandGitHub 737d66d97d Merge pull request #1428 from OpenSignLabs/validation
fix: signature type not visible in signpad for public template
2024-11-08 12:47:13 +05:30
prafull-opensignlabs b77b57d3fd fix: signature type not visible in signpad for public template 2024-11-08 12:34:21 +05:30
AndrewandGitHub 240c7766c1 Merge pull request #1427 from OpenSignLabs/validation 2024-11-07 21:53:16 +05:30
prafull-opensignlabs 508b2e43d3 refactor: add restriction foe default signature type 2024-11-07 21:51:39 +05:30
prafull-opensignlabsandGitHub d6129e21e9 Merge pull request #1426 from OpenSignLabs/validation
fix: issue of signature types
2024-11-07 19:02:07 +05:30
prafull-opensignlabs a11a2444f1 Merge branch 'staging' of https://github.com/OpenSignLabs/OpenSign into validation 2024-11-07 18:59:10 +05:30
prafull-opensignlabs db1fb1c0e1 fix: issue of signature types 2024-11-07 18:56:42 +05:30
prafull-opensignlabsandGitHub 7f326b19aa Merge pull request #1425 from OpenSignLabs/raktima-patch-11
refactor code
2024-11-07 17:53:05 +05:30
RaktimaNXG 2a1d7d2502 refactor code 2024-11-07 17:18:03 +05:30
prafull-opensignlabsandGitHub 01edfce6e7 Merge pull request #1424 from OpenSignLabs/raktima-patch-11
fix: text type widgets space issue in mobile view
2024-11-07 16:40:13 +05:30
RaktimaNXG 9176b8f99c fix: increase text widgets space 2024-11-07 16:25:54 +05:30
RaktimaNXG 0ff2e57424 fix: text widgets issue in mobile view 2024-11-07 15:37:56 +05:30
prafull-opensignlabsandGitHub 567966866c Merge pull request #1422 from OpenSignLabs/validation
feat: add functionality to enable/disable signature types
2024-11-07 14:15:27 +05:30
prafull-opensignlabs e03f07a8ef fix: incompatible pdf issue and signturetype issues 2024-11-07 14:12:15 +05:30
prafull-opensignlabs 9915a700bb fix: incompatible pdf issue and signturetype issues 2024-11-07 14:12:01 +05:30
prafull-opensignlabsandGitHub f0a406a397 Merge pull request #1423 from OpenSignLabs/raktima-patch-10
fix: profile and side bar menu togglling issue in mobile view
2024-11-07 13:22:49 +05:30
prafull-opensignlabs 851ea24be4 feat: validation for signature type 2024-11-06 18:27:24 +05:30
RaktimaNXG 50c4eff790 fix: profile and side panel menu toggle problem in mobile view 2024-11-06 17:49:05 +05:30
prafull-opensignlabsandGitHub e69e6998c9 Merge pull request #1420 from OpenSignLabs/raktima-patch-10
fix: signer list selection issue in request sign flow
2024-11-06 14:36:29 +05:30
RaktimaNXG c87873cfb6 fix: signer list selection issue in request sign flow 2024-11-06 11:46:39 +05:30
prafull-opensignlabsandGitHub b09becf3eb Merge pull request #1419 from OpenSignLabs/validation
fix: user does not exist error while creating document
2024-11-06 11:41:58 +05:30
prafull-opensignlabs 0673242f41 fix: user does not exist error while creating document 2024-11-06 11:17:14 +05:30
prafull-opensignlabsandGitHub 1776931df5 Merge pull request #1378 from OpenSignLabs/raktima-patch-8
fix: form advanced options panel currently opens or closes when clicking outside the panel.
2024-11-06 10:09:52 +05:30
prafull-opensignlabsandGitHub a2c0921345 Merge pull request #1417 from OpenSignLabs/validation
fix: something went wrong issue while signing document
2024-11-05 16:20:00 +05:30
prafull-opensignlabs ad0a974c14 fix: something went wrong issue while signing document 2024-11-05 15:49:39 +05:30
ZathielandGitHub 2d4a7d336c Merge pull request #1404 from OpenSignLabs/dependabot/npm_and_yarn/apps/OpenSignServer/aws-sdk/s3-request-presigner-3.685.0
build(deps): bump @aws-sdk/s3-request-presigner from 3.670.0 to 3.685.0 in /apps/OpenSignServer
2024-11-04 23:16:01 +01:00
dependabot[bot]andGitHub 8d2df87de3 build(deps): bump @aws-sdk/s3-request-presigner in /apps/OpenSignServer
Bumps [@aws-sdk/s3-request-presigner](https://github.com/aws/aws-sdk-js-v3/tree/HEAD/packages/s3-request-presigner) from 3.670.0 to 3.685.0.
- [Release notes](https://github.com/aws/aws-sdk-js-v3/releases)
- [Changelog](https://github.com/aws/aws-sdk-js-v3/blob/main/packages/s3-request-presigner/CHANGELOG.md)
- [Commits](https://github.com/aws/aws-sdk-js-v3/commits/v3.685.0/packages/s3-request-presigner)

---
updated-dependencies:
- dependency-name: "@aws-sdk/s3-request-presigner"
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-11-04 22:15:27 +00:00
ZathielandGitHub 873e7e2068 Merge pull request #1390 from OpenSignLabs/dependabot/npm_and_yarn/apps/OpenSign/babel/runtime-corejs2-7.26.0
build(deps-dev): bump @babel/runtime-corejs2 from 7.25.7 to 7.26.0 in /apps/OpenSign
2024-11-04 23:15:10 +01:00
dependabot[bot]andGitHub 3fcb1d0138 build(deps-dev): bump @babel/runtime-corejs2 in /apps/OpenSign
Bumps [@babel/runtime-corejs2](https://github.com/babel/babel/tree/HEAD/packages/babel-runtime-corejs2) from 7.25.7 to 7.26.0.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.26.0/packages/babel-runtime-corejs2)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-11-04 22:13:24 +00:00
ZathielandGitHub ce41f9a0ce Merge pull request #1406 from OpenSignLabs/dependabot/npm_and_yarn/apps/OpenSignServer/aws-sdk/client-s3-3.685.0
build(deps): bump @aws-sdk/client-s3 from 3.675.0 to 3.685.0 in /apps/OpenSignServer
2024-11-04 23:13:23 +01:00
ZathielandGitHub 34d8ed19bf Merge pull request #1408 from OpenSignLabs/dependabot/npm_and_yarn/apps/OpenSign/babel/core-7.26.0
build(deps-dev): bump @babel/core from 7.25.8 to 7.26.0 in /apps/OpenSign
2024-11-04 23:12:08 +01:00
ZathielandGitHub ea9f34f0b3 Merge pull request #1387 from OpenSignLabs/dependabot/npm_and_yarn/apps/OpenSignServer/parse/s3-files-adapter-3.0.0
build(deps): bump @parse/s3-files-adapter from 2.2.0 to 3.0.0 in /apps/OpenSignServer
2024-11-04 23:11:57 +01:00
dependabot[bot]andGitHub 4e9cbd23f2 build(deps-dev): bump @babel/core in /apps/OpenSign
Bumps [@babel/core](https://github.com/babel/babel/tree/HEAD/packages/babel-core) from 7.25.8 to 7.26.0.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.26.0/packages/babel-core)

---
updated-dependencies:
- dependency-name: "@babel/core"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-11-04 22:11:41 +00:00
ZathielandGitHub bbd65c01e9 Merge pull request #1359 from OpenSignLabs/dependabot/npm_and_yarn/apps/OpenSignServer/parse-server-api-mail-adapter-4.1.0
build(deps): bump parse-server-api-mail-adapter from 4.0.0 to 4.1.0 in /apps/OpenSignServer
2024-11-04 23:10:55 +01:00
ZathielandGitHub 5dc30b7702 Merge pull request #1407 from OpenSignLabs/dependabot/npm_and_yarn/apps/OpenSign/react-cookie-7.2.2
build(deps): bump react-cookie from 7.2.1 to 7.2.2 in /apps/OpenSign
2024-11-04 23:10:09 +01:00
ZathielandGitHub eb3b31bd59 Merge pull request #1409 from OpenSignLabs/dependabot/npm_and_yarn/apps/OpenSign/babel/preset-env-7.26.0
build(deps-dev): bump @babel/preset-env from 7.25.8 to 7.26.0 in /apps/OpenSign
2024-11-04 23:09:26 +01:00
dependabot[bot]andGitHub 57597dfef0 build(deps-dev): bump @babel/preset-env in /apps/OpenSign
Bumps [@babel/preset-env](https://github.com/babel/babel/tree/HEAD/packages/babel-preset-env) from 7.25.8 to 7.26.0.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.26.0/packages/babel-preset-env)

---
updated-dependencies:
- dependency-name: "@babel/preset-env"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-11-04 22:08:46 +00:00
ZathielandGitHub 8cb7a610c7 Merge pull request #1405 from OpenSignLabs/dependabot/npm_and_yarn/apps/OpenSignServer/mongoose-8.8.0
build(deps): bump mongoose from 8.7.3 to 8.8.0 in /apps/OpenSignServer
2024-11-04 23:08:24 +01:00
ZathielandGitHub 2c464978b4 Merge pull request #1410 from OpenSignLabs/dependabot/npm_and_yarn/apps/OpenSign/babel/preset-react-7.25.9
build(deps-dev): bump @babel/preset-react from 7.25.7 to 7.25.9 in /apps/OpenSign
2024-11-04 23:06:39 +01:00
AmolandGitHub 8d0bf6abe8 docs: update feature comparison 2024-11-04 23:03:18 +05:30
AmolandGitHub 82c724a768 docs: update feature comparison 2024-11-04 21:33:31 +05:30
prafull-opensignlabsandGitHub 6146fe5f86 Merge pull request #1413 from OpenSignLabs/raktima-patch-9
fix: text size issue after complete signature in mobile view
2024-11-04 18:15:30 +05:30
RaktimaNXG 24ce6eae3b fix: remove extra space from bottom after embed text widgets in mobile view 2024-11-04 18:09:38 +05:30
RaktimaNXG 8db934a2c2 fix: increase space from bottom in text widgets 2024-11-04 17:31:20 +05:30
AndrewandGitHub dc90d412ca Merge pull request #1415 from OpenSignLabs/prafull-opensignlabs-patch-2 2024-11-04 17:29:26 +05:30
prafull-opensignlabsandGitHub b8415c8995 fix: invalid type object save in signers field 2024-11-04 17:26:36 +05:30
RaktimaNXG 0d86f39ba3 refactor code 2024-11-04 16:48:02 +05:30
prafull-opensignlabsandGitHub 0bab033673 Merge pull request #1414 from OpenSignLabs/validation
fix: ensure webhook is triggered when document is created via quick send
2024-11-04 16:26:48 +05:30
prafull-opensignlabs 72a0ce3f51 fix: ensure webhook is triggered when document is created via quick send 2024-11-04 16:22:41 +05:30
RaktimaNXG c3a14b82b3 refactor code 2024-11-04 16:07:49 +05:30
RaktimaNXG b3252e276b fix: remove blank space from text widgets,fix text size conflict issue 2024-11-04 15:43:45 +05:30
prafull-opensignlabsandGitHub 10c63a66f6 Merge pull request #1412 from OpenSignLabs/validation
fix: invalid template id error while opening opening public template
2024-11-04 15:22:51 +05:30
prafull-opensignlabs f44205b90d fix: invalid template id error in while opening opening public template 2024-11-04 15:20:03 +05:30
dependabot[bot]andGitHub cd087d410f build(deps-dev): bump @babel/preset-react in /apps/OpenSign
Bumps [@babel/preset-react](https://github.com/babel/babel/tree/HEAD/packages/babel-preset-react) from 7.25.7 to 7.25.9.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.25.9/packages/babel-preset-react)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-11-04 00:40:58 +00:00
dependabot[bot]andGitHub c5812ba938 build(deps): bump react-cookie from 7.2.1 to 7.2.2 in /apps/OpenSign
Bumps [react-cookie](https://github.com/bendotcodes/cookies) from 7.2.1 to 7.2.2.
- [Release notes](https://github.com/bendotcodes/cookies/releases)
- [Changelog](https://github.com/bendotcodes/cookies/blob/main/LEGACY-CHANGELOG.md)
- [Commits](https://github.com/bendotcodes/cookies/compare/v7.2.1...v7.2.2)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-11-04 00:40:19 +00:00
dependabot[bot]andGitHub 2e4c7f7690 build(deps): bump @aws-sdk/client-s3 in /apps/OpenSignServer
Bumps [@aws-sdk/client-s3](https://github.com/aws/aws-sdk-js-v3/tree/HEAD/clients/client-s3) from 3.675.0 to 3.685.0.
- [Release notes](https://github.com/aws/aws-sdk-js-v3/releases)
- [Changelog](https://github.com/aws/aws-sdk-js-v3/blob/main/clients/client-s3/CHANGELOG.md)
- [Commits](https://github.com/aws/aws-sdk-js-v3/commits/v3.685.0/clients/client-s3)

---
updated-dependencies:
- dependency-name: "@aws-sdk/client-s3"
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-11-04 00:17:30 +00:00
dependabot[bot]andGitHub a7389efb00 build(deps): bump mongoose from 8.7.3 to 8.8.0 in /apps/OpenSignServer
Bumps [mongoose](https://github.com/Automattic/mongoose) from 8.7.3 to 8.8.0.
- [Release notes](https://github.com/Automattic/mongoose/releases)
- [Changelog](https://github.com/Automattic/mongoose/blob/master/CHANGELOG.md)
- [Commits](https://github.com/Automattic/mongoose/compare/8.7.3...8.8.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-11-04 00:16:54 +00:00
AmolandGitHub 532062687c Merge pull request #1402 from OpenSignLabs/validation
fix: make documentation url copy and clickable in draft template
2024-10-31 17:29:00 +05:30
prafull-opensignlabs d3a603d115 fix: make documentation url copy and clickable in draft ui 2024-10-31 17:02:49 +05:30
AmolandGitHub 26fece78c5 Merge pull request #1401 from OpenSignLabs/validation
fix: drattemplate ui changes, signers not visible in list, alert message
2024-10-31 13:13:00 +05:30
prafull-opensignlabs b8fb626591 fix: drattemplate ui changes, signers not visible in list, alert message 2024-10-31 12:58:43 +05:30
RaktimaNXG 732786067f fix: text size issue after complete signature in mobile view 2024-10-30 13:56:26 +05:30
AndrewandGitHub 45c0cd48c7 Merge pull request #1399 from OpenSignLabs/validation 2024-10-29 19:11:50 +05:30
prafull-opensignlabs 50d7982dd5 feat: add support for non-email usernames in SMTP configuration 2024-10-29 19:05:11 +05:30
AmolandGitHub ff085b1284 Merge pull request #1398 from OpenSignLabs/validation
fix: template variable is not define in draft template
2024-10-29 18:23:01 +05:30
prafull-opensignlabs c3564b1f8f fix: template variable is not define in draft template api 2024-10-29 17:35:33 +05:30
AmolandGitHub 32eba21e7a Merge pull request #1396 from OpenSignLabs/validation
feat: draft template api
2024-10-29 15:42:53 +05:30
prafull-opensignlabs 9952afcc38 feat: draft template api 2024-10-29 15:41:35 +05:30
AndrewandGitHub b3feccab0d Merge pull request #1392 from OpenSignLabs/validation 2024-10-28 17:42:29 +05:30
prafull-opensignlabs 86ebd4903b fix: document creator didn't receive completion mail 2024-10-28 17:15:11 +05:30
ZathielandGitHub 0533bb9c30 Merge pull request #1356 from OpenSignLabs/dependabot/npm_and_yarn/apps/OpenSign/eslint-9.13.0 2024-10-28 08:12:07 +01:00
ZathielandGitHub 185e90494c Merge pull request #1357 from OpenSignLabs/dependabot/npm_and_yarn/apps/OpenSign/react-datepicker-7.5.0 2024-10-28 08:10:02 +01:00
ZathielandGitHub 3f77b497ce Merge pull request #1386 from OpenSignLabs/dependabot/npm_and_yarn/apps/OpenSignServer/mongoose-8.7.3 2024-10-28 08:09:14 +01:00
ZathielandGitHub 87a8333cdf Merge pull request #1389 from OpenSignLabs/dependabot/npm_and_yarn/apps/OpenSign/serve-14.2.4 2024-10-28 08:08:20 +01:00
dependabot[bot]andGitHub 3d12261aa7 build(deps): bump serve from 14.2.3 to 14.2.4 in /apps/OpenSign
Bumps [serve](https://github.com/vercel/serve) from 14.2.3 to 14.2.4.
- [Release notes](https://github.com/vercel/serve/releases)
- [Commits](https://github.com/vercel/serve/compare/14.2.3...14.2.4)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-10-28 00:43:50 +00:00
dependabot[bot]andGitHub 19c6cbbcd3 build(deps): bump @parse/s3-files-adapter in /apps/OpenSignServer
Bumps [@parse/s3-files-adapter](https://github.com/parse-community/parse-server-s3-adapter) from 2.2.0 to 3.0.0.
- [Release notes](https://github.com/parse-community/parse-server-s3-adapter/releases)
- [Changelog](https://github.com/parse-community/parse-server-s3-adapter/blob/master/CHANGELOG.md)
- [Commits](https://github.com/parse-community/parse-server-s3-adapter/compare/2.2.0...3.0.0)

---
updated-dependencies:
- dependency-name: "@parse/s3-files-adapter"
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-10-28 00:35:57 +00:00
dependabot[bot]andGitHub 39c191db7c build(deps): bump mongoose from 8.7.2 to 8.7.3 in /apps/OpenSignServer
Bumps [mongoose](https://github.com/Automattic/mongoose) from 8.7.2 to 8.7.3.
- [Release notes](https://github.com/Automattic/mongoose/releases)
- [Changelog](https://github.com/Automattic/mongoose/blob/master/CHANGELOG.md)
- [Commits](https://github.com/Automattic/mongoose/compare/8.7.2...8.7.3)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-10-28 00:35:48 +00:00
RaktimaNXG 58c36266e0 fix: form advanced options panel currently opens or closes when clicking outside the panel. 2024-10-23 11:19:02 +05:30
RaktimaandGitHub 0ebdfffdeb Merge pull request #1374 from OpenSignLabs/validation
fix: widgets get removed from doc when signers try to sign at a time
2024-10-22 19:54:03 +05:30
prafull-opensignlabs ed840f3048 fix: widgets get removed from doc when signers try to sign at a time 2024-10-22 19:45:41 +05:30
AmolandGitHub 1e13b509df Merge pull request #1372 from OpenSignLabs/validation
fix: report UI
2024-10-22 17:37:32 +05:30
prafull-opensignlabs d76a9a4628 fix: report UI 2024-10-22 17:36:01 +05:30
AndrewandGitHub f70e20498e Merge pull request #1367 from OpenSignLabs/raktima-patch-7 2024-10-21 17:28:21 +05:30
RaktimaNXG 1715b39629 refactor code 2024-10-21 17:20:28 +05:30
RaktimaNXG 3c63db8c9c refactor code 2024-10-21 14:24:58 +05:30
RaktimaNXG 7af78c95dd fix: resolve the copy widgets glitch and provide a warning tour for text widgets left empty. 2024-10-21 14:07:31 +05:30
ZathielandGitHub 1c4a377641 Merge pull request #1360 from OpenSignLabs/dependabot/npm_and_yarn/apps/OpenSign/i18next-23.16.2 2024-10-21 07:42:57 +02:00
dependabot[bot]andGitHub bf56937585 build(deps-dev): bump eslint from 9.12.0 to 9.13.0 in /apps/OpenSign
Bumps [eslint](https://github.com/eslint/eslint) from 9.12.0 to 9.13.0.
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/compare/v9.12.0...v9.13.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-10-21 05:41:38 +00:00
dependabot[bot]andGitHub e97442b0c8 build(deps): bump i18next from 23.16.0 to 23.16.2 in /apps/OpenSign
Bumps [i18next](https://github.com/i18next/i18next) from 23.16.0 to 23.16.2.
- [Release notes](https://github.com/i18next/i18next/releases)
- [Changelog](https://github.com/i18next/i18next/blob/master/CHANGELOG.md)
- [Commits](https://github.com/i18next/i18next/compare/v23.16.0...v23.16.2)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-10-21 05:41:36 +00:00
ZathielandGitHub d029ce5380 Merge pull request #1361 from OpenSignLabs/dependabot/npm_and_yarn/apps/OpenSign/react-syntax-highlighter-15.6.1 2024-10-21 07:41:10 +02:00
ZathielandGitHub 20049921ad Merge pull request #1362 from OpenSignLabs/dependabot/npm_and_yarn/apps/OpenSignServer/aws-sdk/client-s3-3.675.0 2024-10-21 07:40:29 +02:00
ZathielandGitHub 05a0db75db Merge pull request #1363 from OpenSignLabs/dependabot/npm_and_yarn/apps/OpenSign/reduxjs/toolkit-2.3.0 2024-10-21 07:39:27 +02:00
ZathielandGitHub a7b8100a18 Merge pull request #1364 from OpenSignLabs/dependabot/npm_and_yarn/apps/OpenSignServer/mongoose-8.7.2 2024-10-21 07:38:01 +02:00
ZathielandGitHub 112369b283 Merge pull request #1365 from OpenSignLabs/dependabot/npm_and_yarn/apps/OpenSignServer/eslint-9.13.0 2024-10-21 07:37:15 +02:00
dependabot[bot]andGitHub f9b915b728 build(deps-dev): bump eslint in /apps/OpenSignServer
Bumps [eslint](https://github.com/eslint/eslint) from 9.12.0 to 9.13.0.
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/compare/v9.12.0...v9.13.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-10-21 00:31:53 +00:00
dependabot[bot]andGitHub 8acdbc928e build(deps): bump mongoose from 8.7.1 to 8.7.2 in /apps/OpenSignServer
Bumps [mongoose](https://github.com/Automattic/mongoose) from 8.7.1 to 8.7.2.
- [Release notes](https://github.com/Automattic/mongoose/releases)
- [Changelog](https://github.com/Automattic/mongoose/blob/master/CHANGELOG.md)
- [Commits](https://github.com/Automattic/mongoose/compare/8.7.1...8.7.2)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-10-21 00:31:43 +00:00
dependabot[bot]andGitHub 9665e14e6d build(deps): bump @reduxjs/toolkit from 2.2.8 to 2.3.0 in /apps/OpenSign
Bumps [@reduxjs/toolkit](https://github.com/reduxjs/redux-toolkit) from 2.2.8 to 2.3.0.
- [Release notes](https://github.com/reduxjs/redux-toolkit/releases)
- [Commits](https://github.com/reduxjs/redux-toolkit/compare/v2.2.8...v2.3.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-10-21 00:31:41 +00:00
dependabot[bot]andGitHub b45e05cc9e build(deps): bump @aws-sdk/client-s3 in /apps/OpenSignServer
Bumps [@aws-sdk/client-s3](https://github.com/aws/aws-sdk-js-v3/tree/HEAD/clients/client-s3) from 3.670.0 to 3.675.0.
- [Release notes](https://github.com/aws/aws-sdk-js-v3/releases)
- [Changelog](https://github.com/aws/aws-sdk-js-v3/blob/main/clients/client-s3/CHANGELOG.md)
- [Commits](https://github.com/aws/aws-sdk-js-v3/commits/v3.675.0/clients/client-s3)

---
updated-dependencies:
- dependency-name: "@aws-sdk/client-s3"
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-10-21 00:31:33 +00:00
dependabot[bot]andGitHub 116f4d94ea build(deps): bump react-syntax-highlighter in /apps/OpenSign
Bumps [react-syntax-highlighter](https://github.com/react-syntax-highlighter/react-syntax-highlighter) from 15.5.0 to 15.6.1.
- [Release notes](https://github.com/react-syntax-highlighter/react-syntax-highlighter/releases)
- [Changelog](https://github.com/react-syntax-highlighter/react-syntax-highlighter/blob/master/CHANGELOG.MD)
- [Commits](https://github.com/react-syntax-highlighter/react-syntax-highlighter/compare/15.5.0...v15.6.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-10-21 00:31:23 +00:00
dependabot[bot]andGitHub f18b5b49c5 build(deps): bump parse-server-api-mail-adapter in /apps/OpenSignServer
Bumps [parse-server-api-mail-adapter](https://github.com/parse-community/parse-server-api-mail-adapter) from 4.0.0 to 4.1.0.
- [Release notes](https://github.com/parse-community/parse-server-api-mail-adapter/releases)
- [Changelog](https://github.com/parse-community/parse-server-api-mail-adapter/blob/main/CHANGELOG.md)
- [Commits](https://github.com/parse-community/parse-server-api-mail-adapter/compare/4.0.0...4.1.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-10-21 00:31:14 +00:00
dependabot[bot]andGitHub 09a4db7c03 build(deps): bump react-datepicker from 7.4.0 to 7.5.0 in /apps/OpenSign
Bumps [react-datepicker](https://github.com/Hacker0x01/react-datepicker) from 7.4.0 to 7.5.0.
- [Release notes](https://github.com/Hacker0x01/react-datepicker/releases)
- [Commits](https://github.com/Hacker0x01/react-datepicker/compare/v7.4.0...v7.5.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-10-21 00:31:00 +00:00
prafull-opensignlabsandGitHub 2616a5776b Merge pull request #1350 from OpenSignLabs/validation
fix: show invalid password error if pfx password is invalid
2024-10-18 17:21:59 +05:30
prafull-opensignlabs 36cfc4a867 fix: show invalid password error if pfx password is invalid 2024-10-17 10:55:43 +05:30
AndrewandGitHub 631f118afb Merge pull request #1347 from OpenSignLabs/validation
fix: document loading err and report UI
2024-10-16 20:26:22 +05:30
prafull-opensignlabs b43e3a61e6 refactor: remove unnecessary code 2024-10-16 16:22:06 +05:30
prafull-opensignlabs 04100adece fix: add space below in last row from reports 2024-10-16 14:48:34 +05:30
prafull-opensignlabs a103f93925 fix: add space after last record in reports 2024-10-16 13:02:24 +05:30
prafull-opensignlabs 8467340fb5 fix: report UI 2024-10-16 12:13:19 +05:30
prafull-opensignlabs 3a8e41de27 fix: duplicate id warning 2024-10-15 18:57:15 +05:30
prafull-opensignlabs 97c2f183ca fix: document loading err and report UI 2024-10-15 18:56:50 +05:30
prafull-opensignlabsandGitHub f1ab35e71e Merge pull request #1340 from OpenSignLabs/mobile-issue
fix: issue of assigned signer gets deselected in mobile view
2024-10-15 10:25:18 +05:30
RaktimaNXG 240d892b94 fix: issue of assigned signer gets deselected in mobile view 2024-10-14 17:09:16 +05:30
AndrewandGitHub 364d96e7f6 Merge pull request #1339 from OpenSignLabs/validation 2024-10-14 16:16:29 +05:30
prafull-opensignlabs 03dfd58ac5 feat: custom PFX functionality 2024-10-14 16:14:54 +05:30
prafull-opensignlabsandGitHub 716023b534 Merge pull request #1323 from OpenSignLabs/react-tour
Fix: resolved text box font size issue during resizing and prevented unnecessary popups from opening when resizing widgets.
2024-10-11 19:15:26 +05:30
RaktimaandGitHub 67b3417ac9 Update Placeholder.js 2024-10-11 19:13:00 +05:30
RaktimaandGitHub f3667f6aaf Update Placeholder.js 2024-10-11 19:07:54 +05:30
AndrewandGitHub 7b35e71f3d Merge pull request #1321 from OpenSignLabs/validation 2024-10-10 17:17:04 +05:30
prafull-opensignlabs 51031878eb Fix 'something went wrong' error when non-existing signer attempts to sign the document 2024-10-10 17:13:22 +05:30
prafull-opensignlabsandGitHub 19d96230cd Merge pull request #1320 from OpenSignLabs/raktima-patch-5
fix: enableTour issue when enableOtp enabled
2024-10-10 14:50:15 +05:30
RaktimaNXG dbee7e2894 fix: enableTour issue when enableOtp enabled 2024-10-10 14:46:59 +05:30
AndrewandGitHub 656241da54 Merge pull request #1318 from OpenSignLabs/validation 2024-10-10 13:33:51 +05:30
prafull-opensignlabs 2a3947ea1d feat: send completed mail to all signers 2024-10-10 12:50:26 +05:30
prafull-opensignlabsandGitHub 9c1b4261dc Merge pull request #1316 from OpenSignLabs/validation
refactor: changes in output of file-adapter's cloud function
2024-10-09 18:41:07 +05:30
prafull-opensignlabs 7c37d8128e refactor: changes in output of fileadapter's cloud function 2024-10-09 18:39:33 +05:30
RaktimaNXG 404785bf29 fix: text box font size issue 2024-10-09 18:05:10 +05:30
prafull-opensignlabsandGitHub dc7fd34b07 Merge pull request #1315 from OpenSignLabs/validation
fix: url is not define
2024-10-09 15:09:09 +05:30
prafull-opensignlabs 86a2975b3c fix: url is not define 2024-10-09 15:06:49 +05:30
prafull-opensignlabsandGitHub f824fc7c81 Merge pull request #1314 from OpenSignLabs/react-tour
fix: issue of enableTour in createDocumentWithTemplate api
2024-10-09 14:39:46 +05:30
RaktimaNXG 244cc30eb6 fix: issue of enableTour in createDocumentWithTemplate api 2024-10-09 14:36:29 +05:30
AndrewandGitHub a833ed8060 Merge pull request #1313 from OpenSignLabs/validation 2024-10-09 13:52:19 +05:30
prafull-opensignlabs 1e869d2d2b fix: handle server down error in add admin for self-hosting 2024-10-09 13:50:20 +05:30
prafull-opensignlabsandGitHub 64df5cfff3 Merge pull request #1312 from OpenSignLabs/validation
fix: handle invalid credentials err while uploading file in form
2024-10-09 11:42:07 +05:30
prafull-opensignlabs d8b2a80e90 fix: handle invalid credentials err while uploading file in form 2024-10-09 11:39:59 +05:30
prafull-opensignlabsandGitHub 10061c061e Merge pull request #1311 from OpenSignLabs/validation
fix: correct migration script
2024-10-09 10:55:04 +05:30
prafull-opensignlabs 6a4124fdf0 fix: migration script 2024-10-09 10:52:38 +05:30
RaktimaandGitHub faaa915163 Merge pull request #1308 from OpenSignLabs/react-tour
fix: resolve duplicate auto-reminder input box issue in request signature form
2024-10-08 21:18:19 +05:30
AndrewandGitHub 3fb911298d Merge pull request #1309 from OpenSignLabs/validation 2024-10-08 20:14:26 +05:30
prafull-opensignlabs 761f81d27c fix: pdf is not loading when custom file storage change 2024-10-08 20:09:38 +05:30
RaktimaNXG d4b7c8ae97 fix: resolve duplicate auto-reminder input box issue in request signature form 2024-10-08 19:02:47 +05:30
prafull-opensignlabsandGitHub 23679e58e1 Merge pull request #1307 from OpenSignLabs/react-tour
fix: enable tour is not working
2024-10-08 16:47:05 +05:30
RaktimaNXG f3e39f18ef fix: enable tour is not working 2024-10-08 16:38:06 +05:30
prafull-opensignlabsandGitHub 55a4cda351 Merge pull request #1302 from OpenSignLabs/react-tour
feat: add enable tour option in request signature and template form
2024-10-08 14:15:19 +05:30
RaktimaNXG f0f270b44d fix: handle form advanced options data for self hosting user 2024-10-08 13:31:30 +05:30
RaktimaNXG 529de2bd90 fix: refactor code 2024-10-08 11:53:06 +05:30
RaktimaNXG 51dd83df09 refactor code 2024-10-08 10:29:14 +05:30
RaktimaNXG 9abe4ffd8e feat: update translation file 2024-10-08 10:27:26 +05:30
RaktimaNXG cdd92f6990 Merge branch 'staging' of https://github.com/OpenSignLabs/OpenSign into react-tour 2024-10-08 10:18:05 +05:30
prafull-opensignlabsandGitHub b08fa9bf60 Merge pull request #1298 from OpenSignLabs/dependabot/npm_and_yarn/apps/OpenSign/react-quill-new-3.3.3
build(deps): bump react-quill-new from 3.3.2 to 3.3.3 in /apps/OpenSign
2024-10-08 10:12:20 +05:30
prafull-opensignlabsandGitHub f0bcc3c3e7 Merge pull request #1299 from OpenSignLabs/dependabot/npm_and_yarn/apps/OpenSignServer/aws-sdk/s3-request-presigner-3.665.0
build(deps): bump @aws-sdk/s3-request-presigner from 3.664.0 to 3.665.0 in /apps/OpenSignServer
2024-10-08 10:11:59 +05:30
ZathielandGitHub b9c45f24f5 Merge pull request #1295 from OpenSignLabs/dependabot/npm_and_yarn/apps/OpenSign/i18next-23.15.2
build(deps): bump i18next from 23.15.1 to 23.15.2 in /apps/OpenSign
2024-10-07 20:33:06 +02:00
ZathielandGitHub d5f3967558 Merge pull request #1296 from OpenSignLabs/dependabot/npm_and_yarn/apps/OpenSign/daisyui-4.12.12
build(deps-dev): bump daisyui from 4.12.11 to 4.12.12 in /apps/OpenSign
2024-10-07 20:32:25 +02:00
ZathielandGitHub d3fccc9b87 Merge pull request #1297 from OpenSignLabs/dependabot/npm_and_yarn/apps/OpenSign/eslint-9.12.0
build(deps-dev): bump eslint from 9.11.1 to 9.12.0 in /apps/OpenSign
2024-10-07 20:31:19 +02:00
dependabot[bot]andGitHub 7e6c03faf5 build(deps): bump @aws-sdk/s3-request-presigner in /apps/OpenSignServer
Bumps [@aws-sdk/s3-request-presigner](https://github.com/aws/aws-sdk-js-v3/tree/HEAD/packages/s3-request-presigner) from 3.664.0 to 3.665.0.
- [Release notes](https://github.com/aws/aws-sdk-js-v3/releases)
- [Changelog](https://github.com/aws/aws-sdk-js-v3/blob/main/packages/s3-request-presigner/CHANGELOG.md)
- [Commits](https://github.com/aws/aws-sdk-js-v3/commits/v3.665.0/packages/s3-request-presigner)

---
updated-dependencies:
- dependency-name: "@aws-sdk/s3-request-presigner"
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-10-07 18:28:34 +00:00
ZathielandGitHub 02b2a52280 Merge pull request #1300 from OpenSignLabs/dependabot/npm_and_yarn/apps/OpenSignServer/eslint-9.12.0
build(deps-dev): bump eslint from 9.11.1 to 9.12.0 in /apps/OpenSignServer
2024-10-07 20:28:06 +02:00
ZathielandGitHub 6eb708b155 Merge pull request #1301 from OpenSignLabs/dependabot/npm_and_yarn/apps/OpenSignServer/aws-sdk/client-s3-3.665.0
build(deps): bump @aws-sdk/client-s3 from 3.664.0 to 3.665.0 in /apps/OpenSignServer
2024-10-07 20:26:18 +02:00
prafull-opensignlabsandGitHub 83e6444ddc Merge pull request #1306 from OpenSignLabs/validation
fix: custom file storage not working while create document using template
2024-10-07 16:42:40 +05:30
prafull-opensignlabs 168fe4d680 fix: custom file storage not working while create document using template 2024-10-07 16:40:49 +05:30
prafull-opensignlabsandGitHub 0a10c9a7c9 Merge pull request #1305 from OpenSignLabs/validation
refactor: remove unnecessary code
2024-10-07 14:29:11 +05:30
prafull-opensignlabs 204c530712 refactor: remove unncessary code 2024-10-07 14:22:18 +05:30
RaktimaandGitHub 5e55f0debf Merge branch 'staging' into react-tour 2024-10-07 11:31:58 +05:30
prafull-opensignlabsandGitHub f8bd5a6c86 Merge pull request #1304 from OpenSignLabs/validation
fix: custom file storage not working in use template
2024-10-07 11:29:09 +05:30
prafull-opensignlabs 101e7a9a49 fix: custom file storage not working in use template 2024-10-07 11:27:45 +05:30
RaktimaandGitHub 271e79d6a2 Update translation.json 2024-10-07 10:38:57 +05:30
RaktimaandGitHub 2ca8f8aff8 Update translation.json 2024-10-07 10:38:34 +05:30
RaktimaandGitHub bc6891e746 Update translation.json 2024-10-07 10:38:10 +05:30
RaktimaandGitHub 26aaeccf11 Update translation.json 2024-10-07 10:37:38 +05:30
RaktimaandGitHub 91b512b693 Merge branch 'staging' into react-tour 2024-10-07 10:05:50 +05:30
dependabot[bot]andGitHub 88d7917a84 build(deps): bump @aws-sdk/client-s3 in /apps/OpenSignServer
Bumps [@aws-sdk/client-s3](https://github.com/aws/aws-sdk-js-v3/tree/HEAD/clients/client-s3) from 3.664.0 to 3.665.0.
- [Release notes](https://github.com/aws/aws-sdk-js-v3/releases)
- [Changelog](https://github.com/aws/aws-sdk-js-v3/blob/main/clients/client-s3/CHANGELOG.md)
- [Commits](https://github.com/aws/aws-sdk-js-v3/commits/v3.665.0/clients/client-s3)

---
updated-dependencies:
- dependency-name: "@aws-sdk/client-s3"
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-10-07 00:57:25 +00:00
dependabot[bot]andGitHub 7ae0964dd1 build(deps-dev): bump eslint in /apps/OpenSignServer
Bumps [eslint](https://github.com/eslint/eslint) from 9.11.1 to 9.12.0.
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/compare/v9.11.1...v9.12.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-10-07 00:57:02 +00:00
dependabot[bot]andGitHub edb0c305dd build(deps): bump react-quill-new from 3.3.2 to 3.3.3 in /apps/OpenSign
Bumps [react-quill-new](https://github.com/VaguelySerious/react-quill) from 3.3.2 to 3.3.3.
- [Changelog](https://github.com/VaguelySerious/react-quill/blob/master/CHANGELOG.md)
- [Commits](https://github.com/VaguelySerious/react-quill/commits)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-10-07 00:08:54 +00:00
dependabot[bot]andGitHub 0321f35869 build(deps-dev): bump eslint from 9.11.1 to 9.12.0 in /apps/OpenSign
Bumps [eslint](https://github.com/eslint/eslint) from 9.11.1 to 9.12.0.
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/compare/v9.11.1...v9.12.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-10-07 00:08:42 +00:00
dependabot[bot]andGitHub 1870f8e90e build(deps-dev): bump daisyui from 4.12.11 to 4.12.12 in /apps/OpenSign
Bumps [daisyui](https://github.com/saadeghi/daisyui) from 4.12.11 to 4.12.12.
- [Release notes](https://github.com/saadeghi/daisyui/releases)
- [Changelog](https://github.com/saadeghi/daisyui/blob/master/CHANGELOG.md)
- [Commits](https://github.com/saadeghi/daisyui/compare/v4.12.11...v4.12.12)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-10-07 00:08:30 +00:00
dependabot[bot]andGitHub 6e112b904f build(deps): bump i18next from 23.15.1 to 23.15.2 in /apps/OpenSign
Bumps [i18next](https://github.com/i18next/i18next) from 23.15.1 to 23.15.2.
- [Release notes](https://github.com/i18next/i18next/releases)
- [Changelog](https://github.com/i18next/i18next/blob/master/CHANGELOG.md)
- [Commits](https://github.com/i18next/i18next/compare/v23.15.1...v23.15.2)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-10-07 00:08:12 +00:00
AndrewandGitHub dca8d2533e Merge pull request #1294 from OpenSignLabs/validation 2024-10-04 18:59:29 +05:30
prafull-opensignlabs c57957b56d fix: add error for uncompatible pdf 2024-10-04 18:45:15 +05:30
AndrewandGitHub 1f5ab87653 Merge pull request #1293 from OpenSignLabs/validation 2024-10-04 15:28:55 +05:30
RaktimaNXG d5513e90bd fix: update form advanced option layout design 2024-10-04 15:17:15 +05:30
prafull-opensignlabs 00fcd17285 feat: enable custom file storage for document siging 2024-10-04 12:59:10 +05:30
AndrewandGitHub 356ab4e7cb Merge pull request #1291 from OpenSignLabs/form-layout
fix: mobile view issue with text box widget design for value entry.
2024-10-03 21:36:56 +05:30
AndrewandGitHub 572cb55bf8 Update node version 2024-10-03 21:33:25 +05:30
RaktimaNXG 08b83469e3 fix: text box widgets font size issue 2024-10-03 20:36:34 +05:30
prafull-opensignlabsandGitHub 6939150d2b Merge pull request #1290 from OpenSignLabs/fix-issue
fix: issue of optional widget fields disappear after signing process
2024-10-03 19:25:01 +05:30
RaktimaNXG cf9a4d8a26 fix: issue of optional widgets disappear after signing 2024-10-03 18:34:30 +05:30
RaktimaNXG a5f8e4fc58 fix: updated documents order issue in opensign drive 2024-10-03 16:52:15 +05:30
prafull-opensignlabsandGitHub 775e325503 Merge pull request #1289 from OpenSignLabs/update_spanish
fix: update some phrase of spanish translation and add spanish language dropdown
2024-10-03 15:51:29 +05:30
RaktimaNXG 0c472ba22c fix: update form advanced options design 2024-10-03 14:20:28 +05:30
RaktimaNXG 4c0d15d6ef feat: update spanish translation 2024-10-03 13:40:37 +05:30
AndrewandGitHub 28cea81f61 Merge pull request #1288 from OpenSignLabs/all-contributors/add-1024mb
docs: add 1024mb as a contributor for translation
2024-10-03 13:15:53 +05:30
allcontributors[bot]andGitHub d975dae88f docs: update .all-contributorsrc 2024-10-03 07:45:30 +00:00
allcontributors[bot]andGitHub 30297584d5 docs: update README.md 2024-10-03 07:45:29 +00:00
AndrewandGitHub 1105f8e608 Merge pull request #1285 from 1024mb/spanish-translation
Add Spanish translation
2024-10-03 13:14:28 +05:30
Ángel Beretta eeae097a54 Update the changed strings from the original lang file 2024-10-01 21:40:22 -05:00
1024mbandGitHub 8199e5a253 Merge branch 'OpenSignLabs:staging' into spanish-translation 2024-10-01 21:31:40 -05:00
Ángel Beretta 08c7f4b491 Add Spanish translation 2024-10-01 21:28:57 -05:00
RaktimaNXG 634744c22d fix: text box widgets design to enter value issue in mobile view 2024-10-01 17:58:30 +05:30
prafull-opensignlabsandGitHub 45f4bdd1c5 Merge pull request #1282 from OpenSignLabs/form-layout
fix: document download issue in the disabled OTP public sign flow before signing and subscription issue in the guest login process
2024-10-01 12:46:34 +05:30
RaktimaNXG c8f5c80d5b fix: update tagline maxlength 2024-10-01 12:40:53 +05:30
RaktimaNXG 5556fafa94 fix: document download issue in the disabled OTP public sign flow before signing and subscription issue in the guest login process 2024-10-01 12:20:28 +05:30
prafull-opensignlabsandGitHub 20c21cb964 Merge pull request #1279 from OpenSignLabs/form-layout
fix: unexpected finish button visible after finish signature in disable otp public signing flow
2024-09-30 21:27:43 +05:30
AndrewandGitHub d2de889995 Merge pull request #1278 from OpenSignLabs/validation 2024-09-30 21:26:23 +05:30
RaktimaNXG 05cf3ef7fe fix: unexpected finish button visible after finish signature in disable otp public signing flow 2024-09-30 20:55:43 +05:30
prafull-opensignlabs 6bd8a8fea8 refactor: set fileAcl to none 2024-09-30 19:51:17 +05:30
prafull-opensignlabsandGitHub 4cba1a2fd2 Merge pull request #1277 from OpenSignLabs/form-layout
fix: disable otp issue in public signing flow
2024-09-30 19:38:31 +05:30
RaktimaNXG 86f0622c4a fix: disable otp issue in public signing flow 2024-09-30 19:37:17 +05:30
RaktimaNXG 85ad7ca187 feat: re-design form layout 2024-09-30 17:20:31 +05:30
AndrewandGitHub 879279a382 Merge pull request #1276 from OpenSignLabs/validation 2024-09-30 16:25:31 +05:30
prafull-opensignlabs 74df84e449 feat: add upload option in initials in my signature 2024-09-30 16:23:48 +05:30
ZathielandGitHub 2862ae3302 Merge pull request #1270 from OpenSignLabs/dependabot/npm_and_yarn/apps/OpenSignServer/mongoose-8.7.0 2024-09-30 11:47:27 +02:00
ZathielandGitHub 7d0dfe480c Merge pull request #1271 from OpenSignLabs/dependabot/npm_and_yarn/apps/OpenSign/react-bootstrap-2.10.5 2024-09-30 11:47:10 +02:00
ZathielandGitHub c47748ed4d Merge pull request #1272 from OpenSignLabs/dependabot/npm_and_yarn/apps/OpenSign/eslint-plugin-react-7.37.0 2024-09-30 11:46:59 +02:00
ZathielandGitHub 396504138c Merge pull request #1274 from OpenSignLabs/dependabot/npm_and_yarn/apps/OpenSign/commitizen-4.3.1 2024-09-30 11:46:44 +02:00
ZathielandGitHub 6e067a160c Merge pull request #1268 from OpenSignLabs/dependabot/npm_and_yarn/apps/OpenSign/npm_and_yarn-dcddfe2757 2024-09-30 11:46:27 +02:00
RaktimaNXG 66a56757d1 Merge branch 'staging' of https://github.com/OpenSignLabs/OpenSign into react-tour 2024-09-30 12:35:11 +05:30
RaktimaNXG 088ec5580a feat: add enable tour option in request signature and template form 2024-09-30 12:27:33 +05:30
prafull-opensignlabsandGitHub 63b2693fe0 Merge pull request #1275 from OpenSignLabs/validation
fix: enableOTP is not working correctly
2024-09-30 10:44:14 +05:30
prafull-opensignlabs 76a69d8f3b fix: enableOTP is not working correctly 2024-09-30 10:42:31 +05:30
dependabot[bot]andGitHub 5cd0f55cb2 build(deps-dev): bump commitizen from 4.3.0 to 4.3.1 in /apps/OpenSign
Bumps [commitizen](https://github.com/commitizen/cz-cli) from 4.3.0 to 4.3.1.
- [Release notes](https://github.com/commitizen/cz-cli/releases)
- [Commits](https://github.com/commitizen/cz-cli/compare/v4.3.0...v4.3.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-09-30 01:05:02 +00:00
dependabot[bot]andGitHub db640b04a6 build(deps-dev): bump eslint-plugin-react in /apps/OpenSign
Bumps [eslint-plugin-react](https://github.com/jsx-eslint/eslint-plugin-react) from 7.36.1 to 7.37.0.
- [Release notes](https://github.com/jsx-eslint/eslint-plugin-react/releases)
- [Changelog](https://github.com/jsx-eslint/eslint-plugin-react/blob/master/CHANGELOG.md)
- [Commits](https://github.com/jsx-eslint/eslint-plugin-react/compare/v7.36.1...v7.37.0)

---
updated-dependencies:
- dependency-name: eslint-plugin-react
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-09-30 01:04:29 +00:00
dependabot[bot]andGitHub 0665bcf30a build(deps): bump react-bootstrap in /apps/OpenSign
Bumps [react-bootstrap](https://github.com/react-bootstrap/react-bootstrap) from 2.10.4 to 2.10.5.
- [Release notes](https://github.com/react-bootstrap/react-bootstrap/releases)
- [Changelog](https://github.com/react-bootstrap/react-bootstrap/blob/master/CHANGELOG.md)
- [Commits](https://github.com/react-bootstrap/react-bootstrap/compare/v2.10.4...v2.10.5)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-09-30 01:04:19 +00:00
dependabot[bot]andGitHub 7e8ed42f46 build(deps): bump mongoose from 8.6.3 to 8.7.0 in /apps/OpenSignServer
Bumps [mongoose](https://github.com/Automattic/mongoose) from 8.6.3 to 8.7.0.
- [Release notes](https://github.com/Automattic/mongoose/releases)
- [Changelog](https://github.com/Automattic/mongoose/blob/master/CHANGELOG.md)
- [Commits](https://github.com/Automattic/mongoose/compare/8.6.3...8.7.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-09-30 00:49:48 +00:00
dependabot[bot]andGitHub 8d7b1a5b9b build(deps): bump rollup in /apps/OpenSign in the npm_and_yarn group
Bumps the npm_and_yarn group in /apps/OpenSign with 1 update: [rollup](https://github.com/rollup/rollup).


Updates `rollup` from 2.79.1 to 2.79.2
- [Release notes](https://github.com/rollup/rollup/releases)
- [Changelog](https://github.com/rollup/rollup/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rollup/rollup/compare/v2.79.1...v2.79.2)

---
updated-dependencies:
- dependency-name: rollup
  dependency-type: indirect
  dependency-group: npm_and_yarn
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-09-28 10:45:46 +00:00
prafull-opensignlabsandGitHub c6829a7d5e Merge pull request #1267 from OpenSignLabs/feat-embed
update the Angular code snippet syntax for use in the @opensign/angular package
2024-09-27 15:17:56 +05:30
RaktimaNXG bef8fbf183 update the Angular code snippet syntax for use in the @opensign/angular package 2024-09-27 14:56:38 +05:30
prafull-opensignlabsandGitHub fca95f09cc Merge pull request #1266 from OpenSignLabs/validation
fix: when pull latest using docker pdf files get remove with useLocal
2024-09-26 17:09:49 +05:30
prafull-opensignlabs 4d6cdf8823 fix: admin exists error 2024-09-26 17:05:06 +05:30
prafull-opensignlabs e34f52dcc5 fix: when pull latest using docker pdf files get remove with useLocal 2024-09-26 17:02:42 +05:30
prafull-opensignlabsandGitHub 91cc4e6f3d Merge pull request #1265 from OpenSignLabs/feat-embed
feat: add copy public URL option in template report to copy public template URL for public signing
2024-09-26 16:20:37 +05:30
RaktimaNXG 429b7dcb0e fix: refactor code 2024-09-26 16:06:37 +05:30
RaktimaNXG 5ffa681a80 feat: add copy public URL option to copy public url 2024-09-26 14:56:25 +05:30
AndrewandGitHub 91364db608 Merge pull request #1263 from OpenSignLabs/validation 2024-09-25 21:24:04 +05:30
prafull-opensignlabs 2433c68f27 fix: capture error message correctly 2024-09-25 21:22:48 +05:30
prafull-opensignlabs 6ea254d9ac fix: show proper error if server down in self-hosting 2024-09-25 21:01:17 +05:30
AndrewandGitHub a4d1df8324 Merge pull request #1262 from OpenSignLabs/validation
feat: add signature and png type image with transparent background in pdf
2024-09-25 17:02:05 +05:30
prafull-opensignlabs ba15611903 feat: add signature and png type image with transparent background in pdf 2024-09-25 17:01:03 +05:30
prafull-opensignlabsandGitHub eda6113792 Merge pull request #1261 from OpenSignLabs/raktima-patch-2
fix: update npm package name of public sign
2024-09-25 12:04:21 +05:30
RaktimaNXG 4f1509c836 fix: handle condition of embed options 2024-09-25 11:53:15 +05:30
prafull-opensignlabsandGitHub dfcf32ef3e Merge pull request #1260 from OpenSignLabs/validation
build(deps): update dependencies
2024-09-25 11:14:53 +05:30
prafull-opensignlabs 4a95257ee2 build(deps): update googleapis package 2024-09-25 11:13:18 +05:30
prafull-opensignlabs ee1e13ef61 build(deps): update dependencies 2024-09-25 11:00:57 +05:30
prafull-opensignlabsandGitHub c9c099ffc5 Merge pull request #1259 from OpenSignLabs/raktima-patch-4
fix: document download & document redirect on wrong route issue in opensign-drive
2024-09-25 10:23:30 +05:30
RaktimaNXG a80f4fb3c9 fix: document download & document redirect on wrong route issue in opensign-drive 2024-09-25 10:21:16 +05:30
prafull-opensignlabsandGitHub 941f3ac47f Merge pull request #1258 from OpenSignLabs/validation
fix: valid file is not attached to mail in signyourself flow
2024-09-25 10:12:11 +05:30
prafull-opensignlabs 80d3200d57 fix: valid file is not attached to mail in signyourself flow 2024-09-25 10:11:01 +05:30
ZathielandGitHub 55926e25d2 Merge pull request #1206 from OpenSignLabs/dependabot/npm_and_yarn/apps/OpenSign/eslint-plugin-react-7.36.1
build(deps-dev): bump eslint-plugin-react from 7.35.0 to 7.36.1 in /apps/OpenSign
2024-09-24 19:46:14 +02:00
ZathielandGitHub a31f3ebad7 Merge pull request #1251 from OpenSignLabs/dependabot/npm_and_yarn/apps/OpenSignServer/eslint-9.11.1
build(deps-dev): bump eslint from 9.9.1 to 9.11.1 in /apps/OpenSignServer
2024-09-24 19:44:11 +02:00
RaktimaNXG dc9c32c6ee fix: update npm package name of public sign 2024-09-24 20:19:16 +05:30
dependabot[bot]andGitHub dac3aac2a1 build(deps-dev): bump eslint in /apps/OpenSignServer
Bumps [eslint](https://github.com/eslint/eslint) from 9.9.1 to 9.11.1.
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/compare/v9.9.1...v9.11.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-09-24 14:06:57 +00:00
AndrewandGitHub 40196e823c Merge pull request #1252 from OpenSignLabs/validation
build(deps): bump parse-server from 7.2.0 to 7.3.0-alpha.7 in /apps/OpenSignServer
2024-09-24 19:35:40 +05:30
prafull-opensignlabs 7708b7e938 build(deps): bump googleapis from 7.2.0 to 7.3.0-alpha.7 in /apps/OpenSignServer 2024-09-24 19:34:38 +05:30
prafull-opensignlabsandGitHub 8bbc5a9bc6 Merge pull request #1149 from OpenSignLabs/dependabot/npm_and_yarn/apps/OpenSign/babel/runtime-corejs2-7.25.6
build(deps-dev): bump @babel/runtime-corejs2 from 7.25.4 to 7.25.6 in /apps/OpenSign
2024-09-24 19:13:56 +05:30
prafull-opensignlabsandGitHub 4dbdfb1b77 Merge pull request #1238 from OpenSignLabs/dependabot/npm_and_yarn/apps/OpenSignServer/nodemon-3.1.7
build(deps-dev): bump nodemon from 3.1.4 to 3.1.7 in /apps/OpenSignServer
2024-09-24 19:10:12 +05:30
prafull-opensignlabsandGitHub 05c51edce3 Merge pull request #1209 from OpenSignLabs/dependabot/npm_and_yarn/apps/OpenSignServer/aws-sdk-2.1691.0
build(deps): bump aws-sdk from 2.1687.0 to 2.1691.0 in /apps/OpenSignServer
2024-09-24 19:09:24 +05:30
prafull-opensignlabsandGitHub 379e8cd95e Merge pull request #1208 from OpenSignLabs/dependabot/npm_and_yarn/apps/OpenSign/react-router-dom-6.26.2
build(deps): bump react-router-dom from 6.26.1 to 6.26.2 in /apps/OpenSign
2024-09-24 19:08:57 +05:30
prafull-opensignlabsandGitHub 9fd00d4427 Merge pull request #1250 from OpenSignLabs/dependabot/npm_and_yarn/apps/OpenSign/tailwindcss-3.4.13
build(deps-dev): bump tailwindcss from 3.4.12 to 3.4.13 in /apps/OpenSign
2024-09-24 19:08:27 +05:30
dependabot[bot]andGitHub ca114cf124 build(deps-dev): bump eslint-plugin-react in /apps/OpenSign
Bumps [eslint-plugin-react](https://github.com/jsx-eslint/eslint-plugin-react) from 7.35.0 to 7.36.1.
- [Release notes](https://github.com/jsx-eslint/eslint-plugin-react/releases)
- [Changelog](https://github.com/jsx-eslint/eslint-plugin-react/blob/master/CHANGELOG.md)
- [Commits](https://github.com/jsx-eslint/eslint-plugin-react/compare/v7.35.0...v7.36.1)

---
updated-dependencies:
- dependency-name: eslint-plugin-react
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-09-24 13:37:44 +00:00
prafull-opensignlabsandGitHub 75128784db Merge pull request #1240 from OpenSignLabs/dependabot/npm_and_yarn/apps/OpenSignServer/mongoose-8.6.3
build(deps): bump mongoose from 8.6.1 to 8.6.3 in /apps/OpenSignServer
2024-09-24 19:07:23 +05:30
dependabot[bot]andGitHub 722f0e277e build(deps-dev): bump tailwindcss in /apps/OpenSign
Bumps [tailwindcss](https://github.com/tailwindlabs/tailwindcss) from 3.4.12 to 3.4.13.
- [Release notes](https://github.com/tailwindlabs/tailwindcss/releases)
- [Changelog](https://github.com/tailwindlabs/tailwindcss/blob/v3.4.13/CHANGELOG.md)
- [Commits](https://github.com/tailwindlabs/tailwindcss/compare/v3.4.12...v3.4.13)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-09-24 13:36:58 +00:00
prafull-opensignlabsandGitHub 7089998966 Merge pull request #1241 from OpenSignLabs/dependabot/npm_and_yarn/apps/OpenSign/tailwindcss-3.4.12
build(deps-dev): bump tailwindcss from 3.4.10 to 3.4.12 in /apps/OpenSign
2024-09-24 19:06:28 +05:30
prafull-opensignlabsandGitHub 52211ddfa4 Merge pull request #1242 from OpenSignLabs/dependabot/npm_and_yarn/apps/OpenSign/postcss-8.4.47
build(deps-dev): bump postcss from 8.4.45 to 8.4.47 in /apps/OpenSign
2024-09-24 19:05:24 +05:30
AndrewandGitHub 2b8b762d35 Merge pull request #1225 from OpenSignLabs/raktima-patch-2
feat: introduce embedding feature for template
2024-09-24 19:03:11 +05:30
AndrewandGitHub 04c228cd36 Merge pull request #1249 from OpenSignLabs/validation
fix: pagination move on the top records in reports
2024-09-24 18:30:28 +05:30
prafull-opensignlabs 915f8e7700 fix: pagination move on the top records in reports 2024-09-24 18:26:43 +05:30
AndrewandGitHub 218cea00b5 Merge pull request #1247 from OpenSignLabs/validation 2024-09-24 17:29:03 +05:30
prafull-opensignlabs f38f5ea670 fix: file upload get stuck while uploading docx 2024-09-24 17:28:24 +05:30
RaktimaNXG a9c08c8a9f fix: update angular package name 2024-09-24 16:11:58 +05:30
RaktimaNXG 9406c4f718 Merge branch 'raktima-patch-2' of https://github.com/OpenSignLabs/OpenSign into raktima-patch-2 2024-09-24 15:01:23 +05:30
AndrewandGitHub 791d8beb06 Merge pull request #1246 from OpenSignLabs/validation 2024-09-24 13:58:51 +05:30
prafull-opensignlabs 57a9f3aca0 fix: document title not get generated when upload image 2024-09-24 13:56:25 +05:30
prafull-opensignlabs ae8bf187c8 fix: not able draw boxes in debug ui on single page pdf 2024-09-24 12:37:50 +05:30
prafull-opensignlabs 88f2ab1f8e fix: close sidebar in mobile view when user click on profile menu from header 2024-09-24 12:19:32 +05:30
AndrewandGitHub 76f5136073 Merge pull request #1245 from OpenSignLabs/validation 2024-09-23 18:10:14 +05:30
prafull-opensignlabs 0f84cd8949 feat: generate document title automatically on the basis file name 2024-09-23 18:09:23 +05:30
AndrewandGitHub adfdf7606f Merge pull request #1244 from OpenSignLabs/validation
feat: add validatesmtp endpoint
2024-09-23 17:01:25 +05:30
prafull-opensignlabs ce671d4294 feat: add validatesmtp endpoint 2024-09-23 17:00:45 +05:30
AndrewandGitHub 2e7cf7a9df Merge pull request #1243 from OpenSignLabs/validation 2024-09-23 11:54:22 +05:30
prafull-opensignlabs f699d93e44 fix: resend mail is not went throught customsmtp 2024-09-23 11:53:15 +05:30
dependabot[bot]andGitHub 531ef4d0b2 build(deps-dev): bump postcss from 8.4.45 to 8.4.47 in /apps/OpenSign
Bumps [postcss](https://github.com/postcss/postcss) from 8.4.45 to 8.4.47.
- [Release notes](https://github.com/postcss/postcss/releases)
- [Changelog](https://github.com/postcss/postcss/blob/main/CHANGELOG.md)
- [Commits](https://github.com/postcss/postcss/compare/8.4.45...8.4.47)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-09-23 00:38:18 +00:00
dependabot[bot]andGitHub 4c6dbb6690 build(deps-dev): bump tailwindcss in /apps/OpenSign
Bumps [tailwindcss](https://github.com/tailwindlabs/tailwindcss) from 3.4.10 to 3.4.12.
- [Release notes](https://github.com/tailwindlabs/tailwindcss/releases)
- [Changelog](https://github.com/tailwindlabs/tailwindcss/blob/v3.4.12/CHANGELOG.md)
- [Commits](https://github.com/tailwindlabs/tailwindcss/compare/v3.4.10...v3.4.12)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-09-23 00:35:44 +00:00
dependabot[bot]andGitHub 0beb60d1b5 build(deps): bump mongoose from 8.6.1 to 8.6.3 in /apps/OpenSignServer
Bumps [mongoose](https://github.com/Automattic/mongoose) from 8.6.1 to 8.6.3.
- [Release notes](https://github.com/Automattic/mongoose/releases)
- [Changelog](https://github.com/Automattic/mongoose/blob/master/CHANGELOG.md)
- [Commits](https://github.com/Automattic/mongoose/compare/8.6.1...8.6.3)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-09-23 00:20:14 +00:00
dependabot[bot]andGitHub 893c9d7c42 build(deps-dev): bump nodemon in /apps/OpenSignServer
Bumps [nodemon](https://github.com/remy/nodemon) from 3.1.4 to 3.1.7.
- [Release notes](https://github.com/remy/nodemon/releases)
- [Commits](https://github.com/remy/nodemon/compare/v3.1.4...v3.1.7)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-09-23 00:19:44 +00:00
AndrewandGitHub b7a22d94db Merge pull request #1236 from OpenSignLabs/validation
refactor: add parenthesis
2024-09-20 20:09:33 +05:30
prafull-opensignlabs 3d854756d1 refactor: add parenthesis 2024-09-20 20:07:17 +05:30
AndrewandGitHub 251e7058f1 Merge pull request #1235 from OpenSignLabs/validation
feat: custom smtp support
2024-09-20 19:59:04 +05:30
prafull-opensignlabs 368eb24217 feat: custom smtp support 2024-09-20 19:57:30 +05:30
AndrewandGitHub f89ef54b82 Merge pull request #1233 from OpenSignLabs/raktima-patch-3
feat: enable dismiss button to hide notification in header
2024-09-20 19:30:15 +05:30
RaktimaNXG b9d9f8772b feat: enable dismiss button to hide notification in header 2024-09-20 18:17:31 +05:30
AndrewandGitHub f2ee03e850 Merge pull request #1232 from OpenSignLabs/raktima-patch-3 2024-09-20 18:11:21 +05:30
RaktimaNXG 92e59a0072 fix: zip file 2024-09-20 17:58:57 +05:30
RaktimaNXG 5394c0b520 refactor code 2024-09-20 16:41:41 +05:30
RaktimaNXG e4a9c6f8c2 fix: remove console 2024-09-20 15:49:50 +05:30
RaktimaNXG e559d037c3 feat: add zip file to dowload pdf and certificate in all download option of completed pdf 2024-09-20 15:33:13 +05:30
RaktimaNXG c9909a0869 Merge branch 'staging' of https://github.com/OpenSignLabs/OpenSign into raktima-patch-3 2024-09-20 12:10:44 +05:30
RaktimaNXG 988fc1bbfd fix: error 2024-09-20 12:08:01 +05:30
RaktimaNXG 1831bbcd70 feat: add zip file to download pdf and certificate 2024-09-20 12:04:10 +05:30
prafull-opensignlabsandGitHub ced9bbdbd5 Merge pull request #1230 from OpenSignLabs/fix-Confetti
fix: tour design
2024-09-20 10:15:36 +05:30
RaktimaNXG 15d57d937b fix: tour design 2024-09-19 19:38:25 +05:30
AndrewandGitHub 555979869d Merge pull request #1228 from OpenSignLabs/validation
refactor: provide appName
2024-09-19 19:09:56 +05:30
prafull-opensignlabs 4e6477297e refactor: provide appName 2024-09-19 19:07:54 +05:30
AndrewandGitHub e9e06fc53b Merge pull request #1227 from OpenSignLabs/fix-Confetti 2024-09-19 19:06:46 +05:30
RaktimaNXG ecb2818589 fix: update confetti effect 2024-09-19 19:04:59 +05:30
RaktimaNXG c442689573 fix: remove console 2024-09-19 18:38:32 +05:30
RaktimaNXG 88919f2634 refactor code 2024-09-19 17:47:50 +05:30
AndrewandGitHub 1a1bc41283 Merge pull request #1226 from OpenSignLabs/validation 2024-09-19 17:44:04 +05:30
prafull-opensignlabs 4188caed33 feat: add document logs in in-progress report 2024-09-19 17:42:44 +05:30
RaktimaNXG 50557d8bc5 Merge branch 'staging' of https://github.com/OpenSignLabs/OpenSign into raktima-patch-2 2024-09-19 17:34:28 +05:30
RaktimaNXG 0f1ef0406e refactor code 2024-09-19 17:19:45 +05:30
prafull-opensignlabsandGitHub ffc742b460 Merge pull request #1224 from OpenSignLabs/raktima-patch-3
fix: ui design in mobile view
2024-09-19 15:57:25 +05:30
RaktimaNXG 0c04cc6ce6 fix: update translation file 2024-09-19 15:27:49 +05:30
RaktimaNXG 4e6dfed838 refactor code 2024-09-19 14:42:13 +05:30
RaktimaNXG fdc0524ad2 fix: ui design in mobile view 2024-09-19 14:35:10 +05:30
AndrewandGitHub 096d5962a3 Merge pull request #1221 from OpenSignLabs/validation 2024-09-19 11:30:35 +05:30
prafull-opensignlabs 9ea36f94a7 fix: enableOTP not working properly in template 2024-09-19 11:28:13 +05:30
AndrewandGitHub 2b66df992f Merge pull request #1220 from OpenSignLabs/validation 2024-09-19 10:27:18 +05:30
prafull-opensignlabs ff3c31975e refactor: remove extra space 2024-09-19 10:26:35 +05:30
AndrewandGitHub beaa5eca69 Merge pull request #1219 from OpenSignLabs/validation 2024-09-18 21:17:16 +05:30
prafull-opensignlabs b98040faac fix: document decline event not trigger on revoke 2024-09-18 21:15:31 +05:30
AndrewandGitHub fbbff0df61 Merge pull request #1218 from OpenSignLabs/validation 2024-09-18 19:57:46 +05:30
prafull-opensignlabs 07d5f393c0 fix: document viewed event not trigger 2024-09-18 19:56:47 +05:30
AndrewandGitHub 8220b15a29 Merge pull request #1217 from OpenSignLabs/validation
refactor: add enableOTP in allowedkeys in update doc
2024-09-18 19:27:42 +05:30
prafull-opensignlabs 7cf638b2be refactor: add enableOTP in allowedkeys in update doc 2024-09-18 19:22:41 +05:30
RaktimaNXG 9852c87be7 fix: design in mobile view 2024-09-18 18:19:08 +05:30
prafull-opensignlabsandGitHub 30fb8f31e3 Merge pull request #1216 from OpenSignLabs/validation
fix: blank page appear when try to add typed signature
2024-09-18 18:10:37 +05:30
prafull-opensignlabs ec4d875547 fix: blank page appear when try to add typed signature 2024-09-18 18:09:18 +05:30
RaktimaNXG 1268f65516 fix: update angular text 2024-09-18 16:58:04 +05:30
RaktimaNXG 6551b2537a feat: implement angular npm package use case in public template 2024-09-18 16:48:20 +05:30
AndrewandGitHub 43eee63df2 Merge pull request #1215 from OpenSignLabs/validation 2024-09-18 14:36:30 +05:30
prafull-opensignlabs 4caf9f598a refactor: change variable from isDisableOTP to isEnableOTP 2024-09-18 14:32:45 +05:30
AndrewandGitHub 107eaca8f0 Merge pull request #1213 from OpenSignLabs/validation
feat: add disable OTP feature to directly sign document without verification
2024-09-17 18:31:15 +05:30
prafull-opensignlabs cc11848346 feat: add disable OTP feature to directly sign document without verification 2024-09-17 18:27:21 +05:30
dependabot[bot]andGitHub b138ccf625 build(deps): bump aws-sdk in /apps/OpenSignServer
Bumps [aws-sdk](https://github.com/aws/aws-sdk-js) from 2.1687.0 to 2.1691.0.
- [Release notes](https://github.com/aws/aws-sdk-js/releases)
- [Commits](https://github.com/aws/aws-sdk-js/compare/v2.1687.0...v2.1691.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-09-16 00:51:57 +00:00
dependabot[bot]andGitHub 27ff7baa6d build(deps): bump react-router-dom in /apps/OpenSign
Bumps [react-router-dom](https://github.com/remix-run/react-router/tree/HEAD/packages/react-router-dom) from 6.26.1 to 6.26.2.
- [Release notes](https://github.com/remix-run/react-router/releases)
- [Changelog](https://github.com/remix-run/react-router/blob/main/packages/react-router-dom/CHANGELOG.md)
- [Commits](https://github.com/remix-run/react-router/commits/react-router-dom@6.26.2/packages/react-router-dom)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-09-16 00:12:46 +00:00
ZathielandGitHub c8ecd34bd3 Merge pull request #1148 from OpenSignLabs/dependabot/npm_and_yarn/apps/OpenSign/lint-staged-15.2.10
build(deps-dev): bump lint-staged from 15.2.9 to 15.2.10 in /apps/OpenSign
2024-09-13 20:00:31 +02:00
ZathielandGitHub d4a4eb3248 Merge pull request #1182 from OpenSignLabs/dependabot/npm_and_yarn/apps/OpenSignServer/mongoose-8.6.1
build(deps): bump mongoose from 8.6.0 to 8.6.1 in /apps/OpenSignServer
2024-09-13 20:00:01 +02:00
ZathielandGitHub f782733397 Merge pull request #1186 from OpenSignLabs/dependabot/npm_and_yarn/apps/OpenSignServer/jasmine-5.3.0
build(deps-dev): bump jasmine from 5.2.0 to 5.3.0 in /apps/OpenSignServer
2024-09-13 19:59:13 +02:00
ZathielandGitHub 7720eddc47 Merge pull request #1183 from OpenSignLabs/dependabot/npm_and_yarn/apps/OpenSignServer/nodemailer-6.9.15
build(deps): bump nodemailer from 6.9.14 to 6.9.15 in /apps/OpenSignServer
2024-09-13 19:58:58 +02:00
AndrewandGitHub 71170a373a Merge pull request #1205 from OpenSignLabs/validation 2024-09-13 12:58:49 +05:30
prafull-opensignlabs 8f080080a7 refactor: changes in text of modal 2024-09-13 12:57:23 +05:30
AndrewandGitHub 71b2958c14 Merge pull request #1204 from OpenSignLabs/validation 2024-09-13 10:56:58 +05:30
prafull-opensignlabs f69aafcbfa refactor: provide userdetails 2024-09-13 10:52:22 +05:30
AndrewandGitHub 5f6a423697 Merge pull request #1203 from OpenSignLabs/validation 2024-09-12 13:29:39 +05:30
prafull-opensignlabs 5d245927c4 fix: user count is not correct 2024-09-12 13:25:11 +05:30
prafull-opensignlabsandGitHub 17c96fb849 Merge pull request #1201 from OpenSignLabs/dependabot/npm_and_yarn/apps/OpenSignServer/npm_and_yarn-d7ff1d4c1a
build(deps): bump the npm_and_yarn group in /apps/OpenSignServer with 2 updates
2024-09-12 12:07:50 +05:30
prafull-opensignlabsandGitHub b7c28cdf36 Merge pull request #1202 from OpenSignLabs/dependabot/npm_and_yarn/apps/OpenSign/npm_and_yarn-cf87d80143
build(deps): bump the npm_and_yarn group in /apps/OpenSign with 2 updates
2024-09-12 12:07:17 +05:30
dependabot[bot]andGitHub d05aa0d350 build(deps): bump the npm_and_yarn group
Bumps the npm_and_yarn group in /apps/OpenSign with 2 updates: [send](https://github.com/pillarjs/send) and [express](https://github.com/expressjs/express).


Updates `send` from 0.18.0 to 0.19.0
- [Release notes](https://github.com/pillarjs/send/releases)
- [Changelog](https://github.com/pillarjs/send/blob/master/HISTORY.md)
- [Commits](https://github.com/pillarjs/send/compare/0.18.0...0.19.0)

Updates `express` from 4.20.0 to 4.21.0
- [Release notes](https://github.com/expressjs/express/releases)
- [Changelog](https://github.com/expressjs/express/blob/4.21.0/History.md)
- [Commits](https://github.com/expressjs/express/compare/4.20.0...4.21.0)

---
updated-dependencies:
- dependency-name: send
  dependency-type: indirect
  dependency-group: npm_and_yarn
- dependency-name: express
  dependency-type: indirect
  dependency-group: npm_and_yarn
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-09-12 06:34:33 +00:00
prafull-opensignlabsandGitHub 875dc086bf Merge pull request #1195 from OpenSignLabs/dependabot/npm_and_yarn/apps/OpenSign/npm_and_yarn-31414ddb3e
build(deps): bump the npm_and_yarn group in /apps/OpenSign with 4 updates
2024-09-12 12:02:55 +05:30
dependabot[bot]andGitHub 4719ebd52a build(deps): bump the npm_and_yarn group
Bumps the npm_and_yarn group in /apps/OpenSignServer with 2 updates: [express](https://github.com/expressjs/express) and [dset](https://github.com/lukeed/dset).


Updates `express` from 4.20.0 to 4.21.0
- [Release notes](https://github.com/expressjs/express/releases)
- [Changelog](https://github.com/expressjs/express/blob/4.21.0/History.md)
- [Commits](https://github.com/expressjs/express/compare/4.20.0...4.21.0)

Updates `dset` from 3.1.3 to 3.1.4
- [Release notes](https://github.com/lukeed/dset/releases)
- [Commits](https://github.com/lukeed/dset/compare/v3.1.3...v3.1.4)

---
updated-dependencies:
- dependency-name: express
  dependency-type: direct:production
  dependency-group: npm_and_yarn
- dependency-name: dset
  dependency-type: indirect
  dependency-group: npm_and_yarn
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-09-11 23:46:04 +00:00
AndrewandGitHub c8a436a7df Merge pull request #1200 from OpenSignLabs/validation 2024-09-11 20:10:47 +05:30
prafull-opensignlabs 8d6f4dd64e fix: issue user count 2024-09-11 20:10:19 +05:30
AndrewandGitHub 63486927d6 Merge pull request #1199 from OpenSignLabs/validation 2024-09-11 17:54:59 +05:30
prafull-opensignlabs c36a70f8d3 refactor: add user validation 2024-09-11 17:50:39 +05:30
AndrewandGitHub 39472d6874 Merge pull request #1197 from OpenSignLabs/validation 2024-09-11 12:26:18 +05:30
prafull-opensignlabs 6207e99cc0 fix: pagination issue 2024-09-11 12:23:09 +05:30
prafull-opensignlabsandGitHub bdc163199d Merge pull request #1196 from OpenSignLabs/raktima-patch-3
fix: after submitting the request sign form a blank page appears on mobile view
2024-09-11 11:06:13 +05:30
RaktimaNXG e7a04ede65 fix: after submitting the request sign form a blank page appears on mobile view 2024-09-11 10:52:18 +05:30
prafull-opensignlabsandGitHub f6aee4148d Merge pull request #1194 from OpenSignLabs/dependabot/npm_and_yarn/apps/OpenSignServer/npm_and_yarn-7a84200127
build(deps): bump express from 4.19.2 to 4.20.0 in /apps/OpenSignServer in the npm_and_yarn group
2024-09-11 10:51:13 +05:30
dependabot[bot]andGitHub 6cb30a6597 build(deps): bump the npm_and_yarn group
Bumps the npm_and_yarn group in /apps/OpenSign with 4 updates: [body-parser](https://github.com/expressjs/body-parser), [express](https://github.com/expressjs/express), [path-to-regexp](https://github.com/pillarjs/path-to-regexp) and [serve-static](https://github.com/expressjs/serve-static).


Updates `body-parser` from 1.20.2 to 1.20.3
- [Release notes](https://github.com/expressjs/body-parser/releases)
- [Changelog](https://github.com/expressjs/body-parser/blob/master/HISTORY.md)
- [Commits](https://github.com/expressjs/body-parser/compare/1.20.2...1.20.3)

Updates `express` from 4.19.2 to 4.20.0
- [Release notes](https://github.com/expressjs/express/releases)
- [Changelog](https://github.com/expressjs/express/blob/master/History.md)
- [Commits](https://github.com/expressjs/express/compare/4.19.2...4.20.0)

Updates `express` from 4.19.2 to 4.20.0
- [Release notes](https://github.com/expressjs/express/releases)
- [Changelog](https://github.com/expressjs/express/blob/master/History.md)
- [Commits](https://github.com/expressjs/express/compare/4.19.2...4.20.0)

Updates `path-to-regexp` from 0.1.7 to 0.1.10
- [Release notes](https://github.com/pillarjs/path-to-regexp/releases)
- [Changelog](https://github.com/pillarjs/path-to-regexp/blob/master/History.md)
- [Commits](https://github.com/pillarjs/path-to-regexp/compare/v0.1.7...v0.1.10)

Updates `serve-static` from 1.15.0 to 1.16.0
- [Release notes](https://github.com/expressjs/serve-static/releases)
- [Changelog](https://github.com/expressjs/serve-static/blob/master/HISTORY.md)
- [Commits](https://github.com/expressjs/serve-static/compare/v1.15.0...1.16.0)

---
updated-dependencies:
- dependency-name: body-parser
  dependency-type: indirect
  dependency-group: npm_and_yarn
- dependency-name: express
  dependency-type: indirect
  dependency-group: npm_and_yarn
- dependency-name: express
  dependency-type: indirect
  dependency-group: npm_and_yarn
- dependency-name: path-to-regexp
  dependency-type: indirect
  dependency-group: npm_and_yarn
- dependency-name: serve-static
  dependency-type: indirect
  dependency-group: npm_and_yarn
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-09-11 04:58:46 +00:00
dependabot[bot]andGitHub 34fcfc8f30 build(deps): bump express
Bumps the npm_and_yarn group in /apps/OpenSignServer with 1 update: [express](https://github.com/expressjs/express).


Updates `express` from 4.19.2 to 4.20.0
- [Release notes](https://github.com/expressjs/express/releases)
- [Changelog](https://github.com/expressjs/express/blob/master/History.md)
- [Commits](https://github.com/expressjs/express/compare/4.19.2...4.20.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-09-11 04:58:43 +00:00
dependabot[bot]andGitHub bc89b33468 build(deps-dev): bump lint-staged in /apps/OpenSign
Bumps [lint-staged](https://github.com/lint-staged/lint-staged) from 15.2.9 to 15.2.10.
- [Release notes](https://github.com/lint-staged/lint-staged/releases)
- [Changelog](https://github.com/lint-staged/lint-staged/blob/master/CHANGELOG.md)
- [Commits](https://github.com/lint-staged/lint-staged/compare/v15.2.9...v15.2.10)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-09-11 04:58:17 +00:00
prafull-opensignlabsandGitHub af9af347e6 Merge pull request #1192 from OpenSignLabs/dependabot/npm_and_yarn/apps/OpenSign/npm_and_yarn-7ee3b15cf5
build(deps-dev): bump postcss from 8.4.44 to 8.4.45 in /apps/OpenSign in the npm_and_yarn group
2024-09-11 10:27:04 +05:30
dependabot[bot]andGitHub 6f46279b52 build(deps-dev): bump postcss
Bumps the npm_and_yarn group in /apps/OpenSign with 1 update: [postcss](https://github.com/postcss/postcss).


Updates `postcss` from 8.4.44 to 8.4.45
- [Release notes](https://github.com/postcss/postcss/releases)
- [Changelog](https://github.com/postcss/postcss/blob/main/CHANGELOG.md)
- [Commits](https://github.com/postcss/postcss/compare/8.4.44...8.4.45)

---
updated-dependencies:
- dependency-name: postcss
  dependency-type: direct:development
  dependency-group: npm_and_yarn
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-09-10 12:53:18 +00:00
AndrewandGitHub 8f93ed8b8e Merge pull request #1191 from OpenSignLabs/validation 2024-09-10 16:41:59 +05:30
prafull-opensignlabs df91363ff4 fix: pagination issue 2024-09-10 16:41:08 +05:30
AndrewandGitHub e40e59714d Merge pull request #1190 from OpenSignLabs/validation 2024-09-10 13:43:28 +05:30
prafull-opensignlabs a43d95afc3 refactor: validation 2024-09-10 13:42:35 +05:30
AndrewandGitHub 8fa4b5ab22 Merge pull request #1189 from OpenSignLabs/validation 2024-09-09 15:46:44 +05:30
prafull-opensignlabs 68a030145f fix: handle invalid session token error while logging out 2024-09-09 15:44:01 +05:30
AndrewandGitHub 4f48657623 Merge pull request #1175 from OpenSignLabs/validation 2024-09-09 10:19:08 +05:30
RaktimaNXG 3fc41f4255 feat : implement credit deduction in the public signature process 2024-09-09 09:59:33 +05:30
dependabot[bot]andGitHub ff2f7f6586 build(deps-dev): bump jasmine in /apps/OpenSignServer
Bumps [jasmine](https://github.com/jasmine/jasmine-npm) from 5.2.0 to 5.3.0.
- [Release notes](https://github.com/jasmine/jasmine-npm/releases)
- [Changelog](https://github.com/jasmine/jasmine-npm/blob/main/RELEASE.md)
- [Commits](https://github.com/jasmine/jasmine-npm/compare/v5.2.0...v5.3.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-09-09 00:12:15 +00:00
dependabot[bot]andGitHub 93f33d73d9 build(deps): bump nodemailer in /apps/OpenSignServer
Bumps [nodemailer](https://github.com/nodemailer/nodemailer) from 6.9.14 to 6.9.15.
- [Release notes](https://github.com/nodemailer/nodemailer/releases)
- [Changelog](https://github.com/nodemailer/nodemailer/blob/master/CHANGELOG.md)
- [Commits](https://github.com/nodemailer/nodemailer/compare/v6.9.14...v6.9.15)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-09-09 00:11:47 +00:00
dependabot[bot]andGitHub 402c176277 build(deps): bump mongoose from 8.6.0 to 8.6.1 in /apps/OpenSignServer
Bumps [mongoose](https://github.com/Automattic/mongoose) from 8.6.0 to 8.6.1.
- [Release notes](https://github.com/Automattic/mongoose/releases)
- [Changelog](https://github.com/Automattic/mongoose/blob/master/CHANGELOG.md)
- [Commits](https://github.com/Automattic/mongoose/compare/8.6.0...8.6.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-09-09 00:11:41 +00:00
prafull-opensignlabs 79b05b4a66 refactor: handle tab in menu 2024-09-06 20:10:56 +05:30
AndrewandGitHub fb9e37e71c Merge pull request #1173 from OpenSignLabs/validation 2024-09-06 19:37:54 +05:30
prafull-opensignlabs cd7a741d53 fix: size of tour 2024-09-06 19:36:27 +05:30
AmolandGitHub 5fdc90b4f9 Merge pull request #1172 from OpenSignLabs/validation
fix: quick send not working
2024-09-06 18:51:45 +05:30
prafull-opensignlabs e775840abb fix: quicksend not working 2024-09-06 18:50:15 +05:30
prafull-opensignlabs d7df54dfa1 fix: quick send not working 2024-09-06 18:45:35 +05:30
AndrewandGitHub 646d165d37 Merge pull request #1171 from OpenSignLabs/validation 2024-09-06 18:04:14 +05:30
prafull-opensignlabs ba0a80cca4 refactor: text change 2024-09-06 18:01:47 +05:30
AndrewandGitHub 9d59858542 Merge pull request #1170 from OpenSignLabs/validation 2024-09-06 17:59:59 +05:30
prafull-opensignlabs aaff0a5697 refactor: text translation 2024-09-06 17:58:18 +05:30
AndrewandGitHub 1bb7cee238 Merge pull request #1169 from OpenSignLabs/validation 2024-09-06 17:46:22 +05:30
prafull-opensignlabs d330e662d3 refactor: correct keys in translation files 2024-09-06 17:14:53 +05:30
prafull-opensignlabs b530ff76c4 refactor: translate text 2024-09-06 16:41:56 +05:30
RaktimaNXG b20aa33a04 Merge branch 'staging' of https://github.com/OpenSignLabs/OpenSign into raktima-patch-2 2024-09-06 15:23:31 +05:30
AndrewandGitHub e59a166445 Merge pull request #1168 from OpenSignLabs/validation 2024-09-06 14:48:47 +05:30
prafull-opensignlabs 980e713735 refactor: validation 2024-09-06 14:47:57 +05:30
prafull-opensignlabsandGitHub 7a5228bbab Merge pull request #1167 from OpenSignLabs/validation
refactor: validation
2024-09-06 12:00:26 +05:30
prafull-opensignlabs 5a26e5c2ee refactor: validaiton 2024-09-06 11:56:54 +05:30
RaktimaNXG a64da4cd85 Merge branch 'staging' of https://github.com/OpenSignLabs/OpenSign into raktima-patch-2 2024-09-06 09:59:41 +05:30
prafull-opensignlabsandGitHub c2dccf17ce Merge pull request #1166 from OpenSignLabs/validation
fix: email count not update until re-login
2024-09-05 19:21:06 +05:30
prafull-opensignlabs 181d6bf1e4 fix: email count not update until re-login 2024-09-05 19:19:15 +05:30
RaktimaNXG e80bcfc586 refactor code 2024-09-05 18:41:09 +05:30
prafull-opensignlabsandGitHub a07be3b5dc Merge pull request #1165 from OpenSignLabs/validation
feat: show email used count
2024-09-05 18:38:23 +05:30
prafull-opensignlabs af2666c83d feat: show email used count 2024-09-05 18:36:30 +05:30
prafull-opensignlabsandGitHub cad9929b56 Merge pull request #1164 from OpenSignLabs/raktima-patch-3
fix: display incorrect count of document on dashboard
2024-09-05 18:35:48 +05:30
RaktimaNXG 3b79da527d fix: display incorrect count of document on dashboard 2024-09-05 18:32:42 +05:30
AndrewandGitHub 3eaba55823 Merge pull request #1163 from OpenSignLabs/validation 2024-09-05 17:00:57 +05:30
prafull-opensignlabs e2eddb6362 refactor: validation 2024-09-05 16:59:47 +05:30
RaktimaNXG de5b8160a2 fix: add embedding functionality for all template & add CopyTemplateId button in template report list options 2024-09-05 16:40:15 +05:30
RaktimaNXG 83df969751 feat: introduce embedding feature after make template public 2024-09-05 12:56:38 +05:30
prafull-opensignlabsandGitHub d885570dd8 Merge pull request #1162 from OpenSignLabs/raktima-patch-2
fix: drop widgets in center of document in mobile view
2024-09-05 10:10:27 +05:30
RaktimaNXG f3de883e39 fix: increase close button size of react tour in mobile view 2024-09-05 09:59:07 +05:30
RaktimaNXG 6da22d23a8 fix: remove console 2024-09-04 19:41:39 +05:30
RaktimaNXG 49461a43bb fix: drop widgets in center of document in mobile view 2024-09-04 19:39:10 +05:30
prafull-opensignlabsandGitHub d4414f99af Merge pull request #1161 from OpenSignLabs/raktima-patch-2
fix: resolve issue to allow edits options on completed documents in the SignYourself flow
2024-09-04 18:52:06 +05:30
RaktimaNXG 52f37b0a37 fix: resolve issue to allow edits options on completed documents in the SignYourself flow 2024-09-04 18:31:19 +05:30
prafull-opensignlabsandGitHub ce949e4029 Merge pull request #1160 from OpenSignLabs/raktima-patch-2
fix: Issue with changing signers list order in report view button
2024-09-04 17:32:09 +05:30
RaktimaNXG 19d3465a13 add comment 2024-09-04 16:03:13 +05:30
RaktimaNXG a0e1425c74 fix: handle condition to send document for signing 2024-09-04 15:58:50 +05:30
prafull-opensignlabsandGitHub a5d8379b18 Merge pull request #1159 from OpenSignLabs/raktima-patch-3
fix: issue while rename document/folder in opensign-drive
2024-09-04 15:44:15 +05:30
RaktimaNXG 9ac487ea5b fix: unexpected view button of signers for signyourself document in report 2024-09-04 15:41:25 +05:30
RaktimaNXG 9cc9a93c3d fix: handle error 2024-09-04 15:13:10 +05:30
RaktimaNXG 4f2b0313de refactor code 2024-09-04 15:09:38 +05:30
RaktimaNXG 806894b24b fix : issue while rename the document/folder in opensign-drive 2024-09-04 14:48:49 +05:30
RaktimaNXG cbb737f96b Merge branch 'staging' of https://github.com/OpenSignLabs/OpenSign into raktima-patch-2 2024-09-04 11:53:22 +05:30
prafull-opensignlabsandGitHub 5407f8156a Merge pull request #1157 from OpenSignLabs/raktima-patch-3
refactor: change order in decline modal
2024-09-04 10:08:47 +05:30
RaktimaNXG a0c2fd09ae fix: resolve issue of disappear widgets when adding it on multiple pages 2024-09-03 21:05:56 +05:30
RaktimaNXG 48b744c8ba refactor code 2024-09-03 20:59:41 +05:30
prafull-opensignlabsandGitHub 812b946d85 Merge pull request #1156 from OpenSignLabs/raktima-patch-3
feat: display the email of the user who declined the document along with the decline reason in the document decline popup.
2024-09-03 20:47:59 +05:30
RaktimaNXG 27eca2b470 fix: add error iin alert 2024-09-03 20:43:45 +05:30
RaktimaNXG ab6c88bebd feat: save declined by user details in-progress report 2024-09-03 20:23:54 +05:30
RaktimaNXG d547e0552a fix: handle error 2024-09-03 20:11:14 +05:30
RaktimaNXG 03fc0b84cb fix: remove console 2024-09-03 19:53:43 +05:30
RaktimaNXG b0825634ee resolve conflict 2024-09-03 19:50:42 +05:30
RaktimaNXG 9675e051bd feat: display the email of the user who declined the document along with the decline reason in the document decline popup. 2024-09-03 19:48:21 +05:30
AndrewandGitHub 981654a2aa Merge pull request #1155 from OpenSignLabs/validation 2024-09-03 19:32:05 +05:30
prafull-opensignlabs 8c97ea0da0 fix: duplicate entry issue 2024-09-03 19:30:51 +05:30
prafull-opensignlabsandGitHub 6c80911c90 Merge pull request #1154 from OpenSignLabs/rotatepage_document
feat: introduce a guide video in profile page for setting up a public template and managing the public profile
2024-09-03 16:57:38 +05:30
RaktimaNXG 740b5ea719 fix: placeholder disappear issue in template flow 2024-09-03 15:49:37 +05:30
RaktimaNXG 76c958fb7a fix: remove unnecessary variable from locales en and fr file 2024-09-03 13:54:08 +05:30
RaktimaNXG 28c53fd115 fix: update text of demo video 2024-09-03 13:31:19 +05:30
RaktimaNXG 6d9fc8b3df fix: resolve error 2024-09-03 13:13:49 +05:30
RaktimaNXG a044f4eceb refactor code 2024-09-03 12:33:23 +05:30
RaktimaNXG 1f35efcd51 Merge branch 'staging' of https://github.com/OpenSignLabs/OpenSign into rotatepage_document 2024-09-03 12:27:37 +05:30
RaktimaNXG c587abddae fix: on edit button show upgrade now validation issue in profile page 2024-09-03 12:26:49 +05:30
prafull-opensignlabsandGitHub d7f4c9a329 Merge pull request #1153 from OpenSignLabs/validation
build(deps): update dependencies
2024-09-03 12:17:00 +05:30
prafull-opensignlabs 8a3e6f5781 build(deps): update dependencies 2024-09-03 12:15:06 +05:30
RaktimaNXG cfbebc4989 refactor code 2024-09-02 21:10:15 +05:30
RaktimaNXG 99ec772d64 feat: embed demo video to create public profile 2024-09-02 21:01:44 +05:30
RaktimaNXG 1f60b0bbcb Merge branch 'staging' of https://github.com/OpenSignLabs/OpenSign into raktima-patch-2 2024-09-02 20:03:47 +05:30
RaktimaNXG c8fb9a5b09 fix: signers list order change issue in reports 2024-09-02 20:01:18 +05:30
AndrewandGitHub d6f117c7bf Merge pull request #1152 from OpenSignLabs/validation
fix: failed to load pdf issue on self-host with docker
2024-09-02 19:34:05 +05:30
prafull-opensignlabs a765668354 fix: failed to load pdf issue on self-host with docker 2024-09-02 19:31:38 +05:30
prafull-opensignlabs da053658e8 refactor: handle uncuaght err in send mail 2024-09-02 19:29:36 +05:30
prafull-opensignlabsandGitHub cb5bcd72e4 Merge pull request #1151 from OpenSignLabs/validation
refactor: add logout btn
2024-09-02 13:07:43 +05:30
prafull-opensignlabs d4d53623ef refactor: add logout btn 2024-09-02 13:03:47 +05:30
RaktimaNXG 8a31b008d2 fix: ui design of mobile view on public script load 2024-09-02 12:55:53 +05:30
prafull-opensignlabsandGitHub fa4541b59f Merge pull request #1150 from OpenSignLabs/validation
fix: get is not function
2024-09-02 11:14:08 +05:30
prafull-opensignlabs aae6b32828 fix: get is not function 2024-09-02 11:09:23 +05:30
RaktimaNXG 7158d6735b resolve conflict 2024-09-02 09:51:26 +05:30
dependabot[bot]andGitHub f04fd16c9e build(deps-dev): bump @babel/runtime-corejs2 in /apps/OpenSign
Bumps [@babel/runtime-corejs2](https://github.com/babel/babel/tree/HEAD/packages/babel-runtime-corejs2) from 7.25.4 to 7.25.6.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.25.6/packages/babel-runtime-corejs2)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-09-02 00:32:16 +00:00
AmolandGitHub f4b896d5e6 Merge pull request #1141 from OpenSignLabs/validation 2024-09-01 18:45:59 +05:30
prafull-opensignlabs d2f814e6f8 refactor: prepare for v2.3.0 2024-09-01 18:45:07 +05:30
prafull-opensignlabs 87cec67e60 refactor: add help test, remove uncessary code 2024-09-01 17:51:56 +05:30
AmolandGitHub 041c46f38e Merge pull request #1140 from OpenSignLabs/validation 2024-08-31 23:30:23 +05:30
prafull-opensignlabs 54a7628f75 fix: quick send not working 2024-08-31 23:28:39 +05:30
AmolandGitHub 7cbbc16390 Merge pull request #1139 from OpenSignLabs/validation 2024-08-31 23:02:51 +05:30
prafull-opensignlabs 14532bf6db refactor: change help text 2024-08-31 22:59:45 +05:30
AmolandGitHub 7bfe18e718 Merge pull request #1137 from OpenSignLabs/validation 2024-08-30 20:04:58 +05:30
prafull-opensignlabs 07903a07a8 refactor: add help text for test token 2024-08-30 19:53:17 +05:30
RaktimaNXG 14fe3b2b98 fix: resolve conflict 2024-08-30 17:55:27 +05:30
AndrewandGitHub fa2756ff3f Merge pull request #1136 from OpenSignLabs/validation 2024-08-30 17:50:58 +05:30
prafull-opensignlabs 9d4841b4dc feat: add api testing token 2024-08-30 17:47:40 +05:30
RaktimaNXG 4b74b08825 fix: update tour messages of show public profile setup 2024-08-30 17:44:03 +05:30
RaktimaNXG 6457cfc958 refactor code 2024-08-30 12:02:59 +05:30
RaktimaNXG 30081c893b fix: tagline input box design 2024-08-30 11:59:34 +05:30
RaktimaNXG e69890a47e feat: add tour message in profile page 2024-08-30 11:42:11 +05:30
prafull-opensignlabsandGitHub 9d31162eec Merge pull request #1093 from OpenSignLabs/dependabot/npm_and_yarn/apps/OpenSignServer/posthog-node-4.1.1
build(deps): bump posthog-node from 4.0.1 to 4.1.1 in /apps/OpenSignServer
2024-08-29 14:18:44 +05:30
prafull-opensignlabsandGitHub 0031cc7418 Merge pull request #1094 from OpenSignLabs/dependabot/npm_and_yarn/apps/OpenSignServer/eslint-9.9.1
build(deps-dev): bump eslint from 9.9.0 to 9.9.1 in /apps/OpenSignServer
2024-08-29 10:57:32 +05:30
prafull-opensignlabsandGitHub 57132892b5 Merge pull request #1130 from OpenSignLabs/dependabot/npm_and_yarn/apps/OpenSign/npm_and_yarn-271b7fd07e
build(deps): bump the npm_and_yarn group in /apps/OpenSign with 2 updates
2024-08-29 10:56:19 +05:30
prafull-opensignlabsandGitHub be084d1570 Merge pull request #1129 from OpenSignLabs/dependabot/npm_and_yarn/apps/OpenSignServer/npm_and_yarn-07a849e1ae
build(deps): bump micromatch from 4.0.7 to 4.0.8 in /apps/OpenSignServer in the npm_and_yarn group
2024-08-29 10:55:41 +05:30
prafull-opensignlabsandGitHub 03d29a9ebd Merge pull request #1096 from OpenSignLabs/dependabot/npm_and_yarn/apps/OpenSignServer/mongoose-8.5.4
build(deps): bump mongoose from 8.5.3 to 8.5.4 in /apps/OpenSignServer
2024-08-29 10:49:14 +05:30
dependabot[bot]andGitHub e9a837b534 build(deps): bump the npm_and_yarn group
Bumps the npm_and_yarn group in /apps/OpenSign with 2 updates: [micromatch](https://github.com/micromatch/micromatch) and [webpack](https://github.com/webpack/webpack).


Updates `micromatch` from 4.0.7 to 4.0.8
- [Release notes](https://github.com/micromatch/micromatch/releases)
- [Changelog](https://github.com/micromatch/micromatch/blob/master/CHANGELOG.md)
- [Commits](https://github.com/micromatch/micromatch/compare/4.0.7...4.0.8)

Updates `webpack` from 5.93.0 to 5.94.0
- [Release notes](https://github.com/webpack/webpack/releases)
- [Commits](https://github.com/webpack/webpack/compare/v5.93.0...v5.94.0)

---
updated-dependencies:
- dependency-name: micromatch
  dependency-type: indirect
  dependency-group: npm_and_yarn
- dependency-name: webpack
  dependency-type: indirect
  dependency-group: npm_and_yarn
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-29 05:18:15 +00:00
prafull-opensignlabsandGitHub 36c601f9fa Merge pull request #1095 from OpenSignLabs/dependabot/npm_and_yarn/apps/OpenSignServer/axios-1.7.5
build(deps): bump axios from 1.7.4 to 1.7.5 in /apps/OpenSignServer
2024-08-29 10:48:06 +05:30
dependabot[bot]andGitHub af41234484 build(deps): bump micromatch
Bumps the npm_and_yarn group in /apps/OpenSignServer with 1 update: [micromatch](https://github.com/micromatch/micromatch).


Updates `micromatch` from 4.0.7 to 4.0.8
- [Release notes](https://github.com/micromatch/micromatch/releases)
- [Changelog](https://github.com/micromatch/micromatch/blob/master/CHANGELOG.md)
- [Commits](https://github.com/micromatch/micromatch/compare/4.0.7...4.0.8)

---
updated-dependencies:
- dependency-name: micromatch
  dependency-type: indirect
  dependency-group: npm_and_yarn
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-29 05:17:14 +00:00
prafull-opensignlabsandGitHub bcaf03a770 Merge pull request #1091 from OpenSignLabs/dependabot/npm_and_yarn/apps/OpenSign/axios-1.7.5
build(deps): bump axios from 1.7.4 to 1.7.5 in /apps/OpenSign
2024-08-29 10:45:59 +05:30
prafull-opensignlabsandGitHub 9429b009ce Merge pull request #1120 from OpenSignLabs/rotatepage_document
fix:  handle conditions and throw errors for public template script loading
2024-08-29 10:44:55 +05:30
RaktimaNXG 3395785cbc refactor code 2024-08-28 17:12:17 +05:30
RaktimaNXG 97c048c7af fix: remove share option from public templateId 2024-08-28 17:07:22 +05:30
RaktimaNXG 726eb2ffe6 fix: templateid share option in mobile view 2024-08-28 11:54:55 +05:30
RaktimaNXG a9f22d3a10 fix: share templatId issue 2024-08-28 11:08:15 +05:30
prafull-opensignlabsandGitHub 5a6437e371 Merge pull request #1116 from OpenSignLabs/validation
fix: all contacts are not visible in request sign form's signers inputbox
2024-08-28 10:59:29 +05:30
prafull-opensignlabs 4ffc98b371 fix: all contacts are not visible in request sign form's signers inputbox 2024-08-28 10:54:56 +05:30
RaktimaNXG 16c73d4f91 Merge branch 'staging' of https://github.com/OpenSignLabs/OpenSign into rotatepage_document 2024-08-27 17:22:53 +05:30
RaktimaNXG 96aff5230f fix: handle condition to load public-template script without templatId 2024-08-27 17:16:21 +05:30
prafull-opensignlabsandGitHub b298571be8 Merge pull request #1106 from OpenSignLabs/validation
fix: api token not visible
2024-08-27 13:26:09 +05:30
prafull-opensignlabs 7b7b10c9a5 fix: api token visible 2024-08-27 13:22:48 +05:30
dependabot[bot]andGitHub 56beed5ad5 build(deps): bump mongoose from 8.5.3 to 8.5.4 in /apps/OpenSignServer
Bumps [mongoose](https://github.com/Automattic/mongoose) from 8.5.3 to 8.5.4.
- [Release notes](https://github.com/Automattic/mongoose/releases)
- [Changelog](https://github.com/Automattic/mongoose/blob/master/CHANGELOG.md)
- [Commits](https://github.com/Automattic/mongoose/compare/8.5.3...8.5.4)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-26 00:37:01 +00:00
dependabot[bot]andGitHub 8c8ef0ea53 build(deps): bump axios from 1.7.4 to 1.7.5 in /apps/OpenSignServer
Bumps [axios](https://github.com/axios/axios) from 1.7.4 to 1.7.5.
- [Release notes](https://github.com/axios/axios/releases)
- [Changelog](https://github.com/axios/axios/blob/v1.x/CHANGELOG.md)
- [Commits](https://github.com/axios/axios/compare/v1.7.4...v1.7.5)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-26 00:36:48 +00:00
dependabot[bot]andGitHub 90377d98c0 build(deps-dev): bump eslint from 9.9.0 to 9.9.1 in /apps/OpenSignServer
Bumps [eslint](https://github.com/eslint/eslint) from 9.9.0 to 9.9.1.
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/compare/v9.9.0...v9.9.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-26 00:36:40 +00:00
dependabot[bot]andGitHub d167e474d8 build(deps): bump posthog-node in /apps/OpenSignServer
Bumps [posthog-node](https://github.com/PostHog/posthog-js-lite/tree/HEAD/posthog-node) from 4.0.1 to 4.1.1.
- [Release notes](https://github.com/PostHog/posthog-js-lite/releases)
- [Changelog](https://github.com/PostHog/posthog-js-lite/blob/main/posthog-node/CHANGELOG.md)
- [Commits](https://github.com/PostHog/posthog-js-lite/commits/posthog-node-v4.1.1/posthog-node)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-26 00:36:32 +00:00
dependabot[bot]andGitHub 0cfacfe057 build(deps): bump axios from 1.7.4 to 1.7.5 in /apps/OpenSign
Bumps [axios](https://github.com/axios/axios) from 1.7.4 to 1.7.5.
- [Release notes](https://github.com/axios/axios/releases)
- [Changelog](https://github.com/axios/axios/blob/v1.x/CHANGELOG.md)
- [Commits](https://github.com/axios/axios/compare/v1.7.4...v1.7.5)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-26 00:32:26 +00:00
RaktimaandGitHub fbda5231d0 Merge pull request #1089 from OpenSignLabs/validation
build(deps): update dependencies
2024-08-23 17:36:40 +05:30
prafull-opensignlabs bd4d333d59 build(deps): update dependencies 2024-08-23 17:32:53 +05:30
prafull-opensignlabs 07878207de fix: validation of api token 2024-08-23 17:06:53 +05:30
RaktimaandGitHub b2352877b9 Merge pull request #1088 from OpenSignLabs/validation
feat: add download btn in expired document
2024-08-23 13:08:36 +05:30
prafull-opensignlabs 669ba9e8cb feat: add download btn in expired document 2024-08-23 12:40:38 +05:30
AmolandGitHub 5fa8a76219 Merge pull request #1087 from OpenSignLabs/validation 2024-08-22 21:07:40 +05:30
prafull-opensignlabs 476dcf051c feat: implement autosave feature in signyourself 2024-08-22 20:28:49 +05:30
prafull-opensignlabsandGitHub db96dbba6a Merge pull request #1086 from OpenSignLabs/validation
feat: autosave document and template while drafting
2024-08-22 17:38:04 +05:30
prafull-opensignlabs e9c6509970 feat: autosave document and template while drafting 2024-08-22 17:23:53 +05:30
prafull-opensignlabsandGitHub b26c7dfa8f Merge pull request #1085 from OpenSignLabs/rotatepage_document
fix: resolve daisy-ui theme issue for public-sign script loading
2024-08-22 15:10:37 +05:30
RaktimaNXG 3f251761d6 fix: resolve daisy-ui theme issue for public sign script loading 2024-08-22 14:53:45 +05:30
prafull-opensignlabsandGitHub bc9d489ee8 Merge pull request #1084 from OpenSignLabs/validation
fix: wrong alert is visible after loader in quicksend popup
2024-08-22 13:03:10 +05:30
prafull-opensignlabs 271563ba9f refactor: correct variable 2024-08-22 13:01:17 +05:30
prafull-opensignlabs 82aba20e83 refactor: remove unnecessary code from add user 2024-08-22 12:56:18 +05:30
prafull-opensignlabs 12f60c9be5 fix: wrong alert is visible after loader in quicksend popup 2024-08-22 12:49:48 +05:30
AndrewandGitHub 1c98a354c7 Merge pull request #1082 from OpenSignLabs/validation 2024-08-21 18:53:30 +05:30
prafull-opensignlabs 9ca7aee859 Merge branch 'staging' of https://github.com/OpenSignLabs/OpenSign into validation 2024-08-21 18:14:05 +05:30
prafull-opensignlabs 937b306128 fix: remove unncessary query from buyaddonusers 2024-08-21 18:10:57 +05:30
prafull-opensignlabsandGitHub 69a2ab0ce2 Merge pull request #1079 from OpenSignLabs/rotatepage_document
feat: implement PDF page rotation feature
2024-08-21 17:16:58 +05:30
RaktimaNXG b720711217 refactor code 2024-08-21 16:20:25 +05:30
prafull-opensignlabs bf56348c62 fix: add users count 2024-08-21 14:39:36 +05:30
RaktimaNXG f993817cb6 fix: issue of onclick yes button rotate pdf page 2024-08-21 14:36:01 +05:30
RaktimaNXG 1c2b4794f3 fix: add copy option eside to widget for signature,stamp and text widgets 2024-08-21 13:55:54 +05:30
prafull-opensignlabs 523d210503 fix: quicksend validation 2024-08-21 12:57:08 +05:30
RaktimaNXG 39da8bd636 refactor code 2024-08-21 10:02:46 +05:30
RaktimaNXG fbea98bbe6 fix: add validation of rotation functionality, add rotation functionality for mobile view 2024-08-20 20:41:14 +05:30
prafull-opensignlabs 5d89f724f4 feat: validtion of quicksend 2024-08-20 15:56:00 +05:30
prafull-opensignlabsandGitHub 0313b6f3ab Merge pull request #1077 from OpenSignLabs/raktima-patch-1
fix: owner's subscription expired alert issue during sign document
2024-08-20 12:27:29 +05:30
RaktimaNXG fe92111dc9 fix: owner's subscription expired alert issue during sign document 2024-08-20 12:08:55 +05:30
prafull-opensignlabs 9a03bfb9e7 Merge branch 'staging' of https://github.com/OpenSignLabs/OpenSign into validation 2024-08-19 12:10:27 +05:30
prafull-opensignlabs 882db6acc9 fix: validation of generate token 2024-08-19 11:28:22 +05:30
RaktimaNXG 5596468b03 refactor code 2024-08-16 18:06:52 +05:30
RaktimaNXG eb66de1220 fix: issue in template flow using roate pdf page functionality 2024-08-16 18:02:29 +05:30
RaktimaNXG f97896f6a6 fix: translate rotate icon title 2024-08-16 17:26:14 +05:30
RaktimaNXG cfb47f880e fix: translate rotate icon title 2024-08-16 17:25:58 +05:30
RaktimaNXG eba87776a0 fix: resolve conflict 2024-08-16 17:14:30 +05:30
RaktimaNXG dda0e6d676 fix: handle pdfRequest sign flow rotate pdf page not allowed 2024-08-16 17:11:51 +05:30
prafull-opensignlabsandGitHub 8d514644c1 Merge pull request #1066 from OpenSignLabs/raktima-opensignlabs-patch-12
feat: add customizable font and color options for Date, Dropdown, Checkbox, and Radio Button widgets.
2024-08-16 15:07:14 +05:30
prafull-opensignlabsandGitHub 0870a34391 Merge pull request #1065 from OpenSignLabs/header_strip
feat: add a header strip to display an announcement about the public profile feature launch
2024-08-16 15:00:21 +05:30
RaktimaNXG 38118986a3 feat: add a header strip to display an announcement about the public profile feature launch 2024-08-16 14:13:51 +05:30
RaktimaNXG 1b4e5247ad feat: implement PDF page rotation feature 2024-08-16 14:10:29 +05:30
AmolandGitHub 3ef2eeef93 Merge pull request #1063 from OpenSignLabs/validation 2024-08-14 20:24:25 +05:30
prafull-opensignlabs 4d5682e79b fix: add user is not working 2024-08-14 20:09:19 +05:30
RaktimaNXG 24100d203f fix: setting icon space issue on widgets 2024-08-14 20:07:14 +05:30
RaktimaNXG 86946a2c21 fix: date setting modal design in mobile view 2024-08-14 20:01:11 +05:30
RaktimaNXG 54f3e4cc6f fix: remove comment from signPdf function 2024-08-14 19:34:55 +05:30
RaktimaNXG d9360b2d8c add comment 2024-08-14 19:29:19 +05:30
RaktimaNXG abb47118c0 fix: dropdown font size issue using pdf-lib 2024-08-14 19:24:23 +05:30
RaktimaNXG 9e4e55bb8d Merge branch 'staging' of https://github.com/OpenSignLabs/OpenSign into raktima-opensignlabs-patch-12 2024-08-14 16:41:30 +05:30
AmolandGitHub 498f720507 Merge pull request #1058 from OpenSignLabs/validation 2024-08-14 16:36:05 +05:30
RaktimaNXG b9bc9cb75e Merge branch 'staging' of https://github.com/OpenSignLabs/OpenSign into raktima-opensignlabs-patch-12 2024-08-14 14:34:40 +05:30
RaktimaNXG 3b65917422 fix: checkbox options position 2024-08-14 14:18:32 +05:30
prafull-opensignlabs 862dd78cd5 Merge branch 'staging' of https://github.com/OpenSignLabs/OpenSign into validation 2024-08-14 12:21:35 +05:30
prafull-opensignlabsandGitHub d0bc48d119 Merge pull request #1054 from OpenSignLabs/deps
build(deps): update dependencies
2024-08-14 11:49:27 +05:30
prafull-opensignlabs 37462ba282 build(deps): update dependencies 2024-08-14 11:46:22 +05:30
prafull-opensignlabs 99e7f5862a build(deps): update dependencies 2024-08-14 11:46:14 +05:30
RaktimaNXG 048e529bb5 fix: checkbox & radio button labels font color issue 2024-08-14 11:41:18 +05:30
AmolandGitHub 5b8b06f3a1 Merge pull request #1051 from OpenSignLabs/prafull-opensignlabs-patch-28 2024-08-13 19:27:42 +05:30
prafull-opensignlabsandGitHub 3c7d025802 refactor: Update env 2024-08-13 19:26:00 +05:30
prafull-opensignlabsandGitHub 4f8b46da14 Merge pull request #1049 from OpenSignLabs/prafull-opensignlabs-patch-27
refactor: Update env
2024-08-13 19:20:25 +05:30
prafull-opensignlabsandGitHub 0b386a882e refactor: Update env 2024-08-13 19:17:28 +05:30
RaktimaNXG 6329d58a67 Merge branch 'staging' of https://github.com/OpenSignLabs/OpenSign into raktima-opensignlabs-patch-12 2024-08-13 17:00:15 +05:30
prafull-opensignlabsandGitHub 0444e17848 Merge pull request #1047 from OpenSignLabs/raktima-opensignlabs-patch-11
fix: something went wrong issue while signing document in public profile
2024-08-13 16:36:01 +05:30
RaktimaNXG c3d039fe45 fix: style of copy alert 2024-08-13 16:24:20 +05:30
RaktimaNXG 1d5d713854 refactor code 2024-08-13 16:07:37 +05:30
RaktimaNXG 4336c15ca4 resolve conflict 2024-08-13 15:58:17 +05:30
RaktimaNXG aac644d15c Merge branch 'staging' of https://github.com/OpenSignLabs/OpenSign into raktima-opensignlabs-patch-11 2024-08-13 15:55:52 +05:30
RaktimaNXG ab3dde17c7 remove times.ttf file to cdn file 2024-08-13 15:48:54 +05:30
AmolandGitHub 924ec33d73 docs: Update README.md with docker installation instructions 2024-08-13 15:37:31 +05:30
RaktimaNXG d798e02126 Merge branch 'staging' of https://github.com/OpenSignLabs/OpenSign into raktima-opensignlabs-patch-11 2024-08-13 15:27:34 +05:30
RaktimaNXG af0d780ac0 fix: add customiize font size and color in checkbox, radio button,dropdown widgets 2024-08-13 15:25:06 +05:30
prafull-opensignlabs 45c2c863ef Merge branch 'staging' of https://github.com/OpenSignLabs/OpenSign into validation 2024-08-13 15:13:43 +05:30
prafull-opensignlabsandGitHub bc08aeb5b7 Merge pull request #1046 from OpenSignLabs/fix_widgets
Fix: issue of unnecessary alert is occurred in request sign flow
2024-08-13 15:05:36 +05:30
AmolandGitHub c32067890c Merge pull request #1043 from OpenSignLabs/docker_beta
Feat: official docker images
2024-08-13 15:03:45 +05:30
prafull-opensignlabs 83a180e3b8 Fix: issue of unccesary alert is occured in request sign flow 2024-08-13 15:03:04 +05:30
prafull-opensignlabs 3372e16409 Fix: issue of unccesary alert is occured in request sign flow 2024-08-13 15:02:26 +05:30
prafull-opensignlabs a04fad9c1f Merge branch 'staging' of https://github.com/OpenSignLabs/OpenSign into validation 2024-08-13 13:32:42 +05:30
prafull-opensignlabsandGitHub 7500797dd0 Merge pull request #1045 from OpenSignLabs/fix_widgets
Fix: special characters are not allowed in dropdown widget
2024-08-13 13:09:44 +05:30
prafull-opensignlabs 9427f4141f Fix: special characters are not allowed in dropdown 2024-08-13 13:07:33 +05:30
prafull-opensignlabsandGitHub 1440244c4d Merge pull request #1044 from OpenSignLabs/fix_reactquill
Fix: security issue of react-quill dependencies
2024-08-13 12:07:47 +05:30
prafull-opensignlabs 47c8b82cfa fix: remove warning of react-quill 2024-08-13 11:56:02 +05:30
prafull-opensignlabs 540f23fb41 fix: security issue of react-quill dependencies 2024-08-13 11:40:54 +05:30
RaktimaNXG 323c9f2d4f fix: add copy & share button for user's public profile url in profile page 2024-08-13 11:00:55 +05:30
prafull-opensignlabsandGitHub 1d648b525f Merge pull request #1035 from OpenSignLabs/dependabot/npm_and_yarn/apps/OpenSign/react-i18next-15.0.1
build(deps): bump react-i18next from 15.0.0 to 15.0.1 in /apps/OpenSign
2024-08-13 10:16:11 +05:30
prafull-opensignlabsandGitHub 11c2771451 Merge pull request #1036 from OpenSignLabs/dependabot/npm_and_yarn/apps/OpenSign/lottiefiles/dotlottie-react-0.8.7
build(deps): bump @lottiefiles/dotlottie-react from 0.8.6 to 0.8.7 in /apps/OpenSign
2024-08-13 10:15:22 +05:30
prafull-opensignlabsandGitHub 1733756b4a Merge pull request #1037 from OpenSignLabs/dependabot/npm_and_yarn/apps/OpenSign/axios-1.7.3
build(deps): bump axios from 1.7.2 to 1.7.3 in /apps/OpenSign
2024-08-13 10:14:51 +05:30
prafull-opensignlabsandGitHub edf1933800 Merge pull request #1038 from OpenSignLabs/dependabot/npm_and_yarn/apps/OpenSign/tailwindcss-3.4.9
build(deps-dev): bump tailwindcss from 3.4.7 to 3.4.9 in /apps/OpenSign
2024-08-13 10:14:28 +05:30
prafull-opensignlabs 38d3165d14 refactor: update branch name 2024-08-12 19:35:12 +05:30
AmolandGitHub 5766b307c1 Merge pull request #1042 from OpenSignLabs/fix_widgets 2024-08-12 19:12:23 +05:30
prafull-opensignlabs 6497703d3b fix: signature is blurly in certificate 2024-08-12 19:10:17 +05:30
AmolandGitHub 60e48580ae Merge pull request #1041 from OpenSignLabs/raktima-opensignlabs-patch-11 2024-08-12 18:05:37 +05:30
RaktimaNXG 08b52f3618 fix: multi-language support issue in public profile 2024-08-12 18:02:32 +05:30
dependabot[bot]andGitHub 55001cc434 build(deps): bump @lottiefiles/dotlottie-react in /apps/OpenSign
Bumps [@lottiefiles/dotlottie-react](https://github.com/LottieFiles/dotlottie-web/tree/HEAD/packages/react) from 0.8.6 to 0.8.7.
- [Release notes](https://github.com/LottieFiles/dotlottie-web/releases)
- [Changelog](https://github.com/LottieFiles/dotlottie-web/blob/main/packages/react/CHANGELOG.md)
- [Commits](https://github.com/LottieFiles/dotlottie-web/commits/@lottiefiles/dotlottie-react@0.8.7/packages/react)

---
updated-dependencies:
- dependency-name: "@lottiefiles/dotlottie-react"
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-12 12:30:33 +00:00
RaktimaandGitHub b84b864396 Merge pull request #1040 from OpenSignLabs/fix_widgets
fix: Hiding the text fields widget if entering the Special Characters
2024-08-12 17:59:09 +05:30
prafull-opensignlabsandGitHub 34835b8cdf Merge pull request #1039 from OpenSignLabs/file_upload
Fix: file upload is not working
2024-08-12 14:14:24 +05:30
prafull-opensignlabs df8bdbf5b3 fix: Hiding the text fields widget if entering the Special Characters 2024-08-12 14:10:41 +05:30
prafull-opensignlabs e775a832cb fix: file upload is not working 2024-08-12 13:08:41 +05:30
dependabot[bot]andGitHub b9c4bada23 build(deps-dev): bump tailwindcss from 3.4.7 to 3.4.9 in /apps/OpenSign
Bumps [tailwindcss](https://github.com/tailwindlabs/tailwindcss) from 3.4.7 to 3.4.9.
- [Release notes](https://github.com/tailwindlabs/tailwindcss/releases)
- [Changelog](https://github.com/tailwindlabs/tailwindcss/blob/v3.4.9/CHANGELOG.md)
- [Commits](https://github.com/tailwindlabs/tailwindcss/compare/v3.4.7...v3.4.9)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-12 00:32:13 +00:00
dependabot[bot]andGitHub 97f35f7ee6 build(deps): bump axios from 1.7.2 to 1.7.3 in /apps/OpenSign
Bumps [axios](https://github.com/axios/axios) from 1.7.2 to 1.7.3.
- [Release notes](https://github.com/axios/axios/releases)
- [Changelog](https://github.com/axios/axios/blob/v1.x/CHANGELOG.md)
- [Commits](https://github.com/axios/axios/compare/v1.7.2...v1.7.3)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-12 00:31:59 +00:00
dependabot[bot]andGitHub 0f90a06028 build(deps): bump react-i18next from 15.0.0 to 15.0.1 in /apps/OpenSign
Bumps [react-i18next](https://github.com/i18next/react-i18next) from 15.0.0 to 15.0.1.
- [Changelog](https://github.com/i18next/react-i18next/blob/master/CHANGELOG.md)
- [Commits](https://github.com/i18next/react-i18next/compare/v15.0.0...v15.0.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-12 00:31:28 +00:00
AndrewandGitHub db4f2e7696 Merge pull request #1032 from OpenSignLabs/raktima-opensignlabs-patch-11 2024-08-10 16:45:50 +05:30
RaktimaNXG 69837b0515 fix: language support issue in public-profile 2024-08-10 16:23:10 +05:30
AndrewandGitHub 9811c49288 Merge pull request #1031 from OpenSignLabs/gmail_login 2024-08-09 20:25:35 +05:30
prafull-opensignlabs d709c99641 Fix: update translation message 2024-08-09 20:16:51 +05:30
prafull-opensignlabs a92666082f Fix: showing the wrong alert when updating the team. 2024-08-09 20:14:11 +05:30
AndrewandGitHub cc05b28a42 Merge pull request #1029 from OpenSignLabs/gmail_login 2024-08-09 20:00:59 +05:30
prafull-opensignlabsandGitHub a2c9953096 Merge pull request #1028 from OpenSignLabs/raktima-opensignlabs-patch-11
fix: issue with empty emails when using customized mail in send-request flow
2024-08-09 19:59:49 +05:30
prafull-opensignlabs 75ef6934b4 fix: gmail login not working 2024-08-09 19:58:29 +05:30
RaktimaNXG aa4d3c039b fix: issue with empty emails when using customized mail in send-request flow 2024-08-09 18:41:28 +05:30
prafull-opensignlabs a8a89dc9bd Merge branch 'staging' of https://github.com/OpenSignLabs/OpenSign into validation 2024-08-09 18:03:34 +05:30
prafull-opensignlabs a0305a745a fix: addon not updated correctly 2024-08-09 18:03:14 +05:30
prafull-opensignlabsandGitHub 290ff54638 Merge pull request #1027 from OpenSignLabs/raktima-opensignlabs-patch-11
fix: unable to enter email issue in add signers form
2024-08-09 18:01:19 +05:30
RaktimaNXG dc4decffe4 fix: unable to enter email issue in add signer form 2024-08-09 17:57:53 +05:30
prafull-opensignlabs f06b702360 Merge branch 'staging' of https://github.com/OpenSignLabs/OpenSign into validation 2024-08-09 16:38:29 +05:30
prafull-opensignlabsandGitHub e2eca66db0 Merge pull request #1024 from OpenSignLabs/raktima-opensignlabs-patch-11
fix: error in auto-sign feature unexpected issue encountered - something went wrong
2024-08-09 16:29:24 +05:30
RaktimaNXG d20913023e fix: email condition issue in adduser file 2024-08-09 16:25:22 +05:30
RaktimaNXG f4466dc325 fix: resolve public url 2024-08-09 15:41:35 +05:30
RaktimaNXG 00e6ea5b3b fix: resolve warning 2024-08-09 15:31:57 +05:30
RaktimaNXG 50b0a3ea17 fix: resolve issue of support multi-language in public script file 2024-08-09 15:03:56 +05:30
RaktimaNXG 0072e3e5ba refactor code 2024-08-09 13:43:39 +05:30
prafull-opensignlabs 6f104c4ee6 fix: langauage support in add user 2024-08-09 13:05:16 +05:30
prafull-opensignlabs c721580516 Merge branch 'staging' of https://github.com/OpenSignLabs/OpenSign into validation 2024-08-09 11:23:10 +05:30
RaktimaNXG 2238f1fafc Merge branch 'staging' of https://github.com/OpenSignLabs/OpenSign into raktima-opensignlabs-patch-11 2024-08-09 10:30:41 +05:30
prafull-opensignlabs 00bc5a00c1 Merge branch 'staging' of https://github.com/OpenSignLabs/OpenSign into docker_beta 2024-08-09 10:17:56 +05:30
prafull-opensignlabs 1fe1381fe2 refactor: user valdation 2024-08-08 20:40:13 +05:30
prafull-opensignlabsandGitHub 6bc0470c69 Merge pull request #1026 from OpenSignLabs/prafull-opensignlabs-patch-26
fix: not able to update company
2024-08-08 20:01:06 +05:30
prafull-opensignlabsandGitHub a9ab25e9c2 fix: not able to update company 2024-08-08 19:57:01 +05:30
prafull-opensignlabsandGitHub fd5bc22a70 Merge pull request #1025 from OpenSignLabs/prafull-opensignlabs-patch-26
fix: not able update user profile
2024-08-08 19:29:36 +05:30
prafull-opensignlabsandGitHub 28fe1fafd6 fix: not able update user profile 2024-08-08 19:14:56 +05:30
RaktimaNXG 6695138244 fix: tour message translation issue of templates report 2024-08-08 17:58:20 +05:30
RaktimaNXG 3fb19cbe96 fix: failed to load message issue while sign document in signyour-self flow 2024-08-08 17:36:08 +05:30
RaktimaNXG 3f8a17c3ea fix: contactbook report title to name in heading 2024-08-08 16:31:26 +05:30
RaktimaNXG 9fa97f27f0 fix: error in auto-sign feature unexpected issue encountered - something went wrong 2024-08-08 15:55:11 +05:30
RaktimaNXG 0e98312d55 Merge branch 'staging' of https://github.com/OpenSignLabs/OpenSign into raktima-opensignlabs-patch-11 2024-08-08 15:25:56 +05:30
AmolandGitHub 06057a1d35 Merge pull request #1023 from OpenSignLabs/prafull-opensignlabs-patch-25
fix: error while calling webhook
2024-08-08 15:01:04 +05:30
prafull-opensignlabsandGitHub 4373fddaa8 fix: Error while calling webhook 2024-08-08 14:58:38 +05:30
AmolandGitHub c45511d9a5 Merge pull request #1019 from OpenSignLabs/raktima-opensignlabs-patch-11
feat: Integrate language support for multiple languages in the application
2024-08-08 14:36:20 +05:30
RaktimaNXG 7d2b2494e5 Merge branch 'staging' of https://github.com/OpenSignLabs/OpenSign into raktima-opensignlabs-patch-11 2024-08-08 13:23:18 +05:30
prafull-opensignlabs 870a25dad1 Merge branch 'staging' of https://github.com/OpenSignLabs/OpenSign into validation 2024-08-08 13:02:39 +05:30
RaktimaNXG d74dc2f4ca fix:improve readability by updating some French words 2024-08-08 12:54:05 +05:30
prafull-opensignlabsandGitHub f8c9c535a0 Merge pull request #1021 from OpenSignLabs/prafull-opensignlabs-patch-23
fix: not able to create user using add user form
2024-08-08 12:30:18 +05:30
prafull-opensignlabsandGitHub d22322be86 fix: not able to create user using add user form 2024-08-08 12:28:31 +05:30
prafull-opensignlabs e4e5d5c6d7 Revert "refactor: change url"
This reverts commit 7e45f23b6c.
2024-08-08 12:11:18 +05:30
prafull-opensignlabs 7e45f23b6c refactor: change url 2024-08-08 12:03:46 +05:30
prafull-opensignlabs 719f61f612 refactor: change url 2024-08-08 12:00:07 +05:30
prafull-opensignlabs 908edda14b feat: validation to add user 2024-08-07 20:02:41 +05:30
RaktimaNXG 74792a9c21 refactor code 2024-08-07 16:08:02 +05:30
RaktimaNXG eb345b5ca2 fix: after filled any input value still show warning of empty field 2024-08-07 15:50:54 +05:30
RaktimaNXG 23c2b4b204 fix: remove console 2024-08-07 14:51:43 +05:30
RaktimaNXG 095e616e4c fix: refactor code 2024-08-07 14:47:37 +05:30
RaktimaNXG 89f4626fce checking error 2024-08-07 14:43:15 +05:30
RaktimaNXG c759d673f0 refactor code 2024-08-07 14:03:45 +05:30
RaktimaNXG 8d1be554d4 fix: input validation warning translation issue 2024-08-07 14:00:52 +05:30
prafull-opensignlabsandGitHub e931d06ed4 Merge pull request #1018 from OpenSignLabs/validation
fix: something went wrong error in signpdf
2024-08-07 13:56:40 +05:30
prafull-opensignlabs 76b90f9bc0 fix: something went wrong error in signpdf 2024-08-07 13:45:49 +05:30
prafull-opensignlabsandGitHub b4e5fedb51 Merge pull request #1016 from OpenSignLabs/dependabot/npm_and_yarn/apps/OpenSign/npm_and_yarn-5105dbd604
build(deps-dev): bump postcss from 8.4.40 to 8.4.41 in /apps/OpenSign in the npm_and_yarn group
2024-08-07 10:09:41 +05:30
dependabot[bot]andGitHub 6a229aabaf build(deps-dev): bump postcss
Bumps the npm_and_yarn group in /apps/OpenSign with 1 update: [postcss](https://github.com/postcss/postcss).


Updates `postcss` from 8.4.40 to 8.4.41
- [Release notes](https://github.com/postcss/postcss/releases)
- [Changelog](https://github.com/postcss/postcss/blob/main/CHANGELOG.md)
- [Commits](https://github.com/postcss/postcss/compare/8.4.40...8.4.41)

---
updated-dependencies:
- dependency-name: postcss
  dependency-type: direct:development
  dependency-group: npm_and_yarn
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-06 16:32:51 +00:00
RaktimaNXG 841c7df2f3 Merge branch 'staging' of https://github.com/OpenSignLabs/OpenSign into raktima-opensignlabs-patch-11 2024-08-06 20:25:56 +05:30
RaktimaNXG dd85ce7cfe fix: after create new user selected language change in en-USA 2024-08-06 20:25:26 +05:30
RaktimaNXG 4c7d771bb3 fix: apply language support in profile also and save in database, issue of text translate in guest login flow and other place 2024-08-06 17:02:16 +05:30
ZathielandGitHub c55bdba948 Merge pull request #1010 from OpenSignLabs/dependabot/npm_and_yarn/apps/OpenSign/lottiefiles/dotlottie-react-0.8.6 2024-08-06 11:10:15 +02:00
ZathielandGitHub 4f2dce0a03 Merge pull request #1014 from OpenSignLabs/dependabot/npm_and_yarn/apps/OpenSignServer/axios-1.7.3 2024-08-06 11:09:51 +02:00
ZathielandGitHub 450a992b26 Merge pull request #1011 from OpenSignLabs/dependabot/npm_and_yarn/apps/OpenSign/lint-staged-15.2.8 2024-08-06 11:07:53 +02:00
dependabot[bot]andGitHub 4284b2402b build(deps): bump axios from 1.7.2 to 1.7.3 in /apps/OpenSignServer
Bumps [axios](https://github.com/axios/axios) from 1.7.2 to 1.7.3.
- [Release notes](https://github.com/axios/axios/releases)
- [Changelog](https://github.com/axios/axios/blob/v1.x/CHANGELOG.md)
- [Commits](https://github.com/axios/axios/compare/v1.7.2...v1.7.3)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-06 09:06:27 +00:00
ZathielandGitHub 50c88f82f4 Merge pull request #1012 from OpenSignLabs/dependabot/npm_and_yarn/apps/OpenSign/react-tooltip-5.28.0 2024-08-06 11:06:04 +02:00
ZathielandGitHub 7dff3dc658 Merge pull request #1013 from OpenSignLabs/dependabot/npm_and_yarn/apps/OpenSign/react-router-dom-6.26.0 2024-08-06 11:04:59 +02:00
ZathielandGitHub adb3864ea9 Merge pull request #1015 from OpenSignLabs/dependabot/npm_and_yarn/apps/OpenSignServer/aws-sdk-2.1667.0 2024-08-06 11:04:20 +02:00
prafull-opensignlabs d6330060dc refactor: moved from yml to env 2024-08-05 21:16:13 +05:30
prafull-opensignlabs 2dcb35a34c fix: docker compose file depends on env file 2024-08-05 17:09:44 +05:30
prafull-opensignlabs 624ba95792 fix: connection refused while sending mail 2024-08-05 14:31:55 +05:30
prafull-opensignlabs ae24a80b95 fix: url variable in sendmail gmail 2024-08-05 13:12:52 +05:30
prafull-opensignlabs e7f1b1cc32 fix: vairable intiailzation error 2024-08-05 12:55:33 +05:30
prafull-opensignlabs e71940ecdc fix:add env in docker compose, save tenantcredit and datafiles is not working 2024-08-05 12:43:44 +05:30
dependabot[bot]andGitHub 65a800701c build(deps): bump aws-sdk in /apps/OpenSignServer
Bumps [aws-sdk](https://github.com/aws/aws-sdk-js) from 2.1665.0 to 2.1667.0.
- [Release notes](https://github.com/aws/aws-sdk-js/releases)
- [Commits](https://github.com/aws/aws-sdk-js/compare/v2.1665.0...v2.1667.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-05 00:57:47 +00:00
dependabot[bot]andGitHub 36dc1fb3e9 build(deps): bump react-router-dom in /apps/OpenSign
Bumps [react-router-dom](https://github.com/remix-run/react-router/tree/HEAD/packages/react-router-dom) from 6.25.1 to 6.26.0.
- [Release notes](https://github.com/remix-run/react-router/releases)
- [Changelog](https://github.com/remix-run/react-router/blob/main/packages/react-router-dom/CHANGELOG.md)
- [Commits](https://github.com/remix-run/react-router/commits/react-router-dom@6.26.0/packages/react-router-dom)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-05 00:28:51 +00:00
dependabot[bot]andGitHub 99305b4185 build(deps): bump react-tooltip from 5.27.1 to 5.28.0 in /apps/OpenSign
Bumps [react-tooltip](https://github.com/ReactTooltip/react-tooltip) from 5.27.1 to 5.28.0.
- [Release notes](https://github.com/ReactTooltip/react-tooltip/releases)
- [Changelog](https://github.com/ReactTooltip/react-tooltip/blob/master/CHANGELOG.md)
- [Commits](https://github.com/ReactTooltip/react-tooltip/compare/v5.27.1...v5.28.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-05 00:28:35 +00:00
dependabot[bot]andGitHub bd2e8be186 build(deps-dev): bump lint-staged in /apps/OpenSign
Bumps [lint-staged](https://github.com/lint-staged/lint-staged) from 15.2.7 to 15.2.8.
- [Release notes](https://github.com/lint-staged/lint-staged/releases)
- [Changelog](https://github.com/lint-staged/lint-staged/blob/master/CHANGELOG.md)
- [Commits](https://github.com/lint-staged/lint-staged/compare/v15.2.7...v15.2.8)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-05 00:28:23 +00:00
dependabot[bot]andGitHub dc4c6ceff5 build(deps): bump @lottiefiles/dotlottie-react in /apps/OpenSign
Bumps [@lottiefiles/dotlottie-react](https://github.com/LottieFiles/dotlottie-web/tree/HEAD/packages/react) from 0.8.5 to 0.8.6.
- [Release notes](https://github.com/LottieFiles/dotlottie-web/releases)
- [Changelog](https://github.com/LottieFiles/dotlottie-web/blob/main/packages/react/CHANGELOG.md)
- [Commits](https://github.com/LottieFiles/dotlottie-web/commits/@lottiefiles/dotlottie-react@0.8.6/packages/react)

---
updated-dependencies:
- dependency-name: "@lottiefiles/dotlottie-react"
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-05 00:28:12 +00:00
RaktimaNXG 10083ac807 fix: detect from browser's language and set it in dropdown by default 2024-08-02 17:50:06 +05:30
prafull-opensignlabs 11023c6400 Merge branch 'staging' of https://github.com/OpenSignLabs/OpenSign into docker_beta 2024-08-02 17:24:00 +05:30
RaktimaNXG 6d31314df6 fix: implement feature to detect lagunage from browser, resolve conflict 2024-08-02 17:22:25 +05:30
prafull-opensignlabs d5367194ab Merge branch 'docker_beta' of https://github.com/OpenSignLabs/OpenSign into docker_beta 2024-08-02 17:21:09 +05:30
prafull-opensignlabs cf179b2f9c fix: change docker images in docker compose file 2024-08-02 17:20:46 +05:30
AndrewandGitHub de82188663 Merge pull request #1007 from OpenSignLabs/fix_self_host 2024-08-02 17:19:58 +05:30
prafull-opensignlabs 4aefe775f9 fix: initial routing error in self-hosting 2024-08-02 17:11:02 +05:30
AmolandGitHub 8c06c98917 build: Update Makefile 2024-08-02 17:00:52 +05:30
prafull-opensignlabsandGitHub ee9f778725 Merge pull request #1003 from OpenSignLabs/fix_err_signpdf
fix: error handling of signing pdf digitally
2024-08-02 16:39:11 +05:30
prafull-opensignlabs ff0883c8e6 fix: error handling of signpdf function 2024-08-02 16:22:44 +05:30
prafull-opensignlabs d4e0f05cef feat: update official docker images 2024-08-02 12:46:01 +05:30
RaktimaNXG dfcb4fe286 refactor-code 2024-08-01 21:05:00 +05:30
RaktimaNXG d546d5d0a7 feat: apply multisupport language for all type alert, buttons and tour-messages 2024-08-01 20:57:22 +05:30
RaktimaNXG c6e93cd3c8 feat: apply multisupport language for signing flow in signyour-self, template , placeholder 2024-07-31 21:26:08 +05:30
RaktimaNXG 779d5df264 feat: appply multi-support language functionality on report, managesign, webhook,api token 2024-07-30 20:02:32 +05:30
RaktimaNXG 77cd52ca04 feat: appply multi-support language functionality on login,signup-page,sidebar menu 2024-07-30 14:09:10 +05:30
RaktimaNXG bed2a77232 feat: implement feature of multisupport language 2024-07-29 20:32:59 +05:30
231 changed files with 27809 additions and 229517 deletions
+9
View File
@@ -232,6 +232,15 @@
"contributions": [
"code"
]
},
{
"login": "1024mb",
"name": "1024mb",
"avatar_url": "https://avatars.githubusercontent.com/u/9301204?v=4",
"profile": "https://github.com/1024mb",
"contributions": [
"translation"
]
}
]
}
+3 -3
View File
@@ -3,11 +3,11 @@
# Note that any data in staging will get cleared from time to time and you may have to sign up again and again
# Set it to the URL form where the app home page will be accessed
PUBLIC_URL=http://localhost:3000
PUBLIC_URL=https://localhost:3001
# Set it to true if you want to generate the Sourcemap for debugging
GENERATE_SOURCEMAP=false
# Set it to the URL from where APIs will be accessible, for local development it should be localhost:3000/api/app (use your local port number instead)
REACT_APP_SERVERURL=http://localhost:8080/app
# REACT_APP_SERVERURL=http://localhost:8080/app
# A 12 character long random app identifier. The value of this should be same as APP_ID which is a variable used by backend API.
REACT_APP_APPID=opensign
@@ -46,7 +46,7 @@ USE_LOCAL=true
MAILGUN_API_KEY=
MAILGUN_DOMAIN=mail.yourdomain.com
MAILGUN_SENDER=postmaster@mail.yourdomain.com
SMTP_ENABLE=
SMTP_ENABLE=true
SMTP_HOST=smtp.yourhost.com
SMTP_PORT=443
SMTP_USER_EMAIL=mailer@yourdomain.com
+1 -1
View File
@@ -2,7 +2,7 @@ name: ci
on:
push:
branches:
- 'staging'
- 'main'
jobs:
docker:
+2 -2
View File
@@ -77,6 +77,6 @@ Engage with the community on our [Gitter Channel](https://gitter.im/OpenSignLabs
## License
By contributing, you agree that your contributions will be licensed under its [MIT License](LICENSE).
By contributing, you agree that your contributions will be licensed under its [AGPL-V3 License](LICENSE).
---
---
+7
View File
@@ -0,0 +1,7 @@
{$HOST_URL} {
reverse_proxy client:3000
handle_path /app/* {
reverse_proxy server:8080
rewrite * /app{uri}
}
}
+6 -1
View File
@@ -1,4 +1,9 @@
GNU AFFERO GENERAL PUBLIC LICENSE
* All content that resides under the "apps/OpenSignServer/cloud/customRoute" directory of this repository, if that directory exists, is licensed under the license defined in "apps/OpenSignServer/cloud/customRoute".
* All third party components incorporated into the OpenSign Software are licensed under the original license provided by the owner of the applicable component.
* Content outside of the above mentioned directories or restrictions above is available under the "GNU AFFERO GENERAL PUBLIC LICENSE" as defined below -
GNU AFFERO GENERAL PUBLIC LICENSE
Version 3, 19 November 2007
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
+4 -2
View File
@@ -1,8 +1,10 @@
build:
@echo "Building with HOST_URL=${HOST_URL}"
cp .env.local_dev .env
cd apps/OpenSign && cp ../../.env.local_dev .env && npm install && npm run build
docker compose up --build --force-recreate
HOST_URL=${HOST_URL} docker compose up --build --force-recreate
run:
@echo "Building with HOST_URL=${HOST_URL}"
cp .env.local_dev .env
docker compose up -d
docker compose up -d
+9 -2
View File
@@ -75,7 +75,13 @@ Welcome to OpenSign, the premier open source docusign alternative - document e-s
### Installation
Please refer to the [Installation Guide](INSTALLATION.md) for detailed instructions on how to install OpenSign on your system.
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/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 -
Please refer to the [Installation Guide](https://docs.opensignlabs.com/docs/self-host/docker/run-locally/) for detailed instructions on how to install OpenSign on your system.
---
@@ -141,7 +147,8 @@ We would like to thank all our contributors and users for their support and feed
<td align="center" valign="top" width="14.28%"><a href="https://github.com/VikramNagwal"><img src="https://avatars.githubusercontent.com/u/123088024?v=4?s=100" width="100px;" alt="Vikram"/><br /><sub><b>Vikram</b></sub></a><br /><a href="#code-VikramNagwal" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/ugoconsonni"><img src="https://avatars.githubusercontent.com/u/13661702?v=4?s=100" width="100px;" alt="ugoconsonni"/><br /><sub><b>ugoconsonni</b></sub></a><br /><a href="#code-ugoconsonni" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/daniel-mutwiri"><img src="https://avatars.githubusercontent.com/u/8936960?v=4?s=100" width="100px;" alt="Daniel Mutwiri"/><br /><sub><b>Daniel Mutwiri</b></sub></a><br /><a href="#code-daniel-mutwiri" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Zathiel"><img src="https://avatars.githubusercontent.com/u/26553418?v=4?s=100" width="100px;" alt="Zathiel"/><br /><sub><b>Zathiel</b></sub></a><br /><a href="#code-Zathiel" title="Code">💻</a><a href="#security-Zathiel" title="Security">🛡️</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Zathiel"><img src="https://avatars.githubusercontent.com/u/26553418?v=4?s=100" width="100px;" alt="Zathiel"/><br /><sub><b>Zathiel</b></sub></a><br /><a href="#code-Zathiel" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/1024mb"><img src="https://avatars.githubusercontent.com/u/9301204?v=4?s=100" width="100px;" alt="1024mb"/><br /><sub><b>1024mb</b></sub></a><br /><a href="#translation-1024mb" title="Translation">🌍</a></td>
</tr>
</tbody>
</table>
+2242 -1891
View File
File diff suppressed because it is too large Load Diff
+42 -32
View File
@@ -4,12 +4,17 @@
"private": true,
"dependencies": {
"@formkit/auto-animate": "^0.8.2",
"@lottiefiles/dotlottie-react": "^0.8.5",
"@radix-ui/themes": "^3.1.1",
"@react-pdf/renderer": "^3.4.4",
"@reduxjs/toolkit": "^2.2.7",
"axios": "^1.7.2",
"@lottiefiles/dotlottie-react": "^0.9.3",
"@pdf-lib/fontkit": "^1.1.1",
"@radix-ui/themes": "^3.1.4",
"@react-pdf/renderer": "^4.0.0",
"@reduxjs/toolkit": "^2.3.0",
"axios": "^1.7.7",
"file-saver": "^2.0.5",
"i18next": "^23.16.5",
"i18next-browser-languagedetector": "^8.0.0",
"i18next-http-backend": "^2.6.2",
"jszip": "^3.10.1",
"jwt-decode": "^4.0.0",
"moment": "^2.30.1",
"nth-check": "^2.1.1",
@@ -18,10 +23,10 @@
"print-js": "^1.6.0",
"radix-ui": "^1.0.1",
"react": "^18.2.0",
"react-bootstrap": "^2.10.4",
"react-bootstrap": "^2.10.5",
"react-confetti": "^6.1.0",
"react-cookie": "^7.2.0",
"react-datepicker": "^7.3.0",
"react-cookie": "^7.2.2",
"react-datepicker": "^7.5.0",
"react-dnd": "^16.0.1",
"react-dnd-html5-backend": "^16.0.1",
"react-dnd-multi-backend": "^8.0.3",
@@ -29,32 +34,34 @@
"react-dom": "^18.2.0",
"react-gtm-module": "^2.0.11",
"react-helmet": "^6.1.0",
"react-i18next": "^15.0.3",
"react-konva": "^18.2.10",
"react-pdf": "^9.1.0",
"react-quill": "^2.0.0",
"react-pdf": "^9.1.1",
"react-quill-new": "^3.3.3",
"react-redux": "^9.1.2",
"react-rnd": "^10.4.11",
"react-router-dom": "^6.25.1",
"react-rnd": "^10.4.13",
"react-router-dom": "^6.27.0",
"react-scripts": "5.0.1",
"react-scrollbars-custom": "^4.1.1",
"react-select": "^5.8.0",
"react-select": "^5.8.3",
"react-signature-canvas": "^1.0.6",
"react-tooltip": "^5.27.1",
"react-syntax-highlighter": "^15.6.1",
"react-tooltip": "^5.28.0",
"react-web-share": "^2.0.2",
"reactour": "^1.19.4",
"redux": "^5.0.1",
"redux-thunk": "^3.1.0",
"regex-parser": "^2.3.0",
"serve": "^14.2.3",
"serve": "^14.2.4",
"styled-components": "^5.3.0",
"web-vitals": "^4.2.2",
"web-vitals": "^4.2.3",
"ws": "^8.18.0"
},
"scripts": {
"build-webpack": "webpack --config webpack.config.js",
"build": "npm run version && npm run build-webpack && react-scripts build",
"build-watch": "webpack --config webpack.config.js --watch",
"start-dev": "concurrently \"npm run build-watch\" \"react-scripts start\"",
"start-dev": "react-scripts start",
"start": "serve -s build",
"version": "curl -s https://api.github.com/repos/opensignlabs/opensign/releases/latest | grep '\"tag_name\":' | awk -F '\"' '{print $4}' > ./public/version.txt",
"version-win": "powershell -Command \"Invoke-RestMethod -Uri 'https://api.github.com/repos/opensignlabs/opensign/releases/latest' | Select-Object -ExpandProperty tag_name | Out-File -FilePath ./public/version.txt\"",
@@ -88,33 +95,36 @@
}
},
"devDependencies": {
"@babel/core": "^7.25.2",
"@babel/preset-env": "^7.25.3",
"@babel/preset-react": "^7.24.7",
"@babel/runtime-corejs2": "^7.25.0",
"autoprefixer": "^10.4.19",
"babel-loader": "^9.1.3",
"@babel/core": "^7.26.0",
"@babel/preset-env": "^7.26.0",
"@babel/preset-react": "^7.25.9",
"@babel/runtime-corejs2": "^7.26.0",
"autoprefixer": "^10.4.20",
"babel-loader": "^9.2.1",
"clean-webpack-plugin": "^4.0.0",
"commitizen": "^4.3.0",
"concurrently": "^8.2.2",
"commitizen": "^4.3.1",
"concurrently": "^9.0.1",
"css-loader": "^7.1.2",
"daisyui": "^4.12.10",
"daisyui": "^4.12.14",
"dotenv": "^16.4.5",
"dotenv-webpack": "^8.1.0",
"eslint": "^8.57.0",
"eslint": "^9.13.0",
"eslint-plugin-prettier": "^5.2.1",
"eslint-plugin-react": "^7.34.3",
"lint-staged": "^15.2.7",
"mini-css-extract-plugin": "^2.9.0",
"postcss": "^8.4.40",
"eslint-plugin-react": "^7.37.1",
"lint-staged": "^15.2.10",
"mini-css-extract-plugin": "^2.9.1",
"postcss": "^8.4.48",
"prettier": "^3.3.3",
"pretty-quick": "^4.0.0",
"tailwindcss": "^3.4.7",
"tailwindcss": "^3.4.14",
"terser-webpack-plugin": "^5.3.10",
"webpack-cli": "^5.1.4"
},
"overrides": {
"nth-check": "$nth-check",
"ws": "$ws"
},
"engines": {
"node": "18 || 20 || 22"
}
}
@@ -0,0 +1,701 @@
{
"header-news": "New feature: Teams plan users can now integrate their own AWS S3 buckets for file storage",
"header-news-btn": "Setup Now",
"create-account": "Create Account",
"login": "Login",
"language": "Language",
"name": "Name",
"phone": "Phone",
"phone-optional": "optional",
"email": "Email",
"company": "Company",
"job-title": "Job title",
"profile": "Profile",
"log-out": "Log Out",
"is-email-verified": "Is Email verified",
"public-profile": "Public profile",
"tagline": "Tagline ",
"has-requested-you-to-sign": "has requested you to sign",
"has-requested-you-to-review-and-sign": " has requested you to review and sign",
"input-required": "Please fill out this field.",
"sort-order": {
"Ascending": "Ascending",
"Descending": "Descending",
"Name": "Name",
"Date": "Date"
},
"context-menu": {
"Download": "Download",
"Rename": "Rename",
"Move": "Move",
"Delete": "Delete"
},
"action": "Action",
"add": "Add",
"add-new-folder": "Add a new folder",
"disable-documentId": "Disable DocumentId",
"edit": "Edit",
"change-password": "Change Password",
"save": "Save",
"cancel": "Cancel",
"upgrade-now": "Upgrade now",
"upgrade-to": "Upgrade to",
"plan": "Plan",
"subscribe-card-teamplan":"Unlock the full power of collaboration! Create unlimited organizations, teams, and hierarchies. Share templates seamlessly across teams and assign custom user roles. Elevate your workflow today!",
"subscribe-card-plan": "Unlock premium features starting at just {{premiumPrice}}/month. Enjoy enhanced performance and only {{addonPrice}} per additional credit after your included premium credits.",
"user-name-limit-char": "To have a username less than 8 character please subscribe",
"tour-content": "Don't show this again",
"pro": "PRO",
"team": "TEAM",
"user": "User",
"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",
"forgot-password": "Forgot Password?",
"loading": "Loading...",
"of": "of",
"sign-SSO": "Sign in with SSO",
"login-page": "Login Page",
"or": "OR",
"signup-page": "Signup page",
"password-length": "Password should be 8 characters long",
"password-case": "Password should contain uppercase letter, lowercase letter, digit",
"password-special-char": " Password should contain special character",
"agreee": "I agree to the",
"term": "Terms of Service",
"subscribe-to-opensign": "Subscribe to OpenSign newsletter",
"register": "Register",
"sidebar": {
"Dashboard": "Dashboard",
"Sign yourself": "Sign yourself",
"Request signatures": "Request signatures",
"Templates": "Templates",
"Templates-Children": {
"Create template": "Create template",
"Manage templates": "Manage templates"
},
"OpenSign™ Drive": "OpenSign™ Drive",
"Reports": "Reports",
"Reports-Children": {
"Need your sign": "Need your sign",
"In Progress": "In Progress",
"Completed": "Completed",
"Drafts": "Drafts",
"Declined": "Declined",
"Expired": "Expired",
"Contactbook": "Contactbook"
},
"Settings": "Settings",
"Settings-Children": {
"My Signature": "My Signature",
"API Token": "API Token",
"Webhook": "Webhook",
"Preferences": "Preferences",
"Teams": "Teams",
"Team-update-successfully": "Team Updated successfully.",
"Users": "Users"
}
},
"dashboard-card": {
"Need your Signature": "Need your Signature",
"Out for signatures": "Out for Signatures"
},
"report-name": {
"Draft Documents": "Draft Documents",
"Need your sign": "Need your sign",
"In-progress documents": "In-progress documents",
"Completed Documents": "Completed Documents",
"Declined Documents": "Declined Documents",
"Expired Documents": "Expired Documents",
"Recently sent for signatures": "Recently sent for signatures",
"Recent signature requests": "Recent signature requests",
"Drafts": "Drafts",
"Contactbook": "Contactbook",
"Templates": "Templates",
"Teams": "Teams",
"Users": "Users"
},
"btnLabel": {
"sign": "sign",
"Sign": "SIGN",
"Resend": "Resend",
"Revoke": "Revoke",
"Delete": "Delete",
"Use": "Use",
"Quick send": "Quick send",
"Edit": "Edit",
"Share with team": "Share with team",
"Share": "Share",
"View": "View",
"option": "Option",
"Embed": "Embed",
"Copy TemplateId":"Copy TemplateId",
"Copy Public URL":"Copy Public URL"
},
"report-heading": {
"Sr.No": "Sr.No",
"Title": "Title",
"Email": "Email",
"Phone": "Phone",
"File": "File",
"Owner": "Owner",
"Signers": "Signers",
"Note": "Note",
"Folder": "Folder",
"Reason": "Reason",
"Parent Team": "Parent Team",
"Active": "Active",
"Role": "Role",
"Team": "Team",
"Name": "Name",
"Status": "Status",
"created-date": "Created Date",
"Type": "Type",
"Logs": "Logs"
},
"report-help": {
"Draft Documents": "These are documents you have started but have not finalized for sending.",
"Need your sign": "This is a list of documents that are waiting for your signature",
"In-progress documents": "This is a list of documents you've sent to other parties for signature.",
"Completed Documents": "This is a list of documents that have been signed by all parties.",
"Declined Documents": "This is a list of documents that have been declined by one of the signers.",
"Expired Documents": "This is a list of documents that have reached their expiration date.",
"Contactbook": "This is a list of contacts/signers added by you. These will appear as suggestions when you try to add signers to a new document.",
"Templates": "This is a list of templates that are available to you for creating documents. You can click the 'use' button to create a new document using a template, modify the document & add signers in the next step."
},
"form-name": {
"Sign Yourself": "Sign Yourself",
"Request Signatures": "Request Signatures",
"New Template": "New Template"
},
"file-type": "pdf, png, jpg, jpeg",
"docx": "docx",
"file-selected": "file selected",
"template-title": "Template Title",
"document-title": "Document Title",
"description": "Description",
"time-to-complete": "Time To Complete (Days)",
"send-in-order": "Send In Order",
"send-in-order-help": {
"p1": "Choose how you want the signing requests to be sent to the document signers:",
"p2": "Selecting this option will send the signing request to the first signer initially. Once the first signer completes their part, the next signer in the sequence will receive the request. This process continues until all signers have signed the document. This method ensures that the document is signed in a specific order.",
"p3": "Selecting this option will send the signing links to all signers simultaneously. Every signer can sign the document at their convenience, regardless of whether other signers have completed their signatures. This method is faster but does not enforce any signing order among the participants.",
"p4": "Select the option that best suits the needs of your document processing."
},
"no": "No",
"auto-reminder": "Auto reminder",
"remind-once": " Remind once in every (Days)",
"next": "Next",
"select-folder": "Select Folder",
"OpenSign-drive": "OpenSign™ Drive",
"drive-document-status": {
"Completed": "Completed",
"Declined": "Declined",
"Draft": "Draft",
"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 OpenSign drive folder.",
"no-data": "No data found",
"save-here": "Save Here",
"back": "Back",
"add-folder": "Add folder",
"create-folder": "Create Folder",
"parent-folder": "Parent Folder",
"create": "Create",
"signers": "Signers",
"signers-help": "Begin typing a contact's name to see suggested signers from your saved contacts or add new ones. Arrange the signing order by adding signers in the desired sequence. Use the '+' button to include signers and the 'x' to remove them. Each signer will receive an email prompt to sign the document in the order listed.",
"add-signer": "Add Signer",
"contact-not-found": "Contact not found",
"add-yourself": "Add Yourself",
"submit": "Submit",
"reset": "Reset",
"my-signature": "My Signature",
"signature": "Signature",
"upload-image": " Upload image",
"clear": "Clear",
"upload-signature/Image": "Please upload signature/Image",
"initials": "Initials",
"API": "API",
"api-token": "API Token",
"regenerate-token": "Regenerate Live Token",
"generate-token": "Generate Live Token",
"view-docs": "View Docs",
"generate-token-alert": "Are you sure you want to regenerate token it will expire old token?",
"yes": "Yes",
"copied": "Copied",
"something-went-wrong-mssg": "Something went wrong, please try again later.",
"token-generated": "Token generated successfully.",
"webhook": "Webhook",
"update-webhook": "Update Webhook",
"add-webhook": "Add Webhook",
"webhook-added": "Webhook added successfully.",
"team-disabled": "Team disabled",
"Team enabled": "Team enabled",
"are-you-sure": "Are you sure you want to",
"disable": "disable",
"enable": "enable",
"this-team": " this team?",
"edit-team": "Edit Team",
"name-of-team": "Name of Team",
"prev": "Prev",
"no-data-avaliable": "No Data Available",
"add-team": "Add Team",
"page-not-found": "Page Not Found",
"users-from-teams": "users from Teams",
"user-status": "User status",
"activate": "activate",
"deactivate": "deactivate",
"this-user": " this user",
"delete-user": "Delete User",
"delete": "delete",
"add-user": "Add User",
"password-generateed": "Password will only be generated once; make sure to copy it.",
"Team status": "Team status",
"user-deactivated": "User deactivated.",
"user-activated": "User activated.",
"public": "Public",
"download": "Download",
"view": "View",
"make-template-public": "Make template public",
"make-template-private": "Make template private",
"make-template-public-alert": "Are you sure you want to make this template public?",
"make-template-private-alert": "Are you sure you want to make this template private? This will remove it from your public profile.",
"public-role": "Public role",
"public-url": "Public profile needed",
"public-url-copy": "Heres your public URL: ",
"public-url-copy-mssg":"Copy it or share it with the signer, and you will be able to see all your publicly set templates.",
"add-public-url-alert": "Please complete your OpenSign public profile setup. Once done, youll be able to make templates public. This process only needs to be completed once.",
"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",
"roles": "Roles",
"delete-document": "Delete Document",
"delete-document-alert": "Are you sure you want to delete this document?",
"quick-send": "Quick send",
"add-new": "Add new",
"send": "Send",
"quick-send-alert-1": "All roles in this document are currently linked to contacts. To quick send copies of this template to multiple signers, please ensure that at least one role is not linked to any contact.",
"quick-send-alert-2": "Please ensure there's at least one signature widget added for all recipients.",
"quick-send-alert-3": "Please add at least one role to this template in order to 'quick send' copies of it to multiple signers.",
"quick-send-alert-4": "Quick send reached limit.",
"copy-link": "Copy link",
"copy": "Copy",
"revoke-document": "Revoke document",
"revoke-document-alert": "Are you sure you want to revoke this document?",
"resend-mail": "Resend Mail",
"resend-mail-help": "You can use following variables which will get replaced with their actual values:- {{document_title}}, {{sender_name}}, {{sender_mail}}, {{sender_phone}}, {{receiver_name}}, {{receiver_email}}, {{receiver_phone}}, {{expiry_date}}, {{company_name}}, {{signing_url}}.",
"subject": "Subject",
"body": "Body",
"add-contact": "Add Contact",
"add-signer-alert": "Contact already exist! Please select it from Signers dropdown",
"record-delete-alert": "Record deleted successfully!",
"record-revoke-alert": "Record revoked successfully!",
"mail-sent-alert": "Mail sent successfully.",
"document-sent-alert": "Document sent successfully!",
"template-share-alert": "Template Shared successfully.",
"template-public-alert-1": "You have successfully made the template public.",
"template-public-alert-2": "You have successfully made the template private.",
"template-public-alert-3": "You need to select a role for the public signers.",
"template-public-alert-4": "Please ensure there's at least one signature widget added for all signers.",
"template-public-alert-5": "Since this template has send-in-order enabled, the public role must be positioned at the top.",
"template-public-alert-6": "Please attach signers to all roles except for the public role user.",
"template-public-alert-7": "Please assign at least one public role to make this template public.",
"loader": " This might take some time",
"pages": "Pages",
"document-signed": "Document signed",
"close": "Close",
"validation-alert": "Validation alert",
"validate-alert-mssg": " The input does not meet the criteria set by the regular expression.",
"otp-verification": "OTP verification",
"enter-otp": "Enter OTP",
"verify": "Verify",
"verify-email-1": "Verify email",
"resend": "Resend",
"contact-details": "Contact Details",
"verify-email": "Please verify your email !",
"send-otp": " Send OTP",
"otp-placeholder": "Enter verification code received over email",
"loading-doc": "Loading Document..",
"widgets-name": {
"signature": "signature",
"stamp": "stamp",
"initials": "initials",
"name": "name",
"job title": "job title",
"company": "company",
"date": "date",
"text": "text",
"text input": "text input",
"checkbox": "checkbox",
"dropdown": "dropdown",
"radio button": "radio button",
"image": "image",
"email": "email"
},
"fields": "Fields",
"recipients": "Recipients",
"please-add": "Please add a",
"signed-by": "Signed By",
"more": "more",
"sent": "sent",
"print": "Print",
"certificate": "Certificate",
"decline": "Decline",
"finish": "Finish",
"mail": "Mail",
"sign-now": "Sign Now",
"successfully-signed": "Successfully signed!",
"email-mssg": " Recipients added here will get a copy of the signed document.",
"email-error-1": " please provide correct email address",
"email-error-2": "You can only send to ten recipients at a time.",
"Email-verified-alert-1": "Email is verified.",
"Email-verified-alert-2": "Email is already verified.",
"upload-stamp-image": "Upload stamp image",
"draw": "Draw",
"type": "Type",
"color-type": {
"red": "red",
"blue": "blue",
"black": "black",
"yellow": "yellow"
},
"my-initials": "My Initials",
"upload": "Upload",
"initial-teb": "Initials",
"signature-tab": "Signature",
"your-signature": "Your signature",
"copy-title": "Copy widget to",
"contact-delete-alert": "Are you sure you want to delete this contact?",
"reset-password-alert-1": "Reset password link has been sent to your email id",
"reset-password-alert-2": "Please setup email adapter ",
"reset-password-alert-3": "Reset Your Password",
"faild-animation": "Failed to load animation",
"apply": "Apply",
"copy-type": {
"All pages": "All pages",
"All pages but last": "All pages but last",
"All pages but first": "All pages but first",
"Next to current widget": "Next to current widget"
},
"options": "Options",
"minimun-check": "Minimun check",
"maximum-check": "Maximum check",
"default-value": "Default value",
"select": "Select",
"read-only": "Is read only",
"hide-labels": "Hide labels",
"checkbox": "Checkbox",
"alert": "Alert",
"zoom-in": "Zoom in",
"zoom-out": "Zoom out",
"document-signed-alert": "Congratulations! 🎉 This document has been successfully signed by you!",
"otp-sent-alert": "OTP sent on your email",
"fields-required": "Fields required",
"signature-widget-alert-1": "Please ensure there's at least one signature widget added",
"signature-widget-alert-2": "Please ensure all field is accurately filled and meets all requirements.",
"encrypted-pdf-alert": "Currently encrypted pdf files are not supported.",
"encrypted-pdf-alert-1": "PFX file password is invalid.",
"user-not-exist": "User does not exist",
"template-signature-field": "Please add at least one signature field for all roles.",
"template-role-alert": "Please add roles first",
"create-document": "Create Document",
"template-created-alert": "Do you want to create a document using the template you just created ?",
"signers-alert": "signers alert",
"template-creation-alert-1": "Please select signer for add placeholder!",
"ok": "Ok",
"radio-group": "Radio group",
"dropdown-options": "Dropdown options",
"add-role": "Add Role",
"role-ex": " e.g: Customer, Hr, Director, Manager, Student, etc",
"add/choose-signer": "Add/Choose Signer",
"choose-from-contacts": "Choose from contacts",
"select-signer": " Please select signer",
"edit-template": "Edit Template",
"widget-info": "Widget info",
"validation": "Validation",
"invalid-default-value": "invalid default value",
"hint": "Hint",
"color": "color",
"role-help": {
"p1": "What are template roles?",
"p2": "Begin by specifying each role needed for the completion of the document. Think about the parties involved in the signing process and what their responsibilities are. Common roles include HR for internal documents, Customer for agreements or Vendor for business agreements.",
"p3": "Why pre-attach users to some roles?",
"p4": "For roles that consistently involve the same individual (e.g., the CEO's signature on employee offer letters), you can pre-attach a user to a role within the template. This step is optional but recommended for efficiency and consistency across documents.",
"p5": "When do i specify the user attached to each role?",
"p6": "When you create a document from your template, you'll be prompted to attach users to each defined role. If a role already has a user attached, this will be pre-filled, but you can modify it as needed before sending out the document."
},
"add-recipients": "Add recipients",
"loading-mssg": "This might take some time",
"send-mail": "Send Mail",
"placeholder-alert-1": "Please ensure there's at least one signature widget added for all recipients.",
"placeholder-alert-2": "Please confirm that you have filled the text field.",
"placeholder-alert-3": " Are you sure you want to send out this document for signatures?",
"placeholder-alert-4": "You have successfully sent mails to all recipients!",
"placeholder-alert-5": "Do you want to sign documents right now ?",
"placeholder-alert-6": "Please setup mail adapter to send mail!",
"placeholder-alert-7": "Please select signer for add placeholder!",
"email-subject": "email subject",
"email-body": "email body",
"email-placeholder": "add body of email",
"reset-to-default": "Reset to default",
"cutomize-email": "Cutomize Email",
"upgrade-to-customize-email": "Upgrade to customize Email",
"sign-url": "Sign url",
"mails-sent": "Mails sent",
"mail-not-delivered": "Mail not delivered",
"document-alert": "Document Alert",
"owner-subscription-expired": "Owner's subscription has expired.",
"subscription-expired": "Subscription Expired",
"alert-message": "Alert message",
"document-decline": "Document decline",
"decline-alert-1": "Are you sure want to decline this document ?",
"decline-alert-2": "You have declined this document!",
"decline-alert-3": "You can not sign this document as it has been declined/revoked.",
"sign here": "Sign here",
"guest-email-alert": "verification code is sent to your email",
"get-otp-alert": "you will get a verification code via Email",
"user-already-exist": "User already exist.",
"server-error": "Internal server error !",
"fill-required-details!": "Please fill required details!",
"sign-up-form": "Sign up form",
"sign-up": "Sign up",
"folder-already-exist!": "folder already exist!",
"please-select-position!": "please select position!",
"default-sign-alert": "Are you sure you want to auto sign at requested all locations?",
"Your-Signature": "Your Signature",
"auto-sign-all": "Auto Sign All",
"generating-certificate": "Generating certificate",
"pdf-download": "PDF Download",
"generate-certificate-alert": " Your completion certificate is being generated. Please wait momentarily. If the download doesn't start shortly, click the button again.",
"folder-already-exist": "Folder already exist!",
"folder-created-successfully": "Folder created successfully!",
"fill-folder-name": "Please fill folder name",
"already-exists-this-username": "User already exists with this username!",
"verification-code-sent": "Verification mail has been sent to your E-mail!",
"registered-user-successfully": "Registered user successfully.",
"role-not-found": "Role not found.",
"do-not-access": "You don't have access, please contact the admin.",
"add-admin": "Add admin",
"opensign-setup": "OpenSign Setup",
"join-discord": "Join our discord server",
"admin-already-exist": "Admin already exist.",
"password-update-alert-1": "Password updated successfully.",
"password-update-alert-2": "Your current password is missing or incorrect.",
"password-update-alert-3": "Your current password is missing or incorrect.",
"password-update-alert-4": "Your password and confirmation password do not match.",
"current-password": "Current Password",
"new-password": "New Password",
"confirm-password": "Confirm Password",
"file-alert-1": "The selected file size is too large. Please select a file less than",
"file-alert-2": "Please select file.",
"file-alert-3": "Please wait while the document is being uploaded.",
"enter-pdf-password": "Enter Pdf Password",
"correct-password": "Please provide correct password",
"decrypting-pdf": " Decrypting pdf please wait...",
"invalid-otp": "Invalid Otp",
"user-not-found": "User not found!",
"enter-otp-alert": "Please Enter OTP!",
"get-verification-code": "Get verification code",
"get-verification-code-2": "You will get a verification code via Email",
"enter-verification-code": "Enter Verification Code",
"provide-your-details": "Provide your details",
"provide-email": "Please provide email.",
"additional-info": "Additional Info",
"signature-saved-alert": "Signature saved successfully.",
"fill-field": "Please fill out this field",
"error-template": "Error: Template not found!",
"error": "Error",
"invalid-document": "Error: invalid document!",
"document-not-found": "Document not Found!",
"document-signed-alert-1": "You have successfully signed the document. You can download or print a copy of the partially signed document. A copy of the digitally signed document will be sent to the owner over email once it is signed by all signers.",
"encrypted-pdf-not-support": "Currently encrypted pdf files are not supported.",
"document-signed-alert-4": " Congratulations! 🎉 This document has been successfully signed by all participants!",
"document-signed-alert-5": "This document has been signed by all Signers.",
"document-signed-alert-6": "This document has been declined by one or more recipient(s).",
"document-signed-alert-7": "This Document is no longer available.",
"document-signed-alert-8": "The document has already been dispatched for signing.",
"yet-to-sign": "Yet to sign",
"validation-alert-1": "The input does not meet the criteria set by the regular expression.",
"account-already-exists": "Account already exists!",
"choose-password": "Choose Password",
"enter-password": "Enter Password",
"sure": "sure",
"subscribed-alert": "You have already subscribed to plan!",
"monthly": "Monthly",
"yearly-upto": "Yearly (upto 66% off)",
"billed-yearly": "Billed Yearly",
"billed-monthly": "Billed Monthly",
"plansubscription-1": "Host it yourself for free",
"visit-github": "Visit Github",
"user-already-exist-name": "User already exists with this username!",
"do-not-access-contact-admin": "You don't have access, please contact the admin.",
"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",
"report-not-found": "Report Not Found",
"please-wait": "please wait",
"select-foler": "Select Folder",
"generated-on": "Generated On",
"text-field": "Text field",
"font-size": "Font size",
"widget-status": {
"Required": "Required",
"Optional": "Optional"
},
"all-right": "All Rights Reserved",
"version": "version",
"social-media": {
"github": "Github",
"linked-in": "LinkedIn",
"twitter": "Twitter",
"discord": "Discord"
},
"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 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.",
"opensign-drive-3": "Sort your documents by Date or Name using this menu.",
"opensign-drive-4": "Click on this menu to display the documents in list view.",
"opensign-drive-5": "The document list is displayed according to the selected sorting option. Icons next to each document indicate its current status.",
"opensign-drive-6": "Right-click on a document to see options such as Download, Rename, Move, and Delete. Click on the document to open it.",
"opensign-drive-7": "Right-click on any folder to see options. Choose Rename to change the folders name or click on the folder to navigate through its contents.",
"pdf-request-file-1": "List of signers who still need to sign the document .",
"pdf-request-file-2": "Click any of the placeholders appearing on the document to sign. You will then see options to draw your signature, type it, or upload an image .",
"pdf-request-file-3": "Click the Back, Decline, or Finish buttons to navigate your document. Use the ellipsis menu for additional options, including the Download button .",
"pdf-request-file-4": "List of signers who have already signed the document .",
"pdf-request-file-5": "You can click 'Auto Sign All' to automatically sign at all the locations meant to be signed by you. Make sure that you review the document properly before you click this button .",
"placeholder-sign-1": "Select a recipient from this list to add a place-holder where he is supposed to sign.The placeholder will appear in the same colour as the recipient name once you drop it on the document.",
"placeholder-sign-2": "Clicking 'Add recipients' button will allow you to add more signers.",
"placeholder-sign-3": "Click this button to add more recipients/signers to the document.",
"placeholder-sign-4": "Drag or click on a field to add it to the document.",
"placeholder-sign-5": "The PDF content area already displays the template's existing placeholders. For your convenience, these placeholders will match the color of the recipient's name, making them easily identifiable.",
"placeholder-sign-6": "Clicking 'Send' will save the document. In the next step you can customize the emails to be sent out to the recipients or copy the signing links and share those with the recipients yourself.",
"report-1": "Click the 'Add' button to create a new template. Templates are reusable documents designed to quickly generate new documents with the same structure and varying signers. For example, an HR template for onboarding could have predefined roles like HR Manager and New Employee. Each time you use the template, you can assign the New Employee role to different incoming staff members, while the HR Manager role remains constant, facilitating a seamless onboarding process for each recruit. ",
"redirect": "Click the 'Use' button to create a new document from an existing template.",
"bulksend": "To quickly create and send multiple documents using an existing template, click the 'Quick Send' button.",
"option": "This menu reveals more options such as Edit & Delete. Use the 'Edit' button to add signer roles, modify fields, and update your template. Changes will apply to all future documents created from this template but wont affect existing documents.Use the Delete button you can delete template. ",
"signyour-self-1": "Select and drag your preferred widgets onto the PDF to customize your document before signing. Choose the perfect spots for each modification to tailor the document to your needs.",
"signyour-self-2": "Drag and drop anywhere in this area. You can resize and move it later.",
"template-placeholder-1": "Clicking 'Add role' button will allow you to add various signer roles. You can attach users to each role in subsequent steps.",
"template-placeholder-2": "Once roles are added, select a role from list to add a place-holder where he is supposed to sign. The placeholder will appear in the same colour as the role name once you drop it on the document.",
"template-placeholder-3": "Drag or click on a field to add it to the document.",
"template-placeholder-4": "Drag the placeholder for a role anywhere on the document.Remember, it will appear in the same colour as the name of the recipient for easy reference.",
"template-placeholder-5": "Clicking 'Next' will store the current template. After saving, youll be prompted to create a new document from this template if you wish.",
"webhook-1": "Upgrade now to set webhook",
"Need your Signature": "Clicking on this card will take you to the list of documents awaiting your review.",
"Out for signatures": "Clicking on this card will take you to a list of documents awaiting signature.",
"Recent signature requests": "This is a list of documents that are waiting for your signature.",
"Recently sent for signatures": "This is a list of documents you've sent to other parties for signature.",
"Drafts": "This are documents you have started but have not finalized for sending.",
"public-template": "This video demonstrates how to set up your personalized public profile, such as https://opensign.me/your-username. Youll also learn how to customize your tagline and make your templates available for public signing."
},
"enter-email-plaholder": "Add an email address and hit enter",
"success-email-alert": "Email sent successfully!",
"expired-doc-title": "Expired Document",
"expired-on-mssg": "This document expired on {{expiredDate}} and is no longer available to sign.",
"signature-validate-alert": "Please confirm that you have selected at least {{minRequiredCount}} checkboxes.",
"signature-validate-alert-2": "Ensure this field is accurately filled and meets all requirements.",
"remaing-users": "Remaining users",
"Role": "Role",
"additional-users": "Please purchase add-on users.",
"Quantity-of-users": "Quantity of users",
"Price": "Price",
"Total-price-for-next-time": "Total price for next time",
"Proceed": "Proceed",
"Select": "Select",
"Add-seats": "Add Seats",
"user-name-exist": "user name already exist",
"format": "format",
"select-date-format": "Select a date format",
"quantity-of-credits": "Quantity of premium credits",
"remaining-credits": "Premium credits available:",
"remaining-credits-help":"Use premium credits for API document signing, bulk sending, or embedding OpenSign integration on your website. You have {{allowedcredits}} included credits and {{addoncredits}} additional purchased credits remaining.",
"additional-credits": "Please purchase premium credits",
"quota-err-quicksend": "Quota Reached, You don't have enough credits.",
"buy-credits": "Buy Premium Credits",
"rotate-right":"Rotate right",
"rotate-left":"Rotate left",
"rotate-alert-mssg":"All widgets on this page will be lost. Are you sure you want to proceed?",
"templateid":"Template-Id",
"bulk-send-subcription-alert":"Please upgrade to Professional or Team plan to use bulk send.",
"generate-test-token":"Generate Test Token",
"regenerate-test-token":"Regenerate Test Token",
"help-test-token":"This token can be used to test the APIs at the https://sandbox.opensignlabs.com/api/v1 endpoint, allowing you to conduct unlimited document signatures. Please note that the sandbox API will sign your documents with self-signed certificates, which may not be recognized as valid by Adobe. Once youve completed your testing, you can upgrade to one of our paid plans to generate a production token.",
"help-api-token":"This token can be used to access the production APIs at the {{origin}}/api/v1 endpoint. It can only be generated on one of our paid plans.",
"reason":"Reason",
"decline-by":"Declined/revoked by",
"document-declined": "Document declined",
"public-template-mssg-1":"To integrate OpenSign into your React or Next.js project, simply run the following command:",
"public-template-mssg-2" :"Ensure you have npm or yarn set up in your project. If youre using Yarn, you can replace npm install with yarn add @opensign/react.",
"public-template-mssg-3" :"Need more details or examples?",
"public-template-mssg-4": "Visit the",
"public-template-mssg-5": " npm for the latest updates, detailed documentation, and version history.",
"public-template-mssg-6" :"Before you can use this code snippet, you must make this template public.",
"copy-code":"COPY",
"copied-code":"COPIED",
"Installation":"Installation",
"Usage" :"Usage",
"insufficient-credits":"Insufficient Signing Credits",
"insufficient-credits-mssg":"The owner of this document currently lacks the necessary OpenSign credits for you to sign. Please reach out to the owner if you require further details.",
"angular-npm-mssg-1": "To integrate OpenSign into your Angular project, simply run the following command:",
"quota-mail-info-head":"Monthly request signatures email limit",
"quota-mail-info": "You can send upto 15 signature request emails every month. Upgrade now to send unlimited signing requests directly.",
"quota-mail": "You've reached your limit of 15 signature request emails for this month. Upgrade now to continue sending emails directly.",
"quota-mail-tip":"Tip: You can still sign <1>unlimited documents</1> by manually sharing the signing request links.",
"quota-mail-head":"Quota Reached",
"unauthorized-modal":"You don't have permission to perform this action, please contact {{adminEmail}}.",
"sent-this-month":"Sent this month",
"available-seats":"Available seats",
"buy-users":"Buy more users",
"isenable-otp": "Enable OTP verification",
"isenable-otp-help": {
"p1": "Would you like to enable the verification process using a one-time password (OTP)?",
"p2": "Selecting this option will enable OTP verification. Users will receive a verification code via email, which they must enter to sign the document.",
"p3": "Selecting this option will disable OTP verification, allowing users to sign the document directly without additional steps.",
"p4": "Please choose the option that best suits your document signing requirements."
},
"advanced-options":"Advanced options",
"hide-advanced-options":"Hide Advanced options",
"download-files":"Download files",
"download-pdf":"Download Pdf",
"pdf-certificate":"Download Pdf + Certificate",
"document-logs":"Document logs",
"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 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 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",
"at-least-one-signature-type": "At least one signature type should be enabled.",
"expect-default-one-more-signature-type": "Please enable one additional signature type apart from the default.",
"add-signer-note": "Note - This contact will be added to your contact list",
"allowed-signature-types-help": {
"p1": "This signature preference controls which signing options are available to your signers. Only the signature types you select will appear in the signature widget when a document is signed. For example, if you choose only the 'Draw' option in preferences, your signer will see only the 'Draw' option in the signature widget, while the other three options will not be available.",
"l1": "Create a handwritten signature directly on the screen using your finger or a stylus.",
"l2": "Enter your name and choose from various font styles to create a signature.",
"l3": "Upload an existing digital version of your signature.",
"l4": "Use a pre-set signature style saved under 'My Signature' in your settings."
}
}
@@ -0,0 +1,701 @@
{
"header-news": "Nueva característica: los usuarios del plan Teams ahora pueden integrar sus propios depósitos de AWS S3 para el almacenamiento de archivos",
"header-news-btn": "Configurar ahora",
"create-account": "Crear cuenta",
"login": "Iniciar sesión",
"language": "Idioma",
"name": "Nombre",
"phone": "Teléfono",
"phone-optional": "opcional",
"email": "Correo",
"company": "Compañía",
"job-title": "Título del puesto",
"profile": "Perfil",
"log-out": "Cerrar sesión",
"is-email-verified": "El correo está verificado",
"public-profile": "Perfil público",
"tagline": "Eslogan ",
"has-requested-you-to-sign": "ha solicitado que firmes",
"has-requested-you-to-review-and-sign": " ha solicitado que revises y firmes",
"input-required": "Por favor, rellena este campo.",
"sort-order": {
"Ascending": "Ascendente",
"Descending": "Descendente",
"Name": "Nombre",
"Date": "Fecha"
},
"context-menu": {
"Download": "Descargar",
"Rename": "Renombrar",
"Move": "Mover",
"Delete": "Eliminar"
},
"action": "Acción",
"add": "Agregar",
"add-new-folder": "Agregar nueva carpeta",
"disable-documentId": "Desactivar ID de documento",
"edit": "Editar",
"change-password": "Cambiar contraseña",
"save": "Guardar",
"cancel": "Cancelar",
"upgrade-now": "Mejorar ahora",
"upgrade-to": "Mejorar a",
"plan": "Plan",
"subscribe-card-teamplan": "¡Libera todo el poder de la colaboración! Crea organizaciones, equipos y jerarquías ilimitadas. Comparte plantillas sin problemas entre equipos y asigna funciones de usuario personalizadas. ¡Mejora tu flujo de trabajo hoy mismo!",
"subscribe-card-plan": "Desbloquea funciones premium desde solo {{premiumPrice}}/mes. Disfruta de un rendimiento mejorado y solo {{addonPrice}} por crédito adicional después de tus créditos premium incluidos.",
"user-name-limit-char": "Para tener un nombre de usuario menor a 8 caracteres por favor suscríbete",
"tour-content": "No mostrar esto otra vez",
"pro": "PRO",
"team": "EQUIPO",
"user": "Usuario",
"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",
"forgot-password": "¿Olvidaste la contraseña?",
"loading": "Cargando...",
"of": "de",
"sign-SSO": "Ingresar con SSO",
"login-page": "Página de inicio de sesión",
"or": "O",
"signup-page": "Página de registro",
"password-length": "La contraseña debe tener 8 caracteres",
"password-case": "La contraseña debe incluir mayúsculas, minúsculas y números",
"password-special-char": " La contraseña debe incluir caracteres especiales",
"agreee": "Estoy de acuerdo con los",
"term": "Términos de Servicio",
"subscribe-to-opensign": "Suscribirse al boletín de OpenSign",
"register": "Registrarse",
"sidebar": {
"Dashboard": "Panel",
"Sign yourself": "Firma tu mismo",
"Request signatures": "Solicitar firmas",
"Templates": "Plantillas",
"Templates-Children": {
"Create template": "Crear plantilla",
"Manage templates": "Administrar plantillas"
},
"OpenSign™ Drive": "OpenSign™ Drive",
"Reports": "Reportes",
"Reports-Children": {
"Need your sign": "Necesitan tu firma",
"In Progress": "En progreso",
"Completed": "Completado",
"Drafts": "Borradores",
"Declined": "Rechazados",
"Expired": "Expirados",
"Contactbook": "Agenda de contactos"
},
"Settings": "Ajustes",
"Settings-Children": {
"My Signature": "Mi firma",
"API Token": "Token API",
"Webhook": "Webhook",
"Preferences": "Preferencias",
"Teams": "Equipos",
"Team-update-successfully": "Equipo actualizado correctamente.",
"Users": "Usuarios"
}
},
"dashboard-card": {
"Need your Signature": "Necesitan tu firma",
"Out for signatures": "En espera de ser firmados"
},
"report-name": {
"Draft Documents": "Documentos borradores",
"Need your sign": "Necesitan tu firma",
"In-progress documents": "Documentos en progreso",
"Completed Documents": "Documentos completados",
"Declined Documents": "Documentos rechazados",
"Expired Documents": "Documentos expirados",
"Recently sent for signatures": "Recientemente enviados para ser firmados",
"Recent signature requests": "Solicitudes de firma recientes",
"Drafts": "Borradores",
"Contactbook": "Agenda de contactos",
"Templates": "Plantillas",
"Teams": "Equipos",
"Users": "Usuarios"
},
"btnLabel": {
"sign": "firmar",
"Sign": "FIRMAR",
"Resend": "Reenviar",
"Revoke": "Revocar",
"Delete": "Eliminar",
"Use": "Usar",
"Quick send": "Envío rápido",
"Edit": "Editar",
"Share with team": "Compartir con el equipo",
"Share": "Compartir",
"View": "Ver",
"option": "Opción",
"Embed": "Incrustar",
"Copy TemplateId": "Copiar ID de plantilla",
"Copy Public URL": "Copiar URL pública"
},
"report-heading": {
"Sr.No": "Nº",
"Title": "Título",
"Email": "Correo",
"Phone": "Teléfono",
"File": "Archivo",
"Owner": "Propietario",
"Signers": "Firmantes",
"Note": "Nota",
"Folder": "Carpeta",
"Reason": "Razón",
"Parent Team": "Equipo padre",
"Active": "Activo",
"Role": "Rol",
"Team": "Equipo",
"Name": "Nombre",
"Status": "Estado",
"created-date": "Fecha de creación",
"Type": "Tipo",
"Logs": "Registros"
},
"report-help": {
"Draft Documents": "Estos son documentos que has iniciado pero no has finalizado para su envío.",
"Need your sign": "Esta es una lista de documentos que esperan tu firma.",
"In-progress documents": "Esta es una lista de documentos que has enviado a otras partes para su firma.",
"Completed Documents": "Esta es una lista de documentos en los que todas las partes han firmado.",
"Declined Documents": "Esta es una lista de documentos que han sido rechazados por uno de los firmantes.",
"Expired Documents": "Esta es una lista de documentos que han alcanzado su fecha de caducidad.",
"Contactbook": "Esta es una lista de contactos/firmantes añadidos por ti. Aparecerán como sugerencias cuando intentes añadir firmantes a un nuevo documento.",
"Templates": "Esta es una lista de plantillas que están a tu disposición para crear documentos. Puedes hacer clic en el botón «usar» para crear un nuevo documento utilizando una plantilla, modifica el documento y añade firmantes en el siguiente paso."
},
"form-name": {
"Sign Yourself": "Firmar",
"Request Signatures": "Solicitar firmas",
"New Template": "Nueva plantilla"
},
"file-type": "pdf, png, jpg, jpeg",
"docx": "docx",
"file-selected": "archivo seleccionado",
"template-title": "Título de la plantilla",
"document-title": "Título del documento",
"description": "Descripción",
"time-to-complete": "Plazo de finalización (días)",
"send-in-order": "Enviar en orden",
"send-in-order-help": {
"p1": "Elige cómo quieres que se envíen las solicitudes de firma a los firmantes del documento:",
"p2": "Seleccionando esta opción se enviará inicialmente la solicitud de firma al primer firmante. Una vez que el primer firmante complete su parte, el siguiente firmante en la secuencia recibirá la solicitud. Este proceso continúa hasta que todos los firmantes hayan firmado el documento. Este método garantiza que el documento se firme en un orden específico.",
"p3": "Seleccionando esta opción se enviarán los enlaces para la firma a todos los firmantes simultáneamente. Cada firmante puede firmar el documento cuando le convenga, independientemente de si otros firmantes han completado sus firmas. Este método es más rápido, pero no impone ningún orden de firma entre los participantes.",
"p4": "Selecciona la opción que mejor se adapte a las necesidades de tu tramitación de documentos."
},
"no": "No",
"auto-reminder": "Recordatorio automático",
"remind-once": " Recordar una vez cada (Días)",
"next": "Siguiente",
"select-folder": "Seleccionar carpeta",
"OpenSign-drive": "OpenSign™ Drive",
"drive-document-status": {
"Completed": "Completado",
"Declined": "Rechazado",
"Draft": "Borrador",
"Expired": "Expirado",
"In Progress": "En progreso"
},
"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",
"add-folder": "Añadir carpeta",
"create-folder": "Crear carpeta",
"parent-folder": "Carpeta superior",
"create": "Crear",
"signers": "Firmantes",
"signers-help": "Empieza a escribir el nombre de un contacto para ver los firmantes sugeridos entre tus contactos guardados o añade otros nuevos. Organiza el orden de firma añadiendo firmantes en la secuencia deseada. Utiliza el botón «+» para añadir nuevos firmantes y la «X» para quitar todos. Cada firmante recibirá una solicitud por correo electrónico para que firme el documento según el orden indicado.",
"add-signer": "Añadir firmante",
"contact-not-found": "Contacto no encontrado",
"add-yourself": "Añadirte a ti mismo",
"submit": "Enviar",
"reset": "Volver a empezar",
"my-signature": "Mi firma",
"signature": "Firma",
"upload-image": " Subir imagen",
"clear": "Limpiar",
"upload-signature/Image": "Por favor, sube la firma/imagen",
"initials": "Iniciales",
"API": "API",
"api-token": "Token API",
"regenerate-token": "Regenerar token activo",
"generate-token": "Generar token activo",
"view-docs": "Ver documentación",
"generate-token-alert": "¿En definitiva quieres regenerar el token? Esto expirará el token antiguo.",
"yes": "Sí",
"copied": "Copiado",
"something-went-wrong-mssg": "Algo salió mal, por favor, intenta de nuevo más tarde.",
"token-generated": "Token generado exitosamente.",
"webhook": "Webhook",
"update-webhook": "Actualizar webhook",
"add-webhook": "Agregar webhook",
"webhook-added": "Webhook agregado exitosamente.",
"team-disabled": "Equipo deshabilitado",
"Team enabled": "Equipo habilitado",
"are-you-sure": "¿En definitiva quieres ",
"disable": "deshabilitar",
"enable": "habilitar",
"this-team": " este equipo?",
"edit-team": "Editar equipo",
"name-of-team": "Nombre del equipo",
"prev": "Anterior",
"no-data-avaliable": "No hay datos disponibles",
"add-team": "Agregar equipo",
"page-not-found": "Página no encontrada",
"users-from-teams": "usuarios de equipos",
"user-status": "Estado del usuario",
"activate": "activar",
"deactivate": "desactivar",
"this-user": " este usuario",
"delete-user": "Eliminar usuario",
"delete": "eliminar",
"add-user": "Agregar usuario",
"password-generateed": "La contraseña solo será generada una vez; asegúrate de copiarla.",
"Team status": "Estado del equipo",
"user-deactivated": "Usuario desactivado.",
"user-activated": "Usuario activado.",
"public": "Público",
"download": "Descargar",
"view": "Ver",
"make-template-public": "Convertir la plantilla en pública",
"make-template-private": "Convertir la plantilla en privada",
"make-template-public-alert": "¿En definitiva quieres convertir esta plantilla en pública?",
"make-template-private-alert": "¿En definitiva quieres convertir esta plantilla en privada? Esto lo removerá de tu perfil público.",
"public-role": "Rol público",
"public-url": "Se requiere perfil público",
"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": "Por favor, completa la configuración de tu perfil público OpenSign. Una vez terminado, podrás crear plantillas públicas. Este proceso solo necesita ser completado una vez.",
"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",
"roles": "Roles",
"delete-document": "Eliminar documento",
"delete-document-alert": "¿En definitiva quieres eliminar este documento?",
"quick-send": "Envío rápido",
"add-new": "Agregar nuevo",
"send": "Enviar",
"quick-send-alert-1": "Todos los roles de este documento están actualmente vinculados a contactos. Para enviar rápidamente copias de esta plantilla a varios firmantes, por favor, asegúrate de que al menos un rol no esté vinculado a ningún contacto.",
"quick-send-alert-2": "Por favor, asegúrate de que hay al menos un widget de firma añadido para cada destinatario.",
"quick-send-alert-3": "Por favor, añade al menos un rol a esta plantilla para poder hacer un «envío rápido» de copias a varios firmantes.",
"quick-send-alert-4": "El envío rápido ha alcanzado el límite.",
"copy-link": "Copiar enlace",
"copy": "Copiar",
"revoke-document": "Revocar documento",
"revoke-document-alert": "¿En definitiva quieres revocar este documento?",
"resend-mail": "Reenviar correo",
"resend-mail-help": "Puedes usar las siguientes variables que serán reemplazadas por sus valores reales:- {{document_title}}, {{sender_name}}, {{sender_mail}}, {{sender_phone}}, {{receiver_name}}, {{receiver_email}}, {{receiver_phone}}, {{expiry_date}}, {{company_name}}, {{signing_url}}.",
"subject": "Asunto",
"body": "Cuerpo",
"add-contact": "Agregar contacto",
"add-signer-alert": "¡El contacto ya existe! Selecciónelo en el menú desplegable 'Firmantes'",
"record-delete-alert": "¡Entrada eliminada exitosamente!",
"record-revoke-alert": "¡Entrada revocada exitosamente!",
"mail-sent-alert": "Correo enviado exitosamente.",
"document-sent-alert": "¡Documento enviado exitosamente!",
"template-share-alert": "Plantilla compartida exitosamente.",
"template-public-alert-1": "Has convertido exitosamente la plantilla en pública.",
"template-public-alert-2": "Has convertido exitosamente la plantilla en privada.",
"template-public-alert-3": "Tienes que seleccionar un rol para los firmantes públicos.",
"template-public-alert-4": "Por favor, asegúrate de que has añadido al menos un widget de firma para cada firmante.",
"template-public-alert-5": "Dado que esta plantilla tiene «enviar en orden» habilitado, el rol público debe estar posicionado arriba al inicio.",
"template-public-alert-6": "Por favor, enlaza firmantes a todos los roles excepto al usuario de rol público.",
"template-public-alert-7": "Por favor, asigna al menos un rol público para convertir está plantilla en pública.",
"loader": " Esto podría llevar algún tiempo",
"pages": "Páginas",
"document-signed": "Documento firmado",
"close": "Cerrar",
"validation-alert": "Alerta de validación",
"validate-alert-mssg": " Los datos ingresados no cumplen con los criterios establecidos por la expresión regular.",
"otp-verification": "Verificación OTP",
"enter-otp": "Ingresar OTP",
"verify": "Verificar",
"verify-email-1": "Verificar correo",
"resend": "Reenviar",
"contact-details": "Detalles del contacto",
"verify-email": "¡Por favor, verifica tu correo!",
"send-otp": " Enviar OTP",
"otp-placeholder": "Ingresa el código de verificación enviado por correo",
"loading-doc": "Cargando documento...",
"widgets-name": {
"signature": "firma",
"stamp": "sello",
"initials": "iniciales",
"name": "nombre",
"job title": "título del puesto",
"company": "compañía",
"date": "fecha",
"text": "texto",
"text input": "entrada de texto",
"checkbox": "casilla",
"dropdown": "desplegable",
"radio button": "botón de radio",
"image": "imagen",
"email": "correo"
},
"fields": "Campos",
"recipients": "Destinatarios",
"please-add": "Por favor, agrega un",
"signed-by": "Firmado por",
"more": "más",
"sent": "enviado",
"print": "Imprimir",
"certificate": "Certificado",
"decline": "Rechazar",
"finish": "Finalizar",
"mail": "Correo",
"sign-now": "Firmar ahora",
"successfully-signed": "¡Firmado exitosamente!",
"email-mssg": " Los destinatarios agregados aquí recibirán una copia del documento firmado.",
"email-error-1": " por favor, proporciona una dirección de correo correcta",
"email-error-2": "Solo puedes enviar hasta a 10 destinatarios a la vez.",
"Email-verified-alert-1": "El correo está verificado.",
"Email-verified-alert-2": "El correo ya ha sido verificado.",
"upload-stamp-image": "Subir imagen del sello",
"draw": "Dibujar",
"type": "Escribir",
"color-type": {
"red": "rojo",
"blue": "azul",
"black": "negro",
"yellow": "amarillo"
},
"my-initials": "Mis iniciales",
"upload": "Subir",
"initial-teb": "Iniciales",
"signature-tab": "Firma",
"your-signature": "Tu firma",
"copy-title": "Copiar widget a",
"contact-delete-alert": "¿En definitiva quieres eliminar este contacto?",
"reset-password-alert-1": "El enlace para restablecer la contraseña ha sido enviado a tu correo electrónico",
"reset-password-alert-2": "Por favor, configura un adaptador de correo ",
"reset-password-alert-3": "Restablece tu contraseña",
"faild-animation": "Error al cargar la animación",
"apply": "Aplicar",
"copy-type": {
"All pages": "Todas las páginas",
"All pages but last": "Todas las páginas menos la última",
"All pages but first": "Todas las páginas menos la primera",
"Next to current widget": "Junto al widget actual"
},
"options": "Opciones",
"minimun-check": "Chequeo mínimo",
"maximum-check": "Chequeo máximo",
"default-value": "Valor por defecto",
"select": "Seleccionar",
"read-only": "Es de solo lectura",
"hide-labels": "Esconder etiquetas",
"checkbox": "Casilla",
"alert": "Alerta",
"zoom-in": "Acercar",
"zoom-out": "Alejar",
"document-signed-alert": "¡Felicitaciones! 🎉 ¡Este documento ha sido firmado por ti exitosamente!",
"otp-sent-alert": "OTP enviado a tu correo",
"fields-required": "Campos requeridos",
"signature-widget-alert-1": "Por favor, asegúrate de que hay al menos un widget de firma agregado",
"signature-widget-alert-2": "Por favor, asegúrate de que todos los campos están correctamente rellenados y de que cumplen todos los requisitos.",
"encrypted-pdf-alert": "Actualmente los archivos PDF encriptados no están soportados.",
"encrypted-pdf-alert-1": "La contraseña del archivo PFX es inválida.",
"user-not-exist": "El usuario no existe",
"template-signature-field": "Por favor, agrega al menos un campo de firma para todos los roles.",
"template-role-alert": "Por favor, primero agrega roles",
"create-document": "Crear documento",
"template-created-alert": "¿Quieres crear un documento usando la plantilla que acabas de crear?",
"signers-alert": "alerta de firmantes",
"template-creation-alert-1": "¡Por favor, selecciona un firmante para agregar un marcador de posición!",
"ok": "OK",
"radio-group": "Grupo de radio",
"dropdown-options": "Opciones del desplegable",
"add-role": "Agregar rol",
"role-ex": " por ejem.: Cliente, RRHH, Director, Administrador, Estudiante, etc.",
"add/choose-signer": "Agregar/Elegir firmante",
"choose-from-contacts": "Elegir desde los contactos",
"select-signer": " Por favor, selecciona el firmante",
"edit-template": "Editar plantilla",
"widget-info": "Información del widget",
"validation": "Validación",
"invalid-default-value": "valor por defecto inválido",
"hint": "Pista",
"color": "color",
"role-help": {
"p1": "¿Qué son los roles de una plantilla?",
"p2": "Empieza por especificar cada uno de los roles necesarios para completar el documento. Piensa en las partes implicadas en el proceso de firma y cuáles son sus responsabilidades. Los roles más habituales son RRHH para los documentos internos, Cliente para los contratos o Proveedor para los convenios comerciales.",
"p3": "¿Por qué preasignar usuarios a algunos roles?",
"p4": "Para los roles que consistentemente involucran al mismo individuo (por ejem., la firma del Gerente en las ofertas de empleo), puedes preasignar un usuario a un rol dentro de una plantilla. Este paso es opcional pero recomendado para la eficiencia y consistencia entre documentos",
"p5": "¿Cuando especifico el usuario asignado a cada rol?",
"p6": "Cuando crees un documento usando tu plantilla, se te pedirá que asignes usuarios a cada rol definido. Si un rol ya tiene un usuario asignado, este será rellenado con anticipación, pero puedes modificarlo según lo necesites antes de enviar el documento."
},
"add-recipients": "Agregar destinatarios",
"loading-mssg": "Esto podría llevar algún tiempo",
"send-mail": "Enviar correo",
"placeholder-alert-1": "Por favor, asegúrate de que hay al menos un widget de firma para cada destinatario.",
"placeholder-alert-2": "Por favor, confirma que hayas rellenado el campo de texto.",
"placeholder-alert-3": " ¿En definitiva quieres enviar este documento para ser firmado?",
"placeholder-alert-4": "¡Has enviado exitosamente correos a todos los destinatarios!",
"placeholder-alert-5": "¿Quieres firmar documentos ahora mismo?",
"placeholder-alert-6": "¡Por favor, configura el adaptador de correo para enviar correos!",
"placeholder-alert-7": "¡Por favor, selecciona un firmante para agregar un marcador de posición!",
"email-subject": "asunto del correo",
"email-body": "cuerpo del correo",
"email-placeholder": "agregar cuerpo del correo",
"reset-to-default": "Restablecer a por defecto",
"cutomize-email": "Personalizar correo",
"upgrade-to-customize-email": "Mejora para personalizar el correo",
"sign-url": "URL de firma",
"mails-sent": "Correos enviados",
"mail-not-delivered": "correo no entregado",
"document-alert": "Alerta de documento",
"owner-subscription-expired": "La suscripción del propietario ha expirado.",
"subscription-expired": "Suscripción expirada",
"alert-message": "Mensaje de alerta",
"document-decline": "Rechazar documento",
"decline-alert-1": "¿En definitiva quieres rechazar este documento?",
"decline-alert-2": "¡Has rechazado este documento!",
"decline-alert-3": "No puedes firmar este documento ya que ha sido rechazado/revocado.",
"sign here": "Firma aquí",
"guest-email-alert": "el código de verificación ha sido enviado a tu correo",
"get-otp-alert": "recibirás un código de verificación por correo",
"user-already-exist": "El usuario ya existe.",
"server-error": "¡Error interno del servidor!",
"fill-required-details!": "¡Por favor, rellena los detalles requeridos!",
"sign-up-form": "Formulario de registro",
"sign-up": "Registrarse",
"folder-already-exist!": "¡la carpeta ya existe!",
"please-select-position!": "¡por favor, selecciona una posición!",
"default-sign-alert": "¿En definitiva quieres firmar automáticamente en todos los lugares solicitados?",
"Your-Signature": "Tu firma",
"auto-sign-all": "Firmar todo automáticamente",
"generating-certificate": "Generando certificado",
"pdf-download": "Descargar PDF",
"generate-certificate-alert": " Tu certificado de finalización se está generando. Por favor, espera un momento. Si la descarga no inicia pronto, presiona el botón otra vez.",
"folder-already-exist": "¡La carpeta ya existe!",
"folder-created-successfully": "¡Carpeta creada exitosamente!",
"fill-folder-name": "Por favor, rellena el nombre de la carpeta",
"already-exists-this-username": "¡Un usuario con este nombre de usuario ya existe!",
"verification-code-sent": "¡El correo de verificación ha sido enviado a tu correo!",
"registered-user-successfully": "Usuario registrado exitosamente.",
"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 OpenSign",
"join-discord": "Únete a nuestro servidor de Discord",
"admin-already-exist": "El administrador ya existe.",
"password-update-alert-1": "Contraseña actualizada exitosamente.",
"password-update-alert-2": "Tu contraseña actual es incorrecta o falta.",
"password-update-alert-3": "Tu contraseña actual es incorrecta o falta.",
"password-update-alert-4": "Tu contraseña y su confirmación no son iguales.",
"current-password": "Contraseña actual",
"new-password": "Contraseña nueva",
"confirm-password": "Confirmar contraseña",
"file-alert-1": "El tamaño del archivo seleccionado es muy grande. Por favor, selecciona un archivo con un tamaño menor a",
"file-alert-2": "Por favor, selecciona un archivo.",
"file-alert-3": "Por favor, espera mientras se sube el documento.",
"enter-pdf-password": "Ingresa la contraseña del PDF",
"correct-password": "Por favor, proporciona la contraseña correcta",
"decrypting-pdf": " Desencriptando PDF, por favor, espera...",
"invalid-otp": "OTP inválido",
"user-not-found": "¡Usuario no encontrado!",
"enter-otp-alert": "¡Por favor, ingresa el OTP!",
"get-verification-code": "Obtener código de verificación",
"get-verification-code-2": "Obtendrás un código de verificación por correo",
"enter-verification-code": "Ingresar código de verificación",
"provide-your-details": "Proporciona tus detalles",
"provide-email": "Por favor, proporciona un correo.",
"additional-info": "Información adicional",
"signature-saved-alert": "Firma guardada exitosamente.",
"fill-field": "Por favor, rellena este campo",
"error-template": "Error: ¡Plantilla no encontrada!",
"error": "Error",
"invalid-document": "Error: ¡Documento inválido!",
"document-not-found": "¡Documento no encontrado!",
"document-signed-alert-1": "Has firmado el documento exitosamente. Puedes descargar o imprimir una copia del documento parcialmente firmado. Una copia del documento firmado digitalmente será enviada al propietario mediante correo electrónico una vez haya sido firmado por todos los firmantes.",
"encrypted-pdf-not-support": "Los archivos PDF encriptados no están soportados actualmente.",
"document-signed-alert-4": " ¡Felicitaciones! 🎉 ¡Este documento ha sido firmado exitosamente por todos los participantes!",
"document-signed-alert-5": "Este documento ha sido firmado por todos los firmantes.",
"document-signed-alert-6": "Este documento ha sido rechazado por uno o más destinatarios.",
"document-signed-alert-7": "Este documento ya no está disponible.",
"document-signed-alert-8": "Este documento ya ha sido enviado para ser firmado.",
"yet-to-sign": "Todavía por firmar",
"validation-alert-1": "Los datos ingresados no cumplen con los criterios establecidos por la expresión regular.",
"account-already-exists": "¡La cuenta ya existe!",
"choose-password": "Elegir contraseña",
"enter-password": "Ingresar contraseña",
"sure": "claro",
"subscribed-alert": "¡Ya te has suscrito al plan!",
"monthly": "Mensual",
"yearly-upto": "Anual (hasta 66% de descuento)",
"billed-yearly": "Facturado anualmente",
"billed-monthly": "Facturado mensualmente",
"plansubscription-1": "Alójalo por tu cuenta gratuitamente",
"visit-github": "Visitar GitHub",
"user-already-exist-name": "¡Un usuario con este nombre de usuario ya existe!",
"do-not-access-contact-admin": "No tienes acceso, por favor, contacta a un administrador.",
"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",
"report-not-found": "Reporte no encontrado",
"please-wait": "por favor, espera",
"select-foler": "Seleccionar carpeta",
"generated-on": "Generado el",
"text-field": "Campo de texto",
"font-size": "Tamaño de la fuente",
"widget-status": {
"Required": "Requerido",
"Optional": "Opcional"
},
"all-right": "Todos los derechos reservados",
"version": "versión",
"social-media": {
"github": "GitHub",
"linked-in": "LinkedIn",
"twitter": "Twitter",
"discord": "Discord"
},
"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 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.",
"opensign-drive-3": "Ordena tus documentos por «Fecha» o «Nombre» usando este menú.",
"opensign-drive-4": "Haz clic en este menú para mostrar los documentos en vista de lista.",
"opensign-drive-5": "La lista de documentos es mostrada de acuerdo a la opción de ordenamiento seleccionada. Los íconos situados junto a cada documento indican su estado actual.",
"opensign-drive-6": "Haz clic con el botón derecho en un documento para ver opciones como «Descargar», «Renombrar», «Mover» y «Eliminar». Haz clic en el documento para abrirlo.",
"opensign-drive-7": "Haz clic con el botón derecho en cualquier carpeta para ver las opciones. Elige «Renombrar» para cambiar el nombre de la carpeta o haz clic en ella para navegar por su contenido.",
"pdf-request-file-1": "Lista de firmantes que todavía tienen que firmar este documento.",
"pdf-request-file-2": "Haz clic en cualquiera de los marcadores de posición que aparecen en el documento para firmar. A continuación, verás opciones para dibujar tu firma, escribirla o subir una imagen .",
"pdf-request-file-3": "Haz clic en los botones «Atrás», «Rechazar» o «Finalizar» para navegar por el documento. Utiliza el menú de tres puntos para ver otras opciones, como el botón «Descargar».",
"pdf-request-file-4": "Lista de firmantes que ya han firmado el documento.",
"pdf-request-file-5": "Puedes hacer clic en «Firmar todo automáticamente» para firmar de manera automática en todos los lugares que deban ser firmados por ti. Asegúrate de revisar correctamente el documento antes de hacer clic en ese botón.",
"placeholder-sign-1": "Selecciona un destinatario de esta lista para agregar un marcador de posición dónde este destinatario tendrá que firmar. El marcador de posición aparecerá con el mismo color que el nombre del destinatario una vez lo sueltes en el documento.",
"placeholder-sign-2": "Hacer clic en el botón «Agregar destinatarios» te permitirá añadir más firmantes.",
"placeholder-sign-3": "Haz clic en este botón para agregar más destinatarios/firmantes al documento.",
"placeholder-sign-4": "Arrastra o haz clic en un capo para agregarlo al documento.",
"placeholder-sign-5": "El área de contenido del PDF ya muestra los marcadores de posición existentes en la plantilla. Para tu comodidad, estos marcadores de posición coincidirán con el color del nombre del destinatario, haciéndolos fácilmente identificables.",
"placeholder-sign-6": "Hacer clic en «Enviar» guardará el documento. En el siguiente paso podrás personalizar los correos que serán enviados a los destinatarios o copiar los enlaces para firmar y compartirlos con los destinatarios por tu cuenta.",
"report-1": "Haz clic en el botón «Agregar» para crear una nueva plantilla. Las plantillas son documentos reusables diseñados para generar rápidamente nuevos documentos con la misma estructura pero diferentes firmantes. Por ejemplo, una plantilla de RR.HH. para el proceso de incorporación podría tener roles predefinidos como «Director de RR.HH.» y «Nuevo empleado». Cada vez que utilices la plantilla, puedes asignar el rol de «Nuevo empleado» a los distintos miembros del personal que se incorporen, mientras que el rol de « Director de RR.HH.» permanece constante, lo que facilita un proceso de incorporación fluido para cada persona contratada.",
"redirect": "Haz clic en el botón «Usar» para crear un nuevo documento desde una plantilla existente.",
"bulksend": "Para crear y enviar rápidamente múltiples documentos usando una plantilla existente, haz clic en el botón «Envío rápido».",
"option": "Este menú revela más opciones como «Editar» y «Eliminar». Usa el botón «Editar» para agregar roles, modificar campos y actualizar tu plantilla. Los cambios aplicarán para todos los documentos futuros que sean creados usando esta plantilla pero no afectarán a los documentos ya existentes. Con el botón «Eliminar» puedes eliminar la plantilla.",
"signyour-self-1": "Para personalizar el documento antes de que sea firmado, selecciona y arrastra al documento los widgets que prefieras. Escoge el espacio perfecto para cada modificación para adaptar el documento a tus necesidades.",
"signyour-self-2": "Arrastra y suelta en cualquier lugar de esta área. Después podrás cambiar el tamaño y moverlo.",
"template-placeholder-1": "Hacer clic en el botón «Agregar rol» te permitirá agregar varios roles de firmantes. Puedes asociar usuarios a cada rol en los siguientes pasos.",
"template-placeholder-2": "Una vez que los roles hayan sido agregados, selecciona un rol de la lista para agregar un marcador de posición donde éste tendrá que firmar. El marcador de posición aparecerá con el mismo color que el nombre del rol una vez lo sueltes en el documento.",
"template-placeholder-3": "Arrastra o haz clic en un capo para agregarlo al documento.",
"template-placeholder-4": "Arrastra el marcador de posición para un rol a cualquier lugar del documento. Recuerda, aparecerá con el mismo color que el nombre del rol para poder referenciarlo fácilmente.",
"template-placeholder-5": "Hacer clic en «Siguiente» guardará la plantilla actual. Luego de guardar, se te consultará si deseas crear un nuevo documento usando esta plantilla.",
"webhook-1": "Mejora ahora para configurar un webhook",
"Need your Signature": "Hacer clic en esta tarjeta te llevará a la lista de documentos que esperan por tu revisión.",
"Out for signatures": "Hacer clic en esta tarjeta te llevará a la lista de documentos que esperan tu firma.",
"Recent signature requests": "Esta es una lista de documentos que esperan por tu firma.",
"Recently sent for signatures": "Esta es una lista de documentos que has enviado a otras partes para que sea firmado.",
"Drafts": "Estos son documentos que has empezado pero que todavía no finalizas para su envío.",
"public-template": "Este video muestra cómo puedes configurar tu perfil público personalizado, como «https://opensign.me/tu-nombre-de-usuario». También aprenderás cómo personalizar tu eslogan y cómo hacer tus plantillas disponibles para su firmado público."
},
"enter-email-plaholder": "Agrega una dirección de correo y presiona «Enter»",
"success-email-alert": "¡Correo enviado exitosamente!",
"expired-doc-title": "Documento expirado",
"expired-on-mssg": "Este documento expiro el {{expiredDate}} y ya no está disponible para ser firmado.",
"signature-validate-alert": "Por favor, confirma que has seleccionado al menos {{minRequiredCount}} casillas.",
"signature-validate-alert-2": "Asegúrate de que este campo esté correctamente rellenado y que cumpla con todos los requisitos.",
"remaing-users": "Usuarios restantes",
"Role": "Rol",
"additional-users": "Por favor, compra el complemento Usuarios.",
"Quantity-of-users": "Cantidad de usuarios",
"Price": "Precio",
"Total-price-for-next-time": "Precio total para la próxima vez",
"Proceed": "Proceder",
"Select": "Seleccionar",
"Add-seats": "Agregar plazas",
"user-name-exist": "el nombre de usuario ya existe",
"format": "formato",
"select-date-format": "Selecciona un formato de fecha",
"quantity-of-credits": "Cantidad de créditos premium",
"remaining-credits": "Créditos premium disponibles:",
"remaining-credits-help": "Usa créditos premium para la API para la firma de documentos, envío en masa, o para incorporar la integración de OpenSign en tu página web. Te quedan {{allowedcredits}} créditos incluidos y {{addoncredits}} créditos comprados adicionalmente.",
"additional-credits": "Por favor, compra créditos premium",
"quota-err-quicksend": "Cuota alcanzada, no tienes créditos suficientes.",
"buy-credits": "Comprar créditos premium",
"rotate-right": "Rotar a la derecha",
"rotate-left": "Rotar a la izquierda",
"rotate-alert-mssg": "Todos los widgets de esta página se perderán. ¿En definitiva quieres proceder?",
"templateid": "ID de plantilla",
"bulk-send-subcription-alert": "Por favor, mejora al plan a Professional o Team para usar envío en masa.",
"generate-test-token": "Generar token de prueba",
"regenerate-test-token": "Regenerar token de prueba",
"help-test-token": "Este token puede ser usado para probar las API en el punto de acceso «https://sandbox.opensignlabs.com/api/v1», permitiéndote realizar firmas de documentos ilimitadas. Por favor, ten en cuenta que el API de pruebas firmará tus documentos con certificados autofirmados, que podrían no ser reconocidos por Adobe como válidos. Una vez hayas completado tus pruebas, puedes mejorar a uno de nuestros planes de pago para generar un token de producción.",
"help-api-token": "Este token puede ser usado para acceder a las API de producción en el punto de acceso «{{origin}}/api/v1». Solo puede ser generado con uno de nuestros planes de pago.",
"reason": "Razón",
"decline-by": "Rechazado/revocado por",
"document-declined": "Documento rechazado",
"public-template-mssg-1": "Para integrar OpenSign a tu proyecto React o Next.js, simplemente ejecuta los siguientes comandos:",
"public-template-mssg-2": "Asegúrate de tener «npm» o «yarn» configurado en tu proyecto. Si estás usando «yarn», puedes reemplazar «npm install» con «yarn add @opensign/react».",
"public-template-mssg-3": "¿Necesitas más detalles o ejemplos?",
"public-template-mssg-4": "Visita la",
"public-template-mssg-5": " «npm» para las últimas actualizaciones, documentación detallada e historial de versiones.",
"public-template-mssg-6": "Antes de que puedas usar este fragmento de código, debes convertir esta plantilla en pública.",
"copy-code": "COPIAR",
"copied-code": "COPIADO",
"Installation": "Instalación",
"Usage": "Uso",
"insufficient-credits": "Créditos de firma insuficientes",
"insufficient-credits-mssg": "El propietario de este documento actualmente carece de los créditos OpenSign necesarios para que puedas firmarlo. Por favor, contacta al propietario si necesitas más detalles.",
"angular-npm-mssg-1": "Para integrar OpenSign a tu proyecto Angular, simplemente ejecuta los siguientes comandos:",
"quota-mail-info-head": "Límite mensual de solicitudes de firma por correo",
"quota-mail-info": "Puedes enviar hasta 15 solicitudes de firma por correo cada mes. Mejora ahora para enviar solicitudes de firma sin límite.",
"quota-mail": "Has alcanzado tu límite de 15 solicitudes de firma por correo para este mes. Mejora ahora para continuar enviando correos.",
"quota-mail-tip": "Consejo: Todavía puedes solciitar la firma de <1>documentos ilimitados</1> compartiendo manualmente los enlaces de solicitud de firma.",
"quota-mail-head": "Cuota alcanzada",
"unauthorized-modal": "No tienes permisos para realizar esta acción, por favor, contacta a {{adminEmail}}.",
"sent-this-month": "Enviados este mes",
"available-seats": "Plazas disponibles",
"buy-users": "Comprar más usuarios",
"isenable-otp": "Habilitar verificación con OTP",
"isenable-otp-help": {
"p1": "¿Te gustaría habilitar el proceso de verificación usando una contraseña de un solo uso (OTP)?",
"p2": "Seleccionar esta opción habilitará la verificación con OTP. Los usuarios recibirán un código de verificación por correo, la cual tendrán que ingresar para poder firmar el documento.",
"p3": "Seleccionar esta opción deshabilitará la verificación con OTP, lo cual permitirá a los usuarios firmar el documento directamente sin pasos adicionales.",
"p4": "Por favor, selecciona la opción que mejor se adapte a tus requisitos para la firma de documentos."
},
"advanced-options": "Opciones avanzadas",
"hide-advanced-options": "Ocultar las opciones avanzadas",
"download-files": "Descargar archivos",
"download-pdf": "Descargar PDF",
"pdf-certificate": "Descargar PDF + Certificado",
"document-logs": "Registros de documentos",
"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 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 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",
"text-field-tour":"Los campos de tipo 'Texto' deben completarse con anticipación antes de enviar el documento. Si necesita que los firmantes proporcionen información, utilice el campo 'Entrada de texto'",
"attach-signer-tour" :"Debe adjuntar un firmante a cada función. Puede hacerlo haciendo clic en este icono. Una vez que seleccione un Firmante, se adjuntará a todos los campos asociados con ese rol que aparecen en el mismo color.",
"allowed-signature-types": "Tipos de firma permitidos",
"at-least-one-signature-type": "Se debe habilitar al menos un tipo de firma.",
"expect-default-one-signature-type": "Habilite un tipo de firma adicional aparte del predeterminado.",
"add-signer-note": "Nota - Este contacto se agregará a su lista de contactos",
"allowed-signature-types-help": {
"p1": "Esta preferencia de firma controla qué opciones de firma están disponibles para sus firmantes. Solo los tipos de firma que seleccione aparecerán en el widget de firma cuando se firme un documento. Por ejemplo, si elige sólo la opción 'Draw' en las preferencias, su firmante verá sólo la opción 'Draw' en el widget de firma, mientras que las otras tres opciones no estarán disponibles.",
"l1": "Cree una firma manuscrita directamente en la pantalla usando su dedo o un lápiz.",
"l2": "Ingrese su nombre y elija entre varios estilos de fuente para crear una firma.",
"l3": "Cargue una versión digital existente de su firma.",
"l4": "Utilice un estilo de firma preestablecido guardado en 'Mi firma' en su configuración."
}
}
@@ -0,0 +1,700 @@
{
"header-news": "Nouvelle fonctionnalité : les utilisateurs du forfait Teams peuvent désormais intégrer leurs propres compartiments AWS S3 pour le stockage de fichiers",
"header-news-btn": "Configurer maintenant",
"create-account": "Créer un compte",
"login": "Se Connecter",
"language": "Langue",
"name": "Nom et Prénom",
"phone": "Téléphone",
"phone-optional": "(facultatif)",
"email": "E-mail",
"company": "Organisation",
"job-title": "Votre Fonction",
"profile": "Profil",
"is-email-verified": "L'e-mail est-il vérifié",
"log-out": "Déconnexion",
"public-profile": "Profil public",
"tagline": "Slogan",
"has-requested-you-to-sign": " vous a demandé de signer",
"has-requested-you-to-review-and-sign": "vous a demandé de consulter et de signer",
"input-required": "Veuillez remplir ce champ.",
"sort-order": {
"Ascending": "Ascendant",
"Descending": "Descendant",
"Name": "Nom et Prénom",
"Date": "Date"
},
"context-menu": {
"Download": "Télécharger",
"Rename": "Renommer",
"Move": "Se déplacer",
"Delete": "Supprimer"
},
"action": "Action",
"add": "Ajouter",
"add-new-folder": "Ajouter un nouveau dossier",
"disable-documentId": "Désactiver l'ID du document",
"edit": "Modifier",
"change-password": "Changer votre mot de passe",
"save": "Sauvegarder",
"cancel": "Annuler",
"upgrade-now": "Mettre à jour maintenant",
"upgrade-to": "Mettre à niveau vers",
"pro": "PRO",
"plan": "Offre",
"subscribe-card-teamplan":"Libérez toute la puissance de la collaboration ! Créez un nombre illimité d'organisations, d'équipes et de hiérarchies. Partagez des modèles de manière transparente entre les équipes et attribuez des rôles d'utilisateur personnalisés. Améliorez votre flux de travail dès aujourd'hui !",
"subscribe-card-plan": "Débloquez des fonctionnalités premium à partir de seulement {{premiumPrice}}/mois. Bénéficiez de performances améliorées et de seulement {{addonPrice}} par crédit supplémentaire après vos crédits premium inclus.",
"user-name-limit-char": "Pour avoir un nom d'utilisateur de moins de 8 caractères s'il vous plaît s'abonner",
"tour-content": "Ne plus afficher",
"team": "Équipe",
"docs": "Documents",
"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",
"forgot-password": "Mot de passe oublié?",
"loading": "Chargement...",
"of": "de",
"sign-SSO": "Connectez-vous avec SSO",
"login-page": "Page de connexion",
"or": "OU",
"signup-page": "Page d'inscription",
"password-length": "Le mot de passe doit être de plus de 8 caractères",
"password-case": "Le mot de passe doit contenir une lettre majuscule, minuscule et un chiffre ",
"password-special-char": "Le mot de passe doit contenir un caractère spécial",
"agreee": "Je suis d'accord avec le",
"term": "Conditions d'utilisation",
"subscribe-to-opensign": "Abonnez-vous à la newsletter OpenSign",
"register": "S'enregistrer ",
"sidebar": {
"Dashboard": "Tableau de bord",
"Sign yourself": "signez vous-même",
"Request signatures": "Demander des signatures",
"Templates": "Modèles",
"Templates-Children": {
"Create template": "Créer un modèle",
"Manage templates": "Gérer les modèles"
},
"OpenSign™ Drive": "Lecteur OpenSign™",
"Reports": "Rapports",
"Reports-Children": {
"Need your sign": "Besoin de votre signature",
"In Progress": "En cours",
"Completed": "Complété",
"Drafts": "Brouillons",
"Declined": "Signature refusé",
"Expired": "Expiré",
"Contactbook": "Carnet de contacts"
},
"Settings": "Paramètres",
"Settings-Children": {
"My Signature": "Ma signature",
"API Token": "Jeton API",
"Webhook": "Webhook",
"Preferences": "Préférences",
"Teams": "Équipe",
"Team-update-successfully": "Équipe mise à jour avec succès.",
"Users": "Utilisateurs"
}
},
"dashboard-card": {
"Need your Signature": "Besoin de votre signature",
"Out for signatures": "En attente de Signature"
},
"report-name": {
"Draft Documents": "Brouillons",
"Need your sign": "Besoin de votre signature",
"In-progress documents": "Documents en cours",
"Completed Documents": "Documents complétés",
"Declined Documents": "Documents refusés",
"Expired Documents": "Documents expirés",
"Recently sent for signatures": "Récemment envoyé pour signature",
"Recent signature requests": "Demandes de signature récentes",
"Drafts": "Brouillons",
"Contactbook": "Carnet de contacts",
"Templates": "Modèles",
"Teams": "Équipe",
"Users": "Utilisateurs"
},
"report-heading": {
"Sr.No": "Numéro",
"Title": "Titre",
"Email": "E-mail",
"Phone": "Téléphone",
"File": "Fichier",
"Owner": "Propriétaire",
"Signers": "Signataires",
"Note": "Note",
"Folder": "Dossier",
"Reason": "Raison",
"Parent Team": "Équipe de parents",
"Active": "Actif",
"Role": "Rôle",
"Team": "Équipe",
"Name": "Nom",
"Status": "Statut",
"created-date": "Date de création",
"Type": "Saisir",
"Logs": "Journaux"
},
"btnLabel": {
"sign": "Signer",
"Resend": "Relancer",
"Revoke": "Révoquer",
"Delete": "Supprimer",
"Use": "Utiliser",
"Quick send": "Envoi rapide",
"Edit": "Modifier",
"Share with team": "Partager avec l'équipe",
"Share": "Partager",
"View": "Voir",
"option": "Option",
"Embed": "Intégrer",
"Copy TemplateId": "Copier l'ID du modèle",
"Copy Public URL":"Copier l'URL publique"
},
"report-help": {
"Draft Documents": "Il s'agit de documents que vous avez commencés mais que vous n'avez pas finalisés pour envoi.",
"Need your sign": "Voici une liste de documents ou votre signature est requise",
"In-progress documents": "Il s'agit d'une liste de documents que vous avez envoyés à d'autres parties pour signature.",
"Completed Documents": "Il s'agit d'une liste de documents signés par toutes les parties.",
"Declined Documents": "Il s'agit d'une liste de documents qui ont été refusés par l'un des signataires.",
"Expired Documents": "Il s'agit d'une liste de documents qui ont atteint leur date d'expiration.",
"Contactbook": "Il s'agit d'une liste de contacts/signataires que vous avez ajoutés. Ceux-ci apparaîtront sous forme de suggestions lorsque vous tenterez d'ajouter des signataires à un nouveau document.",
"Templates": "Il s'agit d'une liste de modèles à votre disposition pour créer des documents. Vous pouvez cliquer sur le bouton 'Utiliser' pour créer un nouveau document à l'aide d'un modèle, modifier le document et ajouter des signataires à l'étape suivante."
},
"form-name": {
"Sign Yourself": "signez vous-même",
"Request Signatures": "Demander des signatures",
"New Template": "Nouveau modèle"
},
"file-type": "pdf, png, jpg, jpeg",
"docx": "docx",
"file-selected": "fichier sélectionné",
"template-title": "Titre du modèle",
"document-title": "Titre du document",
"description": "Description",
"time-to-complete": "Temps de réalisation (jours)",
"send-in-order": "Envoyer dans l'ordre ?",
"send-in-order-help": {
"p1": "Choisissez la manière dont vous souhaitez que les demandes de signature soient envoyées aux signataires du document :",
"p2": "La sélection de cette option enverra initialement la demande de signature au premier signataire. Une fois que le premier signataire a terminé sa partie, le prochain signataire de la séquence recevra la demande. Ce processus se poursuit jusqu'à ce que tous les signataires aient signé le document. Cette méthode garantit que le document est signé dans un ordre spécifique.",
"p3": "La sélection de cette option enverra les liens de signature à tous les signataires simultanément. Chaque signataire peut signer le document à sa convenance, que d'autres signataires aient ou non complété leur signature. Cette méthode est plus rapide mais nimpose aucun ordre de signature entre les participants.",
"p4": "Sélectionnez l'option qui correspond le mieux aux besoins de votre traitement de documents."
},
"no": "Non",
"auto-reminder": "Rappel automatique",
"remind-once": "Rappeler une fois tous les (jours)",
"next": "Suivant",
"select-folder": "Sélectionner le dossier",
"OpenSign-drive": "Lecteur OpenSign™",
"drive-document-status": {
"Completed": "Complété",
"Declined": "Refuser",
"Draft": "Brouillon",
"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 OpenSign.",
"no-data": "Aucune données disponible",
"save-here": "Enregistrer ici",
"back": "Retour",
"add-folder": "Ajouter le dossier",
"create-folder": "Créer le dossier",
"parent-folder": "Dossier Parent",
"create": "Créer",
"signers": "Signataires",
"signers-help": "Commencez à saisir le nom d'un contact pour voir les signataires suggérés par vos contacts enregistrés ou en ajouter de nouveaux. Organisez l'ordre de signature en ajoutant des signataires dans l'ordre souhaité. Utilisez le bouton « + » pour inclure les signataires et le « x » pour les supprimer. Chaque signataire recevra un e-mail invité à signer le document dans l'ordre indiqué.",
"add-signer": "Ajouter un signataire",
"contact-not-found": "Contact introuvable",
"add-yourself": "Ajoutez-vous",
"submit": "Soumettre",
"reset": "Réinitialiser",
"my-signature": "Ma signature",
"signature": "Signature",
"upload-image": "Télécharger une image",
"clear": "Vider",
"upload-signature/Image": "télécharger-signature/Image",
"initials": "Initiales",
"API": "API",
"api-token": "Jeton API",
"regenerate-token": "Régénérer en direct jeton",
"generate-token": "Générer en direct jeton",
"view-docs": "Afficher les documents",
"generate-token-alert": "Êtes-vous sûr de vouloir régénérer le jeton, votre ancien jeton sera supprimer?",
"yes": "Oui",
"copied": "Copié",
"wrong-mssg": "Quelque chose c'est mal passé. Merci d'essayer plus tard.",
"token-generated": "Jeton généré avec succès.",
"webhook": "Webhook",
"update-webhook": "Mettre à jour le webhook",
"add-webhook": "Ajouter un webhook",
"webhook-added": "Webhook ajouté avec succès.",
"team-disabled": "Équipe: Désactivée",
"team-enabled": "Équipe activée",
"are-you-sure": "Êtes-vous sûr de vouloir",
"disable": "désactiver",
"enable": "activer",
"this-team": "cette équipe?",
"edit-team": "Modifier l'équipe",
"name-of-team": "Nom de l'équipe",
"prev": "précédent",
"no-data-avaliable": "pas de données disponibles",
"add-team": "Ajouter une équipe",
"page-not-found": "Page non trouvée",
"users-from-teams": "utilisateurs de votre Équipe",
"user-status": "Statut de l'utilisateur",
"activate": "Activer",
"deactivate": "désactiver",
"this-user": "cet utilisateur ",
"delete-user": "Supprimer l'utilisateur",
"delete": "supprimer",
"add-user": "Ajouter un utilisateur",
"password-generateed": "Le mot de passe ne sera généré qu'une seule fois ; assurez-vous de le copier.",
"Team status": "Statut de l'équipe",
"user-deactivated": "Utilisateur désactivé.",
"user-activated": "Activé par l'utilisateur.",
"public": "Public",
"download": "Téléchargement",
"view": "voir",
"make-template-public": "Rendre le modèle public",
"make-template-private": "Rendre le modèle privé",
"make-template-public-alert": "Êtes-vous sûr de vouloir rendre ce modèle public ?",
"make-template-private-alert": "Êtes-vous sûr de vouloir rendre ce modèle privé ? Cela le supprimera de votre profil public.",
"public-role": "Rôle public",
"public-url": "Profil public requis",
"public-url-copy": "Voici votre URL publique : ",
"public-url-copy-mssg": "copiez-la ou partagez-le avec le signataire et vous pouvoir voir tous vos paramètres publics modèles.",
"add-public-url-alert": "Veuillez terminer la configuration de votre profil public OpenSign. Une fois cela fait, vous pourrez rendre les modèles publics. Ce processus ne doit être effectué quune seule fois.",
"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",
"roles": "Les rôles",
"delete-document": "Supprimer un document",
"delete-document-alert": "Êtes-vous sûr de vouloir supprimer ce document ?",
"quick-send": "Envoi rapide",
"add-new": "Ajouter un nouveau",
"send": "envoyer",
"quick-send-alert-1": "Tous les rôles dans ce document sont actuellement liés à des contacts. Pour envoyer rapidement des copies de ce modèle à plusieurs signataires, veuillez vous assurer qu'au moins un rôle n'est lié à aucun contact.",
"quick-send-alert-2": "Veuillez vous assurer qu'au moins un widget de signature est ajouté pour tous les destinataires.",
"quick-send-alert-3": "Veuillez ajouter au moins un rôle à ce modèle afin d'en « envoyer rapidement » des copies à plusieurs signataires.",
"quick-send-alert-4": "L'envoi rapide a atteint la limite.",
"copy-link": "Copier le lien",
"copy": "Copier",
"revoke-document": "Révoquer le document",
"revoke-document-alert": "Êtes-vous sûr de vouloir révoquer ce document ?",
"resend-mail": "Renvoyer le courrier",
"resend-mail-help": "Vous pouvez utiliser les variables suivantes qui seront remplacées par leurs valeurs réelles : - {{document_title}}, {{sender_name}}, {{sender_mail}}, {{sender_phone}}, {{receiver_name}}, {{receiver_email} }, {{receiver_phone}}, {{expiry_date}}, {{company_name}}, {{signing_url}}.",
"subject": "Sujet",
"body": "Corps",
"add-contact": "Ajouter le contact",
"add-signer-alert": "Le contact existe déjà ! Veuillez le sélectionner dans la liste déroulante 'Signataires'",
"record-delete-alert": "Enregistrement supprimé avec succès !",
"record-revoke-alert": " Enregistrement révoqué avec succès ! ",
"mail-sent-alert": "Courriel envoyé avec succès.",
"document-sent-alert": "Document envoyé avec succès !",
"template-share-alert": "Modèle partagé avec succès.",
"template-public-alert-1": "Vous avez rendu le modèle public avec succès.",
"template-public-alert-2": "Vous avez réussi à rendre le modèle privé.",
"template-public-alert-3": "Vous devez sélectionner un rôle pour les signataires publics.",
"template-public-alert-4": "Veuillez vous assurer qu'au moins un widget de signature est ajouté pour tous les signataires.",
"template-public-alert-5": "Étant donné que l'envoi dans l'ordre est activé sur ce modèle, le rôle public doit être positionné en haut.",
"template-public-alert-6": "Veuillez associer des signataires à tous les rôles, à l'exception du rôle d'utilisateur public.",
"template-public-alert-7": "Veuillez attribuer au moins un rôle public pour rendre ce modèle public.",
"loader": "Cela pourrait prendre un certain temps",
"pages": "Pages",
"document-signed": "Document signé",
"close": "Fermer",
"validation-alert": "Alerte de validation",
"validate-alert-mssg": "L'entrée ne répond pas aux critères définis par l'expression régulière.",
"otp-verification": "Vérification OTP",
"enter-otp": "Entrez OTP",
"verify": "Vérifier",
"verify-email-1": "Vérifier l'e-mail",
"resend": "Renvoyer",
"contact-details": "Coordonnées",
"verify-email": "Veuillez vérifier votre email!",
"send-otp": "envoyer un code à usage unique",
"otp-placeholder": "Entrez le code de vérification reçu par e-mail",
"loading-doc": "Chargement du document..",
"widgets-name": {
"signature": "signature",
"stamp": "tampon",
"initials": "initiales",
"name": "nom et Prénom",
"job title": "votre fonction",
"company": "organisation",
"date": "date",
"text": "texte",
"text input": "saisie de texte",
"checkbox": "case à cocher",
"dropdown": "dérouler",
"radio button": "bouton radio",
"image": "image",
"email": "e-mail"
},
"fields": "Des champs",
"recipients": "Destinataires",
"please-add": "Veuillez ajouter un",
"signed-by": "Signé par",
"more": "plus",
"sent": "Envoyé",
"print": "imprimer",
"certificate": "Certificat",
"decline": "refusé",
"finish": "terminé",
"mail": "Mail",
"sign-now": "Signez maintenant",
"successfully-signed": "Signé avec succès !",
"email-mssg": "Les destinataires ajoutés ici recevront une copie du document signé.",
"email-error-1": "veuillez fournir une adresse e-mail correcte",
"email-error-2": "Vous ne pouvez envoyer qu'à dix destinataires à la fois.",
"Email-verified-alert-1": "L'e-mail est vérifié.",
"Email-verified-alert-2": "L'e-mail est déjà vérifié.",
"upload-stamp-image": "Télécharger l'image du tampon",
"draw": "Dessiner",
"type": "Taper",
"color-type": {
"red": "rouge",
"blue": "bleu",
"black": "noir",
"yellow": "jaune"
},
"my-initials": "Mes initiales",
"upload": "Télécharger",
"initial-teb": "Initiales",
"signature-tab": "Signature",
"your-signature": "Votre signature",
"copy-title": "Copier le widget vers",
"contact-delete-alert": "Êtes-vous sûr de vouloir supprimer ce contact ?",
"reset-password": "Le lien de réinitialisation du mot de passe a été envoyé à votre identifiant de messagerie",
"reset-password-alert-2": "Veuillez configurer l'adaptateur de messagerie",
"reset-password-alert-3": "Réinitialisez votre mot de passe",
"faild-animation": "Échec du chargement de l'animation",
"apply": "Appliquer",
"copy-type": {
"All pages": "Toutes les pages",
"All pages but last": "Toutes les pages sauf la dernière",
"All pages but first": "Toutes les pages sauf la première",
"Next to current widget": "À côté du widget actuel"
},
"options": "Possibilités",
"minimun-check": "Vérification minimale",
"maximum-check": "Contrôle maximum",
"default-value": "Valeur par défaut",
"select": "Sélectionner",
"read-only": "Est en lecture seule",
"hide-labels": "Masquer les étiquettes",
"checkbox": "Case à cocher",
"alert": "Alerte",
"zoom-in": "Agrandir",
"zoom-out": "Dézoomer",
"document-signed-alert": "Félicitations ! 🎉 Votre document à bien été signer!",
"otp-sent-alert": "Le code OTP a bien été envoyer sur votre adresse Email",
"fields-required": "Champs obligatoires",
"signature-widget-alert-1": "Veuillez vous assurer qu'au moins un widget de signature a été ajouté",
"signature-widget-alert-2": "Veuillez vous assurer que tous les champs sont remplis avec précision et répondent à toutes les exigences.",
"encrypted-pdf-alert": "Les fichiers PDF actuellement cryptés ne sont pas pris en charge.",
"encrypted-pdf-alert-1": "Le mot de passe du fichier PFX n'est pas valide.",
"user-not-exist": "L'utilisateur n'existe pas",
"template-signature-field": "Veuillez ajouter au moins un champ de signature pour tous les rôles.",
"template-role-alert": "Veuillez d'abord ajouter des rôles",
"create-document": "Créer un document",
"template-created-alert": "Voulez-vous créer un document en utilisant le modèle que vous vient de créer ?",
"signers-alert": "alerte des signataires",
"template-creation-alert-1": "Veuillez sélectionner le signataire pour ajouter un espace réservé !",
"ok": "D'accord",
"radio-group": "Groupe de radio",
"dropdown-options": "Options déroulantes",
"add-role": "Ajouter un rôle",
"role-ex": "Ex : Client, RH, Directeur, Manager, Étudiant, etc.",
"add/choose-signer": "Ajouter/Choisir un signataire",
"choose-from-contacts": "Choisissez parmis les contacts",
"select-signer": "Veuillez sélectionner le signataire",
"edit-template": "Modifier le modèle",
"widget-info": "Informations sur les widgets",
"validation": "Validation",
"invalid-default-value": "valeur par défaut invalide",
"hint": "Indice",
"color": "couleur",
"role-help": {
"p1": "Que sont les rôles modèles ?",
"p2": "Commencez par spécifier chaque rôle nécessaire à la finalisation du document. Pensez aux parties impliquées dans le processus de signature et à leurs responsabilités. Les rôles courants incluent les RH pour les documents internes, le Client pour les accords ou le Fournisseur pour les accords commerciaux.",
"p3": "Pourquoi pré-attacher les utilisateurs à certains rôles ?",
"p4": "Pour les rôles qui impliquent systématiquement la même personne (par exemple, la signature du PDG sur les lettres d'offre des employés), vous pouvez pré-attacher un utilisateur à un rôle dans le modèle. Cette étape est facultative mais recommandée pour des raisons d'efficacité et de cohérence entre les documents.",
"p5": "Quand dois-je spécifier l'utilisateur attaché à chaque rôle ?",
"p6": "Lorsque vous créez un document à partir de votre modèle, vous serez invité à attacher des utilisateurs à chaque rôle défini. Si un rôle est déjà associé à un utilisateur, celui-ci sera pré-rempli, mais vous pourrez le modifier si nécessaire avant d'envoyer le document."
},
"add-recipients": "Ajouter des destinataires",
"loading-mssg": "Cela pourrait prendre du temps",
"send-mail": "Envoyer un mail",
"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 ? ",
"placeholder-alert-4": "Vous avez envoyé avec succès des mails à tous les",
"placeholder-alert-5": "Voulez-vous signer des documents maintenant ?",
"placeholder-alert-6": "Veuillez configurer l'adaptateur de messagerie pour envoyer du courrier !",
"placeholder-alert-7": "Veuillez sélectionner le signataire pour ajouter un espace réservé !",
"email-subject": "Sujet du courriel",
"email-body": "corps de l'e-mail",
"email-placeholder": "Ajouter le corps de l'e-mail",
"reset-to-default": "Réinitialiser aux valeurs par défaut",
"cutomize-email": "Personnaliser l'e-mail",
"upgrade-to-customize-email": "Mise à niveau pour personnaliser l'e-mail",
"sign-url": "Signer l'URL",
"mails-sent": "Mails envoyés avec succès !",
"mail-not-delivered": "Courrier non distribué",
"document-alert": "Alerte document",
"owner-subscription-expired": "L'abonnement du propriétaire a expiré.",
"subscription-expired": "Abonnement expiré",
"alert-message": "Message d'alerte",
"document-decline": "Document-refusé",
"decline-alert-1": "Etes-vous sûr de vouloir refuser ce document ?",
"decline-alert-2": "Vous avez refusé ce document !",
"decline-alert-3": "Vous ne pouvez pas signer ce document car il a été refusé/révoqué.",
"sign here": "Signer ici",
"guest-email-alert": "le code de vérification a été envoyé sur votre e-mail",
"get-otp-alert": "vous recevrez un code de vérification par e-mail",
"user-already-exist": "L'utilisateur existe déjà.",
"server-error": "Erreur interne du serveur !",
"fill-required-details!": "Veuillez remplir les informations requises !",
"sign-up-form": "Formulaire d'inscription",
"sign-up": "S'inscrire",
"folder-already-exist!": "le dossier existe déjà !",
"please-select-position!": "Veuillez sélectionner un poste !",
"default-sign-alert": "Êtes-vous sûr de vouloir vous connecter automatiquement à tous les emplacements demandés ? ",
"Your-Signature": "Votre signature",
"auto-sign-all": "Tout signer automatiquement",
"generating-certificate": "Génération du certificat",
"pdf-download": "Téléchargement PDF",
"generate-certificate-alert": " Votre certificat d'achèvement est en cours de génération. Veuillez patienter quelques instants. Si le téléchargement ne démarre pas sous peu, cliquez à nouveau sur le bouton. ",
"folder-already-exist": "Le dossier existe déjà !",
"folder-created-successfully": "Dossier créé avec succès !",
"fill-folder-name": "Veuillez indiquer le nom du dossier",
"already-exists-this-username": "Un utilisateur existe déjà avec ce nom d'utilisateur !",
"verification-code-sent": "Un e-mail de vérification a été envoyé à votre adresse e-mail !",
"registered-user-successfully": "Utilisateur enregistré avec succès.",
"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 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.",
"password-update-alert-2": "Votre mot de passe actuel est manquant ou incorrect.",
"password-update-alert-3": "Votre mot de passe actuel est manquant ou incorrect.",
"password-update-alert-4": "Votre mot de passe et votre mot de passe de confirmation ne correspondent pas.",
"current-password": "mot de passe actuel",
"new-password": "nouveau mot de passe",
"confirm-password": "Confirmez le mot de passe",
"file-alert-1": "La taille du fichier sélectionné est trop grande. Veuillez sélectionner un fichier inférieur à",
"file-alert-2": "Veuillez sélectionner un fichier.",
"file-alert-3": "Veuillez patienter pendant le téléchargement du document.",
"enter-pdf-password": "Entrez le mot de passe PDF",
"correct-password": "Veuillez fournir un mot de passe correct",
"decrypting-pdf": "Décryptage du pdf, veuillez patienter...",
"invalid-otp": "OTP invalide",
"user-not-found": "Utilisateur non trouvé!",
"enter-otp-alert": "Veuillez saisir OTP !",
"get-verification-code": "Obtenir le code de vérification",
"get-verification-code-2": "Vous recevrez un code de vérification par e-mail",
"enter-verification-code": "Entrez le code de vérification",
"provide-your-details": "Fournissez vos coordonnées",
"provide-email": "Veuillez fournir un e-mail.",
"additional-info": "Information additionnelle",
"signature-saved-alert": "Signature enregistrée avec succès.",
"fill-field": "Veuillez remplir ce champ",
"error-template": "Erreur : modèle introuvable ! ",
"error": "Erreur",
"invalid-document": "Erreur : document invalide !",
"document-not-found": "Document introuvable !",
"document-signed-alert-1": "Vous avez signé le document avec succès. Vous pouvez télécharger ou imprimer une copie du document partiellement signé. Une copie du document signé numériquement sera envoyée au propriétaire par e-mail une fois qu'il sera signé par tous les signataires.",
"encrypted-pdf-not-support": "Les fichiers PDF actuellement cryptés ne sont pas pris en charge. ",
"document-signed-alert-4": "Toutes nos félicitations! 🎉 Ce document a été signé avec succès par tous les participants !",
"document-signed-alert-5": "Ce document a été signé par tous les signataires.",
"document-signed-alert-6": "Ce document a été refusé par un ou plusieurs destinataire(s).",
"document-signed-alert-7": "Ce document n'est plus disponible.",
"document-signed-alert-8": "Le document a déjà été envoyé pour signature.",
"yet-to-sign": "Reste à signer",
"validation-alert-1": "L'entrée ne répond pas aux critères définis par l'expression régulière.",
"account-already-exists": "Le compte existe déjà!",
"choose-password": "Choisissez un mot de passe",
"enter-password": "Entrer le mot de passe",
"sure": "bien sûr",
"subscribed-alert": "Vous êtes déjà abonné au forfait !",
"monthly": "Mensuel",
"yearly-upto": "Annuel (jusqu'à 66 % de réduction)",
"billed-yearly": "Facturé annuellement",
"billed-monthly": "Facturé mensuellement",
"plansubscription-1": "Hébergez-le vous-même gratuitement",
"visit-github": "Visitez Github",
"user-already-exist-name": "Un utilisateur existe déjà avec ce nom d'utilisateur !",
"do-not-access-contact-admin": "Vous n'y avez pas accès, veuillez contacter l'administrateur.",
"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",
"report-not-found": "Rapport introuvable",
"please-wait": "S'il vous plaît, attendez",
"select-foler": "Sélectionner le dossier",
"generated-on": "Généré le",
"text-field": "Champ de texte",
"font-size": "Taille de police",
"widget-status": {
"Required": "Requis",
"Optional": "Facultative"
},
"all-right": "Tous droits réservés",
"version": "version",
"social-media": {
"github": "Github",
"linked-in": "LinkedIn",
"twitter": "Twitter",
"discord": "Discorde"
},
"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 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.",
"opensign-drive-3": "Triez vos documents par date ou par nom à l'aide de ce menu.",
"opensign-drive-4": "Cliquez sur ce menu pour afficher les documents sous forme de liste.",
"opensign-drive-5": "La liste des documents s'affiche selon l'option de tri sélectionnée. Les icônes à côté de chaque document indiquent son état actuel.",
"opensign-drive-6": "Faites un clic droit sur un document pour voir les options telles que Télécharger, Renommer, Déplacer et Supprimer. Cliquez sur le document pour l'ouvrir.",
"opensign-drive-7": "Faites un clic droit sur n'importe quel dossier pour voir les options. Choisissez 'Renommer' pour changer le nom du dossier ou cliquez sur le dossier pour naviguer dans son contenu.",
"pdf-request-file-1": "Liste des signataires qui doivent encore signer le document.",
"pdf-request-file-2": "Cliquez sur l'un des espaces réservés apparaissant sur le document pour signer. Vous verrez alors des options pour dessiner votre signature, la saisir ou télécharger une image.",
"pdf-request-file-3": "Cliquez sur les boutons Précédent, Refuser ou Terminer pour parcourir votre document. Utilisez le menu points de suspension pour des options supplémentaires, notamment le bouton Télécharger.",
"pdf-request-file-4": "Liste des signataires ayant déjà signé le document.",
"pdf-request-file-5": "Vous pouvez cliquer sur 'Signer automatiquement tout' pour signer automatiquement à tous les emplacements que vous êtes censé signer. Assurez-vous de lire correctement le document avant de cliquer sur ce bouton.",
"placeholder-sign-1": "Sélectionnez un destinataire dans cette liste pour ajouter un espace réservé à l'endroit où il est censé signer. L'espace réservé apparaîtra de la même couleur que le nom du destinataire une fois que vous le déposerez sur le document.",
"placeholder-sign-2": "Cliquer sur le bouton 'Ajouter des destinataires' vous permettra d'ajouter plus de signataires.",
"placeholder-sign-3": "Cliquez sur ce bouton pour ajouter plus de destinataires/signataires au document",
"placeholder-sign-4": "Faites glisser ou cliquez sur un champ pour l'ajouter au document.",
"placeholder-sign-5": "La zone de contenu PDF affiche déjà les espaces réservés existants du modèle. Pour votre commodité, ces espaces réservés correspondront à la couleur du nom du destinataire, ce qui les rendra facilement identifiables.",
"placeholder-sign-6": "Cliquer sur 'Envoyer' enregistrera le document. À l'étape suivante, vous pourrez personnaliser les e-mails à envoyer aux destinataires ou copier les liens de signature et les partager vous-même avec les destinataires.",
"report-1": "Cliquez sur le bouton 'Ajouter' pour créer un nouveau modèle. Les modèles sont des documents réutilisables conçus pour générer rapidement de nouveaux documents avec la même structure et différents signataires. Par exemple, un modèle RH pour l'intégration peut avoir des rôles prédéfinis tels que 'Responsable RH' et ' Nouvel employé'. Chaque fois que vous utilisez le modèle, vous pouvez attribuer le rôle 'Nouvel employé' à différents membres du personnel entrants, tandis que le rôle 'Responsable RH' reste constant, facilitant ainsi un processus d'intégration fluide pour chaque recrue",
"redirect": "Cliquez sur le bouton 'Utiliser' pour créer un nouveau document à partir d'un modèle existant.",
"bulksend": "Pour créer et envoyer rapidement plusieurs documents à l'aide d'un modèle existant, cliquez sur le bouton 'Envoi rapide'.",
"option": "Ce menu révèle plus d'options telles que Modifier et Supprimer. Utilisez le bouton « Modifier » pour ajouter des rôles de signataire, modifier les champs et mettre à jour votre modèle. Les modifications s'appliqueront à tous les futurs documents créés à partir de ce modèle mais n'affecteront pas les documents existants. Utilisez le bouton Supprimer, vous pouvez supprimer le modèle ",
"signyour-self-1": "Sélectionnez et faites glisser vos widgets préférés sur le PDF pour personnaliser votre document avant de le signer. Choisissez les endroits parfaits pour chaque modification afin d'adapter le document à vos besoins.",
"signyour-self-2": "Faites glisser et déposer n'importe où dans cette zone. Vous pourrez la redimensionner et la déplacer plus tard.",
"template-placeholder-1": "Cliquer sur le bouton 'Ajouter un rôle' vous permettra d'ajouter différents rôles de signataire. Vous pourrez attacher des utilisateurs à chaque rôle dans les étapes suivantes.",
"template-placeholder-2": "Une fois les rôles ajoutés, sélectionnez un rôle dans la liste pour ajouter un espace réservé à l'endroit où il est censé signer. L'espace réservé apparaîtra dans la même couleur que le nom du rôle une fois que vous l'aurez déposé sur le document.",
"template-placeholder-3": "Faites glisser ou cliquez sur un champ pour l'ajouter au document.",
"template-placeholder-4": "Faites glisser l'espace réservé pour un rôle n'importe où sur le document. N'oubliez pas qu'il apparaîtra dans la même couleur que le nom du destinataire pour une référence facile.",
"template-placeholder-5": "Cliquer sur 'Suivant' stockera le modèle actuel. Après l'enregistrement, vous serez invité à créer un nouveau document à partir de ce modèle si vous le souhaitez.",
"webhook-1": "Mettez à niveau maintenant pour définir le webhook",
"Need your Signature": "En cliquant sur cette carte, vous accéderez à la liste des documents en attente de révision.",
"Out for signatures": "En cliquant sur cette carte, vous accéderez à une liste de documents en attente de signature.",
"Recent signature requests": "Voici une liste de documents qui attendent votre signature.",
"Recently sent for signatures": "Il s'agit d'une liste de documents que vous avez envoyés à d'autres parties pour signature.",
"Drafts": "Il s'agit de documents que vous avez commencés mais que vous n'avez pas finalisés pour envoi.",
"public-template": "Cette vidéo montre comment configurer votre profil public personnalisé, tel que 'https://opensign.me/your-username'. Vous apprendrez également comment personnaliser votre slogan et rendre vos modèles disponibles pour la signature publique."
},
"enter-email-plaholder": "Ajoutez une adresse email et appuyez sur Entrée",
"success-email-alert": "E-mail envoyé avec succès!",
"expired-doc-title": "Document expiré",
"expired-on-mssg": "Ce document a expiré le {{expiredDate}} et n'est plus disponible pour signature.",
"signature-validate-alert": "Veuillez confirmer que vous avez coché au moins {{minRequiredCount}} cases.",
"signature-validate-alert-2": "Assurez-vous que ce champ est rempli avec précision et répond à toutes les exigences.",
"user-name-exist": "le nom d'utilisateur existe déjà",
"remaing-users": "Utilisateurs restants",
"Role": "Rôle",
"additional-users": "Veuillez acheter des utilisateurs supplémentaires.",
"Quantity-of-users": "Quantité d'utilisateurs",
"Price": "Prix",
"Total-price-for-next-time": "Prix total pour la prochaine fois",
"Proceed": "Procéder",
"Select": "sélectionner",
"Add-seats": "Ajouter des sièges",
"format": "format",
"select-date-format": "Sélectionnez un format de date",
"quantity-of-credits":"Quantité de crédits de prime",
"remaining-credits":"Crédits premium disponibles :",
"additional-credits":"Veuillez acheter des crédits premium",
"remaining-credits-help":"Utilisez des crédits premium pour la signature de documents API, l'envoi groupé ou l'intégration d'OpenSign sur votre site Web. Il vous reste {{allowedcredits}} crédits inclus et {{addoncredits}} crédits achetés supplémentaires.",
"quota-err-quicksend": "Quota atteint, vous n'avez pas assez de crédits.",
"buy-credits": "Acheter des crédits premium",
"rotate-right" :"Faire pivoter à droite",
"rotate-left" :"Faire pivoter à gauche",
"rotate-alert-mssg" :"Tous les widgets de cette page seront perdus. Êtes-vous sûr de vouloir continuer ?",
"templateid":"ID de modèle",
"bulk-send-subcription-alert":"Veuillez passer au forfait Professionnel ou Équipe pour utiliser Quicksend.",
"generate-test-token": "Générer jeton de test",
"regenerate-test-token":"Régénérer le jeton de test",
"help-test-token":"Ce jeton peut être utilisé pour tester les API au niveau du point de terminaison https://sandbox.opensignlabs.com/api/v1, vous permettant ainsi d'effectuer un nombre illimité de signatures de documents. Veuillez noter que l'API sandbox signera vos documents avec des certificats auto-signés, qui peuvent ne pas être reconnus comme valides par Adobe. Une fois vos tests terminés, vous pouvez passer à lun de nos forfaits payants pour générer un jeton de production.",
"help-api-token":"Ce jeton peut être utilisé pour accéder aux API de production au point de terminaison {{origin}}/api/v1. Il ne peut être généré que sur l'un de nos forfaits payants.",
"reason" :"Raison",
"decline-by" :"Refusé/révoqué par",
"document-declined":"document refusé",
"public-template-mssg-1" :"Pour intégrer OpenSign dans votre projet React ou Next.js, exécutez simplement la commande suivante :",
"public-template-mssg-2" :"Assurez-vous que npm ou Yarn est configuré dans votre projet. Si vous utilisez Yarn, vous pouvez remplacer npm install par Yarn Add @opensign/react.",
"public-template-mssg-3" :"Besoin de plus de détails ou d'exemples ?",
"public-template-mssg-4": "Visitez le",
"public-template-mssg-5": "npm pour les dernières mises à jour, une documentation détaillée et l'historique des versions.",
"public-template-mssg-6":"Avant de pouvoir utiliser cet extrait de code, vous devez rendre ce modèle public.",
"copy-code":"COPIE",
"copied-code":"COPIÉ",
"Installation":"Installation",
"Usage" :"Usage",
"insufficient-credits":"Crédits de signature insuffisants",
"insufficient-credits-mssg" :"Le propriétaire de ce document ne dispose actuellement pas des crédits OpenSign nécessaires pour que vous puissiez le signer. Veuillez contacter le propriétaire si vous avez besoin de plus de détails.",
"angular-npm-mssg-1" :"Pour intégrer OpenSign dans votre projet Angular, exécutez simplement la commande suivante :",
"quota-mail-info-head":"Limite mensuelle d'e-mails de signatures de demandes",
"quota-mail-info": "Vous pouvez envoyer jusqu'à 15 e-mails de demande de signature chaque mois. Mettez à niveau maintenant pour envoyer directement des demandes de signature illimitées.",
"quota-mail": "Vous avez atteint votre limite de 15 e-mails de demande de signature pour ce mois. Mettez à niveau maintenant pour continuer à envoyer des e-mails directement.",
"quota-mail-tip-tip":"Astuce : Vous pouvez toujours signer un nombre <1>illimité de documents</1> en partageant manuellement les liens de demande de signature.",
"quota-mail-head":"Quota atteint",
"unauthorized-modal":"Vous n'êtes pas autorisé à effectuer cette action, veuillez contacter {{adminEmail}}.",
"sent-this-month":"envoyé ce mois-ci",
"available-seats":"Disponible sièges",
"buy-users":"Acheter plus d'utilisateurs",
"isenable-otp": "Activer la vérification OTP",
"isenable-otp-help": {
"p1": "Souhaitez-vous activer le processus de vérification à l'aide d'un mot de passe à usage unique (OTP)?",
"p2": "La sélection de cette option activera la vérification OTP. Les utilisateurs recevront un code de vérification par e-mail, qu'ils devront saisir pour signer le document.",
"p3": "La sélection de cette option désactivera la vérification OTP, permettant aux utilisateurs de signer le document directement sans étapes supplémentaires.",
"p4": "Veuillez choisir l'option qui correspond le mieux à vos exigences en matière de signature de documents."
},
"advanced-options":"Options avancées",
"hide-advanced-options": "Masquer les options avancées",
"download-files" :"Télécharger des fichiers",
"download-pdf" :"Télécharger le PDF",
"pdf-certificate" :"Télécharger Pdf + Certificat",
"document-logs":"Journaux de documents",
"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 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":"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",
"at-least-one-signature-type": "Au moins un type de signature doit être activé.",
"expect-default-one-signature-type": "Veuillez activer un type de signature supplémentaire en plus de celui par défaut.",
"add-signer-note": "Remarque - Ce contact sera ajouté à votre liste de contacts",
"allowed-signature-types-help": {
"p1": "Cette préférence de signature contrôle les options de signature disponibles pour vos signataires. Seuls les types de signature que vous sélectionnez apparaîtront dans le widget de signature lorsqu'un document est signé. Par exemple, si vous choisissez uniquement l'option 'Draw' dans les préférences, votre signataire ne verra que l'option 'Draw' dans le widget de signature, tandis que les trois autres options ne seront pas disponibles.",
"l1": "Créez une signature manuscrite directement sur l'écran à l'aide de votre doigt ou d'un stylet.",
"l2": "Entrez votre nom et choisissez parmi différents styles de police pour créer une signature.",
"l3": "Téléchargez une version numérique existante de votre signature.",
"l4": "Utilisez un style de signature prédéfini enregistré sous 'Ma signature' dans vos paramètres."
}
}
File diff suppressed because one or more lines are too long
Binary file not shown.
+12 -3
View File
@@ -20,6 +20,7 @@ import SSOVerify from "./pages/SSOVerify";
import Loader from "./primitives/Loader";
import TeamList from "./pages/TeamList";
import UserList from "./pages/UserList";
import { serverUrl_fn } from "./constant/appinfo";
const DebugPdf = lazy(() => import("./pages/DebugPdf"));
const ForgetPassword = lazy(() => import("./pages/ForgetPassword"));
const GuestLogin = lazy(() => import("./pages/GuestLogin"));
@@ -34,6 +35,8 @@ const GenerateToken = lazy(() => import("./pages/GenerateToken"));
const Webhook = lazy(() => import("./pages/Webhook"));
const AddAdmin = lazy(() => import("./pages/AddAdmin"));
const UpdateExistUserAdmin = lazy(() => import("./pages/UpdateExistUserAdmin"));
const DraftTemplate = lazy(() => import("./pages/DraftTemplate"));
const Preferences = lazy(() => import("./pages/Preferences"));
pdfjs.GlobalWorkerOptions.workerSrc = `//unpkg.com/pdfjs-dist@${pdfjs.version}/legacy/build/pdf.worker.min.mjs`;
const AppLoader = () => {
@@ -53,9 +56,7 @@ function App() {
const appId = process.env.REACT_APP_APPID
? process.env.REACT_APP_APPID
: "opensign";
const baseurl = process.env.REACT_APP_SERVERURL
? process.env.REACT_APP_SERVERURL
: window.location.origin + "/api/app";
const baseurl = serverUrl_fn();
try {
localStorage.setItem("baseUrl", `${baseurl}/`);
localStorage.setItem("parseAppId", appId);
@@ -199,8 +200,16 @@ function App() {
</>
)}
<Route path="/users" element={<UserList />} />
<Route
path="/preferences"
element={<LazyPage Page={Preferences} />}
/>
</Route>
<Route path="/sso" element={<SSOVerify />} />
<Route
path="/drafttemplate/:jwttoken"
element={<DraftTemplate />}
/>
<Route path="*" element={<PageNotFound />} />
</Routes>
</BrowserRouter>
+153 -139
View File
@@ -1,8 +1,11 @@
import React, { useState, useEffect } from "react";
import Parse from "parse";
import Loader from "../primitives/Loader";
import { useTranslation } from "react-i18next";
import { emailRegex } from "../constant/const";
const AddSigner = (props) => {
const { t } = useTranslation();
const [name, setName] = useState("");
const [phone, setPhone] = useState("");
const [email, setEmail] = useState("");
@@ -45,139 +48,143 @@ const AddSigner = (props) => {
const handleSubmit = async (e) => {
e.preventDefault();
e.stopPropagation();
setIsLoader(true);
if (localStorage.getItem("TenantId")) {
try {
const user = Parse.User.current();
const query = new Parse.Query("contracts_Contactbook");
query.equalTo("CreatedBy", user);
query.notEqualTo("IsDeleted", true);
query.equalTo("Email", email);
const res = await query.first();
// console.log(res);
if (!res) {
const contactQuery = new Parse.Object("contracts_Contactbook");
contactQuery.set("Name", name);
if (phone) {
contactQuery.set("Phone", phone);
}
contactQuery.set("Email", email);
contactQuery.set("UserRole", "contracts_Guest");
contactQuery.set("TenantId", {
__type: "Pointer",
className: "partners_Tenant",
objectId: localStorage.getItem("TenantId")
});
try {
const _users = Parse.Object.extend("User");
const _user = new _users();
_user.set("name", name);
_user.set("username", email);
_user.set("email", email);
_user.set("password", email);
if (phone) {
_user.set("phone", phone);
}
const user = await _user.save();
if (user) {
const currentUser = Parse.User.current();
contactQuery.set(
"CreatedBy",
Parse.User.createWithoutData(currentUser.id)
);
contactQuery.set("UserId", user);
const acl = new Parse.ACL();
acl.setPublicReadAccess(true);
acl.setPublicWriteAccess(true);
acl.setReadAccess(currentUser.id, true);
acl.setWriteAccess(currentUser.id, true);
contactQuery.setACL(acl);
const res = await contactQuery.save();
const parseData = JSON.parse(JSON.stringify(res));
if (props.details) {
props.details({
value: parseData[props.valueKey],
label: parseData[props.displayKey]
});
}
if (props.closePopup) {
props.closePopup();
}
if (props.handleUserData) {
props.handleUserData(parseData);
}
setIsLoader(false);
// Reset the form fields
setAddYourself(false);
setName("");
setPhone("");
setEmail("");
}
} catch (err) {
console.log("err ", err);
if (err.code === 202) {
const params = { email: email };
const userRes = await Parse.Cloud.run("getUserId", params);
const currentUser = Parse.User.current();
contactQuery.set(
"CreatedBy",
Parse.User.createWithoutData(currentUser.id)
);
contactQuery.set("UserId", {
__type: "Pointer",
className: "_User",
objectId: userRes.id
});
const acl = new Parse.ACL();
acl.setPublicReadAccess(true);
acl.setPublicWriteAccess(true);
acl.setReadAccess(currentUser.id, true);
acl.setWriteAccess(currentUser.id, true);
contactQuery.setACL(acl);
const res = await contactQuery.save();
const parseData = JSON.parse(JSON.stringify(res));
if (props.details) {
props.details({
value: parseData[props.valueKey],
label: parseData[props.displayKey]
});
}
if (props.closePopup) {
props.closePopup();
}
if (props.handleUserData) {
props.handleUserData(parseData);
}
setIsLoader(false);
// Reset the form fields
setAddYourself(false);
setName("");
setPhone("");
setEmail("");
}
}
} else {
alert("Contact already exist!");
setIsLoader(false);
}
} catch (err) {
console.log("err in fetch contact", err);
setIsLoader(false);
alert("something went wrong, please try again later");
}
if (!emailRegex.test(email)) {
alert("Please enter a valid email address.");
} else {
setIsLoader(false);
alert("something went wrong, please try again later");
setIsLoader(true);
if (localStorage.getItem("TenantId")) {
try {
const user = Parse.User.current();
const query = new Parse.Query("contracts_Contactbook");
query.equalTo("CreatedBy", user);
query.notEqualTo("IsDeleted", true);
query.equalTo("Email", email);
const res = await query.first();
// console.log(res);
if (!res) {
const contactQuery = new Parse.Object("contracts_Contactbook");
contactQuery.set("Name", name);
if (phone) {
contactQuery.set("Phone", phone);
}
contactQuery.set("Email", email);
contactQuery.set("UserRole", "contracts_Guest");
contactQuery.set("TenantId", {
__type: "Pointer",
className: "partners_Tenant",
objectId: localStorage.getItem("TenantId")
});
try {
const _users = Parse.Object.extend("User");
const _user = new _users();
_user.set("name", name);
_user.set("username", email);
_user.set("email", email);
_user.set("password", email);
if (phone) {
_user.set("phone", phone);
}
const user = await _user.save();
if (user) {
const currentUser = Parse.User.current();
contactQuery.set(
"CreatedBy",
Parse.User.createWithoutData(currentUser.id)
);
contactQuery.set("UserId", user);
const acl = new Parse.ACL();
acl.setPublicReadAccess(true);
acl.setPublicWriteAccess(true);
acl.setReadAccess(currentUser.id, true);
acl.setWriteAccess(currentUser.id, true);
contactQuery.setACL(acl);
const res = await contactQuery.save();
const parseData = JSON.parse(JSON.stringify(res));
if (props.details) {
props.details({
value: parseData[props.valueKey],
label: parseData[props.displayKey]
});
}
if (props.closePopup) {
props.closePopup();
}
if (props.handleUserData) {
props.handleUserData(parseData);
}
setIsLoader(false);
// Reset the form fields
setAddYourself(false);
setName("");
setPhone("");
setEmail("");
}
} catch (err) {
console.log("err ", err);
if (err.code === 202) {
const params = { email: email };
const userRes = await Parse.Cloud.run("getUserId", params);
const currentUser = Parse.User.current();
contactQuery.set(
"CreatedBy",
Parse.User.createWithoutData(currentUser.id)
);
contactQuery.set("UserId", {
__type: "Pointer",
className: "_User",
objectId: userRes.id
});
const acl = new Parse.ACL();
acl.setPublicReadAccess(true);
acl.setPublicWriteAccess(true);
acl.setReadAccess(currentUser.id, true);
acl.setWriteAccess(currentUser.id, true);
contactQuery.setACL(acl);
const res = await contactQuery.save();
const parseData = JSON.parse(JSON.stringify(res));
if (props.details) {
props.details({
value: parseData[props.valueKey],
label: parseData[props.displayKey]
});
}
if (props.closePopup) {
props.closePopup();
}
if (props.handleUserData) {
props.handleUserData(parseData);
}
setIsLoader(false);
// Reset the form fields
setAddYourself(false);
setName("");
setPhone("");
setEmail("");
}
}
} else {
alert(t("add-signer-alert"));
setIsLoader(false);
}
} catch (err) {
console.log("err in fetch contact", err);
setIsLoader(false);
alert(t("something-went-wrong-mssg"));
}
} else {
setIsLoader(false);
alert(t("something-went-wrong-mssg"));
}
}
};
@@ -204,6 +211,7 @@ const AddSigner = (props) => {
</div>
)}
<div className="w-full mx-auto p-2 text-base-content">
<p className="mb-3">{t("add-signer-note")}</p>
{isUserExist && (
<div className="mb-3 flex items-center">
<input
@@ -214,14 +222,14 @@ const AddSigner = (props) => {
className="op-checkbox op-checkbox-sm"
/>
<label htmlFor="addYourself" className="ml-2 mb-0">
Add Yourself
{t("add-yourself")}
</label>
</div>
)}
<form onSubmit={handleSubmit}>
<div className="mb-3">
<label htmlFor="name" className="block text-xs font-semibold">
Name
{t("name")}
<span className="text-[red] text-[13px]"> *</span>
</label>
<input
@@ -231,27 +239,33 @@ const AddSigner = (props) => {
onChange={(e) => setName(e.target.value)}
required
disabled={addYourself}
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 htmlFor="email" className="block text-xs font-semibold">
Email
{t("email")}
<span className="text-[red] text-[13px]"> *</span>
</label>
<input
type="email"
id="email"
value={email}
onChange={(e) => setEmail(e.target.value?.toLowerCase())}
onChange={(e) =>
setEmail(e.target.value?.toLowerCase()?.replace(/\s/g, ""))
}
required
onInvalid={(e) => e.target.setCustomValidity(t("input-required"))}
onInput={(e) => e.target.setCustomValidity("")}
disabled={addYourself}
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 font-semibold">
Phone
{t("phone")}
</label>
<input
type="text"
@@ -264,14 +278,14 @@ const AddSigner = (props) => {
</div>
<div className="mt-4 flex gap-x-2 justify-start">
<button type="submit" className="op-btn op-btn-primary">
Submit
{t("submit")}
</button>
<button
type="button"
onClick={() => handleReset()}
className="op-btn op-btn-secondary"
>
Reset
{t("reset")}
</button>
</div>
</form>
+10 -6
View File
@@ -2,8 +2,10 @@ import React, { useEffect, useState } from "react";
import Parse from "parse";
import Title from "./Title";
import Loader from "../primitives/Loader";
import { useTranslation } from "react-i18next";
const AddTeam = (props) => {
const { t } = useTranslation();
const [formdata, setFormdata] = useState({
name: "",
team: ""
@@ -125,10 +127,10 @@ const AddTeam = (props) => {
};
return (
<div className="shadow-md rounded-box my-[1px] p-3 bg-[#ffffff]">
<div className="shadow-md rounded-box my-[1px] p-3 bg-base-100 relative">
<Title title="Add Team" />
{isLoader && (
<div className="fixed inset-0 flex justify-center items-center bg-black bg-opacity-30 z-50 rounded-box">
<div className="absolute w-full h-full inset-0 flex justify-center items-center bg-base-content/30 z-50">
<Loader />
</div>
)}
@@ -140,7 +142,7 @@ const AddTeam = (props) => {
htmlFor="name"
className="block text-xs text-gray-700 font-semibold"
>
Name
{t("name")}
<span className="text-[red] text-[13px]"> *</span>
</label>
<input
@@ -148,6 +150,8 @@ const AddTeam = (props) => {
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"
/>
@@ -157,7 +161,7 @@ const AddTeam = (props) => {
htmlFor="phone"
className="block text-xs text-gray-700 font-semibold"
>
Parent Team
{t("report-heading.Parent Team")}
</label>
<select
value={formdata.team}
@@ -175,14 +179,14 @@ const AddTeam = (props) => {
</div>
<div className="flex items-center mt-3 gap-2 text-white">
<button type="submit" className="op-btn op-btn-primary">
Submit
{t("submit")}
</button>
<div
type="button"
onClick={() => handleReset()}
className="op-btn op-btn-secondary"
>
Reset
{t("reset")}
</div>
</div>
</form>
+477 -298
View File
@@ -2,8 +2,9 @@ import React, { useEffect, useState } from "react";
import Parse from "parse";
import Title from "./Title";
import Loader from "../primitives/Loader";
import { copytoData } from "../constant/Utils";
import { isEnableSubscription } from "../constant/const";
import { copytoData, fetchSubscriptionInfo } from "../constant/Utils";
import { emailRegex, isEnableSubscription } from "../constant/const";
import { useTranslation } from "react-i18next";
function generatePassword(length) {
const characters =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
@@ -17,6 +18,7 @@ function generatePassword(length) {
}
const AddUser = (props) => {
const { t } = useTranslation();
const [formdata, setFormdata] = useState({
name: "",
phone: "",
@@ -25,15 +27,64 @@ const AddUser = (props) => {
password: "",
role: ""
});
const [amount, setAmount] = useState({ quantity: 1, price: 0 });
const [planInfo, setPlanInfo] = useState({
priceperUser: 0,
price: 0,
totalAllowedUser: 0,
adminId: ""
});
const [isFormLoader, setIsFormLoader] = useState(false);
const [isLoader, setIsLoader] = useState(false);
const [teamList, setTeamList] = useState([]);
const [allowedUser, setAllowedUser] = useState(0);
const [err, setErr] = useState("");
const role = ["OrgAdmin", "Editor", "User"];
const extUser =
localStorage.getItem("Extand_Class") &&
JSON.parse(localStorage.getItem("Extand_Class"))?.[0];
useEffect(() => {
getTeamList();
// eslint-disable-next-line
}, []);
const getTeamList = async () => {
if (isEnableSubscription) {
try {
setIsLoader(true);
const resSub = await fetchSubscriptionInfo();
if (!resSub.error) {
setPlanInfo((prev) => ({
...prev,
priceperUser: resSub.price,
totalAllowedUser: resSub.totalAllowedUser,
adminId: resSub.adminId
}));
setAmount((prev) => ({ ...prev, price: resSub.price }));
const res = await Parse.Cloud.run("allowedusers");
if (props.setFormHeader) {
if (res > 0) {
props.setFormHeader(t("add-user"));
} else {
props.setFormHeader(
resSub.adminId !== extUser?.objectId
? "Unauthorized"
: t("Add-seats")
);
}
}
setAllowedUser(res);
} else {
setAllowedUser(0);
}
} catch (err) {
setAllowedUser(0);
console.log("Err in alloweduser", err);
setErr(err.message);
} finally {
setIsLoader(false);
}
}
setFormdata((prev) => ({ ...prev, password: generatePassword(12) }));
const teamRes = await Parse.Cloud.run("getteams", { active: true });
if (teamRes.length > 0) {
@@ -64,333 +115,461 @@ const AddUser = (props) => {
const handleSubmit = async (e) => {
e.preventDefault();
e.stopPropagation();
const localUser = JSON.parse(localStorage.getItem("Extand_Class"))?.[0];
setIsLoader(true);
const res = await checkUserExist();
if (res) {
props.setIsAlert({ type: "danger", msg: "User already exist." });
setIsLoader(false);
setTimeout(() => {
props.setIsAlert({ type: "success", msg: "" });
}, 1000);
if (!emailRegex.test(formdata.email)) {
alert("Please enter a valid email address.");
} else {
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 localUser = JSON.parse(localStorage.getItem("Extand_Class"))?.[0];
setIsFormLoader(true);
const res = await checkUserExist();
if (res) {
props.setIsAlert({ type: "danger", msg: t("user-already-exist") });
setIsFormLoader(false);
setTimeout(() => props.setIsAlert({ type: "success", msg: "" }), 1000);
} else {
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);
const extUser = new Parse.Object("contracts_Users");
extUser.set("Name", formdata.name);
if (formdata.phone) {
_user.set("phone", 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);
}
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);
}
setIsLoader(false);
setFormdata({
name: "",
email: "",
phone: "",
team: "",
role: ""
if (localStorage.getItem("TenantId")) {
extUser.set("TenantId", {
__type: "Pointer",
className: "partners_Tenant",
objectId: localStorage.getItem("TenantId")
});
}
try {
const _users = Parse.Object.extend("User");
const _user = new _users();
_user.set("name", 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: ""
});
}
} 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: ""
});
}
}
} 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);
}
setIsLoader(false);
setFormdata({
name: "",
email: "",
phone: "",
team: "",
role: ""
});
}
console.log("err", err);
setIsFormLoader(false);
props.setIsAlert({
type: "danger",
msg: t("something-went-wrong-mssg")
});
} finally {
setTimeout(
() => props.setIsAlert({ type: "success", msg: "" }),
1500
);
}
} catch (err) {
console.log("err", err);
setIsLoader(false);
props.setIsAlert({ type: "danger", msg: "something went wrong." });
} finally {
setTimeout(() => props.setIsAlert({ type: "success", msg: "" }), 1500);
}
}
};
// Define a function to handle the "add yourself" checkbox
const handleReset = () => {
setFormdata({
name: "",
email: "",
phone: "",
team: "",
role: ""
});
setFormdata({ name: "", email: "", phone: "", team: "", role: "" });
if (props.closePopup) {
props.closePopup();
}
};
const handleChange = (e) => {
setFormdata((prev) => ({ ...prev, [e.target.name]: e.target.value }));
const handleChange = (event) => {
let { name, value } = event.target;
if (name === "email") {
value = value?.toLowerCase()?.replace(/\s/g, "");
}
setFormdata((prev) => ({ ...prev, [name]: value }));
};
const copytoclipboard = (text) => {
copytoData(text);
props.setIsAlert({ type: "success", msg: "Copied" });
props.setIsAlert({ type: "success", msg: t("copied") });
setTimeout(() => props.setIsAlert({ type: "success", msg: "" }), 1500); // Reset copied state after 1.5 seconds
};
const handlePricePerUser = (e) => {
const quantity = e.target.value;
const price = e.target?.value > 0 ? planInfo.priceperUser * quantity : 0;
setAmount((prev) => ({ ...prev, quantity: quantity, price: price }));
};
const handleAddOnSubmit = async (e) => {
e.preventDefault();
e.stopPropagation();
setIsFormLoader(true);
try {
const resAddon = await Parse.Cloud.run("buyaddonusers", {
users: amount.quantity
});
if (resAddon) {
const _resAddon = JSON.parse(JSON.stringify(resAddon));
if (_resAddon.status === "success") {
setAllowedUser(amount.quantity);
setPlanInfo((obj) => ({ ...obj, totalAllowedUser: _resAddon.addon }));
}
if (props.handleBuyUsers) {
props.handleBuyUsers(amount.quantity, _resAddon.addon);
}
}
} catch (err) {
console.log("Err in buy addon", err);
props.setIsAlert({ type: "danger", msg: t("something-went-wrong-mssg") });
} finally {
setTimeout(() => props.setIsAlert({ type: "success", msg: "" }), 2000);
setIsFormLoader(false);
}
};
return (
<div className="shadow-md rounded-box my-[1px] p-3 bg-[#ffffff]">
<Title title={"Add User"} />
{isLoader && (
<div className="fixed inset-0 flex justify-center items-center bg-black bg-opacity-30 z-50 rounded-box">
<div className="shadow-md rounded-box my-[1px] p-3 bg-base-100 relative">
<Title title={t("add-user")} />
{isFormLoader && (
<div className="absolute w-full h-full inset-0 flex justify-center items-center bg-base-content/30 z-50">
<Loader />
</div>
)}
<div className="w-full mx-auto">
<form onSubmit={handleSubmit}>
{/* <h1 className="text-[20px] font-semibold mb-4">Add User</h1> */}
<div className="mb-3">
<label
htmlFor="name"
className="block text-xs text-gray-700 font-semibold"
>
Name
<span className="text-[red] text-[13px]"> *</span>
</label>
<input
type="text"
name="name"
value={formdata.name}
onChange={(e) => handleChange(e)}
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"
>
Email
<span className="text-[red] text-[13px]"> *</span>
</label>
<input
type="email"
name="email"
value={formdata.email}
onChange={(e) => handleChange(e)}
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"
>
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>
{!isLoader ? (
<>
{err ? (
<div className="flex justify-center items-center h-[70px] text-[18px]">
{err}
</div>
<div className="text-[12px] ml-2 mb-0 text-[red] select-none">
Password will only be generated once; make sure to copy it.
</div>
</div>
<div className="mb-3">
<label
htmlFor="phone"
className="block text-xs text-gray-700 font-semibold"
>
Phone
{/* <span className="text-[red] text-[13px]"> *</span> */}
</label>
<input
type="text"
name="phone"
placeholder="optional"
value={formdata.phone}
onChange={(e) => handleChange(e)}
// required
className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs"
/>
</div>
{isEnableSubscription && (
<div className="mb-3">
<label
htmlFor="phone"
className="block text-xs text-gray-700 font-semibold"
>
Team<span className="text-[red] text-[13px]"> *</span>
</label>
<select
value={formdata.team}
onChange={(e) => handleChange(e)}
name="team"
className="op-select op-select-bordered op-select-sm focus:outline-none hover:border-base-content w-full text-xs"
required
>
<option defaultValue={""} value={""}>
select
</option>
{teamList.length > 0 &&
teamList.map((x) => (
<option key={x.objectId} value={x.objectId}>
{x.Name}
</option>
))}
</select>
) : (
<div className="w-full mx-auto">
{!isEnableSubscription || allowedUser > 0 ? (
<form onSubmit={handleSubmit}>
{isEnableSubscription && (
<p className="flex justify-center mb-1">
{t("remaing-users")}{" "}
<span
className={`${
allowedUser < 2 ? "op-text-accent" : "op-text-primary"
} font-medium ml-1`}
>
{allowedUser} {t("of")} {planInfo.totalAllowedUser}
</span>
</p>
)}
<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="optional"
value={formdata.phone}
onChange={(e) => handleChange(e)}
// required
className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs"
/>
</div>
{isEnableSubscription && (
<div className="mb-3">
<label
htmlFor="phone"
className="block text-xs text-gray-700 font-semibold"
>
{t("team")}
<span className="text-[red] text-[13px]"> *</span>
</label>
<select
name="team"
value={formdata.team}
onChange={(e) => handleChange(e)}
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>
{teamList.length > 0 &&
teamList.map((x) => (
<option key={x.objectId} value={x.objectId}>
{x.Name}
</option>
))}
</select>
</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>
) : (
<>
{planInfo.adminId !== extUser?.objectId ? (
<div className="mb-3 mt-1 flex justify-center text-center items-center font-medium break-all">
{t("unauthorized-modal", {
adminEmail: extUser?.TenantId?.EmailAddress
})}
</div>
) : (
<form onSubmit={handleAddOnSubmit}>
<p className="flex justify-center text-center mx-2 mb-3 text-base op-text-accent font-medium">
{t("additional-users")}
</p>
<div className="mb-3 flex justify-between">
<label
htmlFor="quantity"
className="block text-xs text-gray-700 font-semibold"
>
{t("Quantity-of-users")}
<span className="text-[red] text-[13px]"> *</span>
</label>
<input
type="number"
name="quantity"
value={amount.quantity}
onChange={(e) => handlePricePerUser(e)}
className="w-1/4 op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content text-xs"
required
/>
</div>
<div className="mb-3 flex justify-between">
<label className="block text-xs text-gray-700 font-semibold">
{t("Price")} (1 * {planInfo.priceperUser})
</label>
<div className="w-1/4 flex justify-center items-center text-sm">
USD {amount.price}
</div>
</div>
<hr className="text-base-content mb-3" />
<button className="op-btn op-btn-primary w-full">
{t("Proceed")}
</button>
</form>
)}
</>
)}
</div>
)}
<div className="mb-3">
<label
htmlFor="phone"
className="block text-xs text-gray-700 font-semibold"
>
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"
required
>
<option defaultValue={""} value={""}>
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">
Submit
</button>
<div
type="button"
onClick={() => handleReset()}
className="op-btn op-btn-secondary"
>
Cancel
</div>
</div>
</form>
</div>
</>
) : (
<div className="w-full h-[200px] inset-0 flex justify-center items-center z-50">
<Loader />
</div>
)}
</div>
);
};
+432 -171
View File
@@ -2,8 +2,15 @@ import React, { useState, useEffect, useRef } from "react";
import axios from "axios";
import SuggestionInput from "./shared/fields/SuggestionInput";
import Loader from "../primitives/Loader";
import { useTranslation } from "react-i18next";
import Parse from "parse";
import ModalUi from "../primitives/ModalUi";
import { emailRegex, isEnableSubscription } from "../constant/const";
import { fetchSubscription } from "../constant/Utils";
import { useNavigate } from "react-router-dom";
const BulkSendUi = (props) => {
const { t } = useTranslation();
const navigate = useNavigate();
const [forms, setForms] = useState([]);
const [formId, setFormId] = useState(2);
const formRef = useRef(null);
@@ -11,6 +18,22 @@ const BulkSendUi = (props) => {
const [isSubmit, setIsSubmit] = useState(false);
const [allowedForm, setAllowedForm] = useState(0);
const [isSignatureExist, setIsSignatureExist] = useState();
const [isBulkAvailable, setIsBulkAvailable] = useState(false);
const quantityList = [500, 1000, 5000, 50000];
const [amount, setAmount] = useState({
price: (75.0).toFixed(2),
quantity: 500,
priceperbulksend: 0.15,
totalcredits: 0
});
const [isQuotaReached, setIsQuotaReached] = useState(false);
const [isLoader, setIsLoader] = useState(false);
const [isFreePlan, setIsFreePlan] = useState(false);
const [admin, setAdmin] = useState({
objectId: "",
email: "",
isAdmin: true
});
const allowedSigners = 50;
useEffect(() => {
signatureExist();
@@ -18,14 +41,85 @@ const BulkSendUi = (props) => {
}, []);
//function to check atleast one signature field exist
const signatureExist = () => {
const getPlaceholder = props.item?.Placeholders;
const checkIsSignatureExistt = getPlaceholder?.every((placeholderObj) =>
placeholderObj?.placeHolder?.some((holder) =>
holder?.pos?.some((posItem) => posItem?.type === "signature")
)
);
setIsSignatureExist(checkIsSignatureExistt);
const signatureExist = async () => {
if (isEnableSubscription) {
setIsLoader(true);
try {
const subscription = await fetchSubscription();
const extUser =
localStorage.getItem("Extand_Class") &&
JSON.parse(localStorage.getItem("Extand_Class"))?.[0];
if (
subscription?.adminId &&
extUser?.objectId === subscription?.adminId
) {
setAdmin((obj) => ({
...obj,
objectId: subscription?.adminId,
isAdmin: true
}));
} else {
setAdmin((obj) => ({
...obj,
isAdmin: false,
email: extUser?.TenantId?.EmailAddress
}));
}
setAdmin((obj) => ({ ...obj, objectId: subscription?.adminId }));
if (subscription?.plan === "freeplan") {
setIsFreePlan(true);
}
const token = props.jwttoken
? { jwttoken: props.jwttoken }
: { "X-Parse-Session-Token": localStorage.getItem("accesstoken") };
const axiosres = await axios.post(
`${localStorage.getItem("baseUrl")}functions/allowedcredits`,
{},
{
headers: {
"Content-Type": "application/json",
"X-Parse-Application-Id": localStorage.getItem("parseAppId"),
...token
}
}
);
const resCredits = axiosres.data && axiosres.data.result;
if (resCredits) {
const allowedcredits = resCredits?.allowedcredits || 0;
const addoncredits = resCredits?.addoncredits || 0;
const totalcredits = allowedcredits + addoncredits;
if (totalcredits > 0) {
if (subscription?.plan !== "freeplan") {
setIsBulkAvailable(true);
}
}
setAmount((obj) => ({ ...obj, totalcredits: totalcredits }));
}
const getPlaceholder = props?.Placeholders;
const checkIsSignatureExistt = getPlaceholder?.every((placeholderObj) =>
placeholderObj?.placeHolder?.some((holder) =>
holder?.pos?.some((posItem) => posItem?.type === "signature")
)
);
setIsSignatureExist(checkIsSignatureExistt);
setIsLoader(false);
} catch (err) {
setIsLoader(false);
alert(t("something-went-wrong-mssg"));
console.log("Err", err);
}
} else {
setIsBulkAvailable(true);
setAdmin((obj) => ({ ...obj, isAdmin: true }));
const getPlaceholder = props?.Placeholders;
const checkIsSignatureExistt = getPlaceholder?.every((placeholderObj) =>
placeholderObj?.placeHolder?.some((holder) =>
holder?.pos?.some((posItem) => posItem?.type === "signature")
)
);
setIsSignatureExist(checkIsSignatureExistt);
setIsLoader(false);
}
};
useEffect(() => {
if (scrollOnNextUpdate && formRef.current) {
@@ -74,29 +168,33 @@ const BulkSendUi = (props) => {
const handleAddForm = (e) => {
e.preventDefault();
// Check if the quick send limit has been reached
if (forms?.length < allowedForm) {
if (props?.Placeholders.length > 0) {
let newForm = [];
props?.Placeholders?.forEach((element) => {
if (!element.signerObjId) {
newForm = [
...newForm,
{
fieldId: element.Id,
email: "",
label: element.Role,
signer: {}
}
];
}
});
setForms([...forms, { Id: formId, fields: newForm }]);
}
setFormId(formId + 1);
setScrollOnNextUpdate(true);
if (isEnableSubscription && forms.length >= amount.totalcredits) {
setIsQuotaReached(true);
} else {
// If the limit has been reached, throw an error with the appropriate message
alert("Quick send reached limit.");
if (forms?.length < allowedForm) {
if (props?.Placeholders.length > 0) {
let newForm = [];
props?.Placeholders?.forEach((element) => {
if (!element.signerObjId) {
newForm = [
...newForm,
{
fieldId: element.Id,
email: "",
label: element.Role,
signer: {}
}
];
}
});
setForms([...forms, { Id: formId, fields: newForm }]);
}
setFormId(formId + 1);
setScrollOnNextUpdate(true);
} else {
// If the limit has been reached, throw an error with the appropriate message
alert(t("quick-send-alert-4"));
}
}
};
@@ -104,83 +202,101 @@ const BulkSendUi = (props) => {
const updatedForms = forms.filter((_, i) => i !== index);
setForms(updatedForms);
};
function validateEmails(data) {
for (const item of data) {
for (const field of item.fields) {
if (!emailRegex.test(field.email)) {
alert(`Invalid email found: ${field.email}`);
return false;
}
}
}
return true;
}
const handleSubmit = async (e) => {
e.preventDefault();
e.stopPropagation();
setIsSubmit(true);
// Create a copy of Placeholders array from props.item
let Placeholders = [...props.item.Placeholders];
// Initialize an empty array to store updated documents
let Documents = [];
// Loop through each form
forms.forEach((form) => {
//checking if user enter email which already exist as a signer then add user in a signers array
let existSigner = [];
form.fields.map((data) => {
if (data.signer) {
existSigner.push(data.signer);
}
});
// Map through the copied Placeholders array to update email values
const updatedPlaceholders = Placeholders.map((placeholder) => {
// Find the field in the current form that matches the placeholder Id
const field = form.fields.find(
(element) => parseInt(element.fieldId) === placeholder.Id
);
// If a matching field is found, update the email value in the placeholder
const signer = field?.signer?.objectId ? field.signer : "";
if (field) {
if (signer) {
return {
...placeholder,
signerObjId: field?.signer?.objectId || "",
signerPtr: signer
};
} else {
return {
...placeholder,
email: field.email,
signerObjId: field?.signer?.objectId || "",
signerPtr: signer
};
if (validateEmails(forms)) {
// Create a copy of Placeholders array from props.item
let Placeholders = [...props.Placeholders];
// Initialize an empty array to store updated documents
let Documents = [];
// Loop through each form
forms.forEach((form) => {
//checking if user enter email which already exist as a signer then add user in a signers array
let existSigner = [];
form.fields.map((data) => {
if (data.signer) {
existSigner.push(data.signer);
}
}
// If no matching field is found, keep the placeholder as is
return placeholder;
});
});
// Map through the copied Placeholders array to update email values
const updatedPlaceholders = Placeholders.map((placeholder) => {
// Find the field in the current form that matches the placeholder Id
const field = form.fields.find(
(element) => parseInt(element.fieldId) === placeholder.Id
);
// If a matching field is found, update the email value in the placeholder
const signer = field?.signer?.objectId ? field.signer : "";
if (field) {
if (signer) {
return {
...placeholder,
signerObjId: field?.signer?.objectId || "",
signerPtr: signer
};
} else {
return {
...placeholder,
email: field.email,
signerObjId: field?.signer?.objectId || "",
signerPtr: signer
};
}
}
// If no matching field is found, keep the placeholder as is
return placeholder;
});
// Push a new document object with updated Placeholders into the Documents array
if (existSigner?.length > 0) {
Documents.push({
...props.item,
Placeholders: updatedPlaceholders,
Signers: props.item.Signers
? [...props.item.Signers, ...existSigner]
: [...existSigner]
});
} else {
Documents.push({
...props.item,
Placeholders: updatedPlaceholders
});
}
});
//console.log("Documents ", Documents);
await batchQuery(Documents);
// Push a new document object with updated Placeholders into the Documents array
if (existSigner?.length > 0) {
Documents.push({
...props.item,
Placeholders: updatedPlaceholders,
Signers: props.item.Signers
? [...props.item.Signers, ...existSigner]
: [...existSigner]
});
} else {
Documents.push({
...props.item,
Placeholders: updatedPlaceholders,
SignatureType: props.signatureType
});
}
});
await batchQuery(Documents);
} else {
setIsSubmit(false);
}
};
const batchQuery = async (Documents) => {
const serverUrl = localStorage.getItem("baseUrl");
const functionsUrl = `${serverUrl}functions/batchdocuments`;
const token = props.jwttoken
? { jwttoken: props.jwttoken }
: { "X-Parse-Session-Token": localStorage.getItem("accesstoken") };
const functionsUrl = `${localStorage.getItem(
"baseUrl"
)}functions/batchdocuments`;
const headers = {
"Content-Type": "application/json",
"X-Parse-Application-Id": localStorage.getItem("parseAppId"),
sessionToken: localStorage.getItem("accesstoken")
};
const params = {
Documents: JSON.stringify(Documents)
...token
};
const params = { Documents: JSON.stringify(Documents) };
try {
const res = await axios.post(functionsUrl, params, { headers: headers });
// console.log("res ", res);
@@ -194,87 +310,232 @@ const BulkSendUi = (props) => {
setIsSubmit(false);
}
};
const handleAddOnQuickSubmit = async (e) => {
e.preventDefault();
e.stopPropagation();
setIsSubmit(true);
try {
const resAddon = await Parse.Cloud.run("buycredits", {
credits: amount.quantity
});
if (resAddon) {
const _resAddon = JSON.parse(JSON.stringify(resAddon));
if (_resAddon.status === "success") {
setIsBulkAvailable(true);
handleCloseQuotaReached();
setAmount((obj) => ({
...obj,
quantity: 500,
priceperbulksend: 0.15,
price: (75.0).toFixed(2),
totalcredits: obj?.totalcredits + _resAddon.addon
}));
}
}
} catch (err) {
console.log("Err in buy addon", err);
alert(t("something-went-wrong-mssg"));
} finally {
setIsSubmit(false);
}
};
const handlePricePerQuick = async (e) => {
const quantity = e.target?.value;
const price =
quantity > 0
? (Math.round(quantity * amount.priceperbulksend * 100) / 100).toFixed(
2
)
: 500 * amount.priceperbulksend;
setAmount((prev) => ({ ...prev, quantity: quantity, price: price }));
};
const handleCloseQuotaReached = () => {
setIsQuotaReached(false);
};
const handleNavigation = () => {
navigate("/subscription");
};
return (
<>
{isSubmit && (
<div className="absolute z-[999] h-full w-full flex justify-center items-center bg-black bg-opacity-30">
{isLoader ? (
<div className="w-full h-[100px] flex justify-center items-center z-[999]">
<Loader />
</div>
)}
{props.Placeholders?.length > 0 ? (
isSignatureExist ? (
<>
{props.Placeholders?.some((x) => !x.signerObjId) ? (
<form onSubmit={handleSubmit}>
<div className="min-h-max max-h-[250px] overflow-y-auto">
{forms?.map((form, index) => (
<div
key={form.Id}
className="p-3 op-card border-[1px] border-gray-400 mt-3 mx-4 mb-4 bg-base-200 text-base-content grid grid-cols-1 md:grid-cols-2 gap-2 relative"
>
{form?.fields?.map((field, fieldIndex) => (
<div className="flex flex-col" key={field.fieldId}>
<label>{field.label}</label>
<SuggestionInput
required
type="email"
value={field.value}
index={fieldIndex}
onChange={(signer) =>
handleInputChange(index, signer, fieldIndex)
}
/>
</div>
))}
{forms?.length > 1 && (
<button
onClick={() => handleRemoveForm(index)}
className="absolute right-3 top-1 text-[red] border-[1px] border-[red] rounded-lg w-[1.7rem] h-[1.7rem]"
>
<i className="fa-light fa-trash"></i>
</button>
)}
<div ref={formRef}></div>
</div>
))}
</div>
<div className="flex flex-col mx-4 mb-4 gap-3">
<button
onClick={handleAddForm}
className="op-btn op-btn-primary focus:outline-none"
>
<i className="fa-light fa-plus"></i> <span>Add new</span>
</button>
<button
type="submit"
className="op-btn op-btn-secondary focus:outline-none"
>
<i className="fa-light fa-paper-plane"></i>{" "}
<span>Send</span>
</button>
</div>
</form>
) : (
<div className="text-black p-3 bg-white w-full text-sm md:text-base flex justify-center items-center">
All roles in this document are currently linked to contacts. To
&apos;quick send&apos; copies of this template to multiple
signers, please ensure that at least one role is not linked to
any contact.
</div>
)}
</>
) : (
<div className="text-black p-3 bg-white w-full text-sm md:text-base flex justify-center items-center">
Please ensure there&#39;s at least one signature widget added for
all recipients.
</div>
)
) : (
<div className="text-black p-3 bg-white w-full text-sm md:text-base flex justify-center items-center">
Please add at least one role to this template in order to &apos;quick
send&apos; copies of it to multiple signers.
</div>
<>
{isSubmit && (
<div className="absolute z-[999] h-full w-full flex justify-center items-center bg-black bg-opacity-30">
<Loader />
</div>
)}
{isBulkAvailable ? (
<>
{props.Placeholders?.length > 0 ? (
isSignatureExist ? (
<>
{props.Placeholders?.some((x) => !x.signerObjId) ? (
<div>
<form onSubmit={handleSubmit}>
<div className="min-h-max max-h-[250px] overflow-y-auto">
{forms?.map((form, index) => (
<div
key={form.Id}
className="p-3 op-card border-[1px] border-gray-400 mt-3 mx-4 mb-4 bg-base-200 text-base-content grid grid-cols-1 md:grid-cols-2 gap-2 relative"
>
{form?.fields?.map((field, fieldIndex) => (
<div
className="flex flex-col"
key={field.fieldId}
>
<label>{field.label}</label>
<SuggestionInput
required
type="email"
value={field.value}
index={fieldIndex}
onChange={(signer) =>
handleInputChange(
index,
signer,
fieldIndex
)
}
jwttoken={props?.jwttoken}
/>
</div>
))}
{forms?.length > 1 && (
<button
onClick={() => handleRemoveForm(index)}
className="absolute right-3 top-1 text-[red] border-[1px] border-[red] rounded-lg w-[1.7rem] h-[1.7rem]"
>
<i className="fa-light fa-trash"></i>
</button>
)}
<div ref={formRef}></div>
</div>
))}
</div>
<div className="flex flex-col mx-4 mb-4 gap-3">
{isEnableSubscription && (
<button
onClick={handleAddForm}
className="op-btn op-btn-primary focus:outline-none"
>
<i className="fa-light fa-plus"></i>{" "}
<span>{t("add-new")}</span>
</button>
)}
<button
type="submit"
className="op-btn op-btn-accent focus:outline-none"
>
<i className="fa-light fa-paper-plane"></i>{" "}
<span>{t("send")}</span>
</button>
</div>
</form>
<ModalUi
isOpen={isQuotaReached}
handleClose={() => handleCloseQuotaReached()}
>
<div className="p-4 flex justify-center items-center flex-col gap-y-3">
<p className="text-center text-base-content">
{t("quota-err-quicksend")}
</p>
<button
onClick={() => setIsBulkAvailable(false)}
className=" op-btn op-btn-primary w-[200px]"
>
{t("buy-credits")}
</button>
</div>
</ModalUi>
</div>
) : (
<div className="text-black p-3 bg-white w-full text-sm md:text-base flex justify-center items-center">
{t("quick-send-alert-1")}
</div>
)}
</>
) : (
<div className="text-black p-3 bg-white w-full text-sm md:text-base flex justify-center items-center">
{t("quick-send-alert-2")}
</div>
)
) : (
<div className="text-black p-3 bg-white w-full text-sm md:text-base flex justify-center items-center">
{t("quick-send-alert-3")}
</div>
)}
</>
) : (
<>
{isFreePlan ? (
<div className="w-full h-[130px] flex flex-col justify-center items-center text-center p-4">
<p className="text-base font-medium mb-2.5">
{t("bulk-send-subcription-alert")}
</p>
<button
onClick={() => handleNavigation()}
className="op-btn op-btn-primary"
>
{t("upgrade-now")}
</button>
</div>
) : (
<>
{admin?.isAdmin ? (
<form onSubmit={handleAddOnQuickSubmit} className="p-3">
<p className="flex justify-center text-center mx-2 mb-3 text-base op-text-accent font-medium">
{t("additional-credits")}
</p>
<div className="mb-3 flex justify-between">
<label
htmlFor="quantity"
className="block text-xs text-gray-700 font-semibold"
>
{t("quantity-of-credits")}
<span className="text-[red] text-[13px]">*</span>
</label>
<select
value={amount.quantity}
onChange={(e) => handlePricePerQuick(e)}
name="quantity"
className="op-select op-select-bordered op-select-sm focus:outline-none hover:border-base-content w-1/4 text-xs"
required
>
{quantityList.length > 0 &&
quantityList.map((x) => (
<option key={x} value={x}>
{x}
</option>
))}
</select>
</div>
<div className="mb-3 flex justify-between">
<label className="block text-xs text-gray-700 font-semibold">
{t("Price")} (1 * {amount.priceperbulksend})
</label>
<div className="w-1/4 flex justify-center items-center text-sm">
USD {amount.price}
</div>
</div>
<hr className="text-base-content mb-3" />
<button className="op-btn op-btn-primary w-full mt-2">
{t("Proceed")}
</button>
</form>
) : (
<div className="mx-8 mt-4 mb-8 flex justify-center text-center items-center font-medium break-all">
{t("unauthorized-modal", { adminEmail: admin?.email })}
</div>
)}
</>
)}
</>
)}
</>
)}
</>
);
+5 -2
View File
@@ -2,7 +2,9 @@ import React, { useEffect, useState } from "react";
import Package from "../../package.json";
import axios from "axios";
import { openInNewTab } from "../constant/Utils";
import { useTranslation } from "react-i18next";
const Footer = () => {
const { t } = useTranslation();
const [showButton, setShowButton] = useState(false);
const [version, setVersion] = useState("");
useEffect(() => {
@@ -48,9 +50,10 @@ const Footer = () => {
<footer className="op-footer op-footer-center py-3 bg-base-300 text-base-content text-center text-[13px]">
<aside>
<p>
All Rights Reserved &copy; {new Date().getFullYear()} &nbsp;
{t("all-right")} &copy; {new Date().getFullYear()} &nbsp;
<span onClick={openUrl} className="hover:underline cursor-pointer">
{appName} ( version: {version ? version : `${Package.version} `})
{appName} ( {t("version")}:{" "}
{version ? version : `${Package.version} `})
</span>
</p>
</aside>
+206 -128
View File
@@ -6,27 +6,42 @@ import Parse from "parse";
import { useWindowSize } from "../hook/useWindowSize";
import {
checkIsSubscribed,
checkIsSubscribedTeam,
getAppLogo,
openInNewTab
openInNewTab,
saveLanguageInLocal
} from "../constant/Utils";
import { isEnableSubscription, isStaging } from "../constant/const";
import { validplan } from "../json/plansArr";
import { useTranslation } from "react-i18next";
import ModalUi from "../primitives/ModalUi";
import QuotaCard from "../primitives/QuotaCard";
const Header = ({ showSidebar }) => {
const Header = ({ showSidebar, setIsMenu }) => {
const { t, i18n } = useTranslation();
const navigate = useNavigate();
const { width } = useWindowSize();
let username = localStorage.getItem("username");
const current_notification_version = "1"; // Update this with each new feature release
// Get the dismissed version from local storage
const dismissedVersion = localStorage.getItem("notificationDismissedVersion");
const username = localStorage.getItem("username") || "";
const image = localStorage.getItem("profileImg") || dp;
const [isOpen, setIsOpen] = useState(false);
const [isSubscribe, setIsSubscribe] = useState(true);
const [isPro, setIsPro] = useState(false);
const [isTeam, setIsTeam] = useState(false);
const [isTeam, setIsTeam] = useState({ plan: "", isValid: false });
const [applogo, setAppLogo] = useState(
localStorage.getItem("appLogo") || " "
);
const [emailUsed, setEmailUsed] = useState(0);
const [isModal, setIsModal] = useState(false);
const [showNotification, setShowNotification] = useState(
(!dismissedVersion || dismissedVersion !== current_notification_version) &&
true
);
const toggleDropdown = () => {
setIsOpen(!isOpen);
if (width <= 768) {
setIsMenu(false);
}
};
useEffect(() => {
checkSubscription();
@@ -34,9 +49,8 @@ const Header = ({ showSidebar }) => {
}, []);
async function checkSubscription() {
if (isEnableSubscription) {
const getIsSubscribe = await checkIsSubscribed();
const getIsTeam = await checkIsSubscribedTeam();
if (getIsSubscribe) {
const subscribe = await checkIsSubscribed();
if (subscribe.isValid) {
const applogo = await getAppLogo();
if (applogo?.logo) {
setAppLogo(applogo?.logo);
@@ -44,20 +58,31 @@ const Header = ({ showSidebar }) => {
setAppLogo(localStorage.getItem("appLogo") || "");
}
}
setIsPro(getIsSubscribe);
setIsTeam(getIsTeam);
setIsSubscribe(getIsSubscribe);
setIsTeam(subscribe);
setIsSubscribe(subscribe.isValid);
try {
const extUser = await Parse.Cloud.run("getUserDetails");
const MonthlyFreeEmails = extUser?.get("MonthlyFreeEmails") || 0;
setEmailUsed(MonthlyFreeEmails);
} catch (err) {
console.log("err in while fetching monthlyfreeEmails", err);
}
} else {
const applogo = await getAppLogo();
if (applogo?.logo) {
setAppLogo(applogo?.logo);
} else {
setAppLogo(localStorage.getItem("appLogo") || "");
}
}
}
const closeDropdown = () => {
const closeDropdown = async () => {
setIsOpen(false);
if (Parse?.User?.current()) {
try {
Parse.User.logOut();
} catch (err) {
console.log("Err", err);
}
try {
await Parse.User.logOut();
} catch (err) {
console.log("Err while logging out", err);
}
let appdata = localStorage.getItem("userSettings");
let applogo = localStorage.getItem("appLogo");
@@ -67,7 +92,7 @@ const Header = ({ showSidebar }) => {
let appid = localStorage.getItem("parseAppId");
localStorage.clear();
saveLanguageInLocal(i18n);
localStorage.setItem("appLogo", applogo);
localStorage.setItem("defaultmenuid", defaultmenuid);
localStorage.setItem("PageLanding", PageLanding);
@@ -100,128 +125,181 @@ const Header = ({ showSidebar }) => {
window.open("https://console.opensignlabs.com/");
}
};
const handleNavigation = () => {
navigate("/subscription");
};
const handleMailUsed = () => {
setIsModal(!isModal);
};
// Handle dismissing the notification
const dismissNotification = () => {
// Store the current version as dismissed in local storage
localStorage.setItem(
"notificationDismissedVersion",
current_notification_version
);
setShowNotification(false);
};
const handleSetupNowNavigation = () => {
const url = isStaging
? "https://staging-console.opensignlabs.com/fileadapter"
: "https://console.opensignlabs.com/fileadapter";
openInNewTab(url);
};
return (
<div className="op-navbar bg-base-100 shadow">
<div className="flex-none">
<button
className="op-btn op-btn-square op-btn-ghost focus:outline-none hover:bg-transparent op-btn-sm no-animation"
onClick={showSidebar}
>
<i className="fa-light fa-bars text-xl text-base-content"></i>
</button>
</div>
<div className="flex-1 ml-2">
<div className="h-[25px] md:h-[40px] w-auto overflow-hidden">
<img
className="object-contain h-full w-auto"
src={applogo}
alt="img"
/>
</div>
</div>
<div id="profile-menu" className="flex-none gap-2">
{!isSubscribe && (
<div>
<button
className="text-xs md:text-sm shadow op-btn op-btn-outline op-btn-sm md:op-btn-md op-btn-accent"
onClick={() => navigate("/subscription")}
<div>
{isEnableSubscription && showNotification && (
<div className="flex justify-between items-center shadow py-1 bg-[#CAE4FA] p-1">
<div className="text-center text-[14px] ml-auto">
{t("header-news")}
<span
className="cursor-pointer font-medium underline text-blue-800"
onClick={() => handleSetupNowNavigation()}
>
Upgrade Now
</button>
{" " + t("header-news-btn") + "."}
</span>
</div>
)}
{!isTeam && isPro && (
<div className="w-[35px] h-[35px] bg-white rounded-full ring-[1px] ring-offset-2 ring-[#002862] text-[#002862] overflow-hidden font-semibold flex items-center justify-center">
PRO
</div>
)}
{isTeam && (
<div className="w-[35px] h-[35px] bg-white rounded-full ring-[1px] text-[13px] ring-offset-2 ring-[#002862] text-[#002862] overflow-hidden font-semibold flex items-center justify-center">
TEAM
</div>
)}
<div>
<FullScreenButton />
</div>
{width >= 768 && (
<div
onClick={toggleDropdown}
className="cursor-pointer w-[35px] h-[35px] rounded-full ring-[1px] ring-offset-2 ring-gray-400 overflow-hidden"
className="ml-auto mr-1 cursor-pointer"
onClick={() => dismissNotification()}
>
<i className="fa-light fa-xmark"></i>
</div>
</div>
)}
<div className="op-navbar bg-base-100 shadow">
<div className="flex-none">
<button
className="op-btn op-btn-square op-btn-ghost focus:outline-none hover:bg-transparent op-btn-sm no-animation"
onClick={showSidebar}
>
<i className="fa-light fa-bars text-xl text-base-content"></i>
</button>
</div>
<div className="flex-1 ml-2">
<div className="h-[25px] md:h-[40px] w-auto overflow-hidden">
<img
className="w-[35px] h-[35px] object-contain"
src={image}
className="object-contain h-full w-auto"
src={applogo}
alt="img"
/>
</div>
)}
{width >= 768 && (
<div
onClick={toggleDropdown}
className="cursor-pointer text-base-content text-sm"
>
{username && username}
</div>
<div id="profile-menu" className="flex-none gap-2">
{!isSubscribe && (
<div>
<button
className="text-xs md:text-sm shadow op-btn op-btn-outline op-btn-sm md:op-btn-md op-btn-accent"
onClick={() => handleNavigation()}
>
{t("upgrade-now")}
</button>
</div>
)}
{isTeam.isValid && !validplan[isTeam.plan] && (
<div className="w-[35px] h-[35px] bg-white rounded-full ring-[1px] ring-offset-2 ring-[#002862] text-[#002862] overflow-hidden font-semibold flex items-center justify-center">
{t("pro")}
</div>
)}
{validplan[isTeam.plan] && (
<div className="w-[35px] h-[35px] bg-white rounded-full ring-[1px] text-[13px] ring-offset-2 ring-[#002862] text-[#002862] overflow-hidden font-semibold flex items-center justify-center">
{t("team")}
</div>
)}
<div>
<FullScreenButton />
</div>
)}
<div className="op-dropdown op-dropdown-end" id="profile-menu">
<div
tabIndex={0}
role="button"
className="op-btn op-btn-ghost op-btn-xs w-[10px] h-[20px] hover:bg-transparent"
>
<i
{width >= 768 && (
<div
onClick={toggleDropdown}
className="cursor-pointer w-[35px] h-[35px] rounded-full ring-[1px] ring-offset-2 ring-gray-400 overflow-hidden"
>
<img
className="w-[35px] h-[35px] object-contain"
src={image}
alt="img"
/>
</div>
)}
{width >= 768 && (
<div
onClick={toggleDropdown}
className="cursor-pointer text-base-content text-sm"
>
{username && username}
</div>
)}
<div className="op-dropdown op-dropdown-end" id="profile-menu">
<div
tabIndex={0}
role="button"
onClick={toggleDropdown}
className="fa-light fa-angle-down text-base-content"
></i>
className="op-btn op-btn-ghost op-btn-xs w-[10px] h-[20px] hover:bg-transparent"
>
<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-menu op-menu-sm op-dropdown-content text-base-content bg-base-100 rounded-box w-52"
>
<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>
{isEnableSubscription && (
<li onClick={() => handleConsoleRedirect()}>
<span>
<i className="fa-light fa-id-card"></i> Console
</span>
</li>
)}
{isEnableSubscription && isTeam?.plan === "freeplan" && (
<li className="cursor-pointer" onClick={handleMailUsed}>
<span>
<i className="fa-light fa-envelope"></i>
{emailUsed}/15 {t("sent-this-month")}
</span>
</li>
)}
<li onClick={closeDropdown}>
<span>
<i className="fa-light fa-arrow-right-from-bracket"></i>{" "}
{t("log-out")}
</span>
</li>
</ul>
</div>
<ul
tabIndex={0}
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"
>
<li onClick={() => openInNewTab("https://docs.opensignlabs.com")}>
<span>
<i className="fa-light fa-book"></i> Docs
</span>
</li>
<li
onClick={() => {
setIsOpen(false);
navigate("/profile");
}}
>
<span>
<i className="fa-light fa-user"></i> Profile
</span>
</li>
<li
onClick={() => {
setIsOpen(false);
navigate("/changepassword");
}}
>
<span>
<i className="fa-light fa-lock"></i> Change Password
</span>
</li>
<li
onClick={() => {
handleConsoleRedirect();
}}
>
<span>
<i className="fa-light fa-id-card"></i> Console
</span>
</li>
<li onClick={closeDropdown}>
<span>
<i className="fa-light fa-arrow-right-from-bracket"></i> Log Out
</span>
</li>
</ul>
</div>
</div>
<ModalUi isOpen={isModal}>
<QuotaCard isPaidInfo={true} handlClose={handleMailUsed} />
</ModalUi>
</div>
);
};
+19 -7
View File
@@ -1,6 +1,7 @@
import React, { useState } from "react";
import Parse from "parse";
import Loader from "../primitives/Loader";
import { useTranslation } from "react-i18next";
// import FacebookLogin from "react-facebook-login";
const LoginFacebook = ({
@@ -9,6 +10,7 @@ const LoginFacebook = ({
thirdpartyLoader,
setThirdpartyLoader
}) => {
const { t } = useTranslation();
const [isModal, setIsModal] = useState(false);
const [userDetails, setUserDetails] = useState({
Phone: "",
@@ -106,10 +108,10 @@ const LoginFacebook = ({
alert(userSignUp.message);
}
} else {
alert("Internal server error !");
alert(t("server-error"));
}
} else {
alert("Please fill required details!");
alert(t("fill-required-details!"));
}
};
return (
@@ -136,7 +138,7 @@ const LoginFacebook = ({
<div className="modal-dialog" role="document">
<div className="modal-content">
<div className="modal-header">
<h5 className="modal-title">Sign up form</h5>
<h5 className="modal-title">{t("sign-up-form")}</h5>
<span>
<span></span>
</span>
@@ -145,7 +147,8 @@ const LoginFacebook = ({
<form>
<div className="form-group">
<label htmlFor="Phone" className="col-form-label">
Phone <span className="text-[red] text-[13px]">*</span>
{t("phone")}{" "}
<span className="text-[red] text-[13px]">*</span>
</label>
<input
type="tel"
@@ -158,12 +161,17 @@ const LoginFacebook = ({
Phone: e.target.value
})
}
onInvalid={(e) =>
e.target.setCustomValidity(t("input-required"))
}
onInput={(e) => e.target.setCustomValidity("")}
required
/>
</div>
<div className="form-group">
<label htmlFor="Company" className="col-form-label">
Company <span className="text-[red] text-[13px]">*</span>
{t("company")}{" "}
<span className="text-[red] text-[13px]">*</span>
</label>
<input
type="text"
@@ -176,6 +184,10 @@ const LoginFacebook = ({
Company: e.target.value
})
}
onInvalid={(e) =>
e.target.setCustomValidity(t("input-required"))
}
onInput={(e) => e.target.setCustomValidity("")}
required
/>
</div>
@@ -185,14 +197,14 @@ const LoginFacebook = ({
onClick={() => handleSubmitbtn()}
className="btn btn-info mr-[10px]"
>
Sign up
{t("sign-up")}
</button>
<button
type="button"
className="btn btn-secondary w-[90px]"
onClick={() => setIsModal(false)}
>
Cancel
{t("cancel")}
</button>
</div>
</form>
+33 -30
View File
@@ -4,7 +4,8 @@ import { jwtDecode } from "jwt-decode";
import { useScript } from "../hook/useScript";
import ModalUi from "../primitives/ModalUi";
import Loader from "../primitives/Loader";
import { useTranslation } from "react-i18next";
import { saveLanguageInLocal } from "../constant/Utils";
/*
* `GoogleSignInBtn`as it's name indicates it render google sign in button
* and in this `useScript` in which we have created for generate google sign button
@@ -17,6 +18,7 @@ const GoogleSignInBtn = ({
thirdpartyLoader,
setThirdpartyLoader
}) => {
const { t, i18n } = useTranslation();
const [isModal, setIsModal] = useState(false);
const googleBtn = useRef();
const [userDetails, setUserDetails] = useState({
@@ -45,8 +47,10 @@ const GoogleSignInBtn = ({
});
});
const clearStorage = async () => {
if (Parse.User.current()) {
try {
await Parse.User.logOut();
} catch (err) {
console.log("Err while logging out", err);
}
let baseUrl = localStorage.getItem("baseUrl");
let appid = localStorage.getItem("parseAppId");
@@ -56,6 +60,7 @@ const GoogleSignInBtn = ({
let userSettings = localStorage.getItem("userSettings");
localStorage.clear();
saveLanguageInLocal(i18n);
localStorage.setItem("baseUrl", baseUrl);
localStorage.setItem("parseAppId", appid);
@@ -74,10 +79,7 @@ const GoogleSignInBtn = ({
const data = jwtDecode(response.credential);
// console.log("data ", data);
if (data.sub && data.email) {
const details = {
Email: data.email,
Name: data.name
};
const details = { Email: data.email, Name: data.name };
setUserDetails({ ...userDetails, ...details });
const Gdetails = {
Id: data.sub,
@@ -91,26 +93,18 @@ const GoogleSignInBtn = ({
}
};
const checkExtUser = async (details) => {
// const extUser = new Parse.Query("contracts_Users");
// extUser.equalTo("Email", details.Gmail);
// const extRes = await extUser.first();
const params = { email: details.Gmail };
const extRes = await Parse.Cloud.run("getUserDetails", params);
// console.log("extRes ", extRes);
if (extRes) {
const params = { ...details, Phone: extRes?.get("Phone") || "" };
// const params = { ...details, Phone: extRes?.get("Phone") || "" };
const params = { ...details, extUserId: extRes.objectId };
const payload = await Parse.Cloud.run("googlesign", params);
// console.log("payload ", payload);
if (payload && payload.sessiontoken) {
// setThirdpartyLoader(true);
// const billingDate =
// extRes.get("Next_billing_date") && extRes.get("Next_billing_date");
// console.log("billingDate expired", billingDate > new Date());
const LocalUserDetails = {
name: details.Name,
email: details.Gmail,
phone: extRes?.get("Phone") || "",
company: extRes.get("Company")
phone: payload?.phone || "",
company: payload.company
};
localStorage.setItem("userDetails", JSON.stringify(LocalUserDetails));
thirdpartyLoginfn(payload.sessiontoken);
@@ -162,16 +156,19 @@ const GoogleSignInBtn = ({
payload &&
payload.message.replace(/ /g, "_") === "Internal_server_err"
) {
alert("Internal server error !");
alert(t("server-error"));
}
} else {
alert("Please fill required details!");
alert(t("fill-required-details!"));
}
};
const handleCloseModal = () => {
const handleCloseModal = async () => {
setIsModal(false);
Parse.User.logOut();
try {
await Parse.User.logOut();
} catch (err) {
console.log("Err while logging out", err);
}
let appdata = localStorage.getItem("userSettings");
let applogo = localStorage.getItem("appLogo");
let defaultmenuid = localStorage.getItem("defaultmenuid");
@@ -180,7 +177,7 @@ const GoogleSignInBtn = ({
let appid = localStorage.getItem("parseAppId");
localStorage.clear();
saveLanguageInLocal(i18n);
localStorage.setItem("appLogo", applogo);
localStorage.setItem("defaultmenuid", defaultmenuid);
localStorage.setItem("PageLanding", PageLanding);
@@ -196,11 +193,11 @@ const GoogleSignInBtn = ({
</div>
)}
<div ref={googleBtn} className="text-sm"></div>
<ModalUi showClose={false} isOpen={isModal} title="Sign up form">
<ModalUi showClose={false} isOpen={isModal} title={t("sign-up-form")}>
<form className="px-4 py-3 text-base-content">
<div className="mb-3">
<label htmlFor="Phone" className="block text-xs font-semibold">
Phone <span className="text-[13px] text-[red]">*</span>
{t("phone")} <span className="text-[13px] text-[red]">*</span>
</label>
<input
type="tel"
@@ -213,12 +210,14 @@ const GoogleSignInBtn = ({
Phone: e.target.value
})
}
onInvalid={(e) => e.target.setCustomValidity(t("input-required"))}
onInput={(e) => e.target.setCustomValidity("")}
required
/>
</div>
<div className="mb-3">
<label htmlFor="Company" className="block text-xs font-semibold">
Company <span className="text-[13px] text-[red]">*</span>
{t("company")} <span className="text-[13px] text-[red]">*</span>
</label>
<input
type="text"
@@ -231,12 +230,14 @@ const GoogleSignInBtn = ({
Company: e.target.value
})
}
onInvalid={(e) => e.target.setCustomValidity(t("input-required"))}
onInput={(e) => e.target.setCustomValidity("")}
required
/>
</div>
<div className="mb-3">
<label htmlFor="JobTitle" className="block text-xs font-semibold">
Job Title <span className="text-[13px] text-[red]">*</span>
{t("job-title")} <span className="text-[13px] text-[red]">*</span>
</label>
<input
type="text"
@@ -249,6 +250,8 @@ const GoogleSignInBtn = ({
Destination: e.target.value
})
}
onInvalid={(e) => e.target.setCustomValidity(t("input-required"))}
onInput={(e) => e.target.setCustomValidity("")}
required
/>
</div>
@@ -258,14 +261,14 @@ const GoogleSignInBtn = ({
className="op-btn op-btn-primary"
onClick={() => handleSubmitbtn()}
>
Sign up
{t("sign-up")}
</button>
<button
type="button"
className="op-btn op-btn-ghost"
onClick={handleCloseModal}
>
Cancel
{t("cancel")}
</button>
</div>
</form>
@@ -0,0 +1,38 @@
import React from "react";
import ModalUi from "../primitives/ModalUi";
import { useTranslation } from "react-i18next";
function RotateAlert(props) {
const { t } = useTranslation();
return (
<ModalUi
isOpen={props.isRotate}
title={t("Rotation-alert")}
handleClose={() => props.setIsRotate({ status: false, degree: 0 })}
>
{" "}
<div className="p-[20px] h-full">
<p>{t("rotate-alert-mssg")}</p>
<div className="h-[1px] w-full my-[15px] bg-[#9f9f9f]"></div>
<div className="flex gap-1">
<button
onClick={() => props.setIsRotate({ status: false, degree: 0 })}
type="button"
className="op-btn op-btn-ghost shadow-md"
>
{t("no")}
</button>
<button
onClick={() => props.handleRemoveWidgets()}
type="button"
className="op-btn op-btn-primary"
>
{t("yes")}
</button>
</div>
</div>
</ModalUi>
);
}
export default RotateAlert;
@@ -1,9 +1,11 @@
import React from "react";
import { useNavigate } from "react-router-dom";
import { openInNewTab } from "../../constant/Utils";
import { useTranslation } from "react-i18next";
const DashboardButton = (props) => {
const navigate = useNavigate();
const { t } = useTranslation();
function openReport() {
if (props.Data && props.Data.Redirect_type) {
@@ -35,7 +37,9 @@ const DashboardButton = (props) => {
} text-[25px] lg:text-[30px]`}
></i>
</span>
<div className=" text-lg ml-3 text-base-content">{props.Label}</div>
<div className=" text-lg ml-3 text-base-content">
{t(`sidebar.${props.Label}`)}
</div>
</div>
</div>
);
@@ -4,9 +4,11 @@ import Parse from "parse";
import getReplacedHashQuery from "../../constant/getReplacedHashQuery";
import { useNavigate } from "react-router-dom";
import Tooltip from "../../primitives/Tooltip";
import { useTranslation } from "react-i18next";
const DashboardCard = (props) => {
const navigate = useNavigate();
const { t } = useTranslation();
const [parseBaseUrl] = useState(localStorage.getItem("baseUrl"));
const [parseAppId] = useState(localStorage.getItem("parseAppId"));
const [response, setresponse] = useState("");
@@ -23,17 +25,12 @@ const DashboardCard = (props) => {
sessionToken: localStorage.getItem("accesstoken")
};
let body = {};
let currentUser;
let currentUser1 = Parse.User.current();
currentUser = currentUser1.id;
let res;
if (localStorage.getItem("Extand_Class")) {
let data = JSON.parse(localStorage.getItem("Extand_Class"));
res = data[0];
} else {
res = await Parse.Cloud.run("getUserDetails", {
email: currentUser.get("email")
});
res = await Parse.Cloud.run("getUserDetails");
if (res) res = res.toJSON();
}
if (res) {
@@ -94,9 +91,7 @@ const DashboardCard = (props) => {
let data = JSON.parse(localStorage.getItem("Extand_Class"));
resr = data[0];
} else {
resr = await Parse.Cloud.run("getUserDetails", {
email: currentUser.get("email")
});
resr = await Parse.Cloud.run("getUserDetails");
if (resr) resr = resr.toJSON();
}
@@ -218,15 +213,12 @@ const DashboardCard = (props) => {
if (restr.includes("#")) {
try {
const currentUser = Parse.User.current();
let res;
if (localStorage.getItem("Extand_Class")) {
let data = JSON.parse(localStorage.getItem("Extand_Class"));
res = data[0];
} else {
let resr = await Parse.Cloud.run("getUserDetails", {
email: currentUser.get("email")
});
let resr = await Parse.Cloud.run("getUserDetails");
if (res) res = resr.toJSON();
}
@@ -321,6 +313,7 @@ const DashboardCard = (props) => {
}
}
}
return (
<div
onClick={() => openReport()}
@@ -338,8 +331,11 @@ const DashboardCard = (props) => {
} text-[25px] lg:text-[30px]`}
></i>
</span>
<div className="font-medium">
<div className="text-base lg:text-lg"> {props.Label}</div>
<div className="text-base lg:text-lg">
{t(`dashboard-card.${props.Label}`)}
</div>
<div className="text-2xl font-light">
{loading ? <div className="loader-01"></div> : setFormat(response)}
</div>
@@ -349,7 +345,8 @@ const DashboardCard = (props) => {
<Tooltip
id={props.Label}
iconColor={"white"}
message={props?.Data?.tourMessage}
message={t(`tour-mssg.${props.Label}`)}
// {props?.Data?.tourMessage}
/>
</div>
</div>
@@ -4,7 +4,9 @@ import ReportTable from "../../primitives/GetReportDisplay";
import reportJson from "../../json/ReportJson";
import axios from "axios";
import Loader from "../../primitives/Loader";
import { useTranslation } from "react-i18next";
function DashboardReport(props) {
const { t } = useTranslation();
// console.log("props ", props)
const [List, setList] = useState([]);
const [isLoader, setIsLoader] = useState(true);
@@ -141,7 +143,7 @@ function DashboardReport(props) {
) : (
<div className="flex items-center justify-center h-[100px] w-full bg-white rounded">
<div className="text-center">
<p className="text-xl text-black">Report Not Found</p>
<p className="text-xl text-black">{t("report-not-found")}</p>
</div>
</div>
)}
@@ -1,4 +1,5 @@
import React, { Suspense, lazy } from "react";
import { useTranslation } from "react-i18next";
const DashboardButton = lazy(() => import("./DashboardButton"));
const DashboardCard = lazy(() => import("./DashboardCard"));
const DashboardReport = lazy(() => import("./DashboardReport"));
@@ -10,13 +11,14 @@ const buttonList = [
icon: "fa-light fa-pen-nib"
},
{
label: "Request signature",
label: "Request signatures",
redirectId: "8mZzFxbG1z",
redirectType: "Form",
icon: "fa-light fa-paper-plane"
}
];
const GetDashboard = (props) => {
const { t } = useTranslation();
const Button = ({ label, redirectId, redirectType, icon }) => (
<DashboardButton
Icon={icon}
@@ -37,7 +39,7 @@ const GetDashboard = (props) => {
<Suspense
fallback={
<div className="h-[150px] w-full flex justify-center items-center">
loading...
{t("loading")}
</div>
}
>
@@ -2,14 +2,16 @@ import React, { useState, useEffect, useRef } from "react";
import "../../styles/opensigndrive.css";
import axios from "axios";
import * as ContextMenu from "@radix-ui/react-context-menu";
import { saveAs } from "file-saver";
import { useNavigate } from "react-router-dom";
import Table from "react-bootstrap/Table";
import * as HoverCard from "@radix-ui/react-hover-card";
import ModalUi from "../../primitives/ModalUi";
import FolderModal from "../shared/fields/FolderModal";
import { useTranslation } from "react-i18next";
import { handleDownloadPdf } from "../../constant/Utils";
function DriveBody(props) {
const { t } = useTranslation();
const [rename, setRename] = useState("");
const [renameValue, setRenameValue] = useState("");
const inputRef = useRef(null);
@@ -42,7 +44,7 @@ function DriveBody(props) {
props.setFolderName((prev) => [...prev, folderData]);
props.setIsLoading({
isLoad: true,
message: "This might take some time"
message: t("loading-mssg")
});
props.setDocId(data.objectId);
props.setPdfData([]);
@@ -90,7 +92,7 @@ function DriveBody(props) {
console.log("Err ", err);
props.setIsAlert({
isShow: true,
alertMessage: "something went wrong"
alertMessage: t("something-went-wrong-mssg")
});
});
}
@@ -98,16 +100,17 @@ function DriveBody(props) {
//function for navigate user to microapp-signature component
const checkPdfStatus = async (data) => {
const signerExist = data.Signers && data.Signers;
const isDecline = data.IsDeclined && data.IsDeclined;
const isPlaceholder = data.Placeholders && data.Placeholders;
const signedUrl = data.SignedUrl;
const signerExist = data?.Signers;
const isDecline = data?.IsDeclined;
const isPlaceholder = data?.Placeholders;
const signedUrl = data?.SignedUrl;
const isSignYourself = data?.IsSignyourself;
//checking if document has completed and request signature flow
if (data?.IsCompleted && signerExist?.length > 0) {
navigate(`/recipientSignPdf/${data.objectId}`);
}
//checking if document has completed and signyour-self flow
else if (!signerExist && !isPlaceholder) {
else if ((!signerExist && !isPlaceholder) || isSignYourself) {
navigate(`/signaturePdf/${data.objectId}`);
}
//checking if document has declined by someone
@@ -134,12 +137,10 @@ function DriveBody(props) {
}
};
const handleMenuItemClick = (selectType, data) => {
const handleMenuItemClick = async (selectType, data) => {
switch (selectType) {
case "Download": {
const pdfName = data && data.Name;
const pdfUrl = data && data.SignedUrl ? data.SignedUrl : data.URL;
saveAs(pdfUrl, `${sanitizeFileName(pdfName)}_signed_by_OpenSign™.pdf`);
await handleDownloadPdf([data]);
break;
}
case "Rename": {
@@ -191,7 +192,7 @@ function DriveBody(props) {
console.log("Err ", err);
props.setIsAlert({
isShow: true,
alertMessage: "something went wrong"
alertMessage: t("something-went-wrong-mssg")
});
});
};
@@ -258,16 +259,10 @@ function DriveBody(props) {
setIsOpenMoveModal(false);
} else {
alert("folder already exist!");
alert(t("folder-already-exist!"));
setIsOpenMoveModal(false);
}
};
const sanitizeFileName = (pdfName) => {
// Replace spaces with underscore
return pdfName.replace(/ /g, "_");
};
const handleEnterPress = (e, data) => {
if (e.key === "Enter") {
handledRenameDoc(data);
@@ -348,14 +343,14 @@ function DriveBody(props) {
</td>
<td>{createddate}</td>
<td>Pdf</td>
<td>{status}</td>
<td>{t(`drive-document-status.${status}`)}</td>
<td>
<i
onClick={(e) => {
e.stopPropagation();
handleMenuItemClick("Download", data);
}}
className="fa-light fa-download mr-[8px] op-text-primary"
className="fa-light fa-download mr-[8px] op-text-primary cursor-pointer"
aria-hidden="true"
></i>
</td>
@@ -368,7 +363,11 @@ function DriveBody(props) {
{/* folder */}
<div
data-tut={props.dataTutSeventh}
onClick={() => handleOnclikFolder(data)}
onClick={() => {
if (!rename) {
handleOnclikFolder(data);
}
}}
className="cursor-pointer"
>
<svg
@@ -381,7 +380,6 @@ function DriveBody(props) {
{rename === data.objectId ? (
<input
onFocus={() => {
inputRef.current.setSelectionRange(0, 0);
const input = inputRef.current;
if (input) {
input.select();
@@ -393,9 +391,8 @@ function DriveBody(props) {
onKeyDown={(e) => handleEnterPress(e, data)}
ref={inputRef}
defaultValue={renameValue}
// value={renameValue}
onChange={(e) => setRenameValue(e.target.value)}
className="w-[100px] border-[1.5px] border-black rounded-sm text-[10px]"
className="op-input op-input-bordered op-input-xs w-[100px] focus:outline-none hover:border-base-content text-[10px]"
/>
) : (
<span className="fileName">{data.Name}</span>
@@ -421,7 +418,11 @@ function DriveBody(props) {
</ContextMenu.Root>
</div>
) : (
<HoverCard.Root openDelay={0} closeDelay={100}>
<HoverCard.Root
open={rename ? false : undefined}
openDelay={0}
closeDelay={100}
>
<HoverCard.Trigger asChild>
<div>
<ContextMenu.Root>
@@ -430,7 +431,11 @@ function DriveBody(props) {
{/* pdf */}
<div
data-tut={props.dataTutSixth}
onClick={() => checkPdfStatus(data)}
onClick={() => {
if (!rename) {
checkPdfStatus(data);
}
}}
className="cursor-pointer"
>
<svg
@@ -445,7 +450,6 @@ function DriveBody(props) {
autoFocus={true}
type="text"
onFocus={() => {
inputRef.current.setSelectionRange(0, 0);
const input = inputRef.current;
if (input) {
input.select();
@@ -455,9 +459,8 @@ function DriveBody(props) {
onKeyDown={(e) => handleEnterPress(e, data)}
ref={inputRef}
defaultValue={renameValue}
// value={renameValue}
onChange={(e) => setRenameValue(e.target.value)}
className="w-[100px] border-[1.5px] border-black rounded-sm text-[10px]"
className="op-input op-input-bordered op-input-xs w-[100px] focus:outline-none hover:border-base-content text-[10px]"
/>
) : (
<span className="fileName">{data.Name}</span>
@@ -503,7 +506,9 @@ function DriveBody(props) {
className="ContextMenuItem"
>
<i className={menu.icon}></i>
<span className="ml-[8px]">{menu.type}</span>
<span className="ml-[8px]">
{t(`context-menu.${menu.type}`)}
</span>
</ContextMenu.Item>
);
})}
@@ -514,18 +519,28 @@ function DriveBody(props) {
</HoverCard.Trigger>
<HoverCard.Portal>
<HoverCard.Content className="HoverCardContent" sideOffset={5}>
<strong className="text-[13px]">Title: </strong>
<strong className="text-[13px]">
{t("report-heading.Title")}:{" "}
</strong>
<span className="text-[12px] font-medium mb-0"> {data.Name}</span>
<br />
<strong className="text-[13px]">Status: </strong>
<span className="text-[12px] font-medium"> {status}</span>
<strong className="text-[13px]">
{t("report-heading.Status")}:{" "}
</strong>
<span className="text-[12px] font-medium">
{t(`drive-document-status.${status}`)}
</span>
<br />
<strong className="text-[13px]">Created Date: </strong>
<strong className="text-[13px]">
{t("report-heading.created-date")}:{" "}
</strong>
<span className="text-[12px] font-medium">{createddate}</span>
<br />
{signerExist && (
<>
<strong className="text-[13px]">Signers: </strong>
<strong className="text-[13px]">
{t("report-heading.Signers")}:{" "}
</strong>
{signersName()}
</>
)}
@@ -545,11 +560,11 @@ function DriveBody(props) {
<Table striped bordered hover>
<thead>
<tr>
<th>Name</th>
<th>Created Date</th>
<th>Type</th>
<th>Status</th>
<th>Action</th>
<th>{t("report-heading.Name")}</th>
<th>{t("report-heading.created-date")}</th>
<th>{t("report-heading.Type")}</th>
<th>{t("report-heading.Status")}</th>
<th>{t("action")}</th>
</tr>
</thead>
<tbody>
@@ -582,25 +597,25 @@ function DriveBody(props) {
)}
<ModalUi
isOpen={isDeleteDoc}
title={"Delete Document"}
title={t("delete-document")}
handleClose={() => setIsDeleteDoc(false)}
>
<div className="h-full p-[20px] text-base-content">
<p>Are you sure you want to delete this document?</p>
<p>{t("delete-document-alert")}</p>
<div className="h-[1px] w-full bg-[#9f9f9f] my-[15px]"></div>
<button
onClick={() => handleDeleteDocument(selectDoc)}
type="button"
className="op-btn op-btn-primary mr-2"
>
Yes
{t("yes")}
</button>
<button
onClick={() => setIsDeleteDoc(false)}
type="button"
className="op-btn op-btn-neutral"
>
No
{t("no")}
</button>
</div>
</ModalUi>
@@ -1,10 +1,12 @@
import React from "react";
import ModalUi from "../../primitives/ModalUi";
import { useTranslation } from "react-i18next";
const AddRoleModal = (props) => {
const { t } = useTranslation();
return (
<ModalUi
title={"Add Role"}
title={t("add-role")}
isOpen={props.isModalRole}
handleClose={props.handleCloseRoleModal}
>
@@ -21,19 +23,19 @@ const AddRoleModal = (props) => {
className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs mt-1"
/>
<p className="text-[gray] text-[11px] mt-[5px] mb-[10px] ml-[10px]">
e.g: Customer, Hr, Director, Manager, Student, etc...
{t("role-ex")}..
</p>
<div>
<div className="h-[1px] w-full bg-[#9f9f9f] mb-[10px]"></div>
<button type="submit" className="op-btn op-btn-primary">
Add
{t("add")}
</button>
<button
onClick={props.handleCloseRoleModal}
type="button"
className="op-btn op-btn-ghost ml-2"
>
Close
{t("close")}
</button>
</div>
</form>
@@ -1,11 +1,24 @@
import React from "react";
function BorderResize({ right, top }) {
function BorderResize(props) {
const getHeight = () => {
const height = props.posHeight(props.pos, props.isSignYourself);
if (height > 14) {
return "14px";
} else {
return `${height}px`;
}
};
return (
<div
className={`${right ? `-right-[12px]` : "-right-[1px]"} ${
top ? `-bottom-[11px]` : "-bottom-[1px]"
} absolute inline-block w-[14px] h-[14px] hover:cursor-sw-resize border-r-[3px] border-b-[3px] border-[#188ae2]`}
style={{
width: getHeight() || "14px",
height: getHeight() || "14px"
}}
className={`${props.right ? `-right-[12px]` : "-right-[2px]"} ${
props.top ? `-bottom-[12px]` : "-bottom-[2px] "
} absolute inline-block hover:cursor-sw-resize border-r-[3px] border-b-[3px] border-[#188ae2]`}
></div>
);
}
@@ -1,16 +1,18 @@
import React from "react";
function DefaultSignature({ defaultSignImg, xyPostion, setDefaultSignAlert }) {
import { useTranslation } from "react-i18next";
function DefaultSignature(props) {
const { t } = useTranslation();
const confirmToaddDefaultSign = () => {
if (xyPostion.length > 0) {
setDefaultSignAlert({
if (props?.xyPostion.length > 0) {
props?.setDefaultSignAlert({
isShow: true,
alertMessage:
"Are you sure you want to auto sign at requested all locations?"
alertMessage: t("default-sign-alert")
});
} else {
setDefaultSignAlert({
props?.setDefaultSignAlert({
isShow: true,
alertMessage: "please select position!"
alertMessage: t("please-select-position!")
});
}
};
@@ -18,24 +20,32 @@ function DefaultSignature({ defaultSignImg, xyPostion, setDefaultSignAlert }) {
return (
<div data-tut="reactourThird">
<div className="mx-2 pr-2 pt-2 pb-1 text-[15px] text-base-content font-semibold border-b-[1px] border-base-300">
Signature
{t("signature")}
</div>
<div className="flex flex-col items-center mt-[10px] font-semibold">
<p className="text-base-content">Your Signature</p>
<div className="flex flex-col items-center mt-[10px] font-semibold relative">
<p className="text-base-content">{t("Your-Signature")}</p>
<div className="op-card shadow-md h-[111px] w-[90%] p-2">
<img
alt="signature"
className="w-full h-full object-contain"
src={defaultSignImg}
src={props?.defaultSignImg}
/>
</div>
<button
type="button"
className="op-btn op-btn-primary op-btn-sm mt-[10px]"
onClick={() => confirmToaddDefaultSign()}
disabled={!props?.isDefault}
>
Auto Sign All
{t("auto-sign-all")}
</button>
{!props.isDefault && (
<div className="absolute bg-black/70 text-white w-full h-full flex items-center justify-center text-[11px] cursor-default">
<span className="-rotate-45">
Document creator has disabled this option
</span>
</div>
)}
</div>
</div>
);
@@ -3,16 +3,18 @@ import LoaderWithMsg from "../../primitives/LoaderWithMsg";
import { contractDocument } from "../../constant/Utils";
import HandleError from "../../primitives/HandleError";
import { useLocation, useNavigate } from "react-router-dom";
import { useTranslation } from "react-i18next";
function useQuery() {
return new URLSearchParams(useLocation().search);
}
function DraftDocument() {
const { t } = useTranslation();
const navigate = useNavigate();
const query = useQuery();
const docId = query.get("docId");
const [isLoading, setIsLoading] = useState({
isLoader: true,
message: "This might take some time"
message: t("loading-mssg")
});
useEffect(() => {
getDocumentDetails();
@@ -52,7 +54,7 @@ function DraftDocument() {
navigate(`/recipientSignPdf/${data.objectId}`);
}
//checking if document has completed and signyour-self flow
else if (!signerExist && !isPlaceholder) {
else if ((!signerExist && !isPlaceholder) || data?.IsSignyourself) {
navigate(`/signaturePdf/${data.objectId}`);
}
//checking if document has declined by someone
@@ -3,7 +3,11 @@ import { isEnableSubscription } from "../../constant/const";
import ModalUi from "../../primitives/ModalUi";
import { radioButtonWidget } from "../../constant/Utils";
import Upgrade from "../../primitives/Upgrade";
import { useTranslation } from "react-i18next";
import { fontColorArr, fontsizeArr } from "../../constant/Utils";
function DropdownWidgetOption(props) {
const { t } = useTranslation();
const [dropdownOptionList, setDropdownOptionList] = useState([
"option-1",
"option-2"
@@ -155,9 +159,12 @@ function DropdownWidgetOption(props) {
>
<div>
<label className="text-[13px] font-semibold">
Name<span className="text-[red] text-[13px]"> *</span>
{t("name")}
<span className="text-[red] text-[13px]"> *</span>
</label>
<input
onInvalid={(e) => e.target.setCustomValidity(t("input-required"))}
onInput={(e) => e.target.setCustomValidity("")}
required
defaultValue={dropdownName}
value={dropdownName}
@@ -166,7 +173,7 @@ function DropdownWidgetOption(props) {
/>
<label className="text-[13px] font-semibold mt-[5px]">
Options
{t("options")}
</label>
<div className="flex flex-col">
{dropdownOptionList.map((option, index) => (
@@ -196,6 +203,10 @@ function DropdownWidgetOption(props) {
/>
)}
<input
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"
type="text"
@@ -222,12 +233,16 @@ function DropdownWidgetOption(props) {
!props.isSubscribe ? "text-[gray]" : ""
} text-[13px] font-semibold`}
>
Minimun check
{t("minimun-check")}
</label>
{!props.isSubscribe && isEnableSubscription && (
<Upgrade />
)}
<input
onInvalid={(e) =>
e.target.setCustomValidity(t("input-required"))
}
onInput={(e) => e.target.setCustomValidity("")}
required
defaultValue={0}
value={minCount}
@@ -245,9 +260,13 @@ function DropdownWidgetOption(props) {
!props.isSubscribe ? "text-[gray]" : ""
} text-[13px] font-semibold`}
>
Maximum check
{t("maximum-check")}
</label>
<input
onInvalid={(e) =>
e.target.setCustomValidity(t("input-required"))
}
onInput={(e) => e.target.setCustomValidity("")}
required
defaultValue={0}
value={maxCount}
@@ -268,7 +287,7 @@ function DropdownWidgetOption(props) {
{["dropdown", radioButtonWidget].includes(props.type) && (
<>
<label className="text-[13px] font-semibold mt-[5px]">
Default value
{t("default-value")}
</label>
<select
onChange={(e) => setDefaultValue(e.target.value)}
@@ -278,7 +297,7 @@ function DropdownWidgetOption(props) {
placeholder="select default value"
>
<option value="" disabled hidden className="text-[13px]">
Select...
{t("select")}...
</option>
{dropdownOptionList.map((data, ind) => {
return (
@@ -313,6 +332,55 @@ function DropdownWidgetOption(props) {
</div>
</>
)}
<div className="flex items-center mt-3 mb-3">
<span>{t("font-size")} :</span>
<select
className="ml-[7px] op-select op-select-bordered op-select-sm focus:outline-none hover:border-base-content text-xs"
value={
props.fontSize ||
props.currWidgetsDetails?.options?.fontSize ||
12
}
onChange={(e) => props.setFontSize(parseInt(e.target.value))}
>
{fontsizeArr.map((size, ind) => {
return (
<option className="text-[13px]" value={size} key={ind}>
{size}
</option>
);
})}
</select>
<div className="flex flex-row gap-1 items-center ml-4 ">
<span>{t("color")} : </span>
<select
value={
props.fontColor ||
props.currWidgetsDetails?.options?.fontColor ||
"black"
}
onChange={(e) => props.setFontColor(e.target.value)}
className="ml-[7px] op-select op-select-bordered op-select-sm focus:outline-none hover:border-base-content text-xs"
>
{fontColorArr.map((color, ind) => {
return (
<option value={color} key={ind}>
{t(`color-type.${color}`)}
</option>
);
})}
</select>
<span
style={{
background:
props.fontColor ||
props.currWidgetsDetails?.options?.fontColor ||
"black"
}}
className="w-5 h-[19px] ml-1"
></span>
</div>
</div>
{["checkbox", radioButtonWidget].includes(props.type) && (
<div className="flex flex-row gap-5 my-2 items-center text-center">
{!props.isSignYourself && (
@@ -325,7 +393,7 @@ function DropdownWidgetOption(props) {
onChange={(e) => setIsReadOnly(e.target.checked)}
/>
<label className="ml-1 mb-0" htmlFor="isreadonly">
Is read only
{t("read-only")}
</label>
</div>
)}
@@ -339,12 +407,13 @@ function DropdownWidgetOption(props) {
/>
<label className="ml-1 mb-0" htmlFor="ishidelabel">
Hide labels
{t("hide-labels")}
</label>
</div>
</div>
)}
</div>
<div
className={`${
props.type === "checkbox" && !props.isSignYourself
@@ -358,7 +427,7 @@ function DropdownWidgetOption(props) {
type="submit"
className="op-btn op-btn-primary"
>
Save
{t("save")}
</button>
{props.currWidgetsDetails?.options?.values?.length > 0 && (
<button
@@ -369,7 +438,7 @@ function DropdownWidgetOption(props) {
resetState();
}}
>
Cancel
{t("cancel")}
</button>
)}
</form>
+153 -22
View File
@@ -2,17 +2,22 @@ import React, { useState, useEffect } from "react";
import { checkIsSubscribed, getFileName } from "../../constant/Utils";
import Upgrade from "../../primitives/Upgrade";
import { isEnableSubscription } from "../../constant/const";
// import SelectFolder from "../../premitives/SelectFolder";
import { useTranslation } from "react-i18next";
import { Tooltip } from "react-tooltip";
const EditTemplate = ({ template, onSuccess }) => {
// const [folder, setFolder] = useState({ ObjectId: "", Name: "" });
const EditTemplate = ({ template, onSuccess, jwttoken }) => {
const { t } = useTranslation();
const [formData, setFormData] = useState({
Name: template?.Name || "",
Note: template?.Note || "",
Description: template?.Description || "",
SendinOrder: template?.SendinOrder ? `${template?.SendinOrder}` : "false",
AutomaticReminders: template?.AutomaticReminders || false,
RemindOnceInEvery: template?.RemindOnceInEvery || 5
RemindOnceInEvery: template?.RemindOnceInEvery || 5,
IsEnableOTP: template?.IsEnableOTP ? `${template?.IsEnableOTP}` : "false",
IsTourEnabled: template?.IsTourEnabled
? `${template?.IsTourEnabled}`
: "false"
});
const [isSubscribe, setIsSubscribe] = useState(false);
useEffect(() => {
@@ -21,25 +26,22 @@ const EditTemplate = ({ template, onSuccess }) => {
}, []);
const fetchSubscription = async () => {
if (isEnableSubscription) {
const getIsSubscribe = await checkIsSubscribed();
setIsSubscribe(getIsSubscribe);
const subscribe = await checkIsSubscribed(jwttoken);
setIsSubscribe(subscribe.isValid);
}
};
const handleStrInput = (e) => {
setFormData({ ...formData, [e.target.name]: e.target.value });
};
// const handleFolder = (data) => {
// console.log("handleFolder ", data)
// setFolder(data);
// };
// Define a function to handle form submission
const handleSubmit = async (e) => {
e.preventDefault();
e.stopPropagation();
const isChecked = formData.SendinOrder === "true" ? true : false;
const isTourEnabled = formData?.IsTourEnabled === "false" ? false : true;
const AutoReminder = formData?.AutomaticReminders || false;
const IsEnableOTP = formData.IsEnableOTP === "true" ? true : false;
let reminderDate = {};
if (AutoReminder) {
const RemindOnceInEvery = parseInt(formData?.RemindOnceInEvery);
@@ -47,7 +49,13 @@ const EditTemplate = ({ template, onSuccess }) => {
ReminderDate.setDate(ReminderDate.getDate() + RemindOnceInEvery);
reminderDate = { NextReminderDate: ReminderDate };
}
const data = { ...formData, SendinOrder: isChecked, ...reminderDate };
const data = {
...formData,
SendinOrder: isChecked,
IsEnableOTP: IsEnableOTP,
IsTourEnabled: isTourEnabled,
...reminderDate
};
onSuccess(data);
};
const handleAutoReminder = () => {
@@ -62,7 +70,7 @@ const EditTemplate = ({ template, onSuccess }) => {
<form onSubmit={handleSubmit}>
<div className="mb-[0.35rem]">
<label htmlFor="name" className="text-[13px]">
File
{t("report-heading.File")}
</label>
<div className="op-input op-input-bordered op-input-sm focus:outline-none py-2 font-semibold w-full text-xs">
{getFileName(template.URL)}
@@ -70,7 +78,7 @@ const EditTemplate = ({ template, onSuccess }) => {
</div>
<div className="mb-[0.35rem]">
<label htmlFor="name" className="text-[13px]">
Name
{t("Title")}
<span className="text-[13px] text-[red]"> *</span>
</label>
<input
@@ -78,13 +86,15 @@ const EditTemplate = ({ template, onSuccess }) => {
name="Name"
value={formData.Name}
onChange={(e) => handleStrInput(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-[0.35rem]">
<label htmlFor="Note" className="text-[13px]">
Note
{t("report-heading.Note")}
</label>
<input
type="text"
@@ -97,7 +107,7 @@ const EditTemplate = ({ template, onSuccess }) => {
</div>
<div className="mb-[0.35rem]">
<label htmlFor="Description" className="text-[13px]">
Description
{t("description")}
</label>
<input
type="text"
@@ -109,7 +119,7 @@ const EditTemplate = ({ template, onSuccess }) => {
/>
</div>
<div className="mb-[0.35rem]">
<label className="text-[13px]">Send In Order</label>
<label className="text-[13px]">{t("send-in-order")}</label>
<div className="flex items-center gap-[8px] ml-[8px] mb-[5px]">
<input
type="radio"
@@ -119,7 +129,7 @@ const EditTemplate = ({ template, onSuccess }) => {
checked={formData.SendinOrder === "true"}
onChange={handleStrInput}
/>
<div className="text-[12px]">Yes</div>
<div className="text-[12px]">{t("yes")}</div>
</div>
<div className="flex items-center gap-[8px] ml-[8px] mb-[5px]">
<input
@@ -130,7 +140,7 @@ const EditTemplate = ({ template, onSuccess }) => {
checked={formData.SendinOrder === "false"}
onChange={handleStrInput}
/>
<div className="text-[12px]">No</div>
<div className="text-[12px]">{t("no")}</div>
</div>
</div>
{isEnableSubscription && (
@@ -140,7 +150,7 @@ const EditTemplate = ({ template, onSuccess }) => {
isSubscribe ? "font-semibold" : "font-semibold text-gray-300"
}
>
Auto reminder{" "}
{t("auto-reminder")}
{!isSubscribe && isEnableSubscription && <Upgrade />}
</span>
<label
@@ -162,7 +172,7 @@ const EditTemplate = ({ template, onSuccess }) => {
{isSubscribe && formData?.AutomaticReminders === true && (
<div className="text-xs mt-2">
<label className="block">
Remind once in every (Days)
{t("remind-once")}
<span className="text-red-500 text-[13px]">*</span>
</label>
<input
@@ -171,13 +181,134 @@ const EditTemplate = ({ template, onSuccess }) => {
name="RemindOnceInEvery"
className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs"
onChange={handleStrInput}
onInvalid={(e) =>
e.target.setCustomValidity(t("input-required"))
}
onInput={(e) => e.target.setCustomValidity("")}
required
/>
</div>
)}
{isEnableSubscription && (
<div className="text-xs mt-2">
<label className="block">
<span className={isSubscribe ? "" : " text-gray-300"}>
{t("isenable-otp")}{" "}
<a data-tooltip-id="isenableotp-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>{" "}
{!isSubscribe && isEnableSubscription && <Upgrade />}
</span>
<Tooltip id="isenableotp-tooltip" className="z-50">
<div className="max-w-[200px] md:max-w-[450px]">
<p className="font-bold">{t("isenable-otp")}</p>
<p>{t("isenable-otp-help.p1")}</p>
<p className="p-[5px]">
<ol className="list-disc">
<li>
<span className="font-bold">{t("yes")}: </span>
<span>{t("isenable-otp-help.p2")}</span>
</li>
<li>
<span className="font-bold">{t("no")}: </span>
<span>{t("isenable-otp-help.p3")}</span>
</li>
</ol>
</p>
<p>{t("isenable-otp-help.p4")}</p>
</div>
</Tooltip>
</label>
<div
className={`${
isSubscribe ? "" : "pointer-events-none opacity-50"
} flex items-center gap-2 ml-2 mb-1 `}
>
<input
type="radio"
value={"true"}
className="op-radio op-radio-xs"
name="IsEnableOTP"
checked={formData.IsEnableOTP === "true"}
onChange={handleStrInput}
/>
<div className="text-center">{t("yes")}</div>
</div>
<div
className={`${
isSubscribe ? "" : "pointer-events-none opacity-50"
} flex items-center gap-2 ml-2 mb-1 `}
>
<input
type="radio"
value={"false"}
name="IsEnableOTP"
className="op-radio op-radio-xs"
checked={formData.IsEnableOTP === "false"}
onChange={handleStrInput}
/>
<div className="text-center">{t("no")}</div>
</div>
</div>
)}
<div className="text-xs mt-2">
<label className="block">
<span>
{t("enable-tour")}
<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>{" "}
</span>
<Tooltip id="istourenabled-tooltip" className="z-50">
<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")}</p>
</div>
</Tooltip>
</label>
<div className={` flex items-center gap-2 ml-2 mb-1 `}>
<input
type="radio"
value={"true"}
className="op-radio op-radio-xs"
name="IsTourEnabled"
checked={formData.IsTourEnabled === "true"}
onChange={handleStrInput}
/>
<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={formData.IsTourEnabled === "false"}
onChange={handleStrInput}
/>
<div className="text-center">{t("no")}</div>
</div>
</div>
<div className="mt-[1rem] flex justify-start">
<button type="submit" className="op-btn op-btn-primary">
Submit
{t("submit")}
</button>
</div>
</form>
@@ -1,5 +1,5 @@
import React from "react";
import { Quill } from "react-quill";
import { Quill } from "react-quill-new";
// Custom Undo button icon component for Quill editor. You can import it directly
// from 'quill/assets/icons/undo.svg' but I found that a number of loaders do not
@@ -79,7 +79,6 @@ export const formats = [
"blockquote",
"background",
"list",
"bullet",
"indent",
"link",
"image",
+10 -9
View File
@@ -1,35 +1,36 @@
import React from "react";
import Tooltip from "../../primitives/Tooltip";
import ReactQuill from "react-quill";
import "react-quill/dist/quill.snow.css";
import ReactQuill from "react-quill-new";
import "../../styles/quill.css";
import EditorToolbar, { module1, formats } from "./EditorToolbar";
import { useTranslation } from "react-i18next";
export function EmailBody(props) {
const { t } = useTranslation();
return (
<form className="flex flex-col text-base-content text-lg font-normal">
<div className="m-2 md:m-10 p-3 md:p-10 shadow-md hover:shadow-lg border-[1px] border-indigo-800 rounded-md">
<label className="text-sm ml-2">
Subject <Tooltip message={"email subject"} />
{t("subject")} <Tooltip message={t("email-subject")} />
</label>
<input
required
onInvalid={(e) => e.target.setCustomValidity(t("input-required"))}
onInput={(e) => e.target.setCustomValidity("")}
value={props.requestSubject}
onChange={(e) => props.setRequestSubject(e.target.value)}
placeholder='${senderName} has requested you to sign "${documentName}"'
className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs"
/>
<label className="text-sm ml-2 mt-3">
Body <Tooltip message={"email body"} />
{t("body")} <Tooltip message={t("email-body")} />
</label>
<div className="px-3 py-2 w-full focus:outline-none text-xs">
<div className="px-1 py-2 w-full focus:outline-none text-xs">
<EditorToolbar containerId="toolbar1" />
<ReactQuill
theme="snow"
value={props.requestBody}
// value={typedText}
placeholder="add body of email "
// readOnly={loading}
// onChangeSelection={handleTextSelection} // Listen for text selection
placeholder={t("email-placeholder")}
ref={props.editorRef}
modules={module1}
formats={formats}
@@ -1,38 +1,62 @@
import React, { useState } from "react";
import { saveAs } from "file-saver";
import axios from "axios";
import { getBase64FromUrl } from "../../constant/Utils";
import { handleToPrint } from "../../constant/Utils";
import { themeColor, emailRegex } from "../../constant/const";
import printModule from "print-js";
import Loader from "../../primitives/Loader";
import ModalUi from "../../primitives/ModalUi";
import { useTranslation } from "react-i18next";
function EmailComponent({
isEmail,
pdfUrl,
setIsEmail,
setSuccessEmail,
pdfName,
pdfDetails,
sender,
setIsAlert,
extUserId,
activeMailAdapter
activeMailAdapter,
setIsDownloadModal
}) {
const { t } = useTranslation();
const [emailList, setEmailList] = useState([]);
const [emailValue, setEmailValue] = useState("");
const [isLoading, setIsLoading] = useState(false);
const [emailErr, setEmailErr] = useState(false);
const [isDownloading, setIsDownloading] = useState("");
const isAndroid = /Android/i.test(navigator.userAgent);
//function for send email
const sendEmail = async () => {
const pdfName = pdfDetails[0]?.Name;
setIsLoading(true);
let sendMail;
const docId = pdfDetails?.[0]?.objectId || "";
const FileAdapterId = pdfDetails?.[0]?.FileAdapterId
? pdfDetails?.[0]?.FileAdapterId
: "";
let presignedUrl = pdfUrl;
try {
const axiosRes = await axios.post(
`${localStorage.getItem("baseUrl")}/functions/getsignedurl`,
{ url: pdfUrl, docId: docId, fileAdapterId: FileAdapterId },
{
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/`;
let url = `${localStorage.getItem("baseUrl")}functions/sendmailv3`;
const headers = {
"Content-Type": "application/json",
"X-Parse-Application-Id": localStorage.getItem("parseAppId"),
@@ -44,7 +68,7 @@ function EmailComponent({
mailProvider: activeMailAdapter,
extUserId: extUserId,
pdfName: pdfName,
url: pdfUrl,
url: presignedUrl,
recipient: emailList[i],
subject: `${sender.name} has signed the doc - ${pdfName}`,
from: sender.email,
@@ -68,36 +92,25 @@ function EmailComponent({
setIsEmail(false);
setIsAlert({
isShow: true,
alertMessage: "something went wrong"
alertMessage: t("something-went-wrong-mssg")
});
}
}
if (sendMail && sendMail.data.result.status === "success") {
if (sendMail?.data?.result?.status === "success") {
setSuccessEmail(true);
setIsEmail(false);
setTimeout(() => {
setSuccessEmail(false);
setIsEmail(false);
setEmailValue("");
setEmailList([]);
}, 1500);
setIsLoading(false);
} else if (sendMail && sendMail.data.result.status === "error") {
setIsLoading(false);
setIsEmail(false);
setIsAlert({
isShow: true,
alertMessage: "something went wrong"
});
setEmailValue("");
setEmailList([]);
} else {
setIsLoading(false);
setIsEmail(false);
setIsAlert({
isShow: true,
alertMessage: "something went wrong"
alertMessage: t("something-went-wrong-mssg")
});
setEmailValue("");
setEmailList([]);
@@ -111,7 +124,7 @@ function EmailComponent({
};
//function for get email value
const handleEmailValue = (e) => {
const value = e.target.value;
const value = e.target.value?.toLowerCase()?.replace(/\s/g, "");
setEmailErr(false);
setEmailValue(value);
};
@@ -138,43 +151,11 @@ function EmailComponent({
}
}
};
// function for print signed pdf
const handleToPrint = async (event) => {
event.preventDefault();
const pdf = await getBase64FromUrl(pdfUrl);
const isAndroidDevice = navigator.userAgent.match(/Android/i);
const isAppleDevice =
(/iPad|iPhone|iPod/.test(navigator.platform) ||
(navigator.platform === "MacIntel" && navigator.maxTouchPoints > 1)) &&
!window.MSStream;
if (isAndroidDevice || isAppleDevice) {
const byteArray = Uint8Array.from(
atob(pdf)
.split("")
.map((char) => char.charCodeAt(0))
);
const blob = new Blob([byteArray], { type: "application/pdf" });
const blobUrl = URL.createObjectURL(blob);
window.open(blobUrl, "_blank");
} else {
printModule({ printable: pdf, type: "pdf", base64: true });
}
const handleClose = () => {
setIsEmail(false);
setEmailValue("");
setEmailList([]);
};
//handle download signed pdf
const handleDownloadPdf = () => {
saveAs(pdfUrl, `${sanitizeFileName(pdfName)}_signed_by_OpenSign™.pdf`);
};
const sanitizeFileName = (pdfName) => {
// Replace spaces with underscore
return pdfName.replace(/ /g, "_");
};
const isAndroid = /Android/i.test(navigator.userAgent);
return (
<div>
{/* isEmail */}
@@ -184,36 +165,46 @@ function EmailComponent({
<div className="absolute w-full h-full flex flex-col justify-center items-center z-[20] bg-[#e6f2f2]/70">
<Loader />
<span className="text-[12px] text-base-content">
This might take some time
{t("loader")}
</span>
</div>
)}
{isDownloading === "pdf" && (
<div className="fixed z-[200] inset-0 flex justify-center items-center bg-black bg-opacity-30">
<Loader />
</div>
)}
<div className="flex justify-between items-center py-[10px] px-[20px] border-b-[1px] border-base-content">
<span className="text-base-content font-semibold">
Successfully signed!
{t("successfully-signed")}
</span>
<div className="flex flex-row">
{!isAndroid && (
<button
onClick={handleToPrint}
onClick={(e) =>
handleToPrint(e, pdfUrl, setIsDownloading, pdfDetails)
}
className="op-btn op-btn-neutral op-btn-sm text-[15px]"
>
<i className="fa-light fa-print" aria-hidden="true"></i>
Print
{t("print")}
</button>
)}
<button
className="op-btn op-btn-primary op-btn-sm text-[15px] ml-2"
onClick={() => handleDownloadPdf()}
onClick={() => {
handleClose();
setIsDownloadModal(true);
}}
>
<i className="fa-light fa-download" aria-hidden="true"></i>
Download
{t("download")}
</button>
</div>
</div>
<div className="h-full p-[20px]">
<p className="font-medium text-[15px] mb-[5px] text-base-content align-baseline">
Recipients added here will get a copy of the signed document.
{t("email-mssg")}
</p>
{emailList.length > 0 ? (
<div className="p-0 border-[1.5px] op-border-primary rounded w-full text-[15px]">
@@ -245,6 +236,10 @@ function EmailComponent({
onChange={handleEmailValue}
onKeyDown={handleEnterPress}
onBlur={() => emailValue && handleEnterPress("add")}
onInvalid={(e) =>
e.target.setCustomValidity(t("input-required"))
}
onInput={(e) => e.target.setCustomValidity("")}
required
/>
)}
@@ -257,15 +252,19 @@ function EmailComponent({
className="p-[10px] pb-[20px] rounded w-full text-[15px] outline-none bg-transparent border-[1.5px] op-border-primary"
onChange={handleEmailValue}
onKeyDown={handleEnterPress}
placeholder="Add an email address and hit enter"
placeholder={t("enter-email-plaholder")}
onBlur={() => emailValue && handleEnterPress("add")}
onInvalid={(e) =>
e.target.setCustomValidity(t("input-required"))
}
onInput={(e) => e.target.setCustomValidity("")}
required
/>
</div>
)}
{emailErr && (
<p className="text-xs text-[red] ml-1.5 mt-0.5">
please provide correct email address
{t("email-error-1")}
</p>
)}
<button
@@ -278,10 +277,8 @@ function EmailComponent({
</button>
<div className="bg-[#e3e2e1] mt-[10px] p-[5px] rounded">
<span className="font-bold">Note: </span>
<span className="text-[15px]">
You can only send to ten recipients at a time.
</span>
<span className="font-bold">{t("report-heading.Note")}: </span>
<span className="text-[15px]">{t("email-error-2")}</span>
</div>
<hr className="w-full my-[15px] bg-base-content" />
<button
@@ -289,18 +286,14 @@ function EmailComponent({
className="op-btn op-btn-secondary"
onClick={() => emailList.length > 0 && sendEmail()}
>
Send
{t("send")}
</button>
<button
type="button"
className="op-btn op-btn-ghost ml-2"
onClick={() => {
setIsEmail(false);
setEmailValue("");
setEmailList([]);
}}
onClick={() => handleClose()}
>
Close
{t("close")}
</button>
</div>
</ModalUi>
@@ -0,0 +1,269 @@
import React, { useState } from "react";
import { Prism as SyntaxHighlighter } from "react-syntax-highlighter";
import { tomorrow } from "react-syntax-highlighter/dist/esm/styles/prism";
import { copytoData } from "../../constant/Utils";
import { useTranslation } from "react-i18next";
function EmbedTab(props) {
const { t } = useTranslation();
const tabName = [
{ title: "React/Next.js", icon: "fa-brands fa-react", color: "#61dafb" },
{ title: "JavaScript", icon: "fa-brands fa-js", color: "#ffd43b" },
{ title: "Angular", icon: "fa-brands fa-angular", color: "#ff5733" }
];
const [activeTab, setActiveTab] = useState(0);
// State to track if the code has been copied
const [isCopied, setIsCopied] = useState(false);
const reactCode = [
{
id: 0,
title: "Installation",
codeString: `
npm install @opensign/react`
},
{
id: 1,
title: "Usage",
codeString: `
import React from "react";
import Opensign from "@opensign/react";
export function App() {
return (
<div className="app">
<Opensign
onLoad={() => console.log("success")}
onLoadError={(error) => console.log(error)}
templateId= "${props.templateId}"
/>
</div>
);
}
`
}
];
const angularCode = [
{
id: 0,
title: "Installation",
codeString: `
npm install @opensign/angular`
},
{
id: 1,
title: "Usage",
codeString: `
import { Component } from '@angular/core';
import {OpensignComponent} from "@opensign/angular"
@Component({
selector:'app-root',
standalone: true,
imports: [OpensignComponent],
template:\`<opensign templateId="${props.templateId}"
(onLoad)="handleLoad()"
(onLoadError)="handleError($event)"
></opensign>\`,
})
export class AppComponent{
handleLoad() {
console.log("success");
}
handleError(error: string) {
console.log(error);
}
}
`
}
];
const jsCodeString = `
<script
src= "https://app.opensignlabs.com/static/js/public-template.bundle.js"
id="opensign-script"
templateId=${props.templateId}
></script>
`;
const handleCopy = (code, ind) => {
copytoData(code);
setIsCopied({ ...isCopied, [ind]: true });
setTimeout(() => setIsCopied(false), 3000);
};
return (
<div className="mt-4 border-t-[1px]">
<div className="flex justify-center items-center mt-2">
<div role="tablist" className="op-tabs op-tabs-bordered">
{tabName.map((tabData, ind) => (
<div
onClick={() => setActiveTab(ind)}
key={ind}
role="tab"
className={`${
activeTab === ind ? "op-tab-active" : ""
} op-tab flex items-center`}
>
<i
className={`${tabData.icon}`}
style={{ color: tabData.color }}
></i>
<span className="ml-1 text-[10px] font-medium md:font-normal md:text-[15px]">
{tabData.title}
</span>
</div>
))}
</div>
</div>
<div>
{activeTab === 0 ? (
<div className="mt-4">
{reactCode.map((data, ind) => {
return (
<div key={ind}>
<p className="font-medium text-[18px]">
{t(`${data.title}`)}
</p>
{ind === 0 && (
<p className="text-[13px] mt-2">
{t("public-template-mssg-1")}
</p>
)}
<div className="relative p-1">
<div
onClick={() => handleCopy(data.codeString, ind)}
className="absolute top-[20px] right-[20px] cursor-pointer"
>
<i className="fa-light fa-copy text-white mr-[2px]" />
<span className=" text-white">
{isCopied[ind] ? t("copied-code") : t("copy-code")}
</span>
</div>
<SyntaxHighlighter
customStyle={{
borderRadius: "15px"
}}
language="javascript"
style={tomorrow}
>
{data.codeString}
</SyntaxHighlighter>
</div>
</div>
);
})}
<p className="font-medium text-[15px]">
{t("public-template-mssg-3")}
</p>
<p className="my-[6px]">
{" "}
{t("public-template-mssg-4")}
<a
href="https://www.npmjs.com/package/@opensign/react"
target="_blank"
rel="noreferrer"
className="cursor-pointer text-blue-700 "
>
{" "}
OpenSign React package{" "}
</a>
{t("public-template-mssg-5")}
</p>
</div>
) : activeTab === 1 ? (
<div className="mt-4">
<div>
{/* <p className="font-medium text-[18px]">{t(`${data.title}`)}</p> */}
<div className="relative p-1">
<div
onClick={() => handleCopy(jsCodeString, 0)}
className="absolute top-[20px] right-[20px] cursor-pointer"
>
<i className="fa-light fa-copy text-white mr-[2px]" />
<span className=" text-white">
{isCopied[0] ? t("copied-code") : t("copy-code")}
</span>
</div>
<SyntaxHighlighter
customStyle={{
borderRadius: "15px"
}}
language="javascript"
style={tomorrow}
>
{jsCodeString}
</SyntaxHighlighter>
</div>
</div>
</div>
) : (
activeTab === 2 && (
<div className="mt-4">
{angularCode.map((data, ind) => {
return (
<div key={ind}>
<p className="font-medium text-[18px]">
{t(`${data.title}`)}
</p>
{ind === 0 && (
<p className="text-[13px] mt-2">
{t("angular-npm-mssg-1")}
</p>
)}
<div className="relative p-1">
<div
onClick={() => handleCopy(data.codeString, ind)}
className="absolute top-[20px] right-[20px] cursor-pointer"
>
<i className="fa-light fa-copy text-white mr-[2px]" />
<span className=" text-white">
{isCopied[ind] ? t("copied-code") : t("copy-code")}
</span>
</div>
<SyntaxHighlighter
customStyle={{
borderRadius: "15px"
}}
language="javascript"
style={tomorrow}
>
{data.codeString}
</SyntaxHighlighter>
</div>
</div>
);
})}
<p className="font-medium text-[15px]">
{t("public-template-mssg-3")}
</p>
<p className="my-[6px]">
{" "}
{t("public-template-mssg-4")}
<a
href="https://www.npmjs.com/package/@opensign/angular"
target="_blank"
rel="noreferrer"
className="cursor-pointer text-blue-700 "
>
{" "}
OpenSign Angular package{" "}
</a>
{t("public-template-mssg-5")}
</p>
</div>
)
)}
</div>
</div>
);
}
export default EmbedTab;
+186 -107
View File
@@ -9,6 +9,7 @@ import "../../styles/signature.css";
import * as DropdownMenu from "@radix-ui/react-dropdown-menu";
import ModalUi from "../../primitives/ModalUi";
import Loader from "../../primitives/Loader";
import { useTranslation } from "react-i18next";
function Header({
isPdfRequestFiles,
@@ -33,20 +34,28 @@ function Header({
setIsEmail,
completeBtnTitle,
setIsEditTemplate,
isPublicTemplate
isPublicTemplate,
clickOnZoomIn,
clickOnZoomOut,
handleRotationFun,
isDisableRotate,
templateId,
setIsDownloadModal,
disabledBackBtn
}) {
const { t } = useTranslation();
const filterPrefill =
signerPos && signerPos?.filter((data) => data.Role !== "prefill");
const isMobile = window.innerWidth < 767;
const [isDownloading, setIsDownloading] = useState("");
const isGuestSigner = localStorage.getItem("isGuestSigner");
const enabledBackBtn = disabledBackBtn === true ? false : true;
//function for show decline alert
const handleDeclinePdfAlert = async () => {
const currentDecline = { currnt: "Sure", isDeclined: true };
setIsDecline(currentDecline);
};
return (
<div className="flex py-[5px]">
{isMobile && isShowHeader ? (
@@ -71,7 +80,7 @@ function Header({
allPages={allPages}
changePage={changePage}
/>
{pdfUrl && alreadySign ? (
{isCompleted || alreadySign ? (
<DropdownMenu.Root>
<DropdownMenu.Trigger asChild>
<div className="op-link op-link-primary no-underline text-[16px] font-semibold pr-[3px] pl-[5px]">
@@ -88,16 +97,20 @@ function Header({
>
<DropdownMenu.Item
className="DropdownMenuItem"
onClick={() =>
handleDownloadPdf(pdfDetails, pdfUrl, setIsDownloading)
}
onClick={() => {
if (isCompleted) {
setIsDownloadModal(true);
} else {
handleDownloadPdf(pdfDetails, setIsDownloading);
}
}}
>
<div className="flex flex-row">
<i
className="fa-light fa-arrow-down mr-[3px]"
aria-hidden="true"
></i>
Download
{t("download")}
</div>
</DropdownMenu.Item>
{isCompleted && (
@@ -115,7 +128,7 @@ function Header({
className="fa-light fa-award mr-[3px]"
aria-hidden="true"
></i>
Certificate
{t("certificate")}
</div>
</DropdownMenu.Item>
)}
@@ -129,14 +142,14 @@ function Header({
className="fa-light fa-envelope mr-[3px]"
aria-hidden="true"
></i>
Mail
{t("mail")}
</div>
</DropdownMenu.Item>
)}
<DropdownMenu.Item
className="DropdownMenuItem"
onClick={(e) =>
handleToPrint(e, pdfUrl, setIsDownloading)
handleToPrint(e, pdfUrl, setIsDownloading, pdfDetails)
}
>
<div className="flex flex-row">
@@ -144,7 +157,7 @@ function Header({
className="fa-light fa-print mr-[3px]"
aria-hidden="true"
></i>
Print
{t("print")}
</div>
</DropdownMenu.Item>
</DropdownMenu.Content>
@@ -162,7 +175,7 @@ function Header({
onClick={() => handleDeclinePdfAlert()}
className="text-[red] border-none font-[650] text-[14px] mr-2"
>
Decline
{t("decline")}
</div>
)}
{isPlaceholder ? (
@@ -177,21 +190,15 @@ function Header({
} op-link no-underline font-[650] text-[14px]`}
data-tut="headerArea"
>
{completeBtnTitle ? completeBtnTitle : "Send"}
{completeBtnTitle ? completeBtnTitle : t("send")}
</div>
) : (
<div
data-tut="reactourThird"
onClick={() => {
if (!pdfUrl) {
embedWidgetsData();
} else if (isPdfRequestFiles) {
embedWidgetsData();
}
}}
onClick={() => embedWidgetsData()}
className="border-none font-[650] text-[14px] op-link op-link-primary no-underline"
>
Finish
{t("finish")}
</div>
)}
<DropdownMenu.Root>
@@ -205,30 +212,86 @@ function Header({
</DropdownMenu.Trigger>
<DropdownMenu.Portal>
<DropdownMenu.Content
className="bg-white shadow-md rounded-full px-3 py-2"
className="bg-white shadow-md rounded-md px-3 py-2"
sideOffset={5}
>
<DropdownMenu.Item
className="flex flex-row justify-center items-center text-[13px] focus:outline-none cursor-pointer"
className="DropdownMenuItem"
onClick={() =>
handleDownloadPdf(
pdfDetails,
pdfUrl,
setIsDownloading
)
handleDownloadPdf(pdfDetails, setIsDownloading)
}
>
<i
className="fa-light fa-arrow-down mr-[3px]"
aria-hidden="true"
></i>
<span className="font-[500]">Download</span>
<div className="flex flex-row">
<i
className="fa-light fa-arrow-down mr-[3px]"
aria-hidden="true"
></i>
<span className="font-[500]">
{t("download")}
</span>
</div>
</DropdownMenu.Item>
{!isDisableRotate && (
<>
<DropdownMenu.Item
className="DropdownMenuItem"
onClick={() => handleRotationFun(90)}
>
<div className="flex flex-row">
<i className="fa-light fa-rotate-right text-gray-500 2xl:text-[30px] mr-[3px]"></i>
<span className="font-[500]">
{t("rotate-right")}
</span>
</div>
</DropdownMenu.Item>
<DropdownMenu.Item
className="DropdownMenuItem"
onClick={() => handleRotationFun(-90)}
>
<div className="flex flex-row">
<i className="fa-light fa-rotate-left text-gray-500 2xl:text-[30px] mr-[3px]"></i>
<span className="font-[500]">
{t("rotate-left")}
</span>
</div>
</DropdownMenu.Item>
</>
)}
<DropdownMenu.Item
className="DropdownMenuItem"
onClick={() => clickOnZoomIn()}
>
<div className="flex flex-row">
<i className="fa-light fa-magnifying-glass-plus text-gray-500 2xl:text-[30px] mr-[3px]"></i>
<span className="font-[500]">{t("zoom-in")}</span>
</div>
</DropdownMenu.Item>
<DropdownMenu.Item
className="DropdownMenuItem"
onClick={() => clickOnZoomOut()}
>
<div className="flex flex-row">
<i className="fa-light fa-magnifying-glass-minus text-gray-500 2xl:text-[30px] mr-[3px]"></i>
<span className="font-[500]">
{t("zoom-out")}
</span>
</div>
</DropdownMenu.Item>
</DropdownMenu.Content>
</DropdownMenu.Portal>
</DropdownMenu.Root>
</div>
)}
{isPublicTemplate && (
<div
data-tut="reactourThird"
onClick={() => embedWidgetsData()}
className="border-none font-[650] text-[14px] op-link op-link-primary no-underline"
>
{t("sign-now")}
</div>
)}
</div>
)}
</div>
@@ -249,13 +312,14 @@ function Header({
<div>
{filterPrefill.length === 0 ? (
<span className="text-[13px] text-[#f5405e]">
Add {signersdata.length - filterPrefill.length}{" "}
recipients signature
{t("add")} {signersdata.length - filterPrefill.length}{" "}
{t("recipients")} {t("widgets-name.signature")}
</span>
) : (
<span className="text-[13px] text-[#f5405e]">
Add {signersdata.length - filterPrefill.length} more
recipients signature
{t("add")} {signersdata.length - filterPrefill.length}{" "}
{t("more")}
{t("recipients")} {t("widgets-name.signature")}
</span>
)}
</div>
@@ -270,13 +334,15 @@ function Header({
<i className="fa-light fa-gear fa-lg"></i>
</button>
)}
<button
onClick={() => window.history.go(-2)}
type="button"
className="op-btn op-btn-ghost op-btn-sm mr-[3px]"
>
Back
</button>
{enabledBackBtn && (
<button
onClick={() => window.history.go(-2)}
type="button"
className="op-btn op-btn-ghost op-btn-sm mr-[3px]"
>
{t("back")}
</button>
)}
<button
disabled={isMailSend && true}
data-tut="headerArea"
@@ -286,8 +352,8 @@ function Header({
{completeBtnTitle
? completeBtnTitle
: isMailSend
? "Sent"
: "Send"}
? t("sent")
: t("send")}
</button>
</div>
</>
@@ -295,7 +361,9 @@ function Header({
alreadySign ? (
<div className="flex flex-row">
<button
onClick={(e) => handleToPrint(e, pdfUrl, setIsDownloading)}
onClick={(e) =>
handleToPrint(e, pdfUrl, setIsDownloading, pdfDetails)
}
type="button"
className="op-btn op-btn-neutral op-btn-sm mr-[3px] shadow"
>
@@ -303,7 +371,7 @@ function Header({
className="fa-light fa-print py-[3px]"
aria-hidden="true"
></i>
<span className="hidden lg:block">Print</span>
<span className="hidden lg:block">{t("print")}</span>
</button>
{isCompleted && (
<button
@@ -317,57 +385,76 @@ function Header({
className="fa-light fa-award py-[3px]"
aria-hidden="true"
></i>
<span className="hidden lg:block">Certificate</span>
<span className="hidden lg:block">{t("certificate")}</span>
</button>
)}
<button
type="button"
className="op-btn op-btn-primary op-btn-sm mr-[3px] shadow"
onClick={() =>
handleDownloadPdf(pdfDetails, pdfUrl, setIsDownloading)
}
onClick={() => {
if (isCompleted) {
setIsDownloadModal(true);
} else {
handleDownloadPdf(pdfDetails, setIsDownloading);
}
}}
>
<i
className="fa-light fa-download py-[3px]"
aria-hidden="true"
></i>
<span className="hidden lg:block">Download</span>
<span className="hidden lg:block">{t("download")}</span>
</button>
</div>
) : (
<div className="flex" data-tut="reactourFifth">
<button
onClick={() => window.history.go(-2)}
type="button"
className="op-btn op-btn-ghost op-btn-sm mr-[3px]"
>
Back
</button>
{!templateId && (
<button
onClick={() => window.history.go(-2)}
type="button"
className="op-btn op-btn-ghost op-btn-sm mr-[3px]"
>
{t("back")}
</button>
)}
{currentSigner && (
<>
{templateId && (
<button
onClick={() =>
handleDownloadPdf(pdfDetails, setIsDownloading)
}
type="button"
className="op-btn op-btn-ghost op-btn-sm mr-[3px]"
>
<span className="hidden lg:block">{t("download")}</span>
</button>
)}
<button
className="op-btn op-btn-secondary op-btn-sm mr-[3px] shadow"
onClick={() => handleDeclinePdfAlert()}
>
Decline
{t("decline")}
</button>
<button
type="button"
className="op-btn op-btn-primary op-btn-sm mr-[3px] shadow"
onClick={() => embedWidgetsData()}
>
Finish
</button>
<button
type="button"
className="op-btn op-btn-neutral op-btn-sm mr-[3px] shadow"
onClick={() =>
handleDownloadPdf(pdfDetails, pdfUrl, setIsDownloading)
}
>
<i className="fa-light fa-arrow-down font-semibold lg:hidden"></i>
<span className="hidden lg:block">Download</span>
{t("finish")}
</button>
{!templateId && (
<button
type="button"
className="op-btn op-btn-neutral op-btn-sm mr-[3px] shadow"
onClick={() =>
handleDownloadPdf(pdfDetails, setIsDownloading)
}
>
<i className="fa-light fa-arrow-down font-semibold lg:hidden"></i>
<span className="hidden lg:block">{t("download")}</span>
</button>
)}
</>
)}
</div>
@@ -383,26 +470,30 @@ function Header({
className="op-btn op-btn-secondary op-btn-sm gap-0 font-medium text-[12px] mr-[3px] shadow"
>
<i className="fa-light fa-award" aria-hidden="true"></i>
<span className="hidden lg:block ml-1">Certificate</span>
<span className="hidden lg:block ml-1">
{t("certificate")}
</span>
</button>
)}
<button
onClick={(e) => handleToPrint(e, pdfUrl, setIsDownloading)}
onClick={(e) =>
handleToPrint(e, pdfUrl, setIsDownloading, pdfDetails)
}
type="button"
className="op-btn op-btn-neutral op-btn-sm gap-0 font-medium text-[12px] mr-[3px] shadow"
>
<i className="fa-light fa-print" aria-hidden="true"></i>
<span className="hidden lg:block ml-1">Print</span>
<span className="hidden lg:block ml-1">{t("print")}</span>
</button>
<button
type="button"
className="op-btn op-btn-primary op-btn-sm gap-0 font-medium text-[12px] mr-[3px] shadow"
onClick={() =>
handleDownloadPdf(pdfDetails, pdfUrl, setIsDownloading)
}
onClick={() => {
setIsDownloadModal(true);
}}
>
<i className="fa-light fa-download" aria-hidden="true"></i>
<span className="hidden lg:block ml-1">Download</span>
<span className="hidden lg:block ml-1">{t("download")}</span>
</button>
<button
type="button"
@@ -410,23 +501,19 @@ function Header({
onClick={() => setIsEmail(true)}
>
<i className="fa-light fa-envelope" aria-hidden="true"></i>
<span className="hidden lg:block ml-1">Mail</span>
<span className="hidden lg:block ml-1">{t("mail")}</span>
</button>
</div>
) : isPublicTemplate ? (
<>
<div className="flex">
<button
type="button"
className="op-btn op-btn-primary op-btn-sm shadow"
onClick={() => {
embedWidgetsData();
}}
>
Sign Now
</button>
</div>
</>
<div className="flex">
<button
type="button"
className="op-btn op-btn-primary op-btn-sm shadow"
onClick={() => embedWidgetsData()}
>
{t("sign-now")}
</button>
</div>
) : (
<div className="flex">
<button
@@ -434,18 +521,14 @@ function Header({
type="button"
className="op-btn op-btn-ghost op-btn-sm mr-[3px]"
>
Back
{t("back")}
</button>
<button
type="button"
className="op-btn op-btn-primary op-btn-sm mr-[3px]"
onClick={() => {
if (!pdfUrl) {
embedWidgetsData();
}
}}
onClick={() => embedWidgetsData()}
>
Finish
{t("finish")}
</button>
</div>
)}
@@ -460,18 +543,14 @@ function Header({
isOpen={isDownloading === "certificate"}
title={
isDownloading === "certificate"
? "Generating certificate"
: "PDF Download"
? t("generating-certificate")
: t("pdf-download")
}
handleClose={() => setIsDownloading("")}
>
<div className="p-3 md:p-5 text-[13px] md:text-base text-center text-base-content">
{isDownloading === "certificate"}{" "}
<p>
Your completion certificate is being generated. Please wait
momentarily. If the download doesn&apos;t start shortly, click the
button again.
</p>
<p>{t("generate-certificate-alert")}</p>
</div>
</ModalUi>
</div>
+26 -31
View File
@@ -1,48 +1,43 @@
import React from "react";
import { useTranslation } from "react-i18next";
function PdfZoom(props) {
const onClickZoomIn = () => {
props.setScale(props.scale + 0.1 * props.scale);
props.setZoomPercent(props.zoomPercent + 10);
};
const onClickZoomOut = () => {
if (props.zoomPercent > 0) {
if (props.zoomPercent === 10) {
props.setScale(1);
} else {
props.setScale(props.scale - 0.1 * props.scale);
}
props.setZoomPercent(props.zoomPercent - 10);
}
};
const handleReset = () => {
props.setScale(1);
props.setZoomPercent(0);
};
const { t } = useTranslation();
return (
// md:mt-[41px] xl:mt-[63px]mt=[]
<span className="hidden md:flex flex-col gap-1 text-center md:w-[5%] mt-[50px] 2xl:mt-[63px]">
<span className="hidden md:flex flex-col gap-1 text-center md:w-[5%] mt-[43px] 2xl:mt-[63px]">
<span
className="bg-gray-50 px-[4px] 2xl:px-[15px] 2xl:py-[10px] cursor-pointer"
onClick={onClickZoomIn}
title="Zoom in"
onClick={() => props.clickOnZoomIn()}
title={t("zoom-in")}
>
<i className="fa-light fa-magnifying-glass-plus text-gray-500 2xl:text-[30px]"></i>
</span>
<span
className="bg-gray-50 px-[4px] 2xl:px-[15px] 2xl:py-[10px] cursor-pointer"
onClick={handleReset}
title="Reset"
>
<i className="fa-light fa-magnifying-glass-arrows-rotate text-gray-500 2xl:text-[30px]"></i>
</span>
{!props?.isDisableRotate && (
<>
<span
className="bg-gray-50 px-[4px] 2xl:px-[15px] 2xl:py-[10px] cursor-pointer"
onClick={() => props.handleRotationFun(90)}
title={t("rotate-right")}
>
<i className="fa-light fa-rotate-right text-gray-500 2xl:text-[30px]"></i>
</span>
<span
className="bg-gray-50 px-[4px] 2xl:px-[15px] 2xl:py-[10px] cursor-pointer"
title={t("rotate-left")}
onClick={() => props.handleRotationFun(-90)}
>
<i className="fa-light fa-rotate-left text-gray-500 2xl:text-[30px]"></i>
</span>
</>
)}
<span
className="bg-gray-50 px-[4px] 2xl:px-[15px] 2xl:py-[10px]"
onClick={onClickZoomOut}
onClick={() => props.clickOnZoomOut()}
style={{
cursor: props.zoomPercent > 0 ? "pointer" : "default"
}}
title="Zoom out"
title={t("zoom-out")}
>
<i className="fa-light fa-magnifying-glass-minus text-gray-500 2xl:text-[30px]"></i>
</span>
+376 -305
View File
@@ -4,6 +4,8 @@ import PlaceholderBorder from "./PlaceholderBorder";
import { Rnd } from "react-rnd";
import {
defaultWidthHeight,
fontColorArr,
fontsizeArr,
getContainerScale,
handleCopyNextToWidget,
isTabAndMobile,
@@ -15,6 +17,8 @@ import {
import PlaceholderType from "./PlaceholderType";
import moment from "moment";
import "../../styles/opensigndrive.css";
import ModalUi from "../../primitives/ModalUi";
import { useTranslation } from "react-i18next";
const selectFormat = (data) => {
switch (data) {
@@ -89,9 +93,10 @@ const getDefaultdate = (selectedDate, format = "dd-MM-yyyy") => {
const getDefaultFormat = (dateFormat) => dateFormat || "MM/dd/yyyy";
function Placeholder(props) {
const { t } = useTranslation();
const [placeholderBorder, setPlaceholderBorder] = useState({ w: 0, h: 0 });
const [isDraggingEnabled, setDraggingEnabled] = useState(true);
const [isShowDateFormat, setIsShowDateFormat] = useState(false);
const [isDateModal, setIsDateModal] = useState(false);
const [containerScale, setContainerScale] = useState();
const [selectDate, setSelectDate] = useState({
date:
@@ -111,6 +116,7 @@ function Placeholder(props) {
: ""
});
const [dateFormat, setDateFormat] = useState([]);
const [clickonWidget, setClickonWidget] = useState({});
const [startDate, setStartDate] = useState(
props.pos.type === "date" &&
getDefaultdate(
@@ -200,20 +206,6 @@ function Placeholder(props) {
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [selectDate]);
//it detect outside click of date dropdown menu
useEffect(() => {
const closeMenuOnOutsideClick = (e) => {
if (isShowDateFormat && !e.target.closest("#menu-container")) {
setIsShowDateFormat(!isShowDateFormat);
}
};
document.addEventListener("click", closeMenuOnOutsideClick);
return () => {
// Cleanup the event listener when the component unmounts
document.removeEventListener("click", closeMenuOnOutsideClick);
};
}, [isShowDateFormat]);
//`handleWidgetIdandPopup` is used to set current widget id and open relative popup
const handleWidgetIdandPopup = () => {
if (props.setSelectWidgetId) {
@@ -338,12 +330,10 @@ function Placeholder(props) {
//condition for only placeholder and template flow
if (props.data && props?.pos?.type !== textWidget) {
props.setSignerObjId(props?.data?.signerObjId);
props.setUniqueId(props?.data?.Id);
const checkIndex = props.xyPostion.findIndex(
(data) => data.Id === props.data.Id
);
const checkIndex = props.xyPostion
.filter((data) => data.Role !== "prefill")
.findIndex((data) => data.Id === props.data.Id);
props.setIsSelectId(checkIndex || 0);
}
//condition to handle in placeholder and template flow for text widget signerId for text widgets i have to set uniqueId in tempSignerId because
@@ -351,10 +341,6 @@ function Placeholder(props) {
else if (props.data && props.pos.type === textWidget) {
props.setTempSignerId(props.uniqueId);
props.setUniqueId(props?.data?.Id);
const checkIndex = props.xyPostion.findIndex(
(data) => data.Id === props.data.Id
);
props.setIsSelectId(checkIndex || 0);
}
props.setSignKey(props.pos.key);
props.setWidgetType(props.pos.type);
@@ -369,21 +355,14 @@ function Placeholder(props) {
//and on save or cancel button of copy all page popup i have set this temp signer Id in unique id
if (props.data && props?.pos?.type !== textWidget) {
props.setSignerObjId(props?.data?.signerObjId);
props.setUniqueId(props?.data?.Id);
const checkIndex = props.xyPostion.findIndex(
(data) => data.Id === props.data.Id
);
const checkIndex = props.xyPostion
.filter((data) => data.Role !== "prefill")
.findIndex((data) => data.Id === props.data.Id);
props.setIsSelectId(checkIndex || 0);
} else if (props.data && props.pos.type === textWidget) {
props.setTempSignerId(props.uniqueId);
props.setSignerObjId(props?.data?.signerObjId);
props.setUniqueId(props?.data?.Id);
const checkIndex = props.xyPostion.findIndex(
(data) => data.Id === props.data.Id
);
props.setIsSelectId(checkIndex || 0);
}
//checking widget's type and open widget copy modal for required widgets
@@ -430,7 +409,11 @@ function Placeholder(props) {
props.setXyPostion,
props.data && props.data.Id,
false,
data?.format
data?.format,
null,
null,
props.fontSize || props.pos?.options?.fontSize || 12,
props.fontColor || props.pos?.options?.fontColor || "black"
);
setSelectDate({ date: date, format: data?.format });
};
@@ -462,17 +445,13 @@ function Placeholder(props) {
handleOnClickSettingIcon();
}}
className="fa-light fa-gear icon"
style={{
color: "#188ae2",
right: "29px",
top: "-19px"
}}
style={{ color: "#188ae2", right: "29px", top: "-19px" }}
></i>
) : (
/* condition to add setting icon for placeholder & template flow for all widgets except signature and date */
((!props?.pos?.type && props.pos.isStamp) ||
(props?.pos?.type &&
!["date", "signature"].includes(props.pos.type) &&
!["date"].includes(props.pos.type) &&
!props.isSignYourself)) && (
<i
onClick={(e) => {
@@ -486,7 +465,7 @@ function Placeholder(props) {
className="fa-light fa-gear icon"
style={{
color: "#188ae2",
right: props?.pos?.type === textWidget ? "32px" : "47px",
right: props?.pos?.type === textWidget ? "32px" : "51px",
top: "-19px"
}}
></i>
@@ -522,17 +501,12 @@ function Placeholder(props) {
)}
{/* setting icon only for date widgets */}
{props.pos.type === "date" && selectDate && (
<div
id="menu-container"
style={{
zIndex: "99",
top: "-19px",
right: props.isPlaceholder ? "60px" : "44px"
}}
className={`${isShowDateFormat ? "show" : ""} dropdown icon`}
<i
onClick={(e) => {
setIsShowDateFormat(!isShowDateFormat);
props.setCurrWidgetsDetails(props.pos);
setIsDateModal(!isDateModal);
e.stopPropagation();
setClickonWidget(props.pos);
if (props.data) {
props.setSignKey(props.pos.key);
props.setUniqueId(props.data.Id);
@@ -543,8 +517,9 @@ function Placeholder(props) {
}
}}
onTouchEnd={(e) => {
props.setCurrWidgetsDetails(props.pos);
e.stopPropagation();
setIsShowDateFormat(!isShowDateFormat);
setIsDateModal(!isDateModal);
if (props.data) {
props.setSignKey(props.pos.key);
props.setUniqueId(props.data.Id);
@@ -554,44 +529,15 @@ function Placeholder(props) {
props.setIsSelectId(checkIndex || 0);
}
}}
>
<i
className="fa-light fa-gear icon"
style={{
color: "#188ae2",
fontSize: "14px"
}}
></i>
<div
className={
isShowDateFormat ? "dropdown-menu show" : "dropdown-menu"
}
aria-labelledby="dropdownMenuButton"
aria-expanded={isShowDateFormat ? "true" : "false"}
>
{dateFormat.map((data, ind) => {
return (
<span
key={ind}
onTouchEnd={(e) => {
e.stopPropagation();
setIsShowDateFormat(!isShowDateFormat);
setSelectDate(data);
handleSaveDate(data);
}}
onClick={() => {
setIsShowDateFormat(!isShowDateFormat);
setSelectDate(data);
handleSaveDate(data);
}}
className="dropdown-item text-[13px]"
>
{data?.date ? data?.date : "nodata"}
</span>
);
})}
</div>
</div>
style={{
zIndex: "99",
top: "-18px",
right: props.isPlaceholder ? "50px" : "30px",
color: "#188ae2",
fontSize: "14px"
}}
className="fa-light fa-gear icon"
></i>
)}
{/* copy icon for all widgets */}
<i
@@ -691,6 +637,21 @@ function Placeholder(props) {
}
}
};
//function to calculate font size
const calculateFont = (size, isMinHeight) => {
const containerScale = getContainerScale(
props.pdfOriginalWH,
props.pageNumber,
props.containerWH
);
const fontSize = (size || 12) * containerScale * props.scale;
//isMinHeight to set text box minimum height
if (isMinHeight) {
return fontSize * 1.2 + "px";
} else {
return fontSize + "px";
}
};
const getCursor = () => {
if (props.data && props.isNeedSign) {
@@ -705,228 +666,338 @@ function Placeholder(props) {
return "all-scroll";
}
};
return (
<Rnd
id={props.pos.key}
data-tut={props.pos.key === props.unSignedWidgetId ? "IsSigned" : ""}
key={props.pos.key}
lockAspectRatio={
![
textWidget,
"email",
"name",
"company",
"job title",
textInputWidget
].includes(props.pos.type) &&
(props.pos.Width
? props.pos.Width / props.pos.Height
: defaultWidthHeight(props.pos.type).width /
defaultWidthHeight(props.pos.type).height)
}
enableResizing={{
top: false,
right: false,
bottom: false,
left: false,
topRight: false,
bottomRight:
props.data && props.isNeedSign
? props.data?.signerObjId === props.signerObjId &&
props.pos.type !== "checkbox" &&
props.pos.type !== radioButtonWidget
? true
: false
: props.pos.type !== radioButtonWidget &&
props.pos.type !== "checkbox" &&
props.pos.key === props.selectWidgetId &&
true,
bottomLeft: false,
topLeft: false
}}
bounds="parent"
className="signYourselfBlock"
style={{
border: "1px solid #007bff",
borderRadius: "2px",
textAlign:
props.pos.type !== "name" &&
props.pos.type !== "company" &&
props.pos.type !== "job title" &&
"center",
cursor: getCursor(),
zIndex:
props.pos.type === "date"
? props.pos.key === props.selectWidgetId
? 99 + 1
: 99
: props?.pos?.zIndex
? props.pos.zIndex
: "5",
background: props.data ? props.data.blockColor : "rgb(203 233 237)"
}}
onDrag={() => {
setDraggingEnabled(true);
props.handleTabDrag && props.handleTabDrag(props.pos.key);
}}
size={{
width:
props.pos.type === radioButtonWidget || props.pos.type === "checkbox"
? "auto"
: props.posWidth(props.pos, props.isSignYourself),
height:
props.pos.type === radioButtonWidget || props.pos.type === "checkbox"
? "auto"
: props.posHeight(props.pos, props.isSignYourself)
}}
onResizeStart={() => {
setDraggingEnabled(true);
props.setIsResize && props.setIsResize(true);
}}
onResizeStop={(e, direction, ref) => {
props.setIsResize && props.setIsResize(false);
props.handleSignYourselfImageResize &&
props.handleSignYourselfImageResize(
ref,
props.pos.key,
props.xyPostion,
props.setXyPostion,
props.index,
containerScale,
props.scale,
props.data && props.data.Id,
props.isResize
);
}}
disableDragging={
props.isNeedSign
? true
: props.isPlaceholder && ![textWidget].includes(props.pos.type)
? false
: !isDraggingEnabled
}
onDragStop={(event, dragElement) =>
props.handleStop &&
props.handleStop(event, dragElement, props.data?.Id, props.pos?.key)
}
position={{
x: xPos(props.pos, props.isSignYourself),
y: yPos(props.pos, props.isSignYourself)
}}
onResize={(e, direction, ref) => {
setPlaceholderBorder({
w: ref.offsetWidth / (props.scale * containerScale),
h: ref.offsetHeight / (props.scale * containerScale)
});
}}
onClick={() => handleOnClickPlaceholder()}
>
{props.isShowBorder &&
props.pos.type !== radioButtonWidget &&
props.pos.type !== "checkbox" &&
props.pos.key === props.selectWidgetId ? (
<BorderResize right={-12} top={-11} />
) : props.data && props.isNeedSign && props.pos.type !== "checkbox" ? (
props.data?.signerObjId === props.signerObjId &&
props.pos.type !== radioButtonWidget &&
props.pos.type !== "checkbox" ? (
<BorderResize />
) : (
<></>
)
) : (
<>
<Rnd
id={props.pos.key}
data-tut={props.pos.key === props.unSignedWidgetId ? "IsSigned" : ""}
key={props.pos.key}
lockAspectRatio={
![
textWidget,
"email",
"name",
"company",
"job title",
textInputWidget
].includes(props.pos.type) &&
(props.pos.Width
? props.pos.Width / props.pos.Height
: defaultWidthHeight(props.pos.type).width /
defaultWidthHeight(props.pos.type).height)
}
enableResizing={{
top: false,
right: false,
bottom: false,
left: false,
topRight: false,
bottomRight:
props.data && props.isNeedSign
? props.data?.signerObjId === props.signerObjId &&
props.pos.type !== "checkbox" &&
props.pos.type !== radioButtonWidget
? true
: false
: props.pos.type !== radioButtonWidget &&
props.pos.type !== "checkbox" &&
props.pos.key === props.selectWidgetId &&
true,
bottomLeft: false,
topLeft: false
}}
bounds="parent"
className="signYourselfBlock"
style={{
border: "1px solid #007bff",
borderRadius: "2px",
textAlign:
props.pos.type !== "name" &&
props.pos.type !== "company" &&
props.pos.type !== "job title" &&
"center",
cursor: getCursor(),
zIndex:
props.pos.type === "date"
? props.pos.key === props.selectWidgetId
? 99 + 1
: 99
: props?.pos?.zIndex
? props.pos.zIndex
: "5",
background: props.data
? props.data?.blockColor + "b0"
: "rgba(203, 233, 237, 0.69)"
}}
onDrag={() => {
setDraggingEnabled(true);
props.handleTabDrag && props.handleTabDrag(props.pos.key);
}}
size={{
width:
props.pos.type === radioButtonWidget ||
props.pos.type === "checkbox"
? "auto"
: props.posWidth(props.pos, props.isSignYourself),
height:
props.pos.type === radioButtonWidget ||
props.pos.type === "checkbox"
? "auto"
: props.posHeight(props.pos, props.isSignYourself)
}}
minHeight={calculateFont(props.pos.options?.fontSize, true)}
maxHeight="auto"
onResizeStart={() => {
setDraggingEnabled(true);
props.setIsResize && props.setIsResize(true);
}}
onResizeStop={(e, direction, ref) => {
setTimeout(() => {
props.setIsResize && props.setIsResize(false);
}, 50);
props.handleSignYourselfImageResize &&
props.handleSignYourselfImageResize(
ref,
props.pos.key,
props.xyPostion,
props.setXyPostion,
props.index,
containerScale,
props.scale,
props.data && props.data.Id,
props.isResize
);
}}
disableDragging={
props.isNeedSign
? true
: props.isPlaceholder && ![textWidget].includes(props.pos.type)
? false
: !isDraggingEnabled
}
onDragStop={(event, dragElement) =>
props.handleStop &&
props.handleStop(event, dragElement, props.data?.Id, props.pos?.key)
}
position={{
x: xPos(props.pos, props.isSignYourself),
y: yPos(props.pos, props.isSignYourself)
}}
onResize={(e, direction, ref) => {
setPlaceholderBorder({
w: ref.offsetWidth / (props.scale * containerScale),
h: ref.offsetHeight / (props.scale * containerScale)
});
}}
onClick={() => !props.isResize && handleOnClickPlaceholder()}
>
{props.isShowBorder &&
props.pos.type !== radioButtonWidget &&
props.pos.type !== "checkbox" &&
props.pos.key === props.selectWidgetId && <BorderResize />
)}
{props.isShowBorder && props.pos.key === props.selectWidgetId && (
<PlaceholderBorder
setDraggingEnabled={setDraggingEnabled}
pos={props.pos}
isPlaceholder={props.isPlaceholder}
getCheckboxRenderWidth={getCheckboxRenderWidth}
scale={props.scale}
containerScale={containerScale}
placeholderBorder={placeholderBorder}
/>
)}
{isTabAndMobile ? (
<div
className="flex items-stretch"
style={{
left: xPos(props.pos, props.isSignYourself),
top: yPos(props.pos, props.isSignYourself),
width:
props.pos.type === radioButtonWidget ||
props.pos.type === "checkbox"
? "auto"
: props.posWidth(props.pos, props.isSignYourself),
height:
props.pos.type === radioButtonWidget ||
props.pos.type === "checkbox"
? "auto"
: props.posHeight(props.pos, props.isSignYourself),
zIndex: "10"
}}
onTouchEnd={() => handleOnClickPlaceholder()}
onClick={() => handleOnClickPlaceholder()}
>
{props.pos.key === props.selectWidgetId && <PlaceholderIcon />}
<PlaceholderType
props.pos.key === props.selectWidgetId ? (
<BorderResize
right={-12}
top={-11}
pos={props.pos}
xyPostion={props.xyPostion}
index={props.index}
setXyPostion={props.setXyPostion}
data={props.data}
setSignKey={props.setSignKey}
isShowDropdown={props?.isShowDropdown}
isPlaceholder={props.isPlaceholder}
posHeight={props.posHeight}
isSignYourself={props.isSignYourself}
signerObjId={props.signerObjId}
handleUserName={props.handleUserName}
setDraggingEnabled={setDraggingEnabled}
pdfDetails={props?.pdfDetails && props?.pdfDetails[0]}
isNeedSign={props.isNeedSign}
setSelectDate={setSelectDate}
selectDate={selectDate}
setValidateAlert={props.setValidateAlert}
setStartDate={setStartDate}
startDate={startDate}
handleSaveDate={handleSaveDate}
xPos={props.xPos}
/>
) : props.data && props.isNeedSign && props.pos.type !== "checkbox" ? (
props.data?.signerObjId === props.signerObjId &&
props.pos.type !== radioButtonWidget &&
props.pos.type !== "checkbox" ? (
<BorderResize
posHeight={props.posHeight}
isSignYourself={props.isSignYourself}
pos={props.pos}
/>
) : (
<></>
)
) : (
props.pos.type !== radioButtonWidget &&
props.pos.type !== "checkbox" &&
props.pos.key === props.selectWidgetId && <BorderResize />
)}
{props.isShowBorder && props.pos.key === props.selectWidgetId && (
<PlaceholderBorder
setDraggingEnabled={setDraggingEnabled}
pos={props.pos}
isPlaceholder={props.isPlaceholder}
getCheckboxRenderWidth={getCheckboxRenderWidth}
scale={props.scale}
containerScale={containerScale}
placeholderBorder={placeholderBorder}
/>
)}
{isTabAndMobile ? (
<div
className="flex items-stretch justify-center"
style={{
left: xPos(props.pos, props.isSignYourself),
top: yPos(props.pos, props.isSignYourself),
width:
props.pos.type === radioButtonWidget ||
props.pos.type === "checkbox"
? "auto"
: props.posWidth(props.pos, props.isSignYourself),
height:
props.pos.type === radioButtonWidget ||
props.pos.type === "checkbox"
? "auto"
: props.posHeight(props.pos, props.isSignYourself),
zIndex: "10"
}}
onTouchEnd={() => handleOnClickPlaceholder()}
onClick={() => handleOnClickPlaceholder()}
>
{props.pos.key === props.selectWidgetId && <PlaceholderIcon />}
<PlaceholderType
pos={props.pos}
xyPostion={props.xyPostion}
index={props.index}
setXyPostion={props.setXyPostion}
data={props.data}
setSignKey={props.setSignKey}
isShowDropdown={props?.isShowDropdown}
isPlaceholder={props.isPlaceholder}
isSignYourself={props.isSignYourself}
signerObjId={props.signerObjId}
handleUserName={props.handleUserName}
setDraggingEnabled={setDraggingEnabled}
pdfDetails={props?.pdfDetails && props?.pdfDetails[0]}
isNeedSign={props.isNeedSign}
setSelectDate={setSelectDate}
selectDate={selectDate}
setValidateAlert={props.setValidateAlert}
setStartDate={setStartDate}
startDate={startDate}
handleSaveDate={handleSaveDate}
xPos={props.xPos}
calculateFont={calculateFont}
/>
</div>
) : (
<>
{props.pos.key === props.selectWidgetId && <PlaceholderIcon />}
<PlaceholderType
pos={props.pos}
xyPostion={props.xyPostion}
index={props.index}
setXyPostion={props.setXyPostion}
data={props.data}
setSignKey={props.setSignKey}
isShowDropdown={props?.isShowDropdown}
isPlaceholder={props.isPlaceholder}
isSignYourself={props.isSignYourself}
signerObjId={props.signerObjId}
handleUserName={props.handleUserName}
setDraggingEnabled={setDraggingEnabled}
pdfDetails={props?.pdfDetails && props?.pdfDetails[0]}
isNeedSign={props.isNeedSign}
setSelectDate={setSelectDate}
selectDate={selectDate}
setValidateAlert={props.setValidateAlert}
setStartDate={setStartDate}
startDate={startDate}
handleSaveDate={handleSaveDate}
xPos={props.xPos}
calculateFont={calculateFont}
/>
</>
)}
</Rnd>
<ModalUi isOpen={isDateModal} title={t("widget-info")} showClose={false}>
<div className="h-[100%] p-[20px]">
<div className="flex flex-row items-center">
<span>{t("format")} : </span>
<div className="flex">
<select
className="ml-[7px] op-select op-select-bordered op-select-sm focus:outline-none hover:border-base-content text-xs"
defaultValue={""}
onChange={(e) => {
const selectedIndex = e.target.value;
e.stopPropagation();
setSelectDate(dateFormat[selectedIndex]);
}}
>
<option value="" disabled>
{t("select-date-format")}
</option>
{dateFormat.map((data, ind) => {
return (
<option className="text-[13px]" value={ind} key={ind}>
{data?.date ? data?.date : "nodata"}
</option>
);
})}
</select>
</div>
<span className="text-xs text-gray-400 ml-1">
{selectDate.format}
</span>
</div>
<div className="flex items-center mt-4 md:mt-2">
<span>{t("font-size")} :</span>
<select
className="ml-[3px] md:ml:[7px] op-select op-select-bordered op-select-sm focus:outline-none hover:border-base-content text-xs"
value={props.fontSize || clickonWidget.options?.fontSize || 12}
onChange={(e) => props.setFontSize(parseInt(e.target.value))}
>
{fontsizeArr.map((size, ind) => {
return (
<option className="text-[13px]" value={size} key={ind}>
{size}
</option>
);
})}
</select>
<div className="flex flex-row gap-1 items-center ml-2 md:ml-4 ">
<span>{t("color")}: </span>
<select
value={
props.fontColor || clickonWidget.options?.fontColor || "black"
}
onChange={(e) => props.setFontColor(e.target.value)}
className="ml-[4px] md:ml[7px] op-select op-select-bordered op-select-sm focus:outline-none hover:border-base-content text-xs"
>
{fontColorArr.map((color, ind) => {
return (
<option value={color} key={ind}>
{t(`color-type.${color}`)}
</option>
);
})}
</select>
<span
style={{
background:
props.fontColor || props.pos.options?.fontColor || "black"
}}
className="w-5 h-[19px] ml-1"
></span>
</div>
</div>
<div className="h-[1px] w-full my-[15px] bg-[#9f9f9f]"></div>
<button
type="button"
className="op-btn op-btn-primary"
onClick={() => {
setIsDateModal(false);
handleSaveDate(selectDate);
props.setFontColor("");
props.setFontSize("");
}}
>
{t("save")}
</button>
</div>
) : (
<>
{props.pos.key === props.selectWidgetId && <PlaceholderIcon />}
<PlaceholderType
pos={props.pos}
xyPostion={props.xyPostion}
index={props.index}
setXyPostion={props.setXyPostion}
data={props.data}
setSignKey={props.setSignKey}
isShowDropdown={props?.isShowDropdown}
isPlaceholder={props.isPlaceholder}
isSignYourself={props.isSignYourself}
signerObjId={props.signerObjId}
handleUserName={props.handleUserName}
setDraggingEnabled={setDraggingEnabled}
pdfDetails={props?.pdfDetails && props?.pdfDetails[0]}
isNeedSign={props.isNeedSign}
setSelectDate={setSelectDate}
selectDate={selectDate}
setValidateAlert={props.setValidateAlert}
setStartDate={setStartDate}
startDate={startDate}
handleSaveDate={handleSaveDate}
xPos={props.xPos}
/>
</>
)}
</Rnd>
</ModalUi>
</>
);
}
@@ -1,10 +1,21 @@
import React, { useState } from "react";
import ModalUi from "../../primitives/ModalUi";
import { randomId, textWidget } from "../../constant/Utils";
import {
handleCopyNextToWidget,
randomId,
textWidget
} from "../../constant/Utils";
import { useTranslation } from "react-i18next";
function PlaceholderCopy(props) {
const copyType = ["All pages", "All pages but last", "All pages but first"];
const [selectCopyType, setSelectCopyType] = useState("");
const { t } = useTranslation();
const copyType = [
{ id: 1, type: "All pages" },
{ id: 2, type: "All pages but last" },
{ id: 3, type: "All pages but first" },
{ id: 4, type: "Next to current widget" }
];
const [selectCopyType, setSelectCopyType] = useState(1);
//function for get copy placeholder position
const getCopyPlaceholderPosition = (
type,
@@ -18,7 +29,7 @@ function PlaceholderCopy(props) {
(data) => data.xPosition !== currentPlaceholder.xPosition
);
//copy all page placeholder at requested position except first page
if (newPageNumber === 1 && type === "first") {
if (newPageNumber === 1 && type === 3) {
if (filterPosition && filterPosition.length > 0) {
return {
pageNumber: newPageNumber,
@@ -27,7 +38,7 @@ function PlaceholderCopy(props) {
}
}
//copy all page placeholder at requested position except last page
else if (newPageNumber === props.allPages && type === "last") {
else if (newPageNumber === props.allPages && type === 2) {
if (existPlaceholderPosition) {
return {
pageNumber: newPageNumber,
@@ -170,25 +181,65 @@ function PlaceholderCopy(props) {
//function for getting selected type placeholder copy
const handleApplyCopy = () => {
if (selectCopyType === "All pages") {
copyPlaceholder("all");
} else if (selectCopyType === "All pages but last") {
copyPlaceholder("last");
} else if (selectCopyType === "All pages but first") {
copyPlaceholder("first");
if (selectCopyType === 4) {
const signerPosition = props.xyPostion;
let currentXYposition;
const signerId = props.signerObjId ? props.signerObjId : props.Id;
if (signerId) {
const filterSignerPosition = signerPosition.filter(
(item) => item?.Id === signerId
);
currentXYposition = filterSignerPosition[0].placeHolder.filter(
(data) => data.pageNumber === props?.pageNumber
);
//get current placeholder position data which user want to copy
currentXYposition = currentXYposition[0].pos.find(
(position) => position.key === props.signKey
);
//function to create new widget next to just widget
handleCopyNextToWidget(
currentXYposition,
props.widgetType,
props.xyPostion,
props.pageNumber,
props.setXyPostion,
props?.Id
);
} else {
const getIndex = props?.xyPostion.findIndex(
(data) => data.pageNumber === props.pageNumber
);
const placeholderPosition = props?.xyPostion[getIndex];
//get current placeholder position data which user want to copy
currentXYposition = placeholderPosition.pos.find(
(pos) => pos.key === props.signKey
);
//function to create new widget next to just widget
handleCopyNextToWidget(
currentXYposition,
props.widgetType,
props.xyPostion,
getIndex,
props.setXyPostion
);
}
} else {
copyPlaceholder(selectCopyType);
}
};
const handleUniqueId = () => {
if (props.widgetType === textWidget) {
const signerId = props.signerObjId ? props.signerObjId : props.Id;
if (signerId && props.widgetType === textWidget) {
props.setUniqueId(props?.tempSignerId);
props.setTempSignerId("");
}
props.setIsPageCopy(false);
setSelectCopyType(1);
};
return (
<ModalUi
isOpen={props.isPageCopy}
title={"Copy to all pages"}
title={t("copy-title")}
handleClose={() => handleUniqueId()}
>
<div className="h-full p-[20px] text-base-content">
@@ -199,12 +250,11 @@ function PlaceholderCopy(props) {
<input
className="mr-[8px] op-radio op-radio-xs"
type="radio"
value={data}
onChange={() => setSelectCopyType(data)}
checked={selectCopyType === data}
value={data.id}
onChange={() => setSelectCopyType(data.id)}
checked={selectCopyType === data.id}
/>
{data}
{t(`copy-type.${data.type}`)}
</label>
</div>
);
@@ -220,14 +270,14 @@ function PlaceholderCopy(props) {
disabled={!selectCopyType}
className="op-btn op-btn-primary"
>
Apply
{t("apply")}
</button>
<button
type="button"
className="op-btn op-btn-ghost"
onClick={() => handleUniqueId()}
>
Cancel
{t("cancel")}
</button>
</div>
</ModalUi>
@@ -14,18 +14,23 @@ import "react-datepicker/dist/react-datepicker.css";
import "../../styles/signature.css";
import RegexParser from "regex-parser";
import { emailRegex } from "../../constant/const";
import { useTranslation } from "react-i18next";
const textWidgetCls =
"w-full h-full md:min-w-full md:min-h-full z-[999] text-[12px] rounded-[2px] border-[1px] border-[#007bff] overflow-hidden resize-none outline-none text-base-content item-center whitespace-pre-wrap bg-white";
const selectWidgetCls =
"w-full h-full absolute left-0 top-0 border-[1px] border-[#007bff] rounded-[2px] focus:outline-none text-base-content";
function PlaceholderType(props) {
const { t } = useTranslation();
const type = props?.pos?.type;
const widgetTypeTraslation = t(`widgets-name.${props?.pos?.type}`);
const [selectOption, setSelectOption] = useState("");
const [validatePlaceholder, setValidatePlaceholder] = useState("");
const inputRef = useRef(null);
const [textValue, setTextValue] = useState();
const [selectedCheckbox, setSelectedCheckbox] = useState([]);
const years = range(1990, getYear(new Date()) + 16, 1);
const fontSize = props.calculateFont(props.pos.options?.fontSize);
const fontColor = props.pos.options?.fontColor || "black";
const months = [
"January",
"February",
@@ -140,7 +145,12 @@ function PlaceholderType(props) {
const ExampleCustomInput = forwardRef(({ value, onClick }, ref) => (
<div
className={`${selectWidgetCls} text-[12px] overflow-hidden`}
style={{
fontSize: fontSize,
color: fontColor,
fontFamily: "Arial, sans-serif"
}}
className={`${selectWidgetCls} overflow-hidden`}
onClick={onClick}
ref={ref}
>
@@ -311,7 +321,7 @@ function PlaceholderType(props) {
props?.handleUserName(
props?.data?.Id,
props?.data?.Role,
props?.pos?.type
widgetTypeTraslation
)}
</div>
);
@@ -329,7 +339,7 @@ function PlaceholderType(props) {
props?.handleUserName(
props?.data?.Id,
props?.data?.Role,
props?.pos?.type
widgetTypeTraslation
)}
</div>
);
@@ -340,9 +350,13 @@ function PlaceholderType(props) {
return (
<div key={ind} className="flex items-center text-center gap-0.5">
<input
style={{
width: fontSize,
height: fontSize
}}
className={`${
ind === 0 ? "mt-0" : "mt-[5px]"
} flex justify-center op-checkbox op-checkbox-xs rounded-[0.350rem]`}
} flex justify-center op-checkbox rounded-[1px] `}
onBlur={handleInputBlur}
disabled={
props.isNeedSign &&
@@ -376,7 +390,15 @@ function PlaceholderType(props) {
}}
/>
{!props.pos.options?.isHideLabel && (
<label className="text-xs mb-0 text-center">{data}</label>
<label
style={{
fontSize: fontSize,
color: fontColor
}}
className="text-xs mb-0 text-center"
>
{data}
</label>
)}
</div>
);
@@ -407,29 +429,29 @@ function PlaceholderType(props) {
}}
className={textWidgetCls}
style={{
fontSize: props.pos.options?.fontSize
? props.pos.options?.fontSize + "px"
: "12px",
color: props.pos.options?.fontColor || "black"
fontSize: fontSize,
color: fontColor
}}
cols="50"
/>
) : (
<div
style={{
fontSize: props.pos.options?.fontSize
? props.pos.options?.fontSize + "px"
: "12px",
color: props.pos.options?.fontColor || "black",
fontSize: fontSize,
color: fontColor,
overflow: "hidden"
}}
>
<span>{type}</span>
<span>{widgetTypeTraslation}</span>
</div>
);
case "dropdown":
return props.data?.signerObjId === props.signerObjId ? (
<select
style={{
fontSize: fontSize,
color: fontColor
}}
className={`${selectWidgetCls} text-[12px] bg-inherit`}
id="myDropdown"
value={selectOption}
@@ -447,21 +469,44 @@ function PlaceholderType(props) {
}}
>
{/* Default/Title option */}
<option value="" disabled hidden>
<option
style={{
fontSize: fontSize,
color: fontColor
}}
value=""
disabled
hidden
>
{props?.pos?.options?.name}
</option>
{props.pos?.options?.values?.map((data, ind) => {
return (
<option key={ind} value={data}>
<option
style={{
fontSize: fontSize,
color: fontColor
}}
key={ind}
value={data}
>
{data}
</option>
);
})}
</select>
) : (
<div className="text-[12px] overflow-hidden">
{props.pos?.options?.name ? props.pos.options.name : type}
<div
style={{
fontSize: fontSize,
color: fontColor
}}
className=" overflow-hidden"
>
{props.pos?.options?.name
? props.pos.options.name
: widgetTypeTraslation}
</div>
);
case "initials":
@@ -478,7 +523,7 @@ function PlaceholderType(props) {
props?.handleUserName(
props?.data?.Id,
props?.data?.Role,
props?.pos?.type
widgetTypeTraslation
)}
</div>
);
@@ -506,25 +551,21 @@ function PlaceholderType(props) {
}}
className={textWidgetCls}
style={{
fontSize: props.pos.options?.fontSize
? props.pos.options?.fontSize + "px"
: "12px",
color: props.pos.options?.fontColor || "black"
fontSize: fontSize,
color: fontColor
}}
cols="50"
/>
) : (
<div
style={{
fontSize: props.pos.options?.fontSize
? props.pos.options?.fontSize + "px"
: "12px",
color: props.pos.options?.fontColor || "black",
fontSize: fontSize,
color: fontColor,
fontFamily: "Arial, sans-serif",
overflow: "hidden"
}}
>
<span>{type}</span>
<span>{widgetTypeTraslation}</span>
</div>
);
case "company":
@@ -550,25 +591,21 @@ function PlaceholderType(props) {
}}
className={textWidgetCls}
style={{
fontSize: props.pos.options?.fontSize
? props.pos.options?.fontSize + "px"
: "12px",
color: props.pos.options?.fontColor || "black"
fontSize: fontSize,
color: fontColor
}}
cols="50"
/>
) : (
<div
style={{
fontSize: props.pos.options?.fontSize
? props.pos.options?.fontSize + "px"
: "12px",
color: props.pos.options?.fontColor || "black",
fontSize: fontSize,
color: fontColor,
overflow: "hidden",
fontFamily: "Arial, sans-serif"
}}
>
<span>{type}</span>
<span>{widgetTypeTraslation}</span>
</div>
);
case "job title":
@@ -594,25 +631,21 @@ function PlaceholderType(props) {
}}
className={textWidgetCls}
style={{
fontSize: props.pos.options?.fontSize
? props.pos.options?.fontSize + "px"
: "12px",
color: props.pos.options?.fontColor || "black"
fontSize: fontSize,
color: fontColor
}}
cols="50"
/>
) : (
<div
style={{
fontSize: props.pos.options?.fontSize
? props.pos.options?.fontSize + "px"
: "12px",
color: props.pos.options?.fontColor || "black",
fontSize: fontSize,
color: fontColor,
fontFamily: "Arial, sans-serif",
overflow: "hidden"
}}
>
<span>{type}</span>
<span>{widgetTypeTraslation}</span>
</div>
);
case "date":
@@ -675,7 +708,14 @@ function PlaceholderType(props) {
/>
</div>
) : (
<div className="text-[12px] text-black items-center overflow-hidden">
<div
style={{
fontSize: fontSize,
color: fontColor,
fontFamily: "Arial, sans-serif"
}}
className="items-center overflow-hidden"
>
<span>
{props.selectDate
? props.selectDate?.format
@@ -699,7 +739,7 @@ function PlaceholderType(props) {
props?.handleUserName(
props?.data?.Id,
props?.data?.Role,
props?.pos?.type
widgetTypeTraslation
)}
</div>
);
@@ -727,10 +767,8 @@ function PlaceholderType(props) {
}}
className={textWidgetCls}
style={{
fontSize: props.pos.options?.fontSize
? props.pos.options?.fontSize + "px"
: "12px",
color: props.pos.options?.fontColor || "black",
fontSize: fontSize,
color: fontColor,
fontFamily: "Arial, sans-serif"
}}
cols="50"
@@ -738,15 +776,13 @@ function PlaceholderType(props) {
) : (
<div
style={{
fontSize: props.pos.options?.fontSize
? props.pos.options?.fontSize + "px"
: "12px",
color: props.pos.options?.fontColor || "black",
fontSize: fontSize,
color: fontColor,
fontFamily: "Arial, sans-serif",
overflow: "hidden"
}}
>
<span>{type}</span>
<span>{widgetTypeTraslation}</span>
</div>
);
case radioButtonWidget:
@@ -756,9 +792,12 @@ function PlaceholderType(props) {
return (
<div key={ind} className="flex items-center text-center gap-0.5">
<input
className={`${
ind === 0 ? "mt-0" : "mt-[5px]"
} ${"w-[15px] h-[15px]"} flex justify-center op-radio`}
style={{
width: fontSize,
height: fontSize,
marginTop: ind > 0 ? "10px" : "0px"
}}
className={`flex justify-center op-radio`}
type="radio"
disabled={
props.isNeedSign &&
@@ -773,7 +812,15 @@ function PlaceholderType(props) {
}}
/>
{!props.pos.options?.isHideLabel && (
<label className="text-xs mb-0">{data}</label>
<label
style={{
fontSize: fontSize,
color: fontColor
}}
className="text-xs mb-0"
>
{data}
</label>
)}
</div>
);
@@ -803,10 +850,8 @@ function PlaceholderType(props) {
className={textWidgetCls}
style={{
fontFamily: "Arial, sans-serif",
fontSize: props.pos.options?.fontSize
? props.pos.options?.fontSize + "px"
: "12px",
color: props.pos.options?.fontColor || "black"
fontSize: fontSize,
color: fontColor
}}
cols="50"
/>
+5 -5
View File
@@ -1,6 +1,8 @@
import React from "react";
import { useTranslation } from "react-i18next";
function PrevNext({ pageNumber, allPages, changePage }) {
const { t } = useTranslation();
//for go to previous page
function previousPage() {
changePage(-1);
@@ -17,23 +19,21 @@ function PrevNext({ pageNumber, allPages, changePage }) {
disabled={pageNumber <= 1}
onClick={previousPage}
>
<span className="block lg:hidden">
<span className="block">
<i className="fa-light fa-backward" aria-hidden="true"></i>
</span>
<span className="lg:block hidden 2xl:text-[30px]">Prev</span>
</button>
<span className="text-xs text-base-content font-medium mx-2 2xl:text-[30px]">
{pageNumber || (allPages ? 1 : "--")} of {allPages || "--"}
{pageNumber || (allPages ? 1 : "--")} {t("of")} {allPages || "--"}
</span>
<button
className="op-btn op-btn-neutral op-btn-xs md:op-btn-sm font-semibold text-xs"
disabled={pageNumber >= allPages}
onClick={nextPage}
>
<span className="block lg:hidden">
<span className="block">
<i className="fa-light fa-forward" aria-hidden="true"></i>
</span>
<span className="lg:block hidden 2xl:text-[30px]">Next</span>
</button>
</div>
);
@@ -16,7 +16,7 @@ const RecipientList = (props) => {
//function for onhover signer name change background color
const inputRef = useRef(null);
const isWidgetExist = (Id) => {
return props.signerPos.some((x) => x.Id === Id);
return props.signerPos.some((x) => x.Id === Id && x.placeHolder);
};
//handle drag start
@@ -63,9 +63,7 @@ const RecipientList = (props) => {
remainingItems.splice(index, 0, ...draggedItem);
//set current draggable recipient details,objectId,index,contract_className ... after replace recipient list
props?.setSignersData(remainingItems);
props?.setSignerObjId(remainingItems[index]?.objectId || "");
props?.setIsSelectId(index);
props?.setContractName(remainingItems[index]?.className || "");
props?.setUniqueId(remainingItems[index]?.Id);
props?.setRoleName(remainingItems[index]?.Role);
props?.setBlockColor(remainingItems[index]?.blockColor);
@@ -121,9 +119,7 @@ const RecipientList = (props) => {
}}
onClick={(e) => {
e.preventDefault();
props.setSignerObjId(obj?.objectId || "");
props.setIsSelectId(ind);
props.setContractName(obj?.className || "");
props.setUniqueId(obj.Id);
props.setRoleName(obj.Role);
props.setBlockColor(obj?.blockColor);
@@ -1,4 +1,5 @@
import React, { useEffect, useRef, useState } from "react";
import { useTranslation } from "react-i18next";
import { Document, Page } from "react-pdf";
import { useSelector } from "react-redux";
@@ -11,8 +12,10 @@ function RenderAllPdfPage({
pageNumber,
signerPos,
signerObjectId,
containerWH
containerWH,
pdfRotateBase64
}) {
const { t } = useTranslation();
const [signPageNumber, setSignPageNumber] = useState([]);
const [bookmarkColor, setBookmarkColor] = useState("");
//set all number of pages after load pdf
@@ -64,19 +67,20 @@ function RenderAllPdfPage({
)
);
};
const pdfDataBase64 = `data:application/pdf;base64,${pdfRotateBase64}`;
return (
<div ref={pageContainer} className="hidden w-[20%] bg-base-100 md:block">
<div className="mx-2 pr-2 pt-2 pb-1 text-[15px] text-base-content font-semibold border-b-[1px] border-base-300">
Pages
{t("pages")}
</div>
<div
className={`flex h-[90%] flex-col items-center m-2
autoSignScroll hide-scrollbar max-h-[100vh] `}
>
<Document
loading={"Loading Document.."}
loading={t("loading-doc")}
onLoadSuccess={onDocumentLoad}
file={signPdfUrl}
file={(pdfRotateBase64 && pdfDataBase64) || signPdfUrl}
>
{Array.from(new Array(allPages), (el, index) => (
<div
@@ -93,16 +97,16 @@ function RenderAllPdfPage({
>
{signerPos && addSignatureBookmark(index)}
<div className="relative z-[1] overflow-hidden">
<Page
key={`page_${index + 1}`}
pageNumber={index + 1}
width={pageWidth - 60}
scale={1}
renderAnnotationLayer={false}
renderTextLayer={false}
/>
</div>
{/* <div className="relative z-[1] overflow-hidden"> */}
<Page
key={`page_${index + 1}`}
pageNumber={index + 1}
width={pageWidth - 60}
scale={1}
renderAnnotationLayer={false}
renderTextLayer={false}
/>
{/* </div> */}
</div>
))}
</Document>
+268 -218
View File
@@ -9,6 +9,7 @@ import {
} from "../../constant/Utils";
import Placeholder from "./Placeholder";
import Alert from "../../primitives/Alert";
import { useTranslation } from "react-i18next";
function RenderPdf({
pageNumber,
@@ -24,7 +25,6 @@ function RenderPdf({
setSignKey,
pdfDetails,
xyPostion,
pdfUrl,
pageDetails,
pdfRequest,
signerObjectId,
@@ -41,7 +41,6 @@ function RenderPdf({
setUniqueId,
signersdata,
setIsPageCopy,
setSignerObjId,
setShowDropdown,
setIsInitial,
setIsValidate,
@@ -61,9 +60,17 @@ function RenderPdf({
scale,
setIsSelectId,
ispublicTemplate,
handleUserDetails
handleUserDetails,
pdfRotateBase64,
fontSize,
setFontSize,
fontColor,
setFontColor,
isResize
}) {
const { t } = useTranslation();
const isMobile = window.innerWidth < 767;
//check isGuestSigner is present in local if yes than handle login flow header in mobile view
const isGuestSigner = localStorage.getItem("isGuestSigner");
@@ -98,6 +105,7 @@ function RenderPdf({
}
}
};
const posHeight = (pos, signYourself) => {
const containerScale = getContainerScale(
pdfOriginalWH,
@@ -201,6 +209,7 @@ function RenderPdf({
pageNumber={pageNumber}
ispublicTemplate={ispublicTemplate}
handleUserDetails={handleUserDetails}
isResize={isResize}
/>
</React.Fragment>
)
@@ -247,154 +256,185 @@ function RenderPdf({
);
}
};
const pdfDataBase64 = `data:application/pdf;base64,${pdfRotateBase64}`;
return (
<>
{successEmail && <Alert type={"success"}>Email sent successfully!</Alert>}
{successEmail && (
<Alert type={"success"}>{t("success-email-alert")}</Alert>
)}
{isMobile ? (
<div
data-tut="reactourForth"
className={`${
isGuestSigner ? "30px" : ""
} border-[0.1px] border-[#ebe8e8]`}
ref={drop}
id="container"
<RSC
style={{
position: "relative",
boxShadow: "rgba(17, 12, 46, 0.15) 0px 48px 100px 0px",
height: window.innerHeight - 200,
zIndex: 0
}}
className="h-full"
noScrollY={false}
noScrollX={scale === 1 ? true : false}
>
{containerWH?.width &&
pdfOriginalWH.length > 0 &&
(pdfRequest
? signerPos.map((data, key) => {
return (
<React.Fragment key={key}>
{checkSignedSigners(data)}
</React.Fragment>
);
})
: placeholder // placeholder mobile
? signerPos.map((data, ind) => {
<div
data-tut="reactourForth"
className={`${
isGuestSigner ? "30px" : ""
} border-[0.1px] border-[#ebe8e8] overflow-x-auto`}
style={{
width: containerWH?.width && containerWH?.width * scale
}}
ref={drop}
id="container"
>
{containerWH?.width &&
pdfOriginalWH.length > 0 &&
(pdfRequest
? signerPos.map((data, key) => {
return (
<React.Fragment key={ind}>
{data.placeHolder.map((placeData, index) => {
return (
<React.Fragment key={index}>
{placeData.pageNumber === pageNumber &&
placeData.pos.map((pos) => {
return (
<React.Fragment key={pos.key}>
<Placeholder
pos={pos}
setIsPageCopy={setIsPageCopy}
setSignKey={setSignKey}
handleDeleteSign={handleDeleteSign}
setIsStamp={setIsStamp}
handleTabDrag={handleTabDrag}
handleStop={handleStop}
handleSignYourselfImageResize={
handleImageResize
}
index={pageNumber}
xyPostion={signerPos}
setXyPostion={setSignerPos}
setSignerObjId={setSignerObjId}
data={data}
setIsResize={setIsResize}
setShowDropdown={setShowDropdown}
isShowBorder={true}
isPlaceholder={true}
setUniqueId={setUniqueId}
handleLinkUser={handleLinkUser}
handleUserName={handleUserName}
isSignYourself={false}
posWidth={posWidth}
posHeight={posHeight}
isDragging={isDragging}
setIsValidate={setIsValidate}
setWidgetType={setWidgetType}
setIsRadio={setIsRadio}
setIsCheckbox={setIsCheckbox}
setCurrWidgetsDetails={
setCurrWidgetsDetails
}
setSelectWidgetId={setSelectWidgetId}
selectWidgetId={selectWidgetId}
handleNameModal={handleNameModal}
setTempSignerId={setTempSignerId}
uniqueId={uniqueId}
handleTextSettingModal={
handleTextSettingModal
}
scale={scale}
containerWH={containerWH}
pdfOriginalWH={pdfOriginalWH}
pageNumber={pageNumber}
setIsSelectId={setIsSelectId}
/>
</React.Fragment>
);
})}
</React.Fragment>
);
})}
<React.Fragment key={key}>
{checkSignedSigners(data)}
</React.Fragment>
);
})
: xyPostion.map((data, ind) => {
return (
<React.Fragment key={ind}>
{data.pageNumber === pageNumber &&
data.pos.map((pos) => {
return (
pos && (
<Placeholder
pos={pos}
setIsPageCopy={setIsPageCopy}
setSignKey={setSignKey}
handleDeleteSign={handleDeleteSign}
setIsStamp={setIsStamp}
handleTabDrag={handleTabDrag}
handleStop={handleStop}
handleSignYourselfImageResize={
handleSignYourselfImageResize
}
index={index}
xyPostion={xyPostion}
setXyPostion={setXyPostion}
containerWH={containerWH}
setIsSignPad={setIsSignPad}
isShowBorder={true}
isSignYourself={true}
posWidth={posWidth}
posHeight={posHeight}
pdfDetails={pdfDetails[0]}
isDragging={isDragging}
setIsInitial={setIsInitial}
setWidgetType={setWidgetType}
setSelectWidgetId={setSelectWidgetId}
selectWidgetId={selectWidgetId}
handleUserName={handleUserName}
setIsCheckbox={setIsCheckbox}
setValidateAlert={setValidateAlert}
setCurrWidgetsDetails={setCurrWidgetsDetails}
handleTextSettingModal={
handleTextSettingModal
}
scale={scale}
pdfOriginalWH={pdfOriginalWH}
pageNumber={pageNumber}
/>
)
);
})}
</React.Fragment>
);
}))}
: placeholder // placeholder mobile
? signerPos?.map((data, ind) => {
return (
<React.Fragment key={ind}>
{data?.placeHolder &&
data?.placeHolder.map((placeData, index) => {
return (
<React.Fragment key={index}>
{placeData.pageNumber === pageNumber &&
placeData.pos.map((pos) => {
return (
<React.Fragment key={pos.key}>
<Placeholder
pos={pos}
setIsPageCopy={setIsPageCopy}
setSignKey={setSignKey}
handleDeleteSign={handleDeleteSign}
setIsStamp={setIsStamp}
handleTabDrag={handleTabDrag}
handleStop={handleStop}
handleSignYourselfImageResize={
handleImageResize
}
index={pageNumber}
xyPostion={signerPos}
setXyPostion={setSignerPos}
data={data}
setIsResize={setIsResize}
setShowDropdown={setShowDropdown}
isShowBorder={true}
isPlaceholder={true}
setUniqueId={setUniqueId}
handleLinkUser={handleLinkUser}
handleUserName={handleUserName}
isSignYourself={false}
posWidth={posWidth}
posHeight={posHeight}
isDragging={isDragging}
setIsValidate={setIsValidate}
setWidgetType={setWidgetType}
setIsRadio={setIsRadio}
setIsCheckbox={setIsCheckbox}
setCurrWidgetsDetails={
setCurrWidgetsDetails
}
setSelectWidgetId={
setSelectWidgetId
}
selectWidgetId={selectWidgetId}
handleNameModal={handleNameModal}
setTempSignerId={setTempSignerId}
uniqueId={uniqueId}
handleTextSettingModal={
handleTextSettingModal
}
scale={scale}
containerWH={containerWH}
pdfOriginalWH={pdfOriginalWH}
pageNumber={pageNumber}
setIsSelectId={setIsSelectId}
fontSize={fontSize}
setFontSize={setFontSize}
fontColor={fontColor}
setFontColor={setFontColor}
isResize={isResize}
unSignedWidgetId={unSignedWidgetId}
/>
</React.Fragment>
);
})}
</React.Fragment>
);
})}
</React.Fragment>
);
})
: !pdfDetails?.[0]?.IsCompleted &&
xyPostion.map((data, ind) => {
return (
<React.Fragment key={ind}>
{data.pageNumber === pageNumber &&
data.pos.map((pos) => {
return (
pos && (
<Placeholder
pos={pos}
setIsPageCopy={setIsPageCopy}
setSignKey={setSignKey}
handleDeleteSign={handleDeleteSign}
setIsStamp={setIsStamp}
handleTabDrag={handleTabDrag}
handleStop={handleStop}
handleSignYourselfImageResize={
handleSignYourselfImageResize
}
index={index}
xyPostion={xyPostion}
setXyPostion={setXyPostion}
containerWH={containerWH}
setIsSignPad={setIsSignPad}
isShowBorder={true}
isSignYourself={true}
posWidth={posWidth}
posHeight={posHeight}
pdfDetails={pdfDetails[0]}
isDragging={isDragging}
setIsInitial={setIsInitial}
setWidgetType={setWidgetType}
setSelectWidgetId={setSelectWidgetId}
selectWidgetId={selectWidgetId}
handleUserName={handleUserName}
setIsCheckbox={setIsCheckbox}
setValidateAlert={setValidateAlert}
setCurrWidgetsDetails={
setCurrWidgetsDetails
}
handleTextSettingModal={
handleTextSettingModal
}
scale={scale}
pdfOriginalWH={pdfOriginalWH}
pageNumber={pageNumber}
fontSize={fontSize}
setFontSize={setFontSize}
fontColor={fontColor}
setFontColor={setFontColor}
isResize={isResize}
setIsResize={setIsResize}
/>
)
);
})}
</React.Fragment>
);
}))}
{/* this component for render pdf document is in middle of the component */}
<div className="flex items-center justify-center">
<Document
onLoadError={() => {
setPdfLoad(false);
}}
loading={"Loading Document.."}
onLoadError={() => setPdfLoad(false)}
loading={t("loading-doc")}
onLoadSuccess={pageDetails}
// ref={pdfRef}'
onClick={() => {
@@ -403,14 +443,13 @@ function RenderPdf({
}
}}
file={
pdfUrl
? pdfUrl
: pdfDetails[0] && pdfDetails[0].SignedUrl
? pdfDetails[0].SignedUrl
: pdfDetails[0].URL
(pdfRotateBase64 && pdfDataBase64) ||
pdfDetails[0]?.SignedUrl ||
pdfDetails[0].URL
}
>
<Page
scale={scale || 1}
key={index}
pageNumber={pageNumber}
width={containerWH.width}
@@ -422,7 +461,7 @@ function RenderPdf({
/>
</Document>
</div>
</div>
</RSC>
) : (
<RSC
style={{
@@ -456,71 +495,80 @@ function RenderPdf({
? signerPos.map((data, ind) => {
return (
<React.Fragment key={ind}>
{data.placeHolder.map((placeData, index) => {
return (
<React.Fragment key={index}>
{placeData.pageNumber === pageNumber &&
placeData.pos.map((pos) => {
return (
<React.Fragment key={pos.key}>
<Placeholder
pos={pos}
setIsPageCopy={setIsPageCopy}
setSignKey={setSignKey}
handleDeleteSign={handleDeleteSign}
setIsStamp={setIsStamp}
handleTabDrag={handleTabDrag}
handleStop={handleStop}
handleSignYourselfImageResize={
handleImageResize
}
index={pageNumber}
xyPostion={signerPos}
setXyPostion={setSignerPos}
setSignerObjId={setSignerObjId}
data={data}
setIsResize={setIsResize}
setShowDropdown={setShowDropdown}
isShowBorder={true}
isPlaceholder={true}
setUniqueId={setUniqueId}
handleLinkUser={handleLinkUser}
handleUserName={handleUserName}
isSignYourself={false}
posWidth={posWidth}
posHeight={posHeight}
isDragging={isDragging}
setIsValidate={setIsValidate}
setWidgetType={setWidgetType}
setIsRadio={setIsRadio}
setIsCheckbox={setIsCheckbox}
setCurrWidgetsDetails={
setCurrWidgetsDetails
}
setSelectWidgetId={setSelectWidgetId}
selectWidgetId={selectWidgetId}
handleNameModal={handleNameModal}
setTempSignerId={setTempSignerId}
uniqueId={uniqueId}
handleTextSettingModal={
handleTextSettingModal
}
scale={scale}
containerWH={containerWH}
pdfOriginalWH={pdfOriginalWH}
pageNumber={pageNumber}
setIsSelectId={setIsSelectId}
/>
</React.Fragment>
);
})}
</React.Fragment>
);
})}
{data?.placeHolder &&
data?.placeHolder.map((placeData, index) => {
return (
<React.Fragment key={index}>
{placeData.pageNumber === pageNumber &&
placeData.pos.map((pos) => {
return (
<React.Fragment key={pos.key}>
<Placeholder
pos={pos}
setIsPageCopy={setIsPageCopy}
setSignKey={setSignKey}
handleDeleteSign={handleDeleteSign}
setIsStamp={setIsStamp}
handleTabDrag={handleTabDrag}
handleStop={handleStop}
handleSignYourselfImageResize={
handleImageResize
}
index={pageNumber}
xyPostion={signerPos}
setXyPostion={setSignerPos}
data={data}
setIsResize={setIsResize}
setShowDropdown={setShowDropdown}
isShowBorder={true}
isPlaceholder={true}
setUniqueId={setUniqueId}
handleLinkUser={handleLinkUser}
handleUserName={handleUserName}
isSignYourself={false}
posWidth={posWidth}
posHeight={posHeight}
isDragging={isDragging}
setIsValidate={setIsValidate}
setWidgetType={setWidgetType}
setIsRadio={setIsRadio}
setIsCheckbox={setIsCheckbox}
setCurrWidgetsDetails={
setCurrWidgetsDetails
}
setSelectWidgetId={
setSelectWidgetId
}
selectWidgetId={selectWidgetId}
handleNameModal={handleNameModal}
setTempSignerId={setTempSignerId}
uniqueId={uniqueId}
handleTextSettingModal={
handleTextSettingModal
}
scale={scale}
containerWH={containerWH}
pdfOriginalWH={pdfOriginalWH}
pageNumber={pageNumber}
setIsSelectId={setIsSelectId}
fontSize={fontSize}
setFontSize={setFontSize}
fontColor={fontColor}
setFontColor={setFontColor}
isResize={isResize}
unSignedWidgetId={unSignedWidgetId}
/>
</React.Fragment>
);
})}
</React.Fragment>
);
})}
</React.Fragment>
);
})
: xyPostion.map((data, ind) => {
: !pdfDetails?.[0]?.IsCompleted &&
xyPostion?.map((data, ind) => {
// signyourself flow
return (
<React.Fragment key={ind}>
@@ -568,6 +616,12 @@ function RenderPdf({
containerWH={containerWH}
pdfOriginalWH={pdfOriginalWH}
pageNumber={pageNumber}
fontSize={fontSize}
setFontSize={setFontSize}
fontColor={fontColor}
setFontColor={setFontColor}
isResize={isResize}
setIsResize={setIsResize}
/>
</React.Fragment>
);
@@ -578,10 +632,8 @@ function RenderPdf({
{/* this component for render pdf document is in middle of the component */}
<Document
onLoadError={() => {
setPdfLoad(false);
}}
loading={"Loading Document.."}
onLoadError={() => setPdfLoad(false)}
loading={t("loading-doc")}
onLoadSuccess={pageDetails}
onClick={() => {
if (setSelectWidgetId) {
@@ -590,11 +642,9 @@ function RenderPdf({
}}
// ref={pdfRef}
file={
pdfUrl
? pdfUrl
: pdfDetails[0] && pdfDetails[0].SignedUrl
? pdfDetails[0].SignedUrl
: pdfDetails[0].URL
(pdfRotateBase64 && pdfDataBase64) ||
pdfDetails[0]?.SignedUrl ||
pdfDetails[0].URL
}
>
<Page
@@ -0,0 +1,46 @@
import i18next from "i18next";
import React, { useState } from "react";
import { useTranslation } from "react-i18next";
function SelectLanguage(props) {
const { i18n } = useTranslation();
const languages = [
{ value: "en", text: "English" },
{ value: "es", text: "Española" },
{ value: "fr", text: "Français" }
];
const defaultLanguage = i18next.language || "en";
const [lang, setLang] = useState(defaultLanguage);
// This function put query that helps to change the language
const handleChangeLang = (e) => {
setLang(e.target.value);
i18n.changeLanguage(e.target.value);
props?.updateExtUser && props.updateExtUser({ language: e.target.value });
};
return (
<div
className={`${
!props.isProfile && " mt-[9px] pb-2 md:pb-0 "
} flex justify-center items-center `}
>
<select
value={lang}
onChange={handleChangeLang}
className={`${
!props.isProfile ? " md:w-[15%] w-[50%]" : "w-[180px]"
} op-select op-select-bordered bg-white op-select-sm `}
>
<option disabled>select</option>
{languages.map((item) => {
return (
<option key={item.value} value={item.value}>
{item.text}
</option>
);
})}
</select>
</div>
);
}
export default SelectLanguage;
+433 -369
View File
@@ -1,37 +1,20 @@
import React, { useRef, useState, useEffect } from "react";
import { useTranslation } from "react-i18next";
import SignatureCanvas from "react-signature-canvas";
function SignPad({
isSignPad,
isStamp,
setIsImageSelect,
onSaveSign,
setIsSignPad,
setImage,
isImageSelect,
imageRef,
onImageChange,
onSaveImage,
image,
defaultSign,
setSignature,
myInitial,
isInitial,
setIsInitial,
setIsStamp,
widgetType,
currWidgetsDetails,
setCurrWidgetsDetails
}) {
function SignPad(props) {
const { t } = useTranslation();
const [penColor, setPenColor] = useState("blue");
const allColor = ["blue", "red", "black"];
const canvasRef = useRef(null);
const [isDefaultSign, setIsDefaultSign] = useState(false);
const [isTab, setIsTab] = useState("draw");
const [isTab, setIsTab] = useState("");
const [isSignImg, setIsSignImg] = useState("");
const [signValue, setSignValue] = useState("");
const [textWidth, setTextWidth] = useState(null);
const [textHeight, setTextHeight] = useState(null);
const [signatureType, setSignatureType] = useState("draw");
const [textWidth, setTextWidth] = useState(0);
const [textHeight, setTextHeight] = useState(0);
const [signatureType, setSignatureType] = useState("");
const [isSignTypes, setIsSignTypes] = useState(true);
const fontOptions = [
{ value: "Fasthand" },
{ value: "Dancing Script" },
@@ -49,26 +32,60 @@ function SignPad({
`Parse/${localStorage.getItem("parseAppId")}/currentUser`
);
const jsonSender = JSON.parse(senderUser);
const currentUserName = jsonSender && jsonSender.name;
const currentUserName = jsonSender && jsonSender?.name;
useEffect(() => {
handleTab();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [props.signatureTypes]);
function handleTab() {
const signtypes = props?.signatureTypes || [];
const index = signtypes?.findIndex((x) => x.enabled === true);
if (index !== -1) {
setIsSignTypes(true);
const tab = props?.signatureTypes[index].name;
if (tab === "draw") {
setIsTab("draw");
setSignatureType("draw");
} else if (tab === "upload") {
props?.setIsImageSelect(true);
setIsTab("uploadImage");
} else if (tab === "typed") {
setIsTab("type");
} else if (tab === "default") {
setIsTab("mysignature");
} else {
setIsTab(true);
}
} else {
setIsSignTypes(false);
}
}
function isTabEnabled(tabName) {
const isEnabled = props?.signatureTypes.find(
(x) => x.name === tabName
)?.enabled;
return isEnabled;
}
//function for clear signature image
const handleClear = () => {
setCurrWidgetsDetails({});
props?.setCurrWidgetsDetails({});
if (isTab === "draw") {
if (canvasRef.current) {
canvasRef.current.clear();
} else if (isStamp) {
setImage("");
} else if (props?.isStamp) {
props?.setImage("");
}
setIsSignImg("");
} else if (isTab === "uploadImage") {
setImage("");
props?.setImage("");
}
// setIsInitial(false);
};
//function for set signature url
const handleSignatureChange = (data) => {
setSignature(data);
props?.setSignature(data);
setIsSignImg(data);
};
//save button component
@@ -81,80 +98,79 @@ function SignPad({
className="op-btn op-btn-ghost mr-1 mt-[2px]"
onClick={() => handleClear()}
>
Clear
{t("clear")}
</button>
)}
<button
onClick={() => {
setCurrWidgetsDetails({});
if (!image) {
props?.setCurrWidgetsDetails({});
if (!props?.image) {
if (isTab === "mysignature") {
setIsSignImg("");
if (isInitial) {
onSaveSign(signatureType, "initials");
if (props?.isInitial) {
props?.onSaveSign(signatureType, "initials");
} else {
onSaveSign(null, "default");
props?.onSaveSign(null, "default");
}
} else {
if (isTab === "type") {
setIsSignImg("");
onSaveSign(
props?.onSaveSign(
null,
false,
!isInitial && textWidth > 150 ? 150 : textWidth,
!isInitial && textHeight > 35 ? 35 : textHeight
!props?.isInitial && textWidth > 150 ? 150 : textWidth,
!props?.isInitial && textHeight > 35 ? 35 : textHeight
);
} else {
setIsSignImg("");
canvasRef.current.clear();
onSaveSign(signatureType);
props?.onSaveSign(signatureType);
}
}
setPenColor("blue");
} else {
setIsSignImg("");
onSaveImage(signatureType);
props?.onSaveImage(signatureType);
}
setIsSignPad(false);
setIsInitial(false);
setIsImageSelect(false);
props?.setIsSignPad(false);
props?.setIsInitial(false);
props?.setIsImageSelect(false);
setIsDefaultSign(false);
setImage();
setIsTab("draw");
props?.setImage();
handleTab();
setSignValue("");
setIsStamp(false);
props?.setIsStamp(false);
}}
type="button"
className={`${
isSignImg || image || isDefaultSign || textWidth
isSignImg || props?.image || isDefaultSign || textWidth
? ""
: "pointer-events-none"
} op-btn op-btn-primary shadow-lg`}
disabled={
(isTab === "draw" && isSignImg) ||
(isTab === "image" && image) ||
(isTab === "image" && props?.image) ||
(isTab === "mysignature" && isDefaultSign) ||
(isTab === "type" && textWidth)
(isTab === "type" && signValue)
? false
: image
: props?.image
? false
: true
}
>
Save
{t("save")}
</button>
</div>
);
};
//useEffect for set already draw or save signature url/text url of signature text type and draw type for initial type and signature type widgets
useEffect(() => {
if (currWidgetsDetails && canvasRef.current) {
const isWidgetType = currWidgetsDetails?.type;
const signatureType = currWidgetsDetails?.signatureType;
const url = currWidgetsDetails?.SignUrl;
if (props?.currWidgetsDetails && canvasRef.current) {
const isWidgetType = props?.currWidgetsDetails?.type;
const signatureType = props?.currWidgetsDetails?.signatureType;
const url = props?.currWidgetsDetails?.SignUrl;
//checking widget type and draw type signature url
if (isInitial) {
if (props?.isInitial) {
if (isWidgetType === "initials" && signatureType === "draw" && url) {
canvasRef.current.fromDataURL(url);
}
@@ -167,14 +183,14 @@ function SignPad({
}
}
const trimmedName = currentUserName && currentUserName.trim();
const trimmedName = currentUserName && currentUserName?.trim();
const firstCharacter = trimmedName?.charAt(0);
const userName = isInitial ? firstCharacter : currentUserName;
setSignValue(userName);
const userName = props?.isInitial ? firstCharacter : currentUserName;
setSignValue(userName || "");
setFontSelect("Fasthand");
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [isSignPad]);
}, [props.isSignPad]);
useEffect(() => {
const loadFont = async () => {
try {
@@ -198,9 +214,11 @@ function SignPad({
canvasRef.current.fromDataURL(isSignImg);
}
if (isTab === "type") {
const trimmedName = signValue ? signValue.trim() : currentUserName.trim();
const firstCharacter = trimmedName.charAt(0);
const userName = isInitial ? firstCharacter : signValue;
const trimmedName = signValue
? signValue?.trim()
: currentUserName?.trim();
const firstCharacter = trimmedName?.charAt(0);
const userName = props?.isInitial ? firstCharacter : signValue;
setSignValue(userName);
convertToImg(fontSelect, userName);
}
@@ -229,7 +247,7 @@ function SignPad({
// Draw the text content on the canvas
const ctx = canvasElement.getContext("2d");
const pixelRatio = window.devicePixelRatio || 1;
const addExtraWidth = isInitial ? 10 : 50;
const addExtraWidth = props?.isInitial ? 10 : 50;
const width = span.offsetWidth + addExtraWidth;
const height = span.offsetHeight;
setTextWidth(width);
@@ -251,7 +269,7 @@ function SignPad({
document.body.removeChild(span);
// Convert the canvas to image data
const dataUrl = canvasElement.toDataURL("image/png");
setSignature(dataUrl);
props?.setSignature(dataUrl);
};
const PenColorComponent = (props) => {
@@ -293,319 +311,365 @@ function SignPad({
</div>
);
};
// `handleCancelBtn` function trigger when user click on cross button
const handleCancelBtn = () => {
setPenColor("blue");
props?.setIsSignPad(false);
props?.setIsInitial(false);
props?.setIsImageSelect(false);
setIsDefaultSign(false);
props?.setImage();
handleTab();
setSignValue("");
props?.setIsStamp(false);
};
return (
<div>
{isSignPad && (
{props?.isSignPad && (
<div className="op-modal op-modal-open">
<div className="op-modal-box px-[13px] pt-2 pb-0">
<div className="flex justify-between text-base-content items-center">
<div className="text-[1.2rem]">
<div className="flex flex-row justify-between mt-[3px]">
<div className="flex flex-row justify-between gap-[5px] md:gap-[8px] text-[11px] md:text-base">
{isStamp ? (
<span className="text-base-content font-bold text-lg">
{widgetType === "image" ||
currWidgetsDetails?.type === "image"
? "Upload image"
: "Upload stamp image"}
</span>
) : (
<>
<div>
<span
onClick={() => {
setIsDefaultSign(false);
setIsImageSelect(false);
setIsTab("draw");
setImage();
if (isSignImg) {
setSignature(isSignImg);
}
}}
className={`${
isTab === "draw"
? "op-link-primary"
: "no-underline"
} op-link underline-offset-8 ml-[2px]`}
>
Draw
{isSignTypes ? (
<>
<div className="flex justify-between text-base-content items-center">
<div className="text-[1.2rem]">
<div className="flex flex-row justify-between mt-[3px]">
<div className="flex flex-row justify-between gap-[5px] md:gap-[8px] text-[11px] md:text-base">
{props?.isStamp ? (
<span className="text-base-content font-bold text-lg">
{props?.widgetType === "image" ||
props?.currWidgetsDetails?.type === "image"
? t("upload-image")
: t("upload-stamp-image")}
</span>
</div>
<div>
<span
onClick={() => {
setIsDefaultSign(false);
setIsImageSelect(true);
setIsTab("uploadImage");
setSignatureType("");
}}
className={`${
isTab === "uploadImage"
? "op-link-primary"
: "no-underline"
} op-link underline-offset-8 ml-[2px]`}
>
Upload Image
</span>
</div>
<div>
<span
onClick={() => {
setIsDefaultSign(false);
setIsImageSelect(false);
setIsTab("type");
setSignatureType("");
setImage();
}}
className={`${
isTab === "type"
? "op-link-primary"
: "no-underline"
} op-link underline-offset-8 ml-[2px]`}
>
Type
</span>
</div>
{!isInitial && defaultSign ? (
<div>
<span
onClick={() => {
setIsDefaultSign(true);
setIsImageSelect(true);
setIsTab("mysignature");
setSignatureType("");
setImage();
}}
className={`${
isTab === "mysignature"
? "op-link-primary"
: "no-underline"
} op-link underline-offset-8 ml-[2px]`}
>
My Signature
</span>
</div>
) : (
isInitial &&
myInitial && (
<div>
<span
onClick={() => {
setIsDefaultSign(true);
setIsImageSelect(true);
setIsTab("mysignature");
setSignatureType("");
setImage();
}}
className={`${
isTab === "mysignature"
? "op-link-primary"
: "no-underline"
} op-link underline-offset-8 ml-[2px]`}
>
My Initials
</span>
</div>
)
<>
{isTabEnabled("draw") && (
<div>
<span
onClick={() => {
setIsDefaultSign(false);
props?.setIsImageSelect(false);
setIsTab("draw");
props?.setImage();
if (isSignImg) {
props?.setSignature(isSignImg);
}
}}
className={`${
isTab === "draw"
? "op-link-primary"
: "no-underline"
} op-link underline-offset-8 ml-[2px]`}
>
{t("draw")}
</span>
</div>
)}
{isTabEnabled("upload") && (
<div>
<span
onClick={() => {
setIsDefaultSign(false);
props?.setIsImageSelect(true);
setIsTab("uploadImage");
setSignatureType("");
}}
className={`${
isTab === "uploadImage"
? "op-link-primary"
: "no-underline"
} op-link underline-offset-8 ml-[2px]`}
>
{t("upload-image")}
</span>
</div>
)}
{isTabEnabled("typed") && (
<div>
<span
onClick={() => {
setIsDefaultSign(false);
props?.setIsImageSelect(false);
setIsTab("type");
setSignatureType("");
props?.setImage();
}}
className={`${
isTab === "type"
? "op-link-primary"
: "no-underline"
} op-link underline-offset-8 ml-[2px]`}
>
{t("type")}
</span>
</div>
)}
{!props?.isInitial &&
props?.defaultSign &&
isTabEnabled("default") ? (
<div>
<span
onClick={() => {
setIsDefaultSign(true);
props?.setIsImageSelect(true);
setIsTab("mysignature");
setSignatureType("");
props?.setImage();
}}
className={`${
isTab === "mysignature"
? "op-link-primary"
: "no-underline"
} op-link underline-offset-8 ml-[2px]`}
>
{t("my-signature")}
</span>
</div>
) : (
props?.isInitial &&
props?.myInitial &&
isTabEnabled("default") && (
<div>
<span
onClick={() => {
setIsDefaultSign(true);
props?.setIsImageSelect(true);
setIsTab("mysignature");
setSignatureType("");
props?.setImage();
}}
className={`${
isTab === "mysignature"
? "op-link-primary"
: "no-underline"
} op-link underline-offset-8 ml-[2px]`}
>
{t("my-initials")}
</span>
</div>
)
)}
</>
)}
</>
)}
</div>
</div>
</div>
<div
className="text-[1.5rem] cursor-pointer"
onClick={() => {
setPenColor("blue");
setIsSignPad(false);
setIsInitial(false);
setIsImageSelect(false);
setIsDefaultSign(false);
setImage();
setIsTab("draw");
setSignatureType("draw");
setSignValue("");
setIsStamp(false);
}}
>
&times;
</div>
</div>
<div className="p-[20px] h-full">
{isDefaultSign ? (
<>
<div className="flex justify-center">
<div
style={{
border: "1.3px solid #007bff",
borderRadius: "2px",
display: "flex",
flexDirection: "column",
justifyContent: "center",
alignItems: "center",
marginBottom: 6,
cursor: "pointer"
}}
className={
isInitial ? "intialSignatureCanvas" : "signatureCanvas"
}
>
<img
alt="stamp img"
className="w-full h-full object-contain bg-white"
draggable="false"
src={isInitial ? myInitial : defaultSign}
/>
</div>
</div>
<div className="flex justify-end">
<SaveBtn />
</div>
</>
) : isImageSelect || isStamp ? (
!image ? (
<div className="flex justify-center">
<div
style={{
border: "1.3px solid #007bff",
borderRadius: "2px",
display: "flex",
flexDirection: "column",
justifyContent: "center",
alignItems: "center",
marginBottom: 6,
cursor: "pointer"
}}
className={
isInitial ? "intialSignatureCanvas" : "signatureCanvas"
}
onClick={() => imageRef.current.click()}
>
<input
type="file"
onChange={onImageChange}
className="filetype"
accept="image/png,image/jpeg"
ref={imageRef}
hidden
/>
<i className="fa-light fa-cloud-upload-alt uploadImgLogo"></i>
<div className="text-[10px]">Upload</div>
</div>
</div>
) : (
<>
<div className="flex justify-center">
<div
style={{
border: "1.3px solid #007bff",
borderRadius: "2px",
marginBottom: 6,
overflow: "hidden"
}}
className={
isInitial
? "intialSignatureCanvas"
: "signatureCanvas"
}
>
<img
alt="print img"
ref={imageRef}
src={image.src}
draggable="false"
className=" object-contain h-full w-full"
/>
</div>
</div>
<div className="flex justify-end">
<SaveBtn />
</div>
</>
)
) : isTab === "type" ? (
<div>
<div className="flex justify-between items-center">
<span className="mr-[5px] text-[12px]">
{isInitial ? "Initials" : "Signature"}:
</span>
<input
maxLength={isInitial ? 3 : 30}
style={{ fontFamily: fontSelect, color: penColor }}
type="text"
className="ml-1 op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-[20px]"
placeholder="Your signature"
value={signValue}
onChange={(e) => {
setSignValue(e.target.value);
convertToImg(fontSelect, e.target.value);
}}
/>
</div>
<div className="border-[1px] border-[#d6d3d3] mt-[10px] ml-[5px]">
{fontOptions.map((font, ind) => {
return (
<div
key={ind}
style={{
cursor: "pointer",
fontFamily: font.value,
backgroundColor:
fontSelect === font.value && "rgb(206 225 247)"
}}
onClick={() => {
setFontSelect(font.value);
convertToImg(font.value, signValue);
}}
>
<div
style={{
padding: "5px 10px 5px 10px",
fontSize: "20px",
color: penColor
}}
>
{signValue ? signValue : "Your signature"}
</div>
</div>
);
})}
</div>
<div className="flex flex-row justify-between mt-[10px]">
<PenColorComponent convertToImg={convertToImg} />
<SaveBtn />
<div
className="text-[1.5rem] cursor-pointer"
onClick={handleCancelBtn}
>
&times;
</div>
</div>
) : (
<>
<div className="flex justify-center">
<SignatureCanvas
ref={canvasRef}
penColor={penColor}
canvasProps={{
className: isInitial
? "intialSignatureCanvas"
: "signatureCanvas",
style: {
border: "1.6px solid #007bff",
borderRadius: "2px"
}
}}
backgroundColor="rgb(255, 255, 255)"
onEnd={() =>
handleSignatureChange(canvasRef.current?.toDataURL())
}
dotSize={1}
/>
<div className="p-[20px] h-full">
{isDefaultSign ? (
<>
<div className="flex justify-center">
<div
style={{
border: "1.3px solid #007bff",
borderRadius: "2px",
display: "flex",
flexDirection: "column",
justifyContent: "center",
alignItems: "center",
marginBottom: 6,
cursor: "pointer"
}}
className={
props?.isInitial
? "intialSignatureCanvas"
: "signatureCanvas"
}
>
<img
alt="stamp img"
className="w-full h-full object-contain bg-white"
draggable="false"
src={
props?.isInitial
? props?.myInitial
: props?.defaultSign
}
/>
</div>
</div>
<div className="flex justify-end">
<SaveBtn />
</div>
</>
) : props?.isImageSelect || props?.isStamp ? (
!props?.image ? (
<div className="flex justify-center">
<div
style={{
border: "1.3px solid #007bff",
borderRadius: "2px",
display: "flex",
flexDirection: "column",
justifyContent: "center",
alignItems: "center",
marginBottom: 6,
cursor: "pointer"
}}
className={
props?.isInitial
? "intialSignatureCanvas"
: "signatureCanvas"
}
onClick={() => props?.imageRef.current.click()}
>
<input
type="file"
onChange={props?.onImageChange}
className="filetype"
accept="image/png,image/jpeg"
ref={props?.imageRef}
hidden
/>
<i className="fa-light fa-cloud-upload-alt uploadImgLogo"></i>
<div className="text-[10px]">{t("upload")}</div>
</div>
</div>
) : (
<>
<div className="flex justify-center">
<div
style={{
border: "1.3px solid #007bff",
borderRadius: "2px",
marginBottom: 6,
overflow: "hidden"
}}
className={
props?.isInitial
? "intialSignatureCanvas"
: "signatureCanvas"
}
>
<img
alt="print img"
ref={props?.imageRef}
src={props?.image.src}
draggable="false"
className=" object-contain h-full w-full"
/>
</div>
</div>
<div className="flex justify-end">
<SaveBtn />
</div>
</>
)
) : isTab === "type" ? (
<div>
<div className="flex justify-between items-center">
<span className="mr-[5px] text-[12px]">
{props?.isInitial
? t("initial-teb")
: t("signature-tab")}
:
</span>
<input
maxLength={props?.isInitial ? 3 : 30}
style={{ fontFamily: fontSelect, color: penColor }}
type="text"
className="ml-1 op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-[20px]"
placeholder="Your signature"
value={signValue}
onChange={(e) => {
setSignValue(e.target.value);
convertToImg(fontSelect, e.target.value);
}}
/>
</div>
<div className="border-[1px] border-[#d6d3d3] mt-[10px] ml-[5px]">
{fontOptions.map((font, ind) => {
return (
<div
key={ind}
style={{
cursor: "pointer",
fontFamily: font.value,
backgroundColor:
fontSelect === font.value &&
"rgb(206 225 247)"
}}
onClick={() => {
setFontSelect(font.value);
convertToImg(font.value, signValue);
}}
>
<div
style={{
padding: "5px 10px 5px 10px",
fontSize: "20px",
color: penColor
}}
>
{signValue ? signValue : "Your signature"}
</div>
</div>
);
})}
</div>
<div className="flex flex-row justify-between mt-[10px]">
<PenColorComponent convertToImg={convertToImg} />
<SaveBtn />
</div>
</div>
) : (
<>
<div className="flex justify-center">
<SignatureCanvas
ref={canvasRef}
penColor={penColor}
canvasProps={{
className: props?.isInitial
? "intialSignatureCanvas"
: "signatureCanvas",
style: {
border: "1.6px solid #007bff",
borderRadius: "2px"
}
}}
// backgroundColor="rgb(255, 255, 255)"
onEnd={() =>
handleSignatureChange(
canvasRef.current?.toDataURL()
)
}
dotSize={1}
/>
</div>
<div className="flex flex-row justify-between mt-[10px]">
<PenColorComponent />
<SaveBtn />
</div>
</>
)}
</div>
</>
) : (
<div className="">
<div className="relative flex flex-row items-center justify-between">
<div className="text-base-content font-bold text-lg">
Signature
</div>
<div className="flex flex-row justify-between mt-[10px]">
<PenColorComponent />
<SaveBtn />
<div
className="text-[1.5rem] cursor-pointer"
onClick={handleCancelBtn}
>
&times;
</div>
</>
)}
</div>
</div>
<div className="mx-3 mb-6 mt-3">
<p>{t("at-least-one-signature-type")}</p>
</div>
</div>
)}
</div>
</div>
)}
+3 -1
View File
@@ -1,6 +1,8 @@
import React from "react";
import "../../styles/signature.css";
import { useTranslation } from "react-i18next";
function Signedby({ pdfDetails }) {
const { t } = useTranslation();
const getFirstLetter = (name) => {
const firstLetter = name.charAt(0);
return firstLetter;
@@ -9,7 +11,7 @@ function Signedby({ pdfDetails }) {
return (
<div className="hidden md:block w-full h-full bg-base-100">
<div className="mx-2 pr-2 pt-2 pb-1 text-[15px] text-base-content font-semibold border-b-[1px] border-base-300">
Signed By
{t("signed-by")}
</div>
<div className="mt-[2px] bg-base-100">
<div className="bg-[#93a3db] rounded-xl mx-1 flex flex-row items-center py-[10px]">
@@ -1,8 +1,10 @@
import React from "react";
import RecipientList from "./RecipientList";
import { Tooltip } from "react-tooltip";
import { useTranslation } from "react-i18next";
function SignerListPlace(props) {
const { t } = useTranslation();
return (
<div>
<div className="mx-2 pr-2 pt-2 pb-1 text-[15px] text-base-content font-semibold border-b-[1px] border-base-300">
@@ -18,36 +20,12 @@ function SignerListPlace(props) {
</a>
<Tooltip id="my-tooltip" className="z-[100]">
<div className="max-w-[450px] 2xl:max-w-[500px] 2xl:text-[20px] p-[1px]">
<p className="font-bold pb-[1px]">
What are template roles?
</p>
<p>
Begin by specifying each role needed for the completion of
the document. Think about the parties involved in the
signing process and what their responsibilities are.
Common roles include HR for internal documents, Customer
for agreements or Vendor for business agreements.{" "}
</p>
<p className="font-bold">
Why pre-attach users to some roles?
</p>
<p>
For roles that consistently involve the same individual
(e.g., the CEO&apos;s signature on employee offer
letters), you can pre-attach a user to a role within the
template. This step is optional but recommended for
efficiency and consistency across documents.
</p>
<p className="font-bold">
When do i specify the user attached to each role?
</p>
<p>
When you create a document from your template, you&apos;ll
be prompted to attach users to each defined role. If a
role already has a user attached, this will be pre-filled,
but you can modify it as needed before sending out the
document.
</p>
<p className="font-bold pb-[1px]">{t("role-help.p1")}</p>
<p>{t("role-help.p2")} </p>
<p className="font-bold">{t("role-help.p3")}</p>
<p>{t("role-help.p4")}</p>
<p className="font-bold">{t("role-help.p5")}</p>
<p>{t("role-help.p6")}</p>
</div>
</Tooltip>
</>
@@ -67,7 +45,7 @@ function SignerListPlace(props) {
className="op-btn op-btn-accent op-btn-outline w-full mt-[14px]"
onClick={() => props.handleAddSigner()}
>
<i className="fa-light fa-plus"></i> Add role
<i className="fa-light fa-plus"></i> {t("add-role")}
</div>
) : (
<div
@@ -77,7 +55,7 @@ function SignerListPlace(props) {
disabled={props?.isMailSend ? true : false}
onClick={() => props.setIsAddSigner(true)}
>
<i className="fa-light fa-plus"></i> Add recipients
<i className="fa-light fa-plus"></i> {t("add-recipients")}
</div>
)}
</div>
@@ -1,27 +1,31 @@
import React from "react";
import ModalUi from "../../primitives/ModalUi";
import { fontColorArr, fontsizeArr } from "../../constant/Utils";
import { useTranslation } from "react-i18next";
function TextFontSetting(props) {
const { t } = useTranslation();
return (
<ModalUi
headerColor={"#dc3545"}
isOpen={props.isTextSetting}
reduceWidth={"max-w-[350px]"}
title={"Text field"}
title={t("text-field")}
handleClose={() => props.setIsTextSetting(false)}
>
<div className="h-full p-[20px]">
<div className="flex items-center">
<span>Font size:</span>
<span>{t("font-size")} :</span>
<select
className="ml-[7px] op-select op-select-bordered op-select-sm focus:outline-none hover:border-base-content text-xs"
value={
props.fontSize ||
props.currWidgetsDetails?.options?.fontSize ||
"12"
12
}
onChange={(e) => props.setFontSize(e.target.value)}
onChange={(e) => {
props.setFontSize(parseInt(e.target.value));
}}
>
{fontsizeArr.map((size, ind) => {
return (
@@ -32,7 +36,7 @@ function TextFontSetting(props) {
})}
</select>
<div className="flex flex-row gap-1 items-center ml-4">
<span>color: </span>
<span>{t("color")}: </span>
<select
value={
props.fontColor ||
@@ -45,7 +49,7 @@ function TextFontSetting(props) {
{fontColorArr.map((color, ind) => {
return (
<option value={color} key={ind}>
{color}
{t(`color-type.${color}`)}
</option>
);
})}
@@ -67,7 +71,7 @@ function TextFontSetting(props) {
type="button"
className="op-btn op-btn-primary mt-2"
>
save
{t("save")}
</button>
</div>
</ModalUi>
+14 -10
View File
@@ -1,12 +1,14 @@
import React from "react";
import Loader from "../../primitives/Loader";
import { useTranslation } from "react-i18next";
function VerifyEmail(props) {
const { t } = useTranslation();
return (
<dialog className="op-modal op-modal-open absolute z-[1999]">
<div className="md:w-[40%] w-[80%] op-modal-box p-0 overflow-y-auto hide-scrollbar text-sm">
<h3 className="font-bold text-lg pt-[15px] px-[20px] text-base-content">
OTP verification
{t("otp-verification")}
</h3>
{props.isVerifyModal ? (
<form
@@ -16,26 +18,30 @@ function VerifyEmail(props) {
}}
>
<div className="px-6 py-3 text-base-content">
<label className="mb-2">Enter OTP</label>
<label className="mb-2">{t("enter-otp")}</label>
<input
onInvalid={(e) =>
e.target.setCustomValidity(t("input-required"))
}
onInput={(e) => e.target.setCustomValidity("")}
required
type="tel"
pattern="[0-9]{4}"
className="w-full op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content text-xs"
placeholder="Enter OTP received over email"
placeholder={t("otp-placeholder")}
value={props.otp}
onChange={(e) => props.setOtp(e.target.value)}
/>
</div>
<div className="px-6 my-3">
<button type="submit" className="op-btn op-btn-primary">
Verify
{t("verify")}
</button>
<button
className="op-btn op-btn-secondary ml-2"
onClick={(e) => props.handleResend(e)}
>
Resend
{t("resend")}
</button>
</div>
</form>
@@ -45,16 +51,14 @@ function VerifyEmail(props) {
</div>
) : (
<div className="px-6 py-3 text-base-content">
<p className="mb-2 text-sm">Please verify your email !</p>
<p className="mb-2 text-sm">{t("verify-email")}</p>
<div className="px-0 mt-3">
<button
className="op-btn op-btn-primary"
type="submit"
onClick={() => {
props.handleVerifyBtn();
}}
onClick={() => props.handleVerifyBtn()}
>
Send OTP
{t("send-otp")}
</button>
</div>
</div>
@@ -4,11 +4,13 @@ import RecipientList from "./RecipientList";
import { useDrag } from "react-dnd";
import WidgetList from "./WidgetList";
import {
color,
radioButtonWidget,
textInputWidget,
textWidget,
widgets
} from "../../constant/Utils";
import { useTranslation } from "react-i18next";
function WidgetComponent({
dragSignature,
signRef,
@@ -19,9 +21,7 @@ function WidgetComponent({
addPositionOfSignature,
signersdata,
isSelectListId,
setSignerObjId,
setIsSelectId,
setContractName,
isSigners,
dataTut,
isMailSend,
@@ -40,166 +40,73 @@ function WidgetComponent({
setIsAddSigner,
uniqueId
}) {
const { t } = useTranslation();
const [isSignersModal, setIsSignersModal] = useState(false);
const [, dropdown] = useDrag({
type: "BOX",
item: {
type: "BOX",
id: 5,
text: "dropdown"
},
item: { type: "BOX", id: 5, text: "dropdown" },
collect: (monitor) => ({
isDragDropdown: !!monitor.isDragging()
})
});
const [, checkbox] = useDrag({
type: "BOX",
item: {
type: "BOX",
id: 6,
text: "checkbox"
},
collect: (monitor) => ({
isDragCheck: !!monitor.isDragging()
})
item: { type: "BOX", id: 6, text: "checkbox" },
collect: (monitor) => ({ isDragCheck: !!monitor.isDragging() })
});
const [, textInput] = useDrag({
type: "BOX",
item: {
type: "BOX",
id: 7,
text: textInputWidget
},
collect: (monitor) => ({
isDragTextInput: !!monitor.isDragging()
})
item: { type: "BOX", id: 7, text: textInputWidget },
collect: (monitor) => ({ isDragTextInput: !!monitor.isDragging() })
});
const [, initials] = useDrag({
type: "BOX",
item: {
type: "BOX",
id: 8,
text: "initials"
},
collect: (monitor) => ({
isDragInitial: !!monitor.isDragging()
})
item: { type: "BOX", id: 8, text: "initials" },
collect: (monitor) => ({ isDragInitial: !!monitor.isDragging() })
});
const [, name] = useDrag({
type: "BOX",
item: {
type: "BOX",
id: 9,
text: "name"
},
collect: (monitor) => ({
isDragName: !!monitor.isDragging()
})
item: { type: "BOX", id: 9, text: "name" },
collect: (monitor) => ({ isDragName: !!monitor.isDragging() })
});
const [, company] = useDrag({
type: "BOX",
item: {
type: "BOX",
id: 10,
text: "company"
},
collect: (monitor) => ({
isDragCompany: !!monitor.isDragging()
})
item: { type: "BOX", id: 10, text: "company" },
collect: (monitor) => ({ isDragCompany: !!monitor.isDragging() })
});
const [, jobTitle] = useDrag({
type: "BOX",
item: {
type: "BOX",
id: 11,
text: "job title"
},
collect: (monitor) => ({
isDragJobtitle: !!monitor.isDragging()
})
item: { type: "BOX", id: 11, text: "job title" },
collect: (monitor) => ({ isDragJobtitle: !!monitor.isDragging() })
});
const [, date] = useDrag({
type: "BOX",
item: {
type: "BOX",
id: 12,
text: "date"
},
collect: (monitor) => ({
isDragDate: !!monitor.isDragging()
})
item: { type: "BOX", id: 12, text: "date" },
collect: (monitor) => ({ isDragDate: !!monitor.isDragging() })
});
const [, image] = useDrag({
type: "BOX",
item: {
type: "BOX",
id: 13,
text: "image"
},
collect: (monitor) => ({
isDragImage: !!monitor.isDragging()
})
item: { type: "BOX", id: 13, text: "image" },
collect: (monitor) => ({ isDragImage: !!monitor.isDragging() })
});
const [, email] = useDrag({
type: "BOX",
item: {
type: "BOX",
id: 14,
text: "email"
},
collect: (monitor) => ({
isDragEmail: !!monitor.isDragging()
})
item: { type: "BOX", id: 14, text: "email" },
collect: (monitor) => ({ isDragEmail: !!monitor.isDragging() })
});
const [, radioButton] = useDrag({
type: "BOX",
item: {
type: "BOX",
id: 15,
text: radioButtonWidget
},
collect: (monitor) => ({
isDragRadiotton: !!monitor.isDragging()
})
item: { type: "BOX", id: 15, text: radioButtonWidget },
collect: (monitor) => ({ isDragRadiotton: !!monitor.isDragging() })
});
const [, text] = useDrag({
type: "BOX",
item: {
type: "BOX",
id: 16,
text: textWidget
},
collect: (monitor) => ({
isDragText: !!monitor.isDragging()
})
item: { type: "BOX", id: 16, text: textWidget },
collect: (monitor) => ({ isDragText: !!monitor.isDragging() })
});
const isMobile = window.innerWidth < 767;
const scrollContainerRef = useRef(null);
const [widget, setWidget] = useState([]);
const color = [
"#93a3db",
"#e6c3db",
"#c0e3bc",
"#bce3db",
"#b8ccdb",
"#ceb8db",
"#ffccff",
"#99ffcc",
"#cc99ff",
"#ffcc99",
"#66ccff",
"#ffffcc"
];
const handleModal = () => {
setIsSignersModal(!isSignersModal);
};
@@ -330,7 +237,7 @@ function WidgetComponent({
} hidden md:block h-full bg-base-100`}
>
<div className="mx-2 pr-2 pt-2 pb-1 text-[15px] text-base-content font-semibold border-b-[1px] border-base-300">
<span>Fields</span>
<span>{t("fields")}</span>
</div>
<div
@@ -348,7 +255,7 @@ function WidgetComponent({
)}
{isSignersModal && (
<ModalUi
title={title ? title : "Recipients"}
title={title ? title : t("recipients")}
isOpen={isSignersModal}
handleClose={handleModal}
>
@@ -358,9 +265,7 @@ function WidgetComponent({
signerPos={signerPos}
signersdata={signersdata}
isSelectListId={isSelectListId}
setSignerObjId={setSignerObjId}
setIsSelectId={setIsSelectId}
setContractName={setContractName}
setUniqueId={setUniqueId}
setRoleName={setRoleName}
handleDeleteUser={handleDeleteUser}
@@ -375,7 +280,7 @@ function WidgetComponent({
</div>
) : (
<div className=" p-[20px] text-[15px] font-medium text-center">
Please add a {title ? title : "recipients"}
{t("please-add")} {title ? title : t("recipients")}
</div>
)}
</ModalUi>
@@ -1,7 +1,10 @@
import React from "react";
import { getWidgetType } from "../../constant/Utils";
import { useTranslation } from "react-i18next";
function WidgetList(props) {
const { t } = useTranslation();
return props.updateWidgets.map((item, ind) => {
return (
<div className="2xl:p-3 mb-[5px]" key={ind}>
@@ -25,7 +28,7 @@ function WidgetList(props) {
onMouseDown={() => props?.handleMouseLeave()}
onTouchStart={props?.handleDivClick}
>
{item.ref && getWidgetType(item)}
{item.ref && getWidgetType(item, t(`widgets-name.${item.type}`))}
</div>
</div>
);
@@ -2,13 +2,20 @@ import React, { useEffect, useState } from "react";
import ModalUi from "../../primitives/ModalUi";
import "../../styles/AddUser.css";
import RegexParser from "regex-parser";
import { textInputWidget, textWidget } from "../../constant/Utils";
import {
signatureTypes,
textInputWidget,
textWidget
} from "../../constant/Utils";
import Upgrade from "../../primitives/Upgrade";
import { isEnableSubscription } from "../../constant/const";
import Tooltip from "../../primitives/Tooltip";
import { fontColorArr, fontsizeArr } from "../../constant/Utils";
import { useTranslation } from "react-i18next";
const WidgetNameModal = (props) => {
const { t } = useTranslation();
const signTypes = props?.signatureType || signatureTypes;
const [formdata, setFormdata] = useState({
name: "",
defaultValue: "",
@@ -19,6 +26,7 @@ const WidgetNameModal = (props) => {
const [isValid, setIsValid] = useState(true);
const statusArr = ["Required", "Optional"];
const inputOpt = ["text", "email", "number"];
const [signatureType, setSignatureType] = useState([]);
useEffect(() => {
if (props.defaultdata) {
@@ -38,12 +46,32 @@ const WidgetNameModal = (props) => {
name: props.defaultdata?.options?.name || ""
});
}
if (signTypes.length > 0) {
const defaultSignatureType = signTypes || [];
setSignatureType(defaultSignatureType);
}
// eslint-disable-next-line
}, [props.defaultdata]);
const handleSubmit = (e) => {
e.preventDefault();
if (props.handleData) {
props.handleData(formdata);
if (["signature", "initials"].includes(props.defaultdata?.type)) {
const enabledSignTypes = signatureType?.filter((x) => x.enabled);
const isDefaultSignTypeOnly =
enabledSignTypes?.length === 1 &&
enabledSignTypes[0]?.name === "default";
if (enabledSignTypes.length === 0) {
alert(t("at-least-one-signature-type"));
} else if (isDefaultSignTypeOnly) {
alert(t("expect-default-one-more-signature-type"));
} else {
const data = { ...formdata, signatureType };
props.handleData(data, props.defaultdata?.type);
}
} else {
props.handleData(formdata);
}
setFormdata({
name: "",
defaultValue: "",
@@ -51,6 +79,7 @@ const WidgetNameModal = (props) => {
hint: "",
textvalidate: ""
});
setSignatureType(signTypes);
}
};
const handleChange = (e) => {
@@ -100,31 +129,48 @@ const WidgetNameModal = (props) => {
}
}
}
const handleCheckboxChange = (index) => {
// Create a copy of the signatureType array
const updatedSignatureType = [...signatureType];
// Toggle the enabled value for the clicked item
updatedSignatureType[index].enabled = !updatedSignatureType[index].enabled;
// Update the state with the modified array
setSignatureType(updatedSignatureType);
};
return (
<ModalUi
isOpen={props.isOpen}
handleClose={props.handleClose && props.handleClose}
title={"Widget info"}
title={t("widget-info")}
>
<form
onSubmit={handleSubmit}
className={`${
props.defaultdata?.type === textInputWidget ? "pt-0" : ""
props.defaultdata?.type === textInputWidget
? "pt-0"
: ["signature", "initials"].includes(props.defaultdata?.type)
? "pt-2"
: ""
} p-[20px] text-base-content`}
>
<div className="mb-[0.75rem] text-[13px]">
<label htmlFor="name">
Name
<span className="text-[red]"> *</span>
</label>
<input
className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs"
name="name"
value={formdata.name}
onChange={(e) => handleChange(e)}
required
/>
</div>
{!["signature", "initials"].includes(props.defaultdata?.type) && (
<div className="mb-[0.75rem] text-[13px]">
<label htmlFor="name">
{t("name")}
<span className="text-[red]"> *</span>
</label>
<input
className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs"
name="name"
value={formdata.name}
onChange={(e) => handleChange(e)}
onInvalid={(e) => e.target.setCustomValidity(t("input-required"))}
onInput={(e) => e.target.setCustomValidity("")}
required
/>
</div>
)}
{props.defaultdata?.type === textInputWidget && (
<>
{isEnableSubscription && (
@@ -138,7 +184,7 @@ const WidgetNameModal = (props) => {
: ""
} text-[13px]`}
>
Validation
{t("validation")}
</label>
<Tooltip
url={"https://www.w3schools.com/jsref/jsref_obj_regexp.asp"}
@@ -192,7 +238,7 @@ const WidgetNameModal = (props) => {
)}
<div className="mb-[0.75rem]">
<label htmlFor="name" className="text-[13px]">
Default value
{t("default-value")}
</label>
<input
className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs"
@@ -216,38 +262,73 @@ const WidgetNameModal = (props) => {
className="fa-light fa-exclamation-circle text-[15px]"
style={{ color: "#fab005" }}
></i>
invalid default value
{t("invalid-default-value")}
</div>
)}
</div>
</>
)}
<div className="mb-[0.75rem]">
<div className="flex flex-row gap-[10px] mb-[0.5rem]">
{statusArr.map((data, ind) => {
return (
<div key={ind} className="flex flex-row gap-[5px] items-center">
<input
className="mr-[2px] op-radio op-radio-xs"
type="radio"
name="status"
onChange={() =>
setFormdata({ ...formdata, status: data.toLowerCase() })
}
checked={
formdata.status.toLowerCase() === data.toLowerCase()
}
/>
<div className="text-[13px] font-medium">{data}</div>
</div>
);
})}
{!["signature", "initials"].includes(props.defaultdata?.type) && (
<div className="mb-[0.75rem]">
<div className="flex flex-row gap-[10px] mb-[0.5rem]">
{statusArr.map((data, ind) => {
return (
<div
key={ind}
className="flex flex-row gap-[5px] items-center"
>
<input
className="mr-[2px] op-radio op-radio-xs"
type="radio"
name="status"
onChange={() =>
setFormdata({ ...formdata, status: data.toLowerCase() })
}
checked={
formdata.status.toLowerCase() === data.toLowerCase()
}
/>
<div className="text-[13px] font-medium">
{t(`widget-status.${data}`)}
</div>
</div>
);
})}
</div>
</div>
</div>
)}
{["signature", "initials"].includes(props.defaultdata?.type) && (
<div className="mb-[0.75rem]">
<label htmlFor="signaturetype" className="text-[14px] mb-[0.7rem]">
{t("allowed-signature-types")}
</label>
<div className=" ml-[7px] flex flex-col md:flex-row gap-[10px] mb-[0.7rem]">
{signatureType.map((type, i) => {
return (
<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}
</div>
</div>
);
})}
</div>
</div>
)}
{props.defaultdata?.type === textInputWidget && (
<div className="mb-[0.75rem]">
<label htmlFor="hint" className="text-[13px]">
Hint
{t("hint")}
</label>
<input
className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs"
@@ -266,13 +347,13 @@ const WidgetNameModal = (props) => {
"email"
].includes(props.defaultdata?.type) && (
<div className="flex items-center mb-[0.75rem]">
<span>Font size:</span>
<span>{t("font-size")}:</span>
<select
className="ml-[7px] op-select op-select-bordered op-select-sm focus:outline-none hover:border-base-content text-xs"
value={
props.fontSize || props.defaultdata?.options?.fontSize || "12"
props.fontSize || props.defaultdata?.options?.fontSize || 12
}
onChange={(e) => props.setFontSize(e.target.value)}
onChange={(e) => props.setFontSize(parseInt(e.target.value))}
>
{fontsizeArr.map((size, ind) => {
return (
@@ -283,7 +364,7 @@ const WidgetNameModal = (props) => {
})}
</select>
<div className="flex flex-row gap-1 items-center ml-4">
<span>color: </span>
<span>{t("color")}: </span>
<select
value={
props.fontColor ||
@@ -296,7 +377,7 @@ const WidgetNameModal = (props) => {
{fontColorArr.map((color, ind) => {
return (
<option value={color} key={ind}>
{color}
{t(`color-type.${color}`)}
</option>
);
})}
@@ -316,7 +397,7 @@ const WidgetNameModal = (props) => {
<div className="h-[1px] w-full mb-[16px] bg-[#b7b3b3]"></div>
<button type="submit" className="op-btn op-btn-primary">
Save
{t("save")}
</button>
</form>
</ModalUi>
@@ -2,6 +2,7 @@ import React, { useEffect, useState } from "react";
import Parse from "parse";
import Alert from "../../../primitives/Alert";
import Loader from "../../../primitives/Loader";
import { useTranslation } from "react-i18next";
const CreateFolder = ({ parentFolderId, onSuccess, folderCls }) => {
const folderPtr = {
@@ -9,6 +10,7 @@ const CreateFolder = ({ parentFolderId, onSuccess, folderCls }) => {
className: folderCls,
objectId: parentFolderId
};
const { t } = useTranslation();
const [name, setName] = useState("");
const [folderList, setFolderList] = useState([]);
const [isAlert, setIsAlert] = useState(false);
@@ -60,7 +62,7 @@ const CreateFolder = ({ parentFolderId, onSuccess, folderCls }) => {
}
const templExist = await exsitQuery.first();
if (templExist) {
setAlert({ type: "danger", message: "Folder already exist!" });
setAlert({ type: "danger", message: t("folder-already-exist") });
setIsAlert(true);
setTimeout(() => {
setIsAlert(false);
@@ -85,7 +87,7 @@ const CreateFolder = ({ parentFolderId, onSuccess, folderCls }) => {
handleLoader(false);
setAlert({
type: "success",
message: "Folder created successfully!"
message: t("folder-created-successfully")
});
setIsAlert(true);
setTimeout(() => {
@@ -98,7 +100,7 @@ const CreateFolder = ({ parentFolderId, onSuccess, folderCls }) => {
}
} else {
handleLoader(false);
setAlert({ type: "info", message: "Please fill folder name" });
setAlert({ type: "info", message: t("fill-folder-name") });
setIsAlert(true);
setTimeout(() => {
setIsAlert(false);
@@ -120,20 +122,25 @@ const CreateFolder = ({ parentFolderId, onSuccess, folderCls }) => {
<Loader />
</div>
)}
<h1 className="text-base font-semibold mt-[0.4rem]">Create Folder</h1>
<h1 className="text-base font-semibold mt-[0.4rem]">
{t("create-folder")}
</h1>
<div className="text-xs mt-2">
<label className="block">
Name<span className="text-red-500 text-[13px]">*</span>
{t("name")}
<span className="text-red-500 text-[13px]">*</span>
</label>
<input
className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs"
value={name}
onChange={(e) => setName(e.target.value)}
onInvalid={(e) => e.target.setCustomValidity(t("input-required"))}
onInput={(e) => e.target.setCustomValidity("")}
required
/>
</div>
<div className="text-xs mt-2">
<label className="block">Parent Folder</label>
<label className="block">{t("parent-folder")}</label>
<select
value={selectedParent}
onChange={handleOptions}
@@ -155,7 +162,7 @@ const CreateFolder = ({ parentFolderId, onSuccess, folderCls }) => {
className="op-btn op-btn-primary op-btn-sm mt-3"
>
<i className="fa-light fa-plus"></i>
<span>Create</span>
<span>{t("create")}</span>
</button>
</div>
</div>
@@ -2,8 +2,10 @@ import React, { useEffect, useState } from "react";
import Parse from "parse";
import CreateFolder from "./CreateFolder";
import ModalUi from "../../../primitives/ModalUi";
import { useTranslation } from "react-i18next";
const FolderModal = (props) => {
const { t } = useTranslation();
const [clickFolder, setClickFolder] = useState("");
const [folderList, setFolderList] = useState([]);
const [tabList, setTabList] = useState([]);
@@ -147,7 +149,7 @@ const FolderModal = (props) => {
return (
<div className="text-xs mt-2">
<ModalUi
title={"Select Folder"}
title={t("select-foler")}
isOpen={props.isOpenModal}
handleClose={handleCancel}
>
@@ -158,7 +160,7 @@ const FolderModal = (props) => {
title="OpenSign™ Drive"
onClick={(e) => removeTabListItem(e)}
>
OpenSign Drive /{" "}
{t("OpenSign-drive")} /{" "}
</span>
{tabList &&
tabList.map((tab, i) => (
@@ -214,7 +216,7 @@ const FolderModal = (props) => {
))
: !isLoader && (
<div className="text-base-content text-center my-2">
No data found
{t("no-data")}
</div>
)}
</div>
@@ -236,27 +238,28 @@ const FolderModal = (props) => {
<div className="flex justify-between items-center py-[.75rem] px-[1.25rem]">
<div
className="op-btn op-btn-seconday op-btn-sm"
title="Save Here"
title={t("save-here")}
onClick={handleCreate}
>
{isAdd ? (
<>
<i className="fa-light fa-arrow-left" aria-hidden="true"></i>
<span className="text-xs">Back</span>
<span className="text-xs">{t("back")}</span>
</>
) : (
<>
<i className="fa-light fa-square-plus" aria-hidden="true"></i>
<span className="">Add folder</span>
<span className="">{t("add-folder")}</span>
</>
)}
</div>
<div
className="op-btn op-btn-primary op-btn-sm"
title="Save Here"
title={t("save-here")}
onClick={handleSubmit}
>
<i className="fa-light fa-save" aria-hidden="true"></i>Save here
<i className="fa-light fa-save" aria-hidden="true"></i>
{t("save-here")}
</div>
</div>
</ModalUi>
@@ -3,8 +3,10 @@ import Parse from "parse";
import CreateFolder from "./CreateFolder";
import ModalUi from "../../../primitives/ModalUi";
import Tooltip from "../../../primitives/Tooltip";
import { useTranslation } from "react-i18next";
const SelectFolder = ({ required, onSuccess, folderCls, isReset }) => {
const { t } = useTranslation();
const [isOpen, SetIsOpen] = useState(false);
const [clickFolder, setClickFolder] = useState("");
const [selectFolder, setSelectedFolder] = useState({});
@@ -169,7 +171,7 @@ const SelectFolder = ({ required, onSuccess, folderCls, isReset }) => {
<div className="text-xs mt-2 ">
<div>
<label className="block">
Select Folder
{t("select-folder")}
{required && <span className="text-red-500 text-[13px]">*</span>}
</label>
</div>
@@ -192,12 +194,12 @@ const SelectFolder = ({ required, onSuccess, folderCls, isReset }) => {
<p>
{selectFolder && selectFolder.Name
? selectFolder.Name
: "OpenSign™ Drive"}
: t("OpenSign-drive")}
</p>
<div className="text-black text-sm">
<i
className="fa-light fa-pencil cursor-pointer"
title="Select Folder"
title={t("select-folder")}
aria-hidden="true"
></i>
</div>
@@ -208,15 +210,11 @@ const SelectFolder = ({ required, onSuccess, folderCls, isReset }) => {
</div>
</div>
<div className="absolute top-2 right-1 cursor-pointer">
<Tooltip
message={
"If you do not select a folder, your signed document will be saved in the Main OpenSign drive folder."
}
/>
<Tooltip message={t("select-folder-help")} />
</div>
</div>
<ModalUi
title={"Select Folder"}
title={t("select-folder")}
isOpen={isOpen}
handleClose={handleCancel}
>
@@ -227,7 +225,7 @@ const SelectFolder = ({ required, onSuccess, folderCls, isReset }) => {
title="OpenSign™ Drive"
onClick={(e) => removeTabListItem(e)}
>
OpenSign Drive /{" "}
{t("OpenSign-drive")} /{" "}
</span>
{tabList &&
tabList.map((tab, i) => (
@@ -283,7 +281,7 @@ const SelectFolder = ({ required, onSuccess, folderCls, isReset }) => {
))
: !isLoader && (
<div className="text-base-content text-center my-2">
No data found
{t("no-data")}
</div>
)}
</div>
@@ -305,27 +303,28 @@ const SelectFolder = ({ required, onSuccess, folderCls, isReset }) => {
<div className="flex justify-between items-center py-[.75rem] px-[1.25rem]">
<div
className="op-btn op-btn-seconday op-btn-sm"
title="Save Here"
title={t("save-here")}
onClick={handleCreate}
>
{isAdd ? (
<>
<i className="fa-light fa-arrow-left" aria-hidden="true"></i>
<span className="text-xs">Back</span>
<span className="text-xs">{t("back")}</span>
</>
) : (
<>
<i className="fa-light fa-square-plus" aria-hidden="true"></i>
<span className="">Add folder</span>
<span className="">{t("add-folder")}</span>
</>
)}
</div>
<div
className="op-btn op-btn-primary op-btn-sm"
title="Save Here"
title={t("save-here")}
onClick={handleSubmit}
>
<i className="fa-light fa-save" aria-hidden="true"></i>Save here
<i className="fa-light fa-save" aria-hidden="true"></i>
{t("save-here")}
</div>
</div>
</ModalUi>
@@ -1,8 +1,10 @@
import React, { useState } from "react";
import Parse from "parse";
import AsyncSelect from "react-select/async";
import { useTranslation } from "react-i18next";
import axios from "axios";
const SelectSigners = (props) => {
const { t } = useTranslation();
const [userList, setUserList] = useState([]);
const [selected, setSelected] = useState();
const [userData, setUserData] = useState({});
@@ -29,17 +31,19 @@ const SelectSigners = (props) => {
const loadOptions = async (inputValue) => {
try {
const currentUser = Parse.User.current();
const contactbook = new Parse.Query("contracts_Contactbook");
contactbook.equalTo(
"CreatedBy",
Parse.User.createWithoutData(currentUser.id)
);
if (inputValue.length > 1) {
contactbook.matches("Name", new RegExp(inputValue, "i"));
}
contactbook.notEqualTo("IsDeleted", true);
const contactRes = await contactbook.find();
const baseURL = localStorage.getItem("baseUrl");
const url = `${baseURL}functions/getsigners`;
const token = props.jwttoken
? { jwttoken: props.jwttoken }
: { "X-Parse-Session-Token": localStorage.getItem("accesstoken") };
const headers = {
"Content-Type": "application/json",
"X-Parse-Application-Id": localStorage.getItem("parseAppId"),
...token
};
const searchEmail = inputValue ? inputValue : "";
const axiosRes = await axios.post(url, { searchEmail }, { headers });
const contactRes = axiosRes?.data?.result || [];
if (contactRes) {
const res = JSON.parse(JSON.stringify(contactRes));
//compareArrays is a function where compare between two array (total signersList and dcument signers list)
@@ -50,11 +54,9 @@ const SelectSigners = (props) => {
!signerObj.find((item2) => item2.objectId === item1.objectId)
);
};
//get update signer's List if signersdata is present
const updateSignersList =
props?.signersData && compareArrays(res, props?.signersData);
const result = updateSignersList ? updateSignersList : res;
setUserList(result);
return await result.map((item) => ({
@@ -66,21 +68,23 @@ const SelectSigners = (props) => {
console.log("err", error);
}
};
return (
<div className="h-full px-[20px] py-[10px] text-base-content">
<div className="w-full mx-auto p-[8px]">
<div className="mb-0">
<label className="text-[14px] font-bold">Choose from contacts</label>
<label className="text-[14px] font-bold">
{t("choose-from-contacts")}
</label>
<AsyncSelect
cacheOptions
defaultOptions
value={selected}
loadingMessage={() => "Loading..."}
noOptionsMessage={() => "Contact not found"}
loadingMessage={() => t("loading")}
noOptionsMessage={() => t("contact-not-found")}
loadOptions={loadOptions}
onChange={handleOptions}
unstyled
onFocus={() => loadOptions()}
classNames={{
control: () =>
"op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full h-full text-[11px]",
@@ -102,11 +106,11 @@ const SelectSigners = (props) => {
isError ? "text-[red]" : "text-transparent"
} text-[11px] ml-[6px] my-[2px]`}
>
Please select signer
{t("select-signer")}
</p>
<div>
<button className="op-btn op-btn-primary" onClick={() => handleAdd()}>
Submit
{t("submit")}
</button>
</div>
</div>
@@ -1,9 +1,10 @@
import React, { useState, useEffect } from "react";
import Select from "react-select";
import AsyncSelect from "react-select/async";
import AddSigner from "../../AddSigner";
import Parse from "parse";
import Tooltip from "../../../primitives/Tooltip";
import { createPortal } from "react-dom";
import { useTranslation } from "react-i18next";
function arrayMove(array, from, to) {
array = array.slice();
array.splice(to < 0 ? array.length + to : to, 0, array.splice(from, 1)[0]);
@@ -32,8 +33,8 @@ const AddSignerModal = ({ isOpen, children }) => {
*/
const SignersInput = (props) => {
const { t } = useTranslation();
const [state, setState] = useState(undefined);
// const [editFormData, setEditFormData] = useState([]);
const [selected, setSelected] = useState([]);
const [isModal, setIsModel] = useState(false);
const onChange = (selectedOptions) => setSelected(selectedOptions);
@@ -44,40 +45,6 @@ const SignersInput = (props) => {
setSelected(newValue);
};
const GetSelectListData = async () => {
try {
const currentUser = Parse.User.current();
const contactbook = new Parse.Query("contracts_Contactbook");
contactbook.equalTo(
"CreatedBy",
Parse.User.createWithoutData(currentUser.id)
);
contactbook.notEqualTo("IsDeleted", true);
const contactRes = await contactbook.find();
if (contactRes) {
const res = JSON.parse(JSON.stringify(contactRes));
let list = [];
// let _selected = [];
res.forEach((x) => {
let obj = {
label: x.Name,
value: x.objectId,
isChecked: true
};
list.push(obj);
});
setState(list);
}
} catch (error) {
console.log("err", error);
}
};
useEffect(() => {
GetSelectListData();
}, []);
useEffect(() => {
if (props.isReset && props.isReset === true) {
setSelected([]);
@@ -116,33 +83,71 @@ const SignersInput = (props) => {
setSelected([data]);
}
};
const loadOptions = async (inputValue) => {
try {
const currentUser = Parse.User.current();
const contactbook = new Parse.Query("contracts_Contactbook");
contactbook.equalTo(
"CreatedBy",
Parse.User.createWithoutData(currentUser.id)
);
if (inputValue.length > 1) {
contactbook.matches("Name", new RegExp(inputValue, "i"));
}
contactbook.notEqualTo("IsDeleted", true);
const contactRes = await contactbook.find();
if (contactRes) {
const res = JSON.parse(JSON.stringify(contactRes));
//compareArrays is a function where compare between two array (total signersList and dcument signers list)
//and filter signers from total signer's list which already present in document's signers list
const compareArrays = (res, signerObj) => {
return res.filter(
(item1) =>
!signerObj.find((item2) => item2.objectId === item1.objectId)
);
};
//get update signer's List if signersdata is present
const updateSignersList =
props?.signersData && compareArrays(res, props?.signersData);
const result = updateSignersList ? updateSignersList : res;
setState(result);
return await result.map((item) => ({
label: item.Name,
value: item.objectId,
isChecked: true
}));
}
} catch (error) {
console.log("err", error);
}
};
return (
<div className="text-xs mt-2 ">
<label className="block relative">
Signers
{t("signers")}
{props.required && <span className="text-red-500 text-[13px]">*</span>}
<span className="absolute ml-1 text-xs z-30">
<Tooltip
id={"signer-tooltip"}
message={
"Begin typing a contact's name to see suggested signers from your saved contacts or add new ones. Arrange the signing order by adding signers in the desired sequence. Use the '+' button to include signers and the 'x' to remove them. Each signer will receive an email prompt to sign the document in the order listed."
}
/>
<Tooltip id={"signer-tooltip"} message={t("signers-help")} />
</span>
</label>
<div className="flex gap-x-[5px]">
<div className="w-full">
<Select
<AsyncSelect
onSortEnd={onSortEnd}
distance={4}
isMulti
cacheOptions
defaultOptions
options={state || []}
value={selected}
onChange={onChange}
closeMenuOnSelect={false}
required={props.required}
noOptionsMessage={() => "Contact not found"}
loadingMessage={() => t("loading")}
noOptionsMessage={() => t("contact-not-found")}
loadOptions={loadOptions}
unstyled
classNames={{
control: () =>
@@ -171,7 +176,7 @@ const SignersInput = (props) => {
</div>
<AddSignerModal isOpen={modalIsOpen}>
<h3 className="text-base-content font-bold text-lg pt-[15px] px-[20px]">
Add Signer
{t("add-signer")}
</h3>
<button
onClick={handleModalCloseClick}
@@ -25,7 +25,7 @@ const SuggestionInput = (props) => {
if (timer) clearTimeout(timer);
timer = setTimeout(() => {
(async () => {
const res = await findContact(inputValue);
const res = await findContact(inputValue, props.jwttoken);
if (res?.length > 0) {
setSuggestions(res);
setShowSuggestions(true);
@@ -37,13 +37,14 @@ const SuggestionInput = (props) => {
}, 1000);
}
return () => clearTimeout(timer);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [inputValue]);
const handleInputChange = async (e) => {
const value = e.target.value;
setInputValue(value?.toLowerCase());
setInputValue(value?.toLowerCase()?.replace(/\s/g, ""));
if (props.onChange) {
props.onChange(value);
props.onChange(value?.toLowerCase()?.replace(/\s/g, ""));
}
if (value.trim() === "") {
+3 -1
View File
@@ -1,7 +1,9 @@
import React from "react";
import { useTranslation } from "react-i18next";
import { NavLink } from "react-router-dom";
const Menu = ({ item, isOpen, closeSidebar }) => {
const { t } = useTranslation();
return (
<li key={item.title} role="none" className="my-0.5">
<NavLink
@@ -20,7 +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">{item.title}</span>
<span className="ml-3 lg:ml-4">{t(`sidebar.${item.title}`)}</span>
</NavLink>
</li>
);
@@ -1,27 +1,54 @@
import React from "react";
import { useTranslation } from "react-i18next";
import { NavLink } from "react-router-dom";
const SocialMedia = () => {
return (
<React.Fragment>
<NavLink to="https://github.com/opensignlabs/opensign" target="_blank" rel="noopener noreferrer">
<i aria-hidden="true" className="fa-brands fa-github"></i>
<span className="fa-sr-only">OpenSign&apos;s Github</span>
</NavLink>
<NavLink to="https://www.linkedin.com/company/opensign%E2%84%A2/" target="_blank" rel="noopener noreferrer">
<i aria-hidden="true" className="fa-brands fa-linkedin"></i>
<span className="fa-sr-only">OpenSign&apos;s LinkedIn</span>
</NavLink>
<NavLink to="https://www.twitter.com/opensignlabs" target="_blank" rel="noopener noreferrer">
<i aria-hidden="true" className="fa-brands fa-square-x-twitter"></i>
<span className="fa-sr-only">OpenSign&apos;s Twitter</span>
</NavLink>
<NavLink to="https://discord.com/invite/xe9TDuyAyj" target="_blank" rel="noopener noreferrer">
<i aria-hidden="true" className="fa-brands fa-discord"></i>
<span className="fa-sr-only">OpenSign&apos;s Discord</span>
</NavLink>
</React.Fragment>
)
}
const { t } = useTranslation();
export default SocialMedia;
return (
<React.Fragment>
<NavLink
to="https://github.com/opensignlabs/opensign"
target="_blank"
rel="noopener noreferrer"
>
<i aria-hidden="true" className="fa-brands fa-github"></i>
<span className="fa-sr-only">
OpenSign&apos;s {t("social-media.github")}
</span>
</NavLink>
<NavLink
to="https://www.linkedin.com/company/opensign%E2%84%A2/"
target="_blank"
rel="noopener noreferrer"
>
<i aria-hidden="true" className="fa-brands fa-linkedin"></i>
<span className="fa-sr-only">
OpenSign&apos;s {t("social-media.linked-in")}
</span>
</NavLink>
<NavLink
to="https://www.twitter.com/opensignlabs"
target="_blank"
rel="noopener noreferrer"
>
<i aria-hidden="true" className="fa-brands fa-square-x-twitter"></i>
<span className="fa-sr-only">
OpenSign&apos;s {t("social-media.twitter")}
</span>
</NavLink>
<NavLink
to="https://discord.com/invite/xe9TDuyAyj"
target="_blank"
rel="noopener noreferrer"
>
<i aria-hidden="true" className="fa-brands fa-discord"></i>
<span className="fa-sr-only">
OpenSign&apos;s {t("social-media.discord")}
</span>
</NavLink>
</React.Fragment>
);
};
export default SocialMedia;
@@ -1,7 +1,9 @@
import React from "react";
import { useTranslation } from "react-i18next";
import { NavLink } from "react-router-dom";
const Submenu = ({ item, closeSidebar, toggleSubmenu, submenuOpen }) => {
const { t } = useTranslation();
const { title, icon, children } = item;
return (
<li role="none" className="my-0.5">
@@ -14,7 +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">{title}</span>
<span className="ml-3 lg:ml-4">{t(`sidebar.${item.title}`)}</span>
<i
className={`${
submenuOpen[item.title]
@@ -48,7 +50,9 @@ const Submenu = ({ item, closeSidebar, toggleSubmenu, submenuOpen }) => {
className={`${childItem.icon} text-[18px]`}
aria-hidden="true"
></i>
<span className="ml-3 lg:ml-4">{childItem.title}</span>
<span className="ml-3 lg:ml-4">
{t(`sidebar.${item.title}-Children.${childItem.title}`)}
</span>
</NavLink>
</li>
))}
File diff suppressed because it is too large Load Diff
+16 -3
View File
@@ -1,10 +1,23 @@
import logo from "../assets/images/logo.png";
import { isEnableSubscription } from "./const";
export function serverUrl_fn() {
let baseUrl;
if (isEnableSubscription) {
baseUrl = process.env.REACT_APP_SERVERURL
? process.env.REACT_APP_SERVERURL
: window.location.origin + "/api/app";
} else {
baseUrl = process.env.REACT_APP_SERVERURL
? process.env.REACT_APP_SERVERURL
: window.location.origin + "/app";
}
return baseUrl;
}
export const appInfo = {
applogo: logo,
appId: process.env.REACT_APP_APPID ? process.env.REACT_APP_APPID : "opensign",
baseUrl: process.env.REACT_APP_SERVERURL
? process.env.REACT_APP_SERVERURL
: window.location.origin + "/api/app",
baseUrl: serverUrl_fn(),
defaultRole: "contracts_User",
fbAppId: process.env.REACT_APP_FBAPPID
? `${process.env.REACT_APP_FBAPPID}`
+2
View File
@@ -11,3 +11,5 @@ export const isEnableSubscription =
: false;
export const isStaging =
window.location.origin === "https://staging-app.opensignlabs.com";
export const isPublicStaging =
window.location.origin === "https://staging.opensign.me";
+2 -4
View File
@@ -1,11 +1,9 @@
import axios from "axios";
import { serverUrl_fn } from "./appinfo";
const parseAppId = process.env.REACT_APP_APPID
? process.env.REACT_APP_APPID
: "opensign";
const serverUrl = process.env.REACT_APP_SERVERURL
? process.env.REACT_APP_SERVERURL
: window.location.origin + "/api/app";
const serverUrl = serverUrl_fn();
export const SaveFileSize = async (size, imageUrl, tenantId) => {
//checking server url and save file's size
const tenantPtr = {
+31
View File
@@ -0,0 +1,31 @@
import i18n from "i18next";
import { initReactI18next } from "react-i18next";
import Backend from "i18next-http-backend";
import LanguageDetector from "i18next-browser-languagedetector";
i18n
.use(Backend)
.use(LanguageDetector) // Use LanguageDetector directly without creating an instance
.use(initReactI18next)
.init({
backend: {
loadPath: "/locales/{{lng}}/{{ns}}.json"
},
fallbackLng: "en", // Fallback to English if no other language is detected
detection: {
// Specifies the default language to fall back to if the detected language is not available.
order: ["localStorage", "navigator"],
// Defines where the detected language should be cached.
caches: ["localStorage"]
},
ns: ["translation"], // default namespace
defaultNS: "translation", // default namespace
//Enables debug mode, which outputs detailed logs to the console about the translation process.
debug: false,
interpolation: {
escapeValue: false // Not needed for react as it escapes by default
},
whitelist: ["en", "es", "fr"] // List of allowed languages
});
export default i18n;
+32 -8
View File
@@ -12,23 +12,35 @@ body {
}
.hide-scrollbar {
-ms-overflow-style: none; /* IE and Edge */
scrollbar-width: none; /* Firefox */
-ms-overflow-style: none;
/* IE and Edge */
scrollbar-width: none;
/* Firefox */
}
@media screen and (max-width: 766px) {
.bBofGr {
width: 14px !important;
}
}
/* below css class replace bootstrap background color with daisy */
.op-bg-primary {
@apply bg-primary;
}
.op-bg-secondary {
@apply bg-secondary;
}
.op-bg-info {
@apply bg-info;
}
.op-bg-success{
.op-bg-success {
@apply bg-success;
}
.op-bg-warning {
@apply bg-warning;
}
@@ -37,25 +49,37 @@ body {
.op-text-primary {
@apply text-primary;
}
.op-text-secondary {
@apply text-secondary;
}
.op-text-info {
@apply text-info;
}
.op-text-success{
.op-text-accent {
@apply text-accent;
}
.op-text-success {
@apply text-success;
}
.op-text-warning {
@apply text-warning;
}
.op-border-primary{
@apply border-primary
.op-border-primary {
@apply border-primary;
}
/* CSS for scrollbar customization */
* {
scrollbar-width: thin; /* For Firefox */
scrollbar-color: gray; /* For Firefox */
scrollbar-width: thin;
/* For Firefox */
scrollbar-color: gray;
/* For Firefox */
}
/* For webkit-based browsers like Chrome, Safari */
+5 -4
View File
@@ -16,13 +16,14 @@ import {
import DragElement from "./components/pdf/DragElement";
import TagManager from "react-gtm-module";
import Parse from "parse";
import './polyfills'
import "./polyfills";
import { serverUrl_fn } from "./constant/appinfo";
import "./i18n";
const appId = process.env.REACT_APP_APPID
? process.env.REACT_APP_APPID
: "opensign";
const serverUrl = process.env.REACT_APP_SERVERURL
? process.env.REACT_APP_SERVERURL
: window.location.origin + "/api/app";
const serverUrl = serverUrl_fn();
Parse.initialize(appId);
Parse.serverURL = serverUrl;
+50 -22
View File
@@ -1,3 +1,5 @@
import { isEnableSubscription } from "../constant/const";
export default function reportJson(id) {
// console.log("json ", json);
const head = ["Sr.No", "Title", "Note", "Folder", "File", "Owner", "Signers"];
@@ -10,9 +12,43 @@ export default function reportJson(id) {
"Owner",
"Signers"
];
const contactbook = ["Sr.No", "Title", "Email", "Phone"];
const iphead = [
"Sr.No",
"Title",
"Note",
"Folder",
"File",
"Status",
"Signers"
];
const contactbook = ["Sr.No", "Name", "Email", "Phone"];
const dashboardReportHead = ["Title", "File", "Owner", "Signers"];
const templateReport = ["Sr.No", "Title", "File", "Owner", "Signers"];
const templateSubAction = isEnableSubscription
? [
{
btnId: "2435",
btnLabel: "Embed",
hoverLabel: "Embed",
btnIcon: "fa-light fa-code",
action: "Embed"
},
{
btnId: "2436",
btnLabel: "Copy TemplateId",
hoverLabel: "Copy TemplateId",
btnIcon: "fa-light fa-copy",
action: "CopyTemplateId"
},
{
btnId: "2437",
btnLabel: "Copy Public URL",
hoverLabel: "Copy Public URL",
btnIcon: "fa-light fa-copy",
action: "CopyPublicURL"
}
]
: [];
switch (id) {
// draft documents report
case "ByHuevtCFY":
@@ -63,7 +99,7 @@ export default function reportJson(id) {
case "1MwEuxLEkF":
return {
reportName: "In-progress documents",
heading: head,
heading: iphead,
actions: [
{
btnId: "8901",
@@ -325,9 +361,7 @@ export default function reportJson(id) {
btnIcon: "fa-light fa-plus",
redirectUrl: "placeHolderSign",
action: "redirect",
selector: "reactourSecond",
message:
"Click the 'Use' button to create a new document from an existing template. "
selector: "reactourSecond"
},
{
btnId: "1631",
@@ -337,9 +371,7 @@ export default function reportJson(id) {
btnIcon: "fa-light fa-envelope",
redirectUrl: "",
action: "bulksend",
selector: "tourbulksend",
message:
"To quickly create and send multiple documents using an existing template, click the 'Quick Send' button."
selector: "tourbulksend"
},
{
btnId: "2234",
@@ -349,8 +381,6 @@ export default function reportJson(id) {
btnIcon: "fa-light fa-ellipsis-vertical fa-lg",
action: "option",
selector: "reactourThird",
message:
"This menu reveals more options such as Edit & Delete. Use the 'Edit' button to add signer roles, modify fields, and update your template. Changes will apply to all future documents created from this template but wont affect existing documents.Use the Delete button you can delete template. ",
subaction: [
{
btnId: "2434",
@@ -360,6 +390,7 @@ export default function reportJson(id) {
redirectUrl: "template",
action: "redirect"
},
...templateSubAction,
{
btnId: "1834",
btnLabel: "Delete",
@@ -381,18 +412,15 @@ export default function reportJson(id) {
if (item.action === "option") {
// Make a shallow copy of the item
const newItem = { ...item };
newItem.subaction = [
{
btnId: "1873",
btnLabel: "Share with team",
hoverLabel: "Share with team",
btnIcon: "fa-light fa-share-nodes",
redirectUrl: "",
action: "sharewith"
},
...newItem.subaction
];
//splice method used to add `Share with team` option on second index of list
newItem.subaction.splice(1, 0, {
btnId: "1873",
btnLabel: "Share with team",
hoverLabel: "Share with team",
btnIcon: "fa-light fa-share-nodes",
redirectUrl: "",
action: "sharewith"
});
return newItem;
}
return item;
+9 -16
View File
@@ -19,9 +19,7 @@ const dashboardJson = [
key: "count",
Redirect_type: "Report",
Redirect_id: "4Hhwbp482K",
tourSection: "tourcard1",
tourMessage:
"Clicking on this card will take you to the list of documents awaiting your review."
tourSection: "tourcard1"
}
}
},
@@ -38,13 +36,11 @@ const dashboardJson = [
queryType: "",
class: "contracts_Document",
query:
'where={"Type":{"#*ne":"Folder"},"Signers":{"#*exists":true,"#*ne":[]},"Placeholders":{"#*ne":null},"IsCompleted":{"#*ne":true},"IsDeclined":{"#*ne":true},"IsArchive":{"#*ne":true},"CreatedBy":{"__type":"Pointer","className":"_User","objectId":"#UserId.objectId#"},"ExpiryDate":{"#*gt":{"__type":"#Date#","iso":"#today#"}}}&count=1',
'where={"Type":{"#*ne":"Folder"},"Signers":{"#*exists":true,"#*ne":[]},"Placeholders":{"#*ne":null},"SignedUrl":{"#*ne":null},"IsCompleted":{"#*ne":true},"IsDeclined":{"#*ne":true},"IsArchive":{"#*ne":true},"CreatedBy":{"__type":"Pointer","className":"_User","objectId":"#UserId.objectId#"},"ExpiryDate":{"#*gt":{"__type":"#Date#","iso":"#today#"}}}&count=1',
key: "count",
Redirect_type: "Report",
Redirect_id: "1MwEuxLEkF",
tourSection: "tourcard2",
tourMessage:
"Clicking on this card will take you to a list of documents awaiting signature."
tourSection: "tourcard2"
}
}
},
@@ -53,10 +49,9 @@ const dashboardJson = [
widget: {
type: "report",
reportId: "5Go51Q7T8r",
label: "Recent signature requests",
data: {
tourSection: "tourreport1",
tourMessage:
"This is a list of documents that are waiting for your signature."
tourSection: "tourreport1"
}
}
},
@@ -65,10 +60,9 @@ const dashboardJson = [
widget: {
type: "report",
reportId: "d9k3UfYHBc",
label: "Recently sent for signatures",
data: {
tourSection: "tourreport2",
tourMessage:
"This is a list of documents you've sent to other parties for signature."
tourSection: "tourreport2"
}
}
},
@@ -77,10 +71,9 @@ const dashboardJson = [
widget: {
type: "report",
reportId: "kC5mfynCi4",
label: "Drafts",
data: {
tourSection: "tourreport3",
tourMessage:
"This are documents you have started but have not finalized for sending."
tourSection: "tourreport3"
}
}
}
+8
View File
@@ -154,6 +154,14 @@ const sidebarList = [
pageType: "",
description: "",
objectId: "webhook"
},
{
icon: "fa-light fa-sliders",
title: "Preferences",
target: "_self",
pageType: "",
description: "",
objectId: "preferences"
}
]
}
+109 -20
View File
@@ -3,6 +3,7 @@ import { isStaging } from "../constant/const";
const plans = [
{
planName: "OPENSIGN™ FREE",
code: { monthly: "freeplan", yearly: "freeplan" },
img: "free.png",
currency: "",
monthlyPrice: "Free",
@@ -12,46 +13,49 @@ const plans = [
url: "",
target: "_blank",
benefits: [
"Unlimited envelopes",
"Unlimited digital signatures",
"Sign documents yourself",
"Request signatures from others",
"Unlimited templates",
"14 field types",
"Automatic e-signatures",
"Completion certificates",
"Send in order",
"Organize docs in OpenSign™ Drive",
"Document templates",
"Import from Dropbox",
"Contact book",
"Document expiry support",
"Decline document support",
"Email notifications",
"Recipient authentication using OTP",
"Bulk send (upto 5 docs)",
"Public profiles",
"And much more"
],
yearlyBenefits: [
"Unlimited envelopes",
"Unlimited digital signatures",
"Sign documents yourself",
"Request signatures from others",
"Unlimited templates",
"14 field types",
"Automatic e-signatures",
"Completion certificates",
"Send in order",
"Organize docs in OpenSign™ Drive",
"Document templates",
"Import from Dropbox",
"Contact book",
"Document expiry support",
"Decline document support",
"Email notifications",
"Recipient authentication using OTP",
"Bulk send (upto 5 docs)",
"Public profiles",
"And much more"
]
},
{
planName: "OPENSIGN™ PROFESSIONAL",
code: isStaging
? { monthly: "pro-weekly", yearly: "pro-yearly" }
: { monthly: "professional-monthly", yearly: "professional-yearly" },
img: "professional.png",
currency: "$",
monthlyPrice: "29.99",
@@ -59,10 +63,10 @@ const plans = [
subtitle: "Exclusive Access to advanced features.",
btn: { text: "Subscribe", color: "op-btn-primary" },
url: isStaging
? "https://billing.zoho.in/subscribe/9627f62a09df1c8ce500f2f4dc8328dd84ecda20eeae13878ce581d60240f206/pro-weekly"
? "https://billing.zohosecure.in/subscribe/9627f62a09df1c8ce500f2f4dc8328dd84ecda20eeae13878ce581d60240f206/pro-weekly"
: "https://billing.opensignlabs.com/subscribe/ef798486e6a0a11ea65f2bae8f2af901d1a09dfa8085585cdd4ec4d7f32137f3/professional-monthly",
yearlyUrl: isStaging
? "https://billing.zoho.in/subscribe/9627f62a09df1c8ce500f2f4dc8328ddc184411129224f1f29ed84f6cef3b862/pro-yearly"
? "https://billing.zohosecure.in/subscribe/9627f62a09df1c8ce500f2f4dc8328ddc184411129224f1f29ed84f6cef3b862/pro-yearly"
: "https://billing.opensignlabs.com/subscribe/ef798486e6a0a11ea65f2bae8f2af901d8ad1135190dff951330360e47585a71/professional-yearly",
target: "_self",
benefits: [
@@ -73,12 +77,14 @@ const plans = [
"Webhooks",
"Zapier integration",
"API Access",
"100 API signatures included",
"upto 100 API signatures",
"Custom email templates",
"Connect your own Gmail or SMTP account for sending emails",
"Auto reminders",
"Bulk send (upto 20 docs)",
"Bulk send (upto 100 docs)",
"Premium Public profile usernames",
"Embedding (coming soon)"
"Enforce email-based verification to confirm signer identity",
"Embedded signing"
],
yearlyBenefits: [
"Everything in OpenSign™ free",
@@ -88,16 +94,19 @@ const plans = [
"Webhooks",
"Zapier integration",
"API Access",
"240 API signatures included",
"upto 240 API signatures",
"Custom email templates",
"Connect your own Gmail or SMTP account for sending emails",
"Auto reminders",
"Bulk send (upto 20 docs)",
"Bulk send (upto 240 docs)",
"Premium Public profile usernames",
"Embedding (coming soon)"
"Enforce email-based verification to confirm signer identity",
"Embedded signing"
]
},
{
planName: "OPENSIGN™ TEAMS",
code: { monthly: "teams-monthly", yearly: "teams-yearly" },
img: "teams.png",
currency: "$",
monthlyPrice: `39.99<sup style="font-size: 17px;">/user</sup>`,
@@ -105,31 +114,33 @@ const plans = [
subtitle: "Exclusive Access to advanced features.",
btn: { text: "Subscribe", color: "op-btn-accent" },
url: isStaging
? "https://billing.zoho.in/subscribe/ed8097273a82b6bf39892c11a3bb3c381eb2705736014cfbdbde1ccf1c7a189d/team-weekly"
? "https://billing.zohosecure.in/subscribe/ed8097273a82b6bf39892c11a3bb3c381eb2705736014cfbdbde1ccf1c7a189d/teams-monthly"
: "https://billing.opensignlabs.com/subscribe/ef798486e6a0a11ea65f2bae8f2af901237d0702bfaa959406306635d80f138c/teams-monthly",
yearlyUrl: isStaging
? "https://billing.zoho.in/subscribe/ed8097273a82b6bf39892c11a3bb3c381eb2705736014cfbdbde1ccf1c7a189d/team-weekly"
? "https://billing.zohosecure.in/subscribe/ed8097273a82b6bf39892c11a3bb3c381eb2705736014cfbdbde1ccf1c7a189d/teams-yearly"
: "https://billing.opensignlabs.com/subscribe/ef798486e6a0a11ea65f2bae8f2af9011a864994bbeeec71fcf106188630199d/teams-yearly",
target: "_self",
benefits: [
"Everything in OpenSign™ professional",
"100 API signatures included",
"upto 100 API signatures",
"Teams and Organizations",
"Share Templates with teams",
"Share Templates with individuals",
"BYOC - Store your documents in your own cloud storage",
"DocumentId removal from signed docs",
"Bulk send (upto 50 docs)",
"Bulk send (upto 100 docs)",
"Request Payments (coming soon)",
"Mobile app (coming soon)"
],
yearlyBenefits: [
"Everything in OpenSign™ professional",
"500 API signatures included",
"upto 500 API signatures",
"Teams and Organizations",
"Share Templates with teams",
"Share Templates with individuals",
"BYOC - Store your documents in your own cloud storage",
"DocumentId removal from signed docs",
"Bulk send (upto 50 docs)",
"Bulk send (upto 500 docs)",
"Request Payments (coming soon)",
"Mobile app (coming soon)"
]
@@ -163,4 +174,82 @@ const plans = [
}
];
export const validplan = {
"team-weekly": true,
"team-yearly": true,
"teams-monthly": true,
"teams-yearly": true,
"enterprise-monthly": true,
"enterprise-yearly": true
};
export const paidUrl = (plan) => {
const teamperiod = {
"team-weekly": "monthly",
"team-yearly": "yearly",
"teams-monthly": "monthly",
"teams-yearly": "yearly"
};
const period = teamperiod[plan] || "";
if (period) {
const extUser =
localStorage.getItem("Extand_Class") &&
JSON.parse(localStorage.getItem("Extand_Class"))?.[0];
const user = {
name: extUser?.Name,
email: extUser?.Email,
company: extUser?.Company,
phone: extUser?.Phone
};
// console.log("userDetails ", userDetails);
const fullname = user && user.name ? user.name.split(" ") : "";
const firstname = fullname?.[0]
? "first_name=" + encodeURIComponent(fullname?.[0])
: "";
const lastname = fullname?.[1]
? "&last_name=" + encodeURIComponent(fullname?.[1])
: "";
const name = firstname ? firstname + lastname : "";
const email =
user && user.email ? "&email=" + encodeURIComponent(user.email) : "";
const company =
user && user.company
? "&company_name=" + encodeURIComponent(user.company)
: "";
const phone =
user && user.phone ? "&mobile=" + encodeURIComponent(user.phone) : "";
const allowedUsers =
localStorage.getItem("allowedUsers") &&
localStorage.getItem("allowedUsers") > 0
? localStorage.getItem("allowedUsers") - 1
: "";
const quantity = allowedUsers
? `addon_code%5B0%5D=extra-teams-users-${period}&addon_quantity%5B0%5D=${allowedUsers}&`
: "";
const details =
"?shipping_country_code=US&billing_country_code=US&billing_state_code=CA&" +
quantity +
name +
email +
company +
phone;
if (user) {
localStorage.setItem("userDetails", JSON.stringify(user));
}
const url = {
monthly: isStaging
? "https://billing.zohosecure.in/subscribe/ed8097273a82b6bf39892c11a3bb3c381eb2705736014cfbdbde1ccf1c7a189d/teams-monthly"
: "https://billing.opensignlabs.com/subscribe/ef798486e6a0a11ea65f2bae8f2af901237d0702bfaa959406306635d80f138c/teams-monthly",
yearly: isStaging
? "https://billing.zohosecure.in/subscribe/ed8097273a82b6bf39892c11a3bb3c381eb2705736014cfbdbde1ccf1c7a189d/teams-yearly"
: "https://billing.opensignlabs.com/subscribe/ef798486e6a0a11ea65f2bae8f2af9011a864994bbeeec71fcf106188630199d/teams-yearly"
};
const planurl = url[period] + details;
return planurl;
} else {
return "/subscription";
}
};
export default plans;
+30 -30
View File
@@ -14,8 +14,10 @@ import { useCookies } from "react-cookie";
import { fetchSubscription } from "../constant/Utils";
import Loader from "../primitives/Loader";
import { showHeader } from "../redux/reducers/showHeader";
import { useTranslation } from "react-i18next";
const HomeLayout = () => {
const { t, i18n } = useTranslation();
const navigate = useNavigate();
const location = useLocation();
const dispatch = useDispatch();
@@ -32,6 +34,13 @@ const HomeLayout = () => {
const [, setCookie] = useCookies(["accesstoken", "main_Domain"]);
const tenantId = localStorage.getItem("TenantId");
useEffect(() => {
const language = localStorage.getItem("i18nextLng");
i18n.changeLanguage(language);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
useEffect(() => {
if (!tenantId) {
setIsUserValid(false);
@@ -86,7 +95,9 @@ const HomeLayout = () => {
domain: updateDomain
});
};
const handleNavigation = () => {
navigate("/subscription");
};
async function checkIsSubscribed() {
if (isEnableSubscription) {
const res = await fetchSubscription();
@@ -98,10 +109,10 @@ const HomeLayout = () => {
setIsUserValid(true);
setIsLoader(false);
} else {
navigate(`/subscription`);
handleNavigation(res.plan);
}
} else {
navigate(`/subscription`);
handleNavigation(res.plan);
}
} else {
setIsUserValid(true);
@@ -150,20 +161,20 @@ const HomeLayout = () => {
setTourConfigs([
{
selector: '[data-tut="reactourFirst"]',
content: `You have logged in successfully! Let's take a look.`,
content: t("tour-mssg.home-layout-1"),
position: "top"
// style: { backgroundColor: "#abd4d2" },
},
{
selector: '[data-tut="tourbutton"]',
content: `To upload documents for self-signing or to request others signatures, simply select the respective buttons.`,
content: t("tour-mssg.home-layout-2"),
position: "top"
// style: { backgroundColor: "#abd4d2" },
},
...resArr,
{
selector: '[data-tut="reactourLast"]',
content: `You are ready to start using OpenSign! If you need support feel free to contact us.`,
content: t("tour-mssg.home-layout-3"),
position: "top"
// style: { backgroundColor: "#abd4d2" },
}
@@ -212,27 +223,14 @@ const HomeLayout = () => {
};
async function checkTourStatus() {
const currentUser = Parse.User.current();
const cloudRes = await Parse.Cloud.run("getUserDetails", {
email: currentUser.get("email")
});
const res = { data: cloudRes.toJSON() };
if (res.data && res.data.TourStatus && res.data.TourStatus.length > 0) {
const tourStatus = res.data.TourStatus;
// console.log("res ", res.data.TourStatus);
const cloudRes = await Parse.Cloud.run("getUserDetails");
if (cloudRes) {
const extUser = JSON.parse(JSON.stringify(cloudRes));
localStorage.setItem("Extand_Class", JSON.stringify([extUser]));
const tourStatus = extUser?.TourStatus || [];
setTourStatusArr(tourStatus);
const filteredtourStatus = tourStatus.filter((obj) => obj["loginTour"]);
if (filteredtourStatus.length > 0) {
const loginTour = filteredtourStatus[0]["loginTour"];
// console.log("loginTour", loginTour);
if (loginTour) {
setIsTour(false);
} else {
setIsTour(true);
}
} else {
setIsTour(true);
}
const loginTour = tourStatus.find((obj) => obj.loginTour)?.loginTour;
setIsTour(!loginTour);
} else {
setIsTour(true);
}
@@ -244,9 +242,9 @@ const HomeLayout = () => {
}
};
const handleLoginBtn = () => {
const handleLoginBtn = async () => {
try {
Parse?.User?.logOut();
await Parse?.User?.logOut();
} catch (err) {
console.log("err ", err);
} finally {
@@ -257,7 +255,9 @@ const HomeLayout = () => {
return (
<div>
<div className="sticky top-0 z-[501]">
{!isLoader && <Header showSidebar={showSidebar} />}
{!isLoader && (
<Header showSidebar={showSidebar} setIsMenu={setIsOpen} />
)}
</div>
{isUserValid ? (
<>
@@ -298,7 +298,7 @@ const HomeLayout = () => {
<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">
Login
{t("login")}
</button>
</div>
</ModalUi>
+147 -99
View File
@@ -2,13 +2,20 @@ import React, { useEffect, useState } from "react";
import Parse from "parse";
import { appInfo } from "../constant/appinfo";
import { NavLink, useNavigate } from "react-router-dom";
import { getAppLogo, openInNewTab } from "../constant/Utils";
import {
getAppLogo,
openInNewTab,
saveLanguageInLocal
} from "../constant/Utils";
import { useDispatch } from "react-redux";
import { showTenant } from "../redux/reducers/ShowTenant";
import Loader from "../primitives/Loader";
import Title from "../components/Title";
import { useTranslation } from "react-i18next";
import { emailRegex } from "../constant/const";
const AddAdmin = () => {
const { t, i18n } = useTranslation();
const navigate = useNavigate();
const dispatch = useDispatch();
const [showPassword, setShowPassword] = useState(false);
@@ -39,19 +46,23 @@ const AddAdmin = () => {
setState((prev) => ({ ...prev, loading: true }));
try {
const app = await getAppLogo();
if (app?.user === "exist") {
setErrMsg("Admin already exist.");
if (app?.error === "invalid_json") {
setErrMsg(t("server-down"));
} else if (app?.user === "exist") {
setErrMsg(t("admin-exists"));
}
} catch (err) {
setErrMsg("Something went wrong.");
setErrMsg(t("something-went-wrong-mssg"));
console.log("err in check user exist", err);
} finally {
setState((prev) => ({ ...prev, loading: false }));
}
};
const clearStorage = async () => {
if (Parse.User.current()) {
try {
await Parse.User.logOut();
} catch (err) {
console.log("Err while logging out", err);
}
const baseUrl = localStorage.getItem("baseUrl");
const appid = localStorage.getItem("parseAppId");
@@ -61,6 +72,7 @@ const AddAdmin = () => {
const userSettings = localStorage.getItem("userSettings");
localStorage.clear();
saveLanguageInLocal(i18n);
localStorage.setItem("baseUrl", baseUrl);
localStorage.setItem("parseAppId", appid);
localStorage.setItem("appLogo", applogo);
@@ -73,77 +85,81 @@ const AddAdmin = () => {
const handleSubmit = async (event) => {
event.preventDefault();
if (lengthValid && caseDigitValid && specialCharValid) {
clearStorage();
setState({ loading: true });
const userDetails = {
name: name,
email: email,
phone: phone,
company: company,
jobTitle: jobTitle
};
localStorage.setItem("userDetails", JSON.stringify(userDetails));
try {
event.preventDefault();
const user = new Parse.User();
user.set("name", name);
user.set("email", email);
user.set("password", password);
user.set("phone", phone);
user.set("username", email);
const userRes = await user.save();
if (userRes) {
const params = {
userDetails: {
jobTitle: jobTitle,
company: company,
name: name,
email: email,
phone: phone,
role: "contracts_Admin"
}
};
try {
const usersignup = await Parse.Cloud.run("addadmin", params);
if (usersignup) {
if (isSubscribeNews) {
subscribeNewsletter();
if (!emailRegex.test(email)) {
alert("Please enter a valid email address.");
} else {
if (lengthValid && caseDigitValid && specialCharValid) {
clearStorage();
setState({ loading: true });
const userDetails = {
name: name,
email: email,
phone: phone,
company: company,
jobTitle: jobTitle
};
localStorage.setItem("userDetails", JSON.stringify(userDetails));
try {
event.preventDefault();
const user = new Parse.User();
user.set("name", name);
user.set("email", email);
user.set("password", password);
user.set("phone", phone);
user.set("username", email);
const userRes = await user.save();
if (userRes) {
const params = {
userDetails: {
jobTitle: jobTitle,
company: company,
name: name,
email: email,
phone: phone,
role: "contracts_Admin"
}
handleNavigation(userRes.getSessionToken());
}
} catch (err) {
alert(err.message);
setState({ loading: false });
}
}
} catch (error) {
console.log("err ", error);
if (error.code === 202) {
const params = { email: email };
const res = await Parse.Cloud.run("getUserDetails", params);
// console.log("Res ", res);
if (res) {
alert("User already exists with this username!");
setState({ loading: false });
} else {
// console.log("state.email ", email);
};
try {
await Parse.User.requestPasswordReset(email).then(
async function (res) {
if (res.data === undefined) {
alert("Verification mail has been sent to your E-mail!");
}
const usersignup = await Parse.Cloud.run("addadmin", params);
if (usersignup) {
if (isSubscribeNews) {
subscribeNewsletter();
}
);
handleNavigation(userRes.getSessionToken());
}
} catch (err) {
console.log(err);
alert(err.message);
setState({ loading: false });
}
}
} catch (error) {
console.log("err ", error);
if (error.code === 202) {
const params = { email: email };
const res = await Parse.Cloud.run("getUserDetails", params);
// console.log("Res ", res);
if (res) {
alert(t("already-exists-this-username"));
setState({ loading: false });
} else {
// console.log("state.email ", email);
try {
await Parse.User.requestPasswordReset(email).then(
async function (res) {
if (res.data === undefined) {
alert(t("verification-code-sent"));
}
}
);
} catch (err) {
console.log(err);
}
setState({ loading: false });
}
} else {
alert(error.message);
setState({ loading: false });
}
} else {
alert(error.message);
setState({ loading: false });
}
}
}
@@ -165,10 +181,7 @@ const AddAdmin = () => {
// Check extended class user role and tenentId
try {
const userSettings = appInfo.settings;
const currentUser = Parse.User.current();
const extUser = await Parse.Cloud.run("getUserDetails", {
email: currentUser.get("email")
});
const extUser = await Parse.Cloud.run("getUserDetails");
if (extUser) {
const IsDisabled = extUser?.get("IsDisabled") || false;
if (!IsDisabled) {
@@ -199,27 +212,27 @@ const AddAdmin = () => {
setState({
loading: false,
alertType: "success",
alertMsg: "Registered user successfully."
alertMsg: t("registered-user-successfully")
});
navigate(`/${menu.pageType}/${menu.pageId}`);
} else {
setState({
loading: false,
alertType: "danger",
alertMsg: "Role not found."
alertMsg: t("role-not-found")
});
}
} else {
setState({
loading: false,
alertType: "danger",
alertMsg: "You don't have access, please contact the admin."
alertMsg: t("do-not-access")
});
}
}
} catch (error) {
console.log("error in fetch extuser", error);
const msg = error.message || "Something went wrong.";
const msg = error.message || t("something-went-wrong-mssg");
setState({ loading: false, alertType: "danger", alertMsg: msg });
} finally {
setTimeout(() => setState({ loading: false, alertMsg: "" }), 2000);
@@ -249,7 +262,7 @@ const AddAdmin = () => {
};
return (
<div className="h-screen flex justify-center">
<Title title={"Add admin"} />
<Title title="Add admin" />
{state.loading ? (
<div className="text-[grey] flex justify-center items-center text-lg md:text-2xl">
<Loader />
@@ -265,7 +278,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">
Opensign Setup
{t("opensign-setup")}
</h2>
<NavLink
to="https://discord.com/invite/xe9TDuyAyj"
@@ -273,7 +286,7 @@ const AddAdmin = () => {
rel="noopener noreferrer"
className="text-center text-sm mt-1 text-[blue] cursor-pointer"
>
Join our discord server
{t("join-discord")}
<i
aria-hidden="true"
className="fa-brands fa-discord ml-1"
@@ -282,52 +295,76 @@ const AddAdmin = () => {
</NavLink>
<div className="px-6 py-3 text-xs">
<label className="block ">
Name <span className="text-[red] text-[13px]">*</span>
{t("name")}{" "}
<span className="text-[red] text-[13px]">*</span>
</label>
<input
type="text"
className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs"
value={name}
onChange={(e) => setName(e.target.value)}
onInvalid={(e) =>
e.target.setCustomValidity(t("input-required"))
}
onInput={(e) => e.target.setCustomValidity("")}
required
/>
<hr className="my-2 border-none" />
<label>
Email <span className="text-[red] text-[13px]">*</span>
{"email"}{" "}
<span className="text-[red] text-[13px]">*</span>
</label>
<input
id="email"
type="email"
className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs"
value={email}
onChange={(e) => setEmail(e.target.value?.toLowerCase())}
onChange={(e) =>
setEmail(
e.target.value?.toLowerCase()?.replace(/\s/g, "")
)
}
onInvalid={(e) =>
e.target.setCustomValidity(t("input-required"))
}
onInput={(e) => e.target.setCustomValidity("")}
required
/>
<hr className="my-2 border-none" />
<label>
Phone <span className="text-[red] text-[13px]">*</span>
{t("phone")}{" "}
<span className="text-[red] text-[13px]">*</span>
</label>
<input
type="tel"
className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs"
value={phone}
onChange={(e) => setPhone(e.target.value)}
onInvalid={(e) =>
e.target.setCustomValidity(t("input-required"))
}
onInput={(e) => e.target.setCustomValidity("")}
required
/>
<hr className="my-2 border-none" />
<label>
Company <span className="text-[red] text-[13px]">*</span>
{t("company")}{" "}
<span className="text-[red] text-[13px]">*</span>
</label>
<input
type="text"
className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs"
value={company}
onChange={(e) => setCompany(e.target.value)}
onInvalid={(e) =>
e.target.setCustomValidity(t("input-required"))
}
onInput={(e) => e.target.setCustomValidity("")}
required
/>
<hr className="my-2 border-none" />
<label>
Job Title{" "}
{t("job-title")}{" "}
<span className="text-[red] text-[13px]">*</span>
</label>
<input
@@ -335,11 +372,16 @@ const AddAdmin = () => {
className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs"
value={jobTitle}
onChange={(e) => setJobTitle(e.target.value)}
onInvalid={(e) =>
e.target.setCustomValidity(t("input-required"))
}
onInput={(e) => e.target.setCustomValidity("")}
required
/>
<hr className="my-2 border-none" />
<label>
Password <span className="text-[red] text-[13px]">*</span>
{t("password")}
<span className="text-[red] text-[13px]">*</span>
</label>
<div className="relative">
<input
@@ -348,6 +390,10 @@ const AddAdmin = () => {
name="password"
value={password}
onChange={(e) => handlePasswordChange(e)}
onInvalid={(e) =>
e.target.setCustomValidity(t("input-required"))
}
onInput={(e) => e.target.setCustomValidity("")}
required
/>
<span
@@ -368,24 +414,22 @@ const AddAdmin = () => {
lengthValid ? "text-green-600" : "text-red-600"
}`}
>
{lengthValid ? "✓" : "✗"} Password should be 8
characters long
{lengthValid ? "✓" : "✗"} {t("password-length")}
</p>
<p
className={`${
caseDigitValid ? "text-green-600" : "text-red-600"
}`}
>
{caseDigitValid ? "✓" : "✗"} Password should contain
uppercase letter, lowercase letter, digit
{caseDigitValid ? "✓" : "✗"} {t("password-case")}
</p>
<p
className={`${
specialCharValid ? "text-green-600" : "text-red-600"
}`}
>
{specialCharValid ? "✓" : "✗"} Password should contain
special character
{specialCharValid ? "✓" : "✗"}{" "}
{t("password-special-char")}
</p>
</div>
)}
@@ -396,13 +440,17 @@ const AddAdmin = () => {
id="termsandcondition"
checked={isAuthorize}
onChange={(e) => setIsAuthorize(e.target.checked)}
onInvalid={(e) =>
e.target.setCustomValidity(t("input-required"))
}
onInput={(e) => e.target.setCustomValidity("")}
required
/>
<label
className="text-xs cursor-pointer ml-1 mb-0"
htmlFor="termsandcondition"
>
I agree to the
{t("agreee")}
</label>
<span
className="underline cursor-pointer ml-1"
@@ -412,7 +460,7 @@ const AddAdmin = () => {
)
}
>
Terms of Service
{t("term")}
</span>
<span>.</span>
</div>
@@ -420,15 +468,15 @@ const AddAdmin = () => {
<input
type="checkbox"
className="op-checkbox op-checkbox-sm"
id="termsandcondition"
id="subscribetoopensign"
checked={isSubscribeNews}
onChange={(e) => setIsSubscribeNews(e.target.checked)}
/>
<label
className="text-xs cursor-pointer ml-1 mb-0"
htmlFor="termsandcondition"
htmlFor="subscribetoopensign"
>
Subscribe to OpenSign newsletter
{t("subscribe-to-opensign")}
</label>
</div>
</div>
@@ -438,7 +486,7 @@ const AddAdmin = () => {
className="op-btn op-btn-primary w-full"
disabled={state.loading}
>
{state.loading ? "Loading..." : "Next"}
{state.loading ? t("loading") : t("next")}
</button>
</div>
</div>
+21 -13
View File
@@ -2,8 +2,10 @@ import React, { useState } from "react";
import Parse from "parse";
import { Navigate } from "react-router-dom";
import Title from "../components/Title";
import { useTranslation } from "react-i18next";
function ChangePassword() {
const { t } = useTranslation();
const [currentpassword, setCurrentPassword] = useState("");
const [newpassword, setnewpassword] = useState("");
const [confirmpassword, setconfirmpassword] = useState("");
@@ -27,23 +29,23 @@ function ChangePassword() {
await Parse.User.become(_user.sessionToken);
localStorage.setItem("accesstoken", _user.sessionToken);
}
alert("Password updated successfully.");
alert(t("password-update-alert-1"));
})
.catch((error) => {
console.log("err", error);
alert("Something went wrong.");
alert(t("something-went-wrong-mssg"));
});
});
} else {
alert("Your current password is missing or incorrect.");
alert(t("password-update-alert-2"));
}
})
.catch((error) => {
alert("Your current password is missing or incorrect.");
alert(t("password-update-alert-3"));
console.error("Error while logging in user", error);
});
} else {
alert("Your password and confirmation password do not match.");
alert(t("password-update-alert-4"));
}
} catch (error) {
console.log("err", error);
@@ -56,13 +58,13 @@ function ChangePassword() {
<div className="w-full bg-base-100 text-base-content shadow rounded-box p-2">
<Title title="Change Password" />
<div className="text-xl font-bold border-b-[1px] border-gray-300">
Change Password
{t("change-password")}
</div>
<div className="m-2">
<form onSubmit={handleSubmit} className=" flex flex-col gap-y-2">
<div>
<label htmlFor="currentpassword" className="block text-xs ml-1">
Current Password
{t("current-password")}
</label>
<input
type="password"
@@ -70,13 +72,15 @@ function ChangePassword() {
value={currentpassword}
onChange={(e) => setCurrentPassword(e.target.value)}
className="op-input op-input-bordered op-input-sm text-xs w-full"
placeholder="Current Password"
placeholder={t("current-password")}
onInvalid={(e) => e.target.setCustomValidity(t("input-required"))}
onInput={(e) => e.target.setCustomValidity("")}
required
/>
</div>
<div>
<label htmlFor="newpassword" className="text-xs block ml-1">
New Password
{t("new-password")}
</label>
<input
type="password"
@@ -84,13 +88,15 @@ function ChangePassword() {
value={newpassword}
onChange={(e) => setnewpassword(e.target.value)}
className="op-input op-input-bordered op-input-sm text-xs w-full"
placeholder="New Password"
placeholder={t("new-password")}
onInvalid={(e) => e.target.setCustomValidity(t("input-required"))}
onInput={(e) => e.target.setCustomValidity("")}
required
/>
</div>
<div>
<label htmlFor="newpassword" className="text-xs block ml-1">
Confirm Password
{t("confirm-password")}
</label>
<input
type="password"
@@ -98,7 +104,9 @@ function ChangePassword() {
className="op-input op-input-bordered op-input-sm text-xs w-full"
value={confirmpassword}
onChange={(e) => setconfirmpassword(e.target.value)}
placeholder="Confirm Password"
placeholder={t("confirm-password")}
onInvalid={(e) => e.target.setCustomValidity(t("input-required"))}
onInput={(e) => e.target.setCustomValidity("")}
required
/>
</div>
@@ -106,7 +114,7 @@ function ChangePassword() {
type="submit"
className="op-btn op-btn-primary shadow-md mt-2"
>
Change Password
{t("change-password")}
</button>
</form>
</div>
+3 -1
View File
@@ -6,8 +6,10 @@ import { useDispatch } from "react-redux";
import { saveTourSteps } from "../redux/reducers/TourStepsReducer";
import dashboardJson from "../json/dashboardJson";
import Loader from "../primitives/Loader";
import { useTranslation } from "react-i18next";
const Dashboard = () => {
const { t } = useTranslation();
const navigate = useNavigate();
const dispatch = useDispatch();
const { id } = useParams();
@@ -40,7 +42,7 @@ const Dashboard = () => {
.map((col) => {
return {
selector: `[data-tut=${col.widget.data.tourSection}]`,
content: col.widget.data.tourMessage,
content: t(`tour-mssg.${col.widget.label}`),
position: "top"
// style: { backgroundColor: "#abd4d2" },
};
+2 -6
View File
@@ -74,7 +74,7 @@ const DebugPdf = () => {
const inferPdfType = async (pdf) => {
try {
const firstPage = await pdf.getPage(2);
const firstPage = await pdf.getPage(pdf?.numPages > 1 ? 2 : 1);
const scale = 1;
const { width, height } = firstPage.getViewport({ scale });
setPdfDimension({ width: width, height: height });
@@ -215,11 +215,7 @@ const DebugPdf = () => {
};
return (
<div>
{copied && (
<Alert type="success">
<span className="ml-3">Copied</span>
</Alert>
)}
{copied && <Alert type="success">Copied</Alert>}
<Title title={"Debug Pdf"} />
{width < 800 ? (
<HandleError handleError={"Debug PDF only availble for PC"} />
File diff suppressed because it is too large Load Diff
+40 -28
View File
@@ -7,22 +7,23 @@ import Alert from "../primitives/Alert";
import { appInfo } from "../constant/appinfo";
import { useDispatch } from "react-redux";
import { fetchAppInfo } from "../redux/reducers/infoReducer";
import { isEnableSubscription } from "../constant/const";
import { emailRegex, isEnableSubscription } from "../constant/const";
import { getAppLogo } from "../constant/Utils";
import { useTranslation } from "react-i18next";
function ForgotPassword() {
const { t } = useTranslation();
const dispatch = useDispatch();
const navigate = useNavigate();
const [state, setState] = useState({
email: "",
password: "",
hideNav: ""
});
const [state, setState] = useState({ email: "", password: "", hideNav: "" });
const [sentStatus, setSentStatus] = useState("");
const [image, setImage] = useState();
const handleChange = (event) => {
const { name, value } = event.target;
let { name, value } = event.target;
if (name === "email") {
value = value?.toLowerCase()?.replace(/\s/g, "");
}
setState({ ...state, [name]: value });
};
@@ -35,18 +36,22 @@ function ForgotPassword() {
const handleSubmit = async (event) => {
event.preventDefault();
localStorage.setItem("appLogo", appInfo.applogo);
localStorage.setItem("userSettings", JSON.stringify(appInfo.settings));
if (state.email) {
const username = state.email;
try {
await Parse.User.requestPasswordReset(username);
setSentStatus("success");
} catch (err) {
console.log("err ", err.code);
setSentStatus("failed");
} finally {
setTimeout(() => setSentStatus(""), 1000);
if (!emailRegex.test(state.email)) {
alert("Please enter a valid email address.");
} else {
localStorage.setItem("appLogo", appInfo.applogo);
localStorage.setItem("userSettings", JSON.stringify(appInfo.settings));
if (state.email) {
const username = state.email;
try {
await Parse.User.requestPasswordReset(username);
setSentStatus("success");
} catch (err) {
console.log("err ", err.code);
setSentStatus("failed");
} finally {
setTimeout(() => setSentStatus(""), 1000);
}
}
}
};
@@ -60,6 +65,11 @@ function ForgotPassword() {
// eslint-disable-next-line
}, []);
const saveLogo = async () => {
try {
await Parse.User.logOut();
} catch (err) {
console.log("err while logging out ", err);
}
if (isEnableSubscription) {
const app = await getAppLogo();
if (app?.logo) {
@@ -75,12 +85,10 @@ function ForgotPassword() {
<div>
<Title title="Forgot password page" />
{sentStatus === "success" && (
<Alert type="success">
Reset password link has been sent to your email id
</Alert>
<Alert type="success">{t("reset-password-alert-1")}</Alert>
)}
{sentStatus === "failed" && (
<Alert type={"danger"}>Please setup email adapter </Alert>
<Alert type={"danger"}>{t("reset-password-alert-2")}</Alert>
)}
<div className="md:p-10 lg:p-16">
<div className="md:p-4 lg:p-10 p-4 bg-base-100 text-base-content op-card">
@@ -96,19 +104,23 @@ function ForgotPassword() {
<div className="grid grid-cols-1 md:grid-cols-2 gap-x-2">
<div>
<form onSubmit={handleSubmit}>
<h2 className="text-[30px] mt-6">Welcome Back !</h2>
<h2 className="text-[30px] mt-6">{t("welcome")}</h2>
<span className="text-[12px] text-[#878787]">
Reset Your Password
{t("reset-password-alert-3")}
</span>
<div className="w-full my-4 op-card bg-base-100 shadow-md outline outline-1 outline-slate-300/50">
<div className="px-6 py-4">
<label className="block text-xs">Email</label>
<label className="block text-xs">{t("email")}</label>
<input
type="email"
name="email"
className="op-input op-input-bordered op-input-sm w-full"
value={state.email}
onChange={handleChange}
onInvalid={(e) =>
e.target.setCustomValidity(t("input-required"))
}
onInput={(e) => e.target.setCustomValidity("")}
required
/>
<hr className="my-2 border-none" />
@@ -116,13 +128,13 @@ function ForgotPassword() {
</div>
<div className="grid grid-cols-1 md:grid-cols-2 gap-2 text-center text-xs font-bold">
<button type="submit" className="op-btn op-btn-primary">
Submit
{t("submit")}
</button>
<button
onClick={() => navigate("/", { replace: true })}
className="op-btn op-btn-secondary"
>
Login
{t("login")}
</button>
</div>
</form>
File diff suppressed because it is too large Load Diff
+307 -52
View File
@@ -9,32 +9,55 @@ import Tooltip from "../primitives/Tooltip";
import Loader from "../primitives/Loader";
import SubscribeCard from "../primitives/SubscribeCard";
import Tour from "reactour";
const tourSteps = [
{
selector: '[data-tut="apisubscribe"]',
content: "Upgrade now to generate API token"
}
];
import { useTranslation } from "react-i18next";
import Parse from "parse";
function GenerateToken() {
const [parseBaseUrl] = useState(localStorage.getItem("baseUrl"));
const [parseAppId] = useState(localStorage.getItem("parseAppId"));
const origin = window.location.origin;
const { t } = useTranslation();
const parseBaseUrl = localStorage.getItem("baseUrl");
const parseAppId = localStorage.getItem("parseAppId");
const [apiToken, SetApiToken] = useState("");
const [isLoader, setIsLoader] = useState(true);
const [isModal, setIsModal] = useState(false);
const [isSubscribe, setIsSubscribe] = useState(false);
const [isModal, setIsModal] = useState({
generateapi: false,
buyapis: false,
unauthorized: false
});
const [isSubscribe, setIsSubscribe] = useState({
plan: "",
isValid: false,
adminId: "",
adminEmail: ""
});
const [isAlert, setIsAlert] = useState({ type: "success", msg: "" });
const [isTour, setIsTour] = useState(false);
const [amount, setAmount] = useState({
quantity: 500,
priceperapi: 0.15,
allowedcredits: 0,
addoncredits: 0,
totalcredits: 0,
price: (75.0).toFixed(2)
});
const [isFormLoader, setIsFormLoader] = useState(false);
const [apitestToken, setApiTestToken] = useState("");
const quantityList = [500, 1000, 5000, 50000];
useEffect(() => {
fetchToken();
// eslint-disable-next-line
}, []);
const tourSteps = [
{
selector: '[data-tut="apisubscribe"]',
content: t("tour-mssg.generate-token")
}
];
const fetchToken = async () => {
try {
if (isEnableSubscription) {
const getIsSubscribe = await checkIsSubscribed();
setIsSubscribe(getIsSubscribe);
const subscribe = await checkIsSubscribed();
setIsSubscribe(subscribe);
}
const url = parseBaseUrl + "functions/getapitoken";
const headers = {
@@ -44,22 +67,40 @@ function GenerateToken() {
};
const res = await axios.post(url, {}, { headers: headers });
if (res) {
SetApiToken(res.data?.result?.result);
const resCredits = await Parse.Cloud.run("allowedcredits");
const allowedcredits = resCredits?.allowedcredits || 0;
const addoncredits = resCredits?.addoncredits || 0;
const totalcredits = allowedcredits + addoncredits;
setAmount((obj) => ({
...obj,
allowedcredits: allowedcredits,
addoncredits: addoncredits,
totalcredits: totalcredits
}));
SetApiToken(res?.data?.result?.result);
}
try {
const body = { email: Parse?.User?.current()?.getEmail() || "" };
const testurl = "https://sandbox.opensignlabs.com/api/gettesttoken";
const testRes = await axios.post(testurl, body);
setApiTestToken(testRes.data?.token);
} catch (err) {
console.log("err in fetch test token", err);
}
setIsLoader(false);
} catch (err) {
SetApiToken();
setIsLoader(false);
console.log("Err", err);
} finally {
setIsLoader(false);
}
};
const handleSubmit = async (e) => {
e.preventDefault();
if (!isSubscribe && isEnableSubscription) {
if (isSubscribe?.plan === "freeplan" && isEnableSubscription) {
setIsTour(true);
} else {
setIsLoader(true);
setIsModal(false);
setIsModal((obj) => ({ ...obj, generateapi: false }));
try {
const url = parseBaseUrl + "functions/generateapitoken";
const headers = {
@@ -70,13 +111,13 @@ function GenerateToken() {
const res = await axios.post(url, {}, { headers: headers });
if (res) {
SetApiToken(res.data.result.token);
setIsAlert({ type: "success", msg: "Token generated successfully." });
setIsAlert({ type: "success", msg: t("token-generated") });
} else {
console.error("Error while generating Token");
setIsAlert({ type: "danger", msg: "Something went wrong." });
setIsAlert({ type: "danger", msg: t("something-went-wrong-mssg") });
}
} catch (error) {
setIsAlert({ type: "danger", msg: "Something went wrong." });
setIsAlert({ type: "danger", msg: t("something-went-wrong-mssg") });
console.log("while generating Token", error);
} finally {
setIsLoader(false);
@@ -89,21 +130,115 @@ function GenerateToken() {
const copytoclipboard = (text) => {
copytoData(text);
setIsAlert({ type: "success", msg: "Copied" });
setTimeout(() => {
setIsAlert({ type: "success", msg: "" });
}, 1500); // Reset copied state after 1.5 seconds
setIsAlert({ type: "success", msg: t("copied") });
setTimeout(() => setIsAlert({ type: "success", msg: "" }), 1500); // Reset copied state after 1.5 seconds
};
const handleModal = () => {
if (isSubscribe?.plan === "freeplan" && isEnableSubscription) {
setIsTour(true);
} else {
setIsModal((obj) => ({ ...obj, generateapi: !obj.generateapi }));
}
};
const handleModal = () => setIsModal(!isModal);
const handleBuyAPIsModal = () => {
if (isSubscribe?.plan === "freeplan" && isEnableSubscription) {
setIsTour(true);
} else {
const extUser =
localStorage.getItem("Extand_Class") &&
JSON.parse(localStorage.getItem("Extand_Class"))?.[0];
if (isSubscribe?.adminId && extUser?.objectId === isSubscribe?.adminId) {
setIsModal((obj) => ({ ...obj, buyapis: !obj.buyapis }));
} else {
setIsSubscribe((obj) => ({
...obj,
adminEmail: extUser?.TenantId?.EmailAddress
}));
setIsModal((obj) => ({ ...obj, unauthorized: !obj.unauthorized }));
}
}
};
const handleCloseModal = () => {
setIsModal({ generateapi: false, buyapis: false, unauthorized: false });
};
const handlePricePerAPIs = (e) => {
const quantity = e.target?.value;
const price =
quantity > 0
? (Math.round(quantity * amount.priceperapi * 100) / 100).toFixed(2)
: (Math.round(500 * amount.priceperapi * 100) / 100).toFixed(2);
setAmount((prev) => ({ ...prev, quantity: quantity, price: price }));
};
const handleAddOnApiSubmit = async (e) => {
e.preventDefault();
e.stopPropagation();
setIsFormLoader(true);
try {
const resAddon = await Parse.Cloud.run("buycredits", {
credits: amount.quantity
});
if (resAddon) {
const _resAddon = JSON.parse(JSON.stringify(resAddon));
if (_resAddon.status === "success") {
setAmount((obj) => ({
...obj,
quantity: 500,
priceperapi: 0.15,
price: (75.0).toFixed(2),
totalcredits: obj?.totalcredits + _resAddon.addon,
addoncredits: obj?.addoncredits + _resAddon.addon
}));
}
}
setIsModal((obj) => ({ ...obj, buyapis: false }));
} catch (err) {
console.log("Err in buy addon", err);
setIsAlert({ type: "danger", msg: t("something-went-wrong-mssg") });
} finally {
setTimeout(() => setIsAlert({ type: "success", msg: "" }), 2000);
setIsFormLoader(false);
}
};
const handleGenerateTestToken = async (e) => {
e.preventDefault();
setIsLoader(true);
// setIsModal((obj) => ({ ...obj, generateapi: false }));
try {
const url = "https://sandbox.opensignlabs.com/api/generatetesttoken";
const headers = {
"Content-Type": "application/json",
token: apitestToken || "1"
};
const extUser = JSON.parse(localStorage.getItem("Extand_Class"))?.[0];
const body = {
name: extUser?.Name,
email: extUser?.Email,
phone: extUser?.Phone,
company: extUser?.Company,
jobTitle: extUser?.JobTitle
};
const res = await axios.post(url, body, { headers: headers });
if (res) {
setApiTestToken(res.data?.token);
setIsAlert({ type: "success", msg: t("token-generated") });
} else {
console.error("Error while generating Token");
setIsAlert({ type: "danger", msg: t("something-went-wrong-mssg") });
}
} catch (error) {
setIsAlert({ type: "danger", msg: t("something-went-wrong-mssg") });
console.log("while generating Token", error);
} finally {
setIsLoader(false);
setTimeout(() => setIsAlert({ type: "success", msg: "" }), 1500);
}
};
return (
<React.Fragment>
<Title title={"API Token"} />
{isAlert.msg && (
<Alert type={isAlert.type}>
<div className="ml-3">{isAlert.msg}</div>
</Alert>
)}
{isAlert.msg && <Alert type={isAlert.type}>{isAlert.msg}</Alert>}
{isLoader ? (
<div className="flex justify-center items-center h-screen">
<Loader />
@@ -112,31 +247,68 @@ function GenerateToken() {
<>
<div className="bg-base-100 text-base-content flex flex-col justify-center shadow-md rounded-box mb-3">
<h1 className={"ml-4 mt-3 mb-2 font-semibold"}>
OpenSign API{" "}
OpenSign {t("API")}{" "}
<Tooltip
url={
"https://docs.opensignlabs.com/docs/API-docs/opensign-api-v-1"
}
url="https://docs.opensignlabs.com/docs/API-docs/opensign-api-v-1"
isSubscribe={true}
/>
</h1>
<ul className="w-full flex flex-col p-2 text-sm">
<li className="flex flex-col md:flex-row justify-between items-center border-t-[1px] border-gray-300 break-all py-2">
<div className="w-full md:w-[70%] flex-col md:flex-row text-xs md:text-[15px] flex items-center gap-x-5">
<span className="ml-1">
<span className="font-medium">API Test Token : </span>
<span className="text-xs">
<Tooltip message={t("help-test-token")} />
</span>
</span>
<span id="token" className="md:text-end py-2 md:py-0">
<span
className="cursor-pointer"
onClick={() => copytoclipboard(apitestToken)}
>
{apitestToken ? apitestToken : "_____"}
</span>
<button
className="op-btn op-btn-accent op-btn-outline op-btn-sm ml-2 cursor-pointer"
onClick={() => copytoclipboard(apitestToken)}
>
<i className="fa-light fa-copy"></i>
</button>
</span>
</div>
<button
onClick={handleGenerateTestToken}
className="op-btn op-btn-primary w-[210px] md:w-auto"
>
{apitestToken
? t("regenerate-test-token")
: t("generate-test-token")}
</button>
</li>
<li className="flex flex-col md:flex-row justify-between items-center border-y-[1px] border-gray-300 break-all py-2">
<div className="w-full md:w-[70%] flex-col md:flex-row text-xs md:text-[15px] flex items-center gap-x-5">
<span className="ml-1">API Token:</span>{" "}
<span className="ml-1">
<span className="font-medium">{t("api-token")} : </span>
<span className="text-xs">
<Tooltip message={t("help-api-token", { origin })} />
</span>
</span>
<span
id="token"
className={`${
isSubscribe
? ""
: "bg-white/20 pointer-events-none select-none"
isSubscribe?.plan === "freeplan"
? "bg-white/20 pointer-events-none select-none"
: ""
} md:text-end py-2 md:py-0`}
>
<span
className="cursor-pointer"
onClick={() => copytoclipboard(apiToken)}
>
{apiToken ? apiToken : "_____"}
{isSubscribe?.plan !== "freeplan" && apiToken
? apiToken
: "_____"}
</span>
<button
className="op-btn op-btn-accent op-btn-outline op-btn-sm ml-2 cursor-pointer"
@@ -148,13 +320,30 @@ function GenerateToken() {
</div>
<button
onClick={apiToken ? handleModal : handleSubmit}
className="op-btn op-btn-primary"
className="op-btn op-btn-primary w-[210px] md:w-auto"
>
{apiToken ? "Regenerate Token" : "Generate Token"}
{apiToken ? t("regenerate-token") : t("generate-token")}
</button>
</li>
<div className="text-xs md:text-[15px] my-3 w-full md:w-[70%] flex-col md:flex-row flex items-center gap-x-5">
<span className="font-medium">
{t("remaining-credits")}{" "}
<span className="text-xs">
<Tooltip
message={t("remaining-credits-help", {
allowedcredits: amount?.allowedcredits || 0,
addoncredits: amount?.addoncredits || 0
})}
/>
</span>
</span>
<span className="md:text-end py-2 md:py-0">
{amount.totalcredits}
</span>
</div>
<hr />
</ul>
<div className="flex items-center justify-center">
<div className="flex flex-col md:flex-row items-center justify-center gap-0 md:gap-1">
<button
type="button"
onClick={() =>
@@ -162,20 +351,26 @@ function GenerateToken() {
"https://docs.opensignlabs.com/docs/API-docs/opensign-api-v-1"
)
}
className="op-btn op-btn-secondary mt-2 mb-3 px-8"
className="op-btn op-btn-secondary mt-2 md:mb-3 px-8 w-[210px] md:w-auto"
>
View Docs
{t("view-docs")}
</button>
<button
type="button"
onClick={() => handleBuyAPIsModal()}
className="op-btn op-btn-accent mt-2 mb-3 px-8 w-[210px] md:w-auto"
>
{t("buy-credits")}
</button>
</div>
<ModalUi
isOpen={isModal}
title={apiToken ? "Regenerate Token" : "Generate Token"}
isOpen={isModal.generateapi}
title={apiToken ? t("regenerate-token") : t("generate-token")}
handleClose={handleModal}
>
<div className="m-[20px]">
<div className="text-lg font-normal text-base-content">
Are you sure you want to regenerate token it will expire old
token?
{t("generate-token-alert")}
</div>
<hr className="bg-[#ccc] mt-4" />
<div className="flex items-center mt-3 gap-2 text-white">
@@ -183,19 +378,79 @@ function GenerateToken() {
onClick={handleSubmit}
className="op-btn op-btn-primary ml-[2px]"
>
Yes
{t("yes")}
</button>
<button
onClick={handleModal}
className="op-btn op-btn-secondary"
>
No
{t("no")}
</button>
</div>
</div>
</ModalUi>
{/* buy APIs */}
<ModalUi
isOpen={isModal.buyapis}
title={"Buy Credits"}
handleClose={handleCloseModal}
>
{isFormLoader && (
<div className="absolute w-full h-full inset-0 flex justify-center items-center bg-base-content/30 z-50">
<Loader />
</div>
)}
<form onSubmit={handleAddOnApiSubmit} className="p-3">
<div className="mb-3 flex justify-between">
<label
htmlFor="quantity"
className="block text-xs text-gray-700 font-semibold"
>
{t("quantity-of-credits")}
<span className="text-[red] text-[13px]"> *</span>
</label>
<select
value={amount.quantity}
onChange={(e) => handlePricePerAPIs(e)}
name="quantity"
className="op-select op-select-bordered op-select-sm focus:outline-none hover:border-base-content w-1/4 text-xs"
required
>
{quantityList.length > 0 &&
quantityList.map((x) => (
<option key={x} value={x}>
{x}
</option>
))}
</select>
</div>
<div className="mb-3 flex justify-between">
<label className="block text-xs text-gray-700 font-semibold">
{t("Price")} (1 * {amount.priceperapi})
</label>
<div className="w-1/4 flex justify-center items-center text-sm">
USD {amount.price}
</div>
</div>
<hr className="text-base-content mb-3" />
<button className="op-btn op-btn-primary w-full mt-2">
{t("Proceed")}
</button>
</form>
</ModalUi>
<ModalUi
isOpen={isModal.unauthorized}
title={"Unauthorized"}
handleClose={handleCloseModal}
>
<div className="m-8 flex justify-center text-center items-center font-medium break-all">
{t("unauthorized-modal", {
adminEmail: isSubscribe?.adminEmail
})}
</div>
</ModalUi>
</div>
{!isSubscribe && isEnableSubscription && (
{isEnableSubscription && isSubscribe?.plan === "freeplan" && (
<div data-tut="apisubscribe">
<SubscribeCard />
</div>
+187 -147
View File
@@ -2,13 +2,20 @@ import React, { useState, useEffect } from "react";
import { useNavigate, useParams } from "react-router-dom";
import axios from "axios";
import { isEnableSubscription } from "../constant/const";
import { contractUsers, getAppLogo } from "../constant/Utils";
import {
contractUsers,
getAppLogo,
saveLanguageInLocal
} from "../constant/Utils";
import logo from "../assets/images/logo.png";
import { appInfo } from "../constant/appinfo";
import Parse from "parse";
import Loader from "../primitives/Loader";
import { useTranslation } from "react-i18next";
import SelectLanguage from "../components/pdf/SelectLanguage";
function GuestLogin() {
const { t, i18n } = useTranslation();
const { id, userMail, contactBookId, base64url } = useParams();
const navigate = useNavigate();
const [email, setEmail] = useState(userMail);
@@ -21,6 +28,28 @@ function GuestLogin() {
const [contactId, setContactId] = useState(contactBookId);
const [sendmail, setSendmail] = useState();
const [contact, setContact] = useState({ name: "", phone: "", email: "" });
const navigateToDoc = async (docId, contactId) => {
try {
const docDetails = await Parse.Cloud.run("getDocument", {
docId: docId
});
if (!docDetails.error) {
if (sendmail === "false") {
navigate(
`/load/recipientSignPdf/${docId}/${contactId}?sendmail=${sendmail}`
);
} else {
navigate(`/load/recipientSignPdf/${docId}/${contactId}`);
}
return true;
} else {
return false;
}
} catch (err) {
console.log("err while getting doc", err);
return false;
}
};
useEffect(() => {
handleServerUrl();
// eslint-disable-next-line react-hooks/exhaustive-deps
@@ -40,6 +69,7 @@ function GuestLogin() {
}
localStorage.clear();
saveLanguageInLocal(i18n);
const parseId = appInfo.appId;
const newServer = `${appInfo.baseUrl}/`;
localStorage.setItem("baseUrl", newServer);
@@ -62,13 +92,14 @@ function GuestLogin() {
"linkcontacttodoc",
params
);
// console.log("linkContactRes ", linkContactRes);
setContactId(linkContactRes?.contactId);
await navigateToDoc(checkSplit[0], linkContactRes?.contactId);
} catch (err) {
console.log("Err in link ext contact", err);
}
} else {
setContactId(checkSplit[2]);
await navigateToDoc(checkSplit[0], checkSplit[2]);
}
}
@@ -87,7 +118,7 @@ function GuestLogin() {
setEnterOtp(true);
}
} catch (error) {
alert("something went wrong!");
alert(t("something-went-wrong-mssg"));
}
};
@@ -106,32 +137,29 @@ function GuestLogin() {
if (OTP) {
setLoading(true);
try {
let url = `${serverUrl}functions/AuthLoginAsMail/`;
let url = `${serverUrl}functions/AuthLoginAsMail`;
const headers = {
"Content-Type": "application/json",
"X-Parse-Application-Id": parseId
};
let body = {
email: email,
otp: OTP
};
let body = { email: email, otp: OTP };
let user = await axios.post(url, body, { headers: headers });
if (user.data.result === "Invalid Otp") {
alert("Invalid Otp");
alert(t("invalid-otp"));
setLoading(false);
} else if (user.data.result === "user not found!") {
alert("User not found!");
alert(t("user-not-found"));
setLoading(false);
} else {
let _user = user.data.result;
await Parse.User.become(_user.sessionToken);
const parseId = localStorage.getItem("parseAppId");
const contractUserDetails = await contractUsers(_user.email);
const contractUserDetails = await contractUsers();
localStorage.setItem("UserInformation", JSON.stringify(_user));
localStorage.setItem(
`Parse/${parseId}/currentUser`,
JSON.stringify(_user)
);
// console.log("contractUserDetails ", contractUserDetails);
if (contractUserDetails && contractUserDetails.length > 0) {
localStorage.setItem(
"Extand_Class",
@@ -156,7 +184,7 @@ function GuestLogin() {
console.log("err ", error);
}
} else {
alert("Please Enter OTP!");
alert(t("enter-otp-alert"));
}
};
const handleUserData = async (e) => {
@@ -165,13 +193,18 @@ function GuestLogin() {
try {
setLoading(true);
const linkContactRes = await Parse.Cloud.run("linkcontacttodoc", params);
// console.log("linkContactRes ", linkContactRes);
setContactId(linkContactRes.contactId);
setEnterOtp(true);
await SendOtp();
const IsEnableOTP = await navigateToDoc(
documentId,
linkContactRes.contactId
);
if (!IsEnableOTP) {
setEnterOtp(true);
await SendOtp();
}
} catch (err) {
setLoading(false);
alert("something went wron, please try agian later.");
alert(t("something-went-wrong-mssg"));
console.log("Err in link ext contact", err);
}
};
@@ -179,153 +212,160 @@ function GuestLogin() {
setContact((prev) => ({ ...prev, [e.target.name]: e.target.value }));
};
return (
<div className="p-[2rem]">
{isLoading ? (
<div className="flex flex-col justify-center items-center h-[100vh]">
<Loader />
<span className="text-[13px] text-[gray]">{isLoading.message}</span>
</div>
) : (
<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" alt="logo" />
)}
<div className="p-14">
<div>
{isLoading ? (
<div className="flex flex-col justify-center items-center h-[100vh]">
<Loader />
<span className="text-[13px] text-[gray]">{isLoading.message}</span>
</div>
{contactId ? (
<>
{!EnterOTP ? (
<div className="w-full md:w-[50%] text-base-content">
<h1 className="text-2xl md:text-[30px]">Welcome Back!</h1>
<legend className="text-[12px] text-[#878787] mt-2 mb-1">
Verification code is sent to your email
</legend>
<div className="p-[20px] outline outline-1 outline-slate-300/50 my-2 op-card shadow-md">
) : (
<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" alt="logo" />
)}
</div>
{contactId ? (
<>
{!EnterOTP ? (
<div className="w-full md:w-[50%] text-base-content">
<h1 className="text-2xl md:text-[30px]">{t("welcome")}</h1>
<legend className="text-[12px] text-[#878787] mt-2 mb-1">
{t("get-otp-alert")}
</legend>
<div className="p-[20px] outline outline-1 outline-slate-300/50 my-2 op-card shadow-md">
<input
type="email"
name="email"
value={email}
className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full disabled:text-[#5c5c5c] text-xs"
disabled
/>
</div>
<div className="mt-3">
<button
className="op-btn op-btn-primary"
onClick={(e) => handleSendOTPBtn(e)}
disabled={loading}
>
{loading ? t("loading") : t("get-verification-code")}
</button>
</div>
</div>
) : (
<form
className="w-full md:w-[50%] text-base-content"
onSubmit={VerifyOTP}
>
<h1 className="text-2xl md:text-[30px]">{t("welcome")}</h1>
<legend className="text-[12px] text-[#878787] mt-2">
{t("guest-email-alert")}
</legend>
<div className="p-[20px] pt-[15px] outline outline-1 outline-slate-300/50 op-card my-2 shadow-md">
<p className="text-sm">{t("enter-verification-code")}</p>
<input
type="number"
className="mt-2 op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs"
name="OTP"
value={OTP}
onChange={(e) => setOTP(e.target.value)}
/>
</div>
<div className="mt-2.5">
<button
className="op-btn op-btn-primary"
type="submit"
disabled={loading}
>
{loading ? t("loading") : t("verify")}
</button>
</div>
</form>
)}
</>
) : (
<div className="w-full md:w-[50%] text-base-content">
<h1 className="text-2xl md:text-[30px]">{t("welcome")}</h1>
<legend className="text-[12px] text-[#878787] mt-2">
{t("provide-your-details")}
</legend>
<form
className="p-[20px] pt-[15px] outline outline-1 outline-slate-300/50 my-2 op-card shadow-md"
onSubmit={handleUserData}
>
<div className="mb-2">
<label
htmlFor="name"
className="block text-xs text-gray-700 font-semibold"
>
{t("name")}
<span className="text-[red] text-[13px]"> *</span>
</label>
<input
type="text"
name="name"
value={contact.name}
onChange={handleInputChange}
className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs"
disabled={loading}
onInvalid={(e) =>
e.target.setCustomValidity(t("input-required"))
}
onInput={(e) => e.target.setCustomValidity("")}
required
/>
</div>
<div className="mb-2">
<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="mobile"
value={email}
className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full disabled:text-[#5c5c5c] text-xs"
name="email"
value={contact.email}
onChange={handleInputChange}
className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs"
required
disabled
/>
</div>
<div className="mt-3">
<button
className="op-btn op-btn-primary"
onClick={(e) => handleSendOTPBtn(e)}
disabled={loading}
<div className="mt-2.5">
<label
htmlFor="phone"
className="block text-xs text-gray-700 font-semibold"
>
{loading ? "Loading..." : "Get verification code"}
</button>
</div>
</div>
) : (
<form
className="w-full md:w-[50%] text-base-content"
onSubmit={VerifyOTP}
>
<h1 className="text-2xl md:text-[30px]">Welcome Back!</h1>
<legend className="text-[12px] text-[#878787] mt-2">
You will get a verification code via Email
</legend>
<div className="p-[20px] pt-[15px] outline outline-1 outline-slate-300/50 op-card my-2 shadow-md">
<p className="text-sm">Enter Verification Code</p>
{t("phone")}
</label>
<input
type="number"
className="mt-2 op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs"
name="OTP"
value={OTP}
onChange={(e) => setOTP(e.target.value)}
type="text"
name="phone"
value={contact.phone}
onChange={handleInputChange}
className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs"
disabled={loading}
/>
</div>
<div className="mt-2.5">
<div className="mt-2 flex justify-start">
<button
className="op-btn op-btn-primary"
type="submit"
className="op-btn op-btn-primary"
disabled={loading}
>
{loading ? "Loading..." : "Verify"}
{loading ? t("loading") : t("next")}
</button>
</div>
</form>
)}
</>
) : (
<div className="w-full md:w-[50%] text-base-content">
<h1 className="text-2xl md:text-[30px]">Welcome</h1>
<legend className="text-[12px] text-[#878787] mt-2">
Provide your details
</legend>
<form
className="p-[20px] pt-[15px] outline outline-1 outline-slate-300/50 my-2 op-card shadow-md"
onSubmit={handleUserData}
>
<div className="mb-2">
<label
htmlFor="name"
className="block text-xs text-gray-700 font-semibold"
>
Name
<span className="text-[red] text-[13px]"> *</span>
</label>
<input
type="text"
name="name"
value={contact.name}
onChange={handleInputChange}
className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs"
disabled={loading}
required
/>
</div>
<div className="mb-2">
<label
htmlFor="email"
className="block text-xs text-gray-700 font-semibold"
>
Email
<span className="text-[red] text-[13px]"> *</span>
</label>
<input
type="email"
name="email"
value={contact.email}
onChange={handleInputChange}
className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs"
required
disabled
/>
</div>
<div className="mt-2.5">
<label
htmlFor="phone"
className="block text-xs text-gray-700 font-semibold"
>
Phone
</label>
<input
type="text"
name="phone"
value={contact.phone}
onChange={handleInputChange}
className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs"
disabled={loading}
/>
</div>
<div className="mt-2 flex justify-start">
<button
type="submit"
className="op-btn op-btn-primary"
disabled={loading}
>
{loading ? "Loading..." : "Next"}
</button>
</div>
</form>
</div>
)}
</div>
)}
</div>
)}
</div>
)}
</div>
<SelectLanguage />
</div>
);
}
+242 -189
View File
@@ -9,14 +9,23 @@ import { NavLink, useNavigate, useLocation } from "react-router-dom";
import login_img from "../assets/images/login_img.svg";
import { useWindowSize } from "../hook/useWindowSize";
import ModalUi from "../primitives/ModalUi";
import { isEnableSubscription } from "../constant/const";
import { emailRegex, isEnableSubscription } from "../constant/const";
import Alert from "../primitives/Alert";
import { appInfo } from "../constant/appinfo";
import { fetchAppInfo } from "../redux/reducers/infoReducer";
import { showTenant } from "../redux/reducers/ShowTenant";
import { fetchSubscription, getAppLogo, openInNewTab } from "../constant/Utils";
import {
fetchSubscription,
getAppLogo,
openInNewTab,
saveLanguageInLocal
} from "../constant/Utils";
import Loader from "../primitives/Loader";
import { useTranslation } from "react-i18next";
import SelectLanguage from "../components/pdf/SelectLanguage";
function Login() {
const { t, i18n } = useTranslation();
const navigate = useNavigate();
const location = useLocation();
const dispatch = useDispatch();
@@ -42,20 +51,18 @@ function Login() {
const [isModal, setIsModal] = useState(false);
const [image, setImage] = useState();
const [isLoginSSO, setIsLoginSSO] = useState(false);
const [errMsg, setErrMsg] = useState();
useEffect(() => {
if (localStorage.getItem("accesstoken")) {
setState({ ...state, loading: true });
GetLoginData();
}
dispatch(fetchAppInfo());
saveLogo();
checkUserExt();
// eslint-disable-next-line
}, []);
const saveLogo = async () => {
const checkUserExt = async () => {
const app = await getAppLogo();
if (!isEnableSubscription && app?.user === "not_exist") {
if (app?.error === "invalid_json") {
setErrMsg(t("server-down"));
} else if (!isEnableSubscription && app?.user === "not_exist") {
navigate("/addadmin");
}
if (app?.logo) {
@@ -63,172 +70,193 @@ function Login() {
} else {
setImage(appInfo?.applogo || undefined);
}
if (localStorage.getItem("accesstoken")) {
setState({ ...state, loading: true });
GetLoginData();
}
dispatch(fetchAppInfo());
};
const handleChange = (event) => {
const { name, value } = event.target;
let { name, value } = event.target;
if (name === "email") {
value = value?.toLowerCase()?.replace(/\s/g, "");
}
setState({ ...state, [name]: value });
};
const handlePaidRoute = () => {
navigate("/subscription");
};
const handleSubmit = async (event) => {
localStorage.removeItem("accesstoken");
event.preventDefault();
const { email, password } = state;
if (email && password) {
try {
setState({ ...state, loading: true });
localStorage.setItem("appLogo", appInfo.applogo);
// Pass the username and password to logIn function
const user = await Parse.User.logIn(email, password);
if (user) {
let _user = user.toJSON();
localStorage.setItem("UserInformation", JSON.stringify(_user));
localStorage.setItem("userEmail", email);
localStorage.setItem("accesstoken", _user.sessionToken);
localStorage.setItem("scriptId", true);
if (_user.ProfilePic) {
localStorage.setItem("profileImg", _user.ProfilePic);
} else {
localStorage.setItem("profileImg", "");
}
// Check extended class user role and tenentId
try {
const userSettings = appInfo.settings;
const currentUser = Parse.User.current();
await Parse.Cloud.run("getUserDetails", {
email: currentUser.get("email")
})
.then(async (extUser) => {
if (extUser) {
const IsDisabled = extUser?.get("IsDisabled") || false;
if (!IsDisabled) {
const userRole = extUser?.get("UserRole");
const menu =
userRole &&
userSettings.find((menu) => menu.role === userRole);
if (menu) {
const _currentRole = userRole;
const redirectUrl =
location?.state?.from ||
`/${menu.pageType}/${menu.pageId}`;
let _role = _currentRole.replace("contracts_", "");
localStorage.setItem("_user_role", _role);
const results = [extUser];
const extUser_str = JSON.stringify(results);
localStorage.setItem("Extand_Class", extUser_str);
const extInfo = JSON.parse(JSON.stringify(extUser));
localStorage.setItem("userEmail", extInfo.Email);
localStorage.setItem("username", extInfo.Name);
if (extInfo?.TenantId) {
const tenant = {
Id: extInfo?.TenantId?.objectId || "",
Name: extInfo?.TenantId?.TenantName || ""
};
localStorage.setItem("TenantId", tenant?.Id);
dispatch(showTenant(tenant?.Name));
localStorage.setItem("TenantName", tenant?.Name);
}
localStorage.setItem("PageLanding", menu.pageId);
localStorage.setItem("defaultmenuid", menu.menuId);
localStorage.setItem("pageType", menu.pageType);
if (isEnableSubscription) {
const LocalUserDetails = {
name: results[0].get("Name"),
email: results[0].get("Email"),
phone: results[0]?.get("Phone") || "",
company: results[0].get("Company")
};
localStorage.setItem(
"userDetails",
JSON.stringify(LocalUserDetails)
);
const res = await fetchSubscription();
const freeplan = res.plan;
const billingDate = res.billingDate;
if (freeplan === "freeplan") {
setState({ ...state, loading: false });
navigate(redirectUrl);
} else if (billingDate) {
if (new Date(billingDate) > new Date()) {
localStorage.removeItem("userDetails");
// Redirect to the appropriate URL after successful login setState({ ...state, loading: false });
if (!emailRegex.test(state.email)) {
alert("Please enter a valid email address.");
} else {
const { email, password } = state;
if (email && password) {
try {
setState({ ...state, loading: true });
localStorage.setItem("appLogo", appInfo.applogo);
// Pass the username and password to logIn function
const user = await Parse.User.logIn(email, password);
if (user) {
let _user = user.toJSON();
localStorage.setItem("UserInformation", JSON.stringify(_user));
localStorage.setItem("userEmail", email);
localStorage.setItem("accesstoken", _user.sessionToken);
localStorage.setItem("scriptId", true);
if (_user.ProfilePic) {
localStorage.setItem("profileImg", _user.ProfilePic);
} else {
localStorage.setItem("profileImg", "");
}
// Check extended class user role and tenentId
try {
const userSettings = appInfo.settings;
await Parse.Cloud.run("getUserDetails")
.then(async (extUser) => {
if (extUser) {
// console.log("extUser", extUser, extUser?.get("IsDisabled"));
const IsDisabled = extUser?.get("IsDisabled") || false;
if (!IsDisabled) {
const userRole = extUser?.get("UserRole");
const menu =
userRole &&
userSettings.find((menu) => menu.role === userRole);
if (menu) {
const _currentRole = userRole;
const redirectUrl =
location?.state?.from ||
`/${menu.pageType}/${menu.pageId}`;
let _role = _currentRole.replace("contracts_", "");
localStorage.setItem("_user_role", _role);
const checkLanguage = extUser?.get("Language");
if (checkLanguage) {
checkLanguage && i18n.changeLanguage(checkLanguage);
}
const results = [extUser];
const extUser_str = JSON.stringify(results);
localStorage.setItem("Extand_Class", extUser_str);
const extInfo = JSON.parse(JSON.stringify(extUser));
localStorage.setItem("userEmail", extInfo.Email);
localStorage.setItem("username", extInfo.Name);
if (extInfo?.TenantId) {
const tenant = {
Id: extInfo?.TenantId?.objectId || "",
Name: extInfo?.TenantId?.TenantName || ""
};
localStorage.setItem("TenantId", tenant?.Id);
dispatch(showTenant(tenant?.Name));
localStorage.setItem("TenantName", tenant?.Name);
}
localStorage.setItem("PageLanding", menu.pageId);
localStorage.setItem("defaultmenuid", menu.menuId);
localStorage.setItem("pageType", menu.pageType);
if (isEnableSubscription) {
const LocalUserDetails = {
name: results[0].get("Name"),
email: results[0].get("Email"),
phone: results[0]?.get("Phone") || "",
company: results[0].get("Company")
};
localStorage.setItem(
"userDetails",
JSON.stringify(LocalUserDetails)
);
const res = await fetchSubscription();
const plan = res.plan;
const billingDate = res.billingDate;
if (plan === "freeplan") {
setState({ ...state, loading: false });
navigate(redirectUrl);
} else if (billingDate) {
if (new Date(billingDate) > new Date()) {
localStorage.removeItem("userDetails");
// Redirect to the appropriate URL after successful login setState({ ...state, loading: false });
setState({ ...state, loading: false });
navigate(redirectUrl);
} else {
setState({ ...state, loading: false });
handlePaidRoute(plan);
}
} else {
setState({ ...state, loading: false });
navigate(`/subscription`, { replace: true });
handlePaidRoute(plan);
}
} else {
setState({ ...state, loading: false });
navigate(`/subscription`, { replace: true });
// Redirect to the appropriate URL after successful login
navigate(redirectUrl);
}
} else {
setState({ ...state, loading: false });
// Redirect to the appropriate URL after successful login
navigate(redirectUrl);
setIsModal(true);
}
} else {
setState({ ...state, loading: false });
setIsModal(true);
setState({
...state,
loading: false,
alertType: "danger",
alertMsg:
"You don't have access, please contact the admin."
});
logOutUser();
}
} else {
setState({
...state,
loading: false,
alertType: "danger",
alertMsg:
"You don't have access, please contact the admin."
});
logOutUser();
if (isEnableSubscription) {
setState({ ...state, loading: false });
setIsModal(true);
} else {
setState({ ...state, loading: false });
setState({
...state,
loading: false,
alertType: "danger",
alertMsg: "User not found."
});
logOutUser();
}
}
} else {
if (isEnableSubscription) {
setState({ ...state, loading: false });
setIsModal(true);
} else {
setState({ ...state, loading: false });
setState({
...state,
loading: false,
alertType: "danger",
alertMsg: "User not found."
});
logOutUser();
}
}
})
.catch((error) => {
// const payload = { sessionToken: user.getSessionToken() };
// handleSubmitbtn(payload);
setState({
...state,
loading: false,
alertType: "danger",
alertMsg: `Something went wrong.`
})
.catch((error) => {
// const payload = { sessionToken: user.getSessionToken() };
// handleSubmitbtn(payload);
setState({
...state,
loading: false,
alertType: "danger",
alertMsg: `Something went wrong.`
});
setTimeout(() => setState({ ...state, alertMsg: "" }), 2000);
console.error("Error while fetching Follow", error);
});
setTimeout(() => setState({ ...state, alertMsg: "" }), 2000);
console.error("Error while fetching Follow", error);
} catch (error) {
setState({
...state,
loading: false,
alertType: "danger",
alertMsg: `${error.message}`
});
} catch (error) {
setState({
...state,
loading: false,
alertType: "danger",
alertMsg: `${error.message}`
});
console.log(error);
setTimeout(() => setState({ ...state, alertMsg: "" }), 2000);
console.log(error);
setTimeout(() => setState({ ...state, alertMsg: "" }), 2000);
}
}
} catch (error) {
setState({
...state,
loading: false,
alertType: "danger",
alertMsg: "Invalid username or password!"
});
console.error("Error while logging in user", error);
} finally {
setTimeout(
() => setState((prev) => ({ ...prev, alertMsg: "" })),
2000
);
}
} catch (error) {
setState({
...state,
loading: false,
alertType: "danger",
alertMsg: "Invalid username or password!"
});
console.error("Error while logging in user", error);
} finally {
setTimeout(() => setState((prev) => ({ ...prev, alertMsg: "" })), 2000);
}
}
};
@@ -245,7 +273,7 @@ function Login() {
}
} catch (err) {
console.log("err in free subscribe", err.message);
alert("Somenthing went wrong, please try again later!");
alert(t("something-went-wrong-mssg"));
}
};
const thirdpartyLoginfn = async (sessionToken) => {
@@ -279,10 +307,7 @@ function Login() {
// Check extended class user role and tenentId
try {
const userSettings = appInfo.settings;
const currentUser = Parse.User.current();
await Parse.Cloud.run("getUserDetails", {
email: currentUser.get("email")
})
await Parse.Cloud.run("getUserDetails")
.then(async (extUser) => {
if (extUser) {
const IsDisabled = extUser?.get("IsDisabled") || false;
@@ -317,9 +342,9 @@ function Login() {
localStorage.setItem("pageType", menu.pageType);
if (isEnableSubscription) {
const res = await fetchSubscription();
const freeplan = res.plan;
const plan = res.plan;
const billingDate = res.billingDate;
if (freeplan === "freeplan") {
if (plan === "freeplan") {
navigate(redirectUrl);
} else if (billingDate) {
if (new Date(billingDate) > new Date()) {
@@ -329,14 +354,14 @@ function Login() {
if (isFreeplan) {
navigate(redirectUrl);
} else {
navigate(`/subscription`, { replace: true });
handlePaidRoute(plan);
}
}
} else {
if (isFreeplan) {
navigate(redirectUrl);
} else {
navigate(`/subscription`, { replace: true });
handlePaidRoute(plan);
}
}
} else {
@@ -408,9 +433,7 @@ function Login() {
localStorage.setItem("profileImg", "");
}
const userSettings = appInfo.settings;
await Parse.Cloud.run("getUserDetails", {
email: _user.email
}).then(async (extUser) => {
await Parse.Cloud.run("getUserDetails").then(async (extUser) => {
if (extUser) {
const IsDisabled = extUser?.get("IsDisabled") || false;
if (!IsDisabled) {
@@ -451,8 +474,8 @@ function Login() {
localStorage.setItem("userDetails", JSON.stringify(userInfo));
const res = await fetchSubscription();
const billingDate = res.billingDate;
const freeplan = res.plan;
if (freeplan === "freeplan") {
const plan = res.plan;
if (plan === "freeplan") {
navigate(redirectUrl);
} else if (billingDate) {
if (new Date(billingDate) > new Date()) {
@@ -460,10 +483,10 @@ function Login() {
// Redirect to the appropriate URL after successful login
navigate(redirectUrl);
} else {
navigate(`/subscription`);
handlePaidRoute(plan);
}
} else {
navigate(`/subscription`);
handlePaidRoute(plan);
}
} else {
// Redirect to the appropriate URL after successful login
@@ -549,7 +572,7 @@ function Login() {
payload &&
payload.message.replace(/ /g, "_") === "Internal_server_err"
) {
alert("Internal server error !");
alert(t("server-error"));
}
} else {
setState({
@@ -562,10 +585,12 @@ function Login() {
}
};
const logOutUser = () => {
const logOutUser = async () => {
setIsModal(false);
if (Parse?.User?.current()) {
Parse.User.logOut();
try {
await Parse.User.logOut();
} catch (err) {
console.log("Err while logging out", err);
}
let appdata = localStorage.getItem("userSettings");
let applogo = localStorage.getItem("appLogo");
@@ -575,6 +600,7 @@ function Login() {
let appid = localStorage.getItem("parseAppId");
localStorage.clear();
saveLanguageInLocal(i18n);
localStorage.setItem("appLogo", applogo);
localStorage.setItem("defaultmenuid", defaultmenuid);
@@ -599,11 +625,16 @@ function Login() {
"_self"
);
} else {
alert("Please provide email.");
alert(t("provide-email"));
}
}
};
return (
return errMsg ? (
<div className="h-screen flex justify-center text-center items-center p-4 text-gray-500 text-base">
{errMsg}
</div>
) : (
<div>
<Title title={"Login Page"} />
{state.loading && (
@@ -634,14 +665,14 @@ function Login() {
<div className="grid grid-cols-1 md:grid-cols-2 gap-x-2">
<div>
<form onSubmit={handleSubmit} aria-label="Login Form">
<h1 className="text-[30px] mt-6">Welcome Back!</h1>
<h1 className="text-[30px] mt-6">{t("welcome")}</h1>
<fieldset>
<legend className="text-[12px] text-[#878787]">
Login to your account
{t("Login-to-your-account")}
</legend>
<div className="w-full px-6 py-3 my-1 op-card bg-base-100 shadow-md outline outline-1 outline-slate-300/50">
<label className="block text-xs" htmlFor="email">
Email
{t("email")}
</label>
<input
id="email"
@@ -652,12 +683,16 @@ function Login() {
value={state.email}
onChange={handleChange}
required
onInvalid={(e) =>
e.target.setCustomValidity(t("input-required"))
}
onInput={(e) => e.target.setCustomValidity("")}
/>
<hr className="my-1 border-none" />
{!isLoginSSO && (
<>
<label className="block text-xs" htmlFor="password">
Password
{t("password")}
</label>
<div className="relative">
<input
@@ -670,6 +705,12 @@ function Login() {
value={state.password}
autoComplete="current-password"
onChange={handleChange}
onInvalid={(e) =>
e.target.setCustomValidity(
t("input-required")
)
}
onInput={(e) => e.target.setCustomValidity("")}
required
/>
<span
@@ -690,7 +731,7 @@ function Login() {
to="/forgetpassword"
className="text-[13px] op-link op-link-primary underline-offset-1 focus:outline-none ml-1"
>
Forgot Password?
{t("forgot-password")}
</NavLink>
</div>
</div>
@@ -701,7 +742,7 @@ function Login() {
className="op-btn op-btn-primary"
disabled={state.loading}
>
{state.loading ? "Loading..." : "Login"}
{state.loading ? t("loading") : t("login")}
</button>
{isEnableSubscription && (
<button
@@ -716,13 +757,13 @@ function Login() {
)
}
>
Create Account
{t("create-account")}
</button>
)}
</div>
</form>
{(appInfo.googleClietId || isEnableSubscription) && (
<div className="op-divider my-4 text-sm">OR</div>
<div className="op-divider my-4 text-sm">{t("or")}</div>
)}
<div className="flex flex-col justify-center items-center gap-y-3">
{/* {appInfo?.fbAppId && (
@@ -746,7 +787,7 @@ function Login() {
className="cursor-pointer border-[1px] border-gray-300 rounded px-[40px] py-2 font-semibold text-sm hover:border-[#d2e3fc] hover:bg-[#ecf3feb7]"
onClick={() => handleSignInWithSSO()}
>
Sign in with SSO
{t("sign-SSO")}
</div>
)}
</div>
@@ -764,13 +805,16 @@ function Login() {
)}
</div>
</div>
<SelectLanguage />
{state.alertMsg && (
<Alert type={state.alertType}>
<div className="ml-3">{state.alertMsg}</div>
</Alert>
<Alert type={state.alertType}>{state.alertMsg}</Alert>
)}
</div>
<ModalUi isOpen={isModal} title="Additional Info" showClose={false}>
<ModalUi
isOpen={isModal}
title={t("additional-info")}
showClose={false}
>
<form className="px-4 py-3 text-base-content">
<div className="mb-3">
<label
@@ -778,7 +822,8 @@ function Login() {
style={{ display: "flex" }}
className="block text-xs text-gray-700 font-semibold"
>
Company <span className="text-[red] text-[13px]">*</span>
{t("company")}{" "}
<span className="text-[red] text-[13px]">*</span>
</label>
<input
type="text"
@@ -791,6 +836,10 @@ function Login() {
Company: e.target.value
})
}
onInvalid={(e) =>
e.target.setCustomValidity(t("input-required"))
}
onInput={(e) => e.target.setCustomValidity("")}
required
/>
</div>
@@ -800,7 +849,7 @@ function Login() {
style={{ display: "flex" }}
className="block text-xs text-gray-700 font-semibold"
>
Job Title
{t("job-title")}
<span className="text-[red] text-[13px]">*</span>
</label>
<input
@@ -814,6 +863,10 @@ function Login() {
Destination: e.target.value
})
}
onInvalid={(e) =>
e.target.setCustomValidity(t("input-required"))
}
onInput={(e) => e.target.setCustomValidity("")}
required
/>
</div>
@@ -823,14 +876,14 @@ function Login() {
className="op-btn op-btn-primary"
onClick={(e) => handleSubmitbtn(e)}
>
Login
{t("login")}
</button>
<button
type="button"
className="op-btn op-btn-ghost"
onClick={logOutUser}
>
Cancel
{t("cancel")}
</button>
</div>
</form>
+126 -69
View File
@@ -2,12 +2,15 @@ import React, { useState, useRef, useEffect } from "react";
import SignatureCanvas from "react-signature-canvas";
import "../styles/managesign.css";
import "../styles/signature.css";
import { toDataUrl } from "../constant/Utils";
import { generateTitleFromFilename, toDataUrl } from "../constant/Utils";
import Parse from "parse";
import { SaveFileSize } from "../constant/saveFileSize";
import Alert from "../primitives/Alert";
import Loader from "../primitives/Loader";
import { useTranslation } from "react-i18next";
import sanitizeFileName from "../primitives/sanitizeFileName";
const ManageSign = () => {
const { t } = useTranslation();
const [penColor, setPenColor] = useState("blue");
const [initialPen, setInitialPen] = useState("blue");
const [image, setImage] = useState();
@@ -21,9 +24,11 @@ const ManageSign = () => {
const [Initials, setInitials] = useState("");
const [isInitials, setIsInitials] = useState(false);
const [id, setId] = useState("");
const [imgInitials, setImgInitials] = useState("");
const canvasRef = useRef(null);
const imageRef = useRef(null);
const initailsRef = useRef(null);
const imgInitialsRef = useRef(null);
useEffect(() => {
fetchUserSign();
// eslint-disable-next-line
@@ -44,14 +49,23 @@ const ManageSign = () => {
if (signRes) {
const res = signRes.toJSON();
setId(res.objectId);
setSignName(res?.SignatureName);
setImage(res.ImageURL);
if (res?.SignatureName) {
const sanitizename = generateTitleFromFilename(res?.SignatureName);
const replaceSpace = sanitizeFileName(sanitizename);
setSignName(replaceSpace);
}
setImage(res?.ImageURL);
if (res && res.Initials) {
setInitials(res.Initials);
// setInitials(res.Initials);
setIsInitials(true);
setImgInitials(res?.Initials);
}
} else {
setSignName(User?.get("name") || "");
if (User?.get("name")) {
const sanitizename = generateTitleFromFilename(User?.get("name"));
const replaceSpace = sanitizeFileName(sanitizename);
setSignName(replaceSpace);
}
}
setIsLoader(false);
} catch (err) {
@@ -84,8 +98,14 @@ const ManageSign = () => {
if (initailsRef.current) {
initailsRef.current.clear();
}
if (imgInitialsRef.current) {
imgInitialsRef.current.value = "";
}
setImgInitials("");
setInitials("");
setIsValue(true);
if (image) {
setIsValue(true);
}
setIsInitials(false);
};
@@ -99,40 +119,54 @@ const ManageSign = () => {
const base64Img = await toDataUrl(file);
setImage(base64Img);
setIsValue(true);
} else {
setImage("");
setIsValue(false);
}
};
const handleSubmit = async (e) => {
e.preventDefault();
const isUrl = image.includes("https");
const isUrl = image?.includes("https") || image?.includes("http");
if (!isvalue) {
setWarning(true);
setTimeout(() => setWarning(false), 1000);
} else {
setIsLoader(true);
const replaceSpace = signName.replace(/ /g, "_");
const sanitizename = generateTitleFromFilename(signName);
const replaceSpace = sanitizeFileName(sanitizename);
let file;
if (signature) {
file = base64StringtoFile(signature, `${replaceSpace}_sign.png`);
file = base64StringtoFile(signature, `${replaceSpace}_sign`);
} else {
if (!isUrl) {
file = base64StringtoFile(image, `${replaceSpace}__sign.png`);
if (image && !isUrl) {
file = base64StringtoFile(image, `${replaceSpace}__sign`);
}
}
let imgUrl;
if (!isUrl) {
if (file && !isUrl) {
imgUrl = await uploadFile(file);
} else {
imgUrl = image;
}
let initialsUrl = "";
const isInitialsUrl = Initials.includes("https");
if (!isInitialsUrl && Initials) {
const initialsImg = base64StringtoFile(
Initials,
`${replaceSpace}_initials.png`
);
initialsUrl = await uploadFile(initialsImg);
const isInitialsUrl =
imgInitials?.includes("https") || imgInitials?.includes("http");
let initialFile;
if (Initials) {
initialFile = base64StringtoFile(Initials, `${replaceSpace}_sign`);
} else {
if (imgInitials && !isInitialsUrl) {
initialFile = base64StringtoFile(
imgInitials,
`${replaceSpace}__sign`
);
}
}
let initialsUrl;
if (initialFile && !isInitialsUrl) {
initialsUrl = await uploadFile(initialFile);
} else {
initialsUrl = imgInitials;
}
if (imgUrl) {
await saveEntry({
@@ -144,15 +178,19 @@ const ManageSign = () => {
}
};
function base64StringtoFile(base64String, filename) {
var arr = base64String.split(","),
let arr = base64String.split(","),
// type of uploaded image
mime = arr[0].match(/:(.*?);/)[1],
// decode base64
bstr = atob(arr[1]),
n = bstr.length,
u8arr = new Uint8Array(n);
while (n--) {
u8arr[n] = bstr.charCodeAt(n);
}
return new File([u8arr], filename, { type: mime });
const ext = mime.split("/").pop();
const name = `${filename}.${ext}`;
return new File([u8arr], name, { type: mime });
}
const uploadFile = async (file) => {
@@ -173,31 +211,24 @@ const ManageSign = () => {
const saveEntry = async (obj) => {
const signCls = "contracts_Signature";
const User = Parse.User.current().id;
const User = Parse?.User?.current()?.id;
const userId = { __type: "Pointer", className: "_User", objectId: User };
if (id) {
try {
const updateSign = new Parse.Object(signCls);
updateSign.id = id;
updateSign.set("Initials", obj.initialsUrl ? obj.initialsUrl : "");
updateSign.set("ImageURL", obj.url);
updateSign.set("ImageURL", obj.url ? obj.url : "");
updateSign.set("SignatureName", obj.name);
updateSign.set("UserId", userId);
const res = await updateSign.save();
setIsLoader(false);
setIsAlert({
type: "success",
message: "Signature saved successfully."
});
setTimeout(() => setIsAlert({}), 2000);
setIsAlert({ type: "success", message: t("signature-saved-alert") });
return res;
} catch (err) {
console.log(err);
setIsAlert({ type: "danger", message: `${err.message}` });
} finally {
setIsLoader(false);
setIsAlert({
type: "danger",
message: `${err.message}`
});
setTimeout(() => setIsAlert({}), 2000);
}
} else {
@@ -208,20 +239,13 @@ const ManageSign = () => {
updateSign.set("SignatureName", obj.name);
updateSign.set("UserId", userId);
const res = await updateSign.save();
setIsLoader(false);
setIsAlert({
type: "success",
message: "Signature saved successfully."
});
setTimeout(() => setIsAlert({}), 2000);
setIsAlert({ type: "success", message: t("signature-saved-alert") });
return res;
} catch (err) {
console.log(err);
setIsAlert({ type: "success", message: `${err.message}` });
} finally {
setIsLoader(false);
setIsAlert({
type: "success",
message: `${err.message}`
});
setTimeout(() => setIsAlert({}), 2000);
}
}
@@ -232,7 +256,29 @@ const ManageSign = () => {
};
const handleInitialsChange = () => {
setInitials(initailsRef.current.toDataURL());
setIsValue(true);
if (image || signature) {
setIsValue(true);
}
};
const handleUploadInitials = () => {
imgInitialsRef.current.click();
};
const onImgInitialsChange = async (event) => {
if (initailsRef.current) {
initailsRef.current.clear();
}
setInitials("");
if (event.target.files && event.target.files[0]) {
const file = event.target.files[0];
const base64Img = await toDataUrl(file);
setImgInitials(base64Img);
if (image || signature) {
setIsValue(true);
}
} else {
setImgInitials("");
setIsValue(false);
}
};
return (
<div className="relative h-full bg-base-100 text-base-content flex shadow-md rounded-box overflow-auto">
@@ -245,12 +291,12 @@ const ManageSign = () => {
<div className="relative w-full">
<div className="ml-[5px] my-[20px] md:m-[20px]">
<div className="text-[20px] font-semibold m-[10px] md:m-0 mb-2">
My Signature
{t("my-signature")}
</div>
<div className="flex flex-col md:flex-row gap-0 md:gap-[12px]">
<div className="relative">
<span className="font-medium select-none flex mb-[10px] pl-[10px]">
Signature
{t("signature")}
</span>
<input
type="file"
@@ -279,7 +325,7 @@ const ManageSign = () => {
height: "180px",
className: "signatureCanvas rounded-box"
}}
backgroundColor="rgb(255, 255, 255)"
// backgroundColor="rgb(255, 255, 255)"
onEnd={() =>
handleSignatureChange(canvasRef.current.toDataURL())
}
@@ -330,14 +376,14 @@ const ManageSign = () => {
className="op-link"
onClick={() => handleUploadBtn()}
>
Upload image
{t("upload")}
</div>
<div
type="button"
className="op-link"
onClick={() => handleClear()}
>
Clear
{t("clear")}
</div>
</div>
</div>
@@ -345,26 +391,30 @@ const ManageSign = () => {
{warning && (
<span className="customwarning signWarning text-[12px] w-[220px] md:w-[300px]">
<i className="fa-light fa-exclamation-circle text-[#fab005] text-[15px] mr-[4px]"></i>
Please upload signature/Image
{t("upload-signature/Image")}
</span>
)}
</div>
</div>
<div className="relative">
<span className="font-medium select-none flex mb-[10px] pl-[10px]">
Initials
{t("initials")}
</span>
<input
type="file"
onChange={onImgInitialsChange}
className="filetype"
accept="image/*"
ref={imgInitialsRef}
hidden
/>
<div>
{isInitials ? (
{imgInitials ? (
<div className="intialSignature relative border-[1px] border-[#888] rounded-box overflow-hidden">
<img
alt="inititals"
src={Initials}
style={{
width: "100%",
height: "100%",
objectFit: "contain"
}}
src={imgInitials}
className="w-[100%] h-[100%] object-contain"
/>
</div>
) : (
@@ -374,10 +424,8 @@ const ManageSign = () => {
canvasProps={{
className: "intialSignature rounded-box"
}}
backgroundColor="rgb(255, 255, 255)"
onEnd={() =>
handleInitialsChange(initailsRef.current.toDataURL())
}
// backgroundColor="rgb(255, 255, 255)"
onEnd={() => handleInitialsChange()}
dotSize={1}
/>
)}
@@ -400,6 +448,7 @@ const ManageSign = () => {
? "2px solid black"
: "2px solid white"
}}
className="fa-light fa-pen-nib"
onClick={() => {
if (key === 0) {
setInitialPen("blue");
@@ -410,7 +459,6 @@ const ManageSign = () => {
}
}}
key={key}
className="fa-light fa-pen-nib"
width={20}
height={20}
></i>
@@ -419,13 +467,22 @@ const ManageSign = () => {
</div>
)}
</div>
<div>
<div className="flex flex-row gap-1">
<div
type="button"
className="op-link text-sm md:text-base mr-1"
onClick={() => handleClearInitials()}
onClick={() => handleUploadInitials()}
>
Clear
{t("upload")}
</div>
<div>
<div
type="button"
className="op-link text-sm md:text-base mr-1"
onClick={() => handleClearInitials()}
>
{t("clear")}
</div>
</div>
</div>
</div>
@@ -437,7 +494,7 @@ const ManageSign = () => {
className="op-btn op-btn-primary"
onClick={(e) => handleSubmit(e)}
>
save
{t("save")}
</button>
</div>
</div>
+43 -45
View File
@@ -10,6 +10,7 @@ import TourContentWithBtn from "../primitives/TourContentWithBtn";
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")
@@ -22,6 +23,7 @@ const AppLoader = () => {
);
};
function Opensigndrive() {
const { t } = useTranslation();
const navigate = useNavigate();
const scrollRef = useRef(null);
const [isList, setIsList] = useState(false);
@@ -37,7 +39,7 @@ function Opensigndrive() {
const [tourStatusArr, setTourStatusArr] = useState([]);
const [isLoading, setIsLoading] = useState({
isLoad: true,
message: "This might take some time"
message: t("loading-mssg")
});
const [docId, setDocId] = useState();
const [handleError, setHandleError] = useState("");
@@ -78,7 +80,7 @@ function Opensigndrive() {
selector: '[data-tut="reactourFirst"]',
content: () => (
<TourContentWithBtn
message={`Click on the breadcrumb links to easily navigate through the folder hierarchy and view the documents within each folder.`}
message={t("tour-mssg.opensign-drive-1")}
isChecked={handleDontShow}
/>
),
@@ -89,7 +91,7 @@ function Opensigndrive() {
selector: '[data-tut="reactourSecond"]',
content: () => (
<TourContentWithBtn
message={`Click the add button to create a new folder or document.`}
message={t("tour-mssg.opensign-drive-2")}
isChecked={handleDontShow}
/>
),
@@ -100,7 +102,7 @@ function Opensigndrive() {
selector: '[data-tut="reactourThird"]',
content: () => (
<TourContentWithBtn
message={`Sort your documents by Date or Name using this menu.`}
message={t("tour-mssg.opensign-drive-3")}
isChecked={handleDontShow}
/>
),
@@ -111,7 +113,7 @@ function Opensigndrive() {
selector: '[data-tut="reactourForth"]',
content: () => (
<TourContentWithBtn
message={`Click on this menu to display the documents in list view.`}
message={t("tour-mssg.opensign-drive-4")}
isChecked={handleDontShow}
/>
),
@@ -126,7 +128,7 @@ function Opensigndrive() {
checkTourStatus();
}
if (!disbaleLoading) {
setIsLoading({ isLoad: true, message: "This might take some time" });
setIsLoading({ isLoad: true, message: t("loading-mssg") });
}
try {
const driveDetails = await getDrive(docId, skip, limit);
@@ -138,7 +140,7 @@ function Opensigndrive() {
selector: '[data-tut="reactourFifth"]',
content: () => (
<TourContentWithBtn
message={`The document list is displayed according to the selected sorting option. Icons next to each document indicate its current status.`}
message={t("tour-mssg.opensign-drive-5")}
isChecked={handleDontShow}
/>
),
@@ -149,7 +151,7 @@ function Opensigndrive() {
selector: '[data-tut="reactourSixth"]',
content: () => (
<TourContentWithBtn
message={`Right-click on a document to see options such as Download, Rename, Move, and Delete. Click on the document to open it.`}
message={t("tour-mssg.opensign-drive-6")}
isChecked={handleDontShow}
/>
),
@@ -160,7 +162,7 @@ function Opensigndrive() {
selector: '[data-tut="reactourSeventh"]',
content: () => (
<TourContentWithBtn
message={`Right-click on any folder to see options. Choose Rename to change the folders name or click on the folder to navigate through its contents.`}
message={t("tour-mssg.opensign-drive-7")}
isChecked={handleDontShow}
/>
),
@@ -190,12 +192,12 @@ function Opensigndrive() {
setTourData(tourConfigs);
}
if (!docId) {
setFolderName([{ name: "OpenSign™ Drive", objectId: "" }]);
setFolderName([{ name: t("OpenSign-drive"), objectId: "" }]);
}
} catch (e) {
setIsAlert({
isShow: true,
alertMessage: "something went wrong"
alertMessage: t("something-went-wrong-mssg")
});
} finally {
setLoading(false);
@@ -319,11 +321,11 @@ function Opensigndrive() {
} catch (e) {
setIsAlert({
isShow: true,
alertMessage: "something went wrong!"
alertMessage: t("something-went-wrong-mssg")
});
}
} else {
setError("Please fill out this field");
setError(t("fill-field"));
}
};
@@ -496,26 +498,14 @@ function Opensigndrive() {
};
//function to use check tour status of open sign drive
async function checkTourStatus() {
const currentUser = Parse.User.current();
const cloudRes = await Parse.Cloud.run("getUserDetails", {
email: currentUser.get("email")
});
const res = { data: cloudRes.toJSON() };
if (res.data && res.data.TourStatus && res.data.TourStatus.length > 0) {
const tourStatus = res.data.TourStatus;
const cloudRes = await Parse.Cloud.run("getUserDetails");
if (cloudRes) {
const extUser = JSON.parse(JSON.stringify(cloudRes));
localStorage.setItem("Extand_Class", JSON.stringify([extUser]));
const tourStatus = extUser?.TourStatus || [];
setTourStatusArr(tourStatus);
const filteredtourStatus = tourStatus.filter((obj) => obj["driveTour"]);
if (filteredtourStatus.length > 0) {
const driveTour = filteredtourStatus[0]["driveTour"];
// console.log("loginTour", loginTour);
if (driveTour) {
setIsTour(false);
} else {
setIsTour(true);
}
} else {
setIsTour(true);
}
const driveTour = tourStatus.find((obj) => obj.driveTour)?.driveTour;
setIsTour(!driveTour);
} else {
setIsTour(true);
}
@@ -525,7 +515,7 @@ function Opensigndrive() {
<Title title={"OpenSign™ Drive"} drive={true} />
<ModalUi
isOpen={isAlert.isShow}
title={"Alert"}
title={t("alert")}
handleClose={() => {
setIsAlert({
isShow: false,
@@ -546,13 +536,13 @@ function Opensigndrive() {
type="button"
className="op-btn op-btn-neutral op-btn-sm"
>
Close
{t("close")}
</button>
</div>
</ModalUi>
<ModalUi
isOpen={isFolder}
title={"Add New Folder"}
title={t("add-new-folder")}
handleClose={oncloseFolder}
>
<div className="h-full p-[20px] pt-[10px] pb-[15px]">
@@ -566,10 +556,14 @@ function Opensigndrive() {
className="flex flex-col text-base-content"
>
<label className="py-[8px] text-[15px] font-[400] mb-0">
Name
{t("name")}
<span className="text-[red]">*</span>
</label>
<input
onInvalid={(e) =>
e.target.setCustomValidity(t("input-required"))
}
onInput={(e) => e.target.setCustomValidity("")}
required
className="op-input op-input-bordered op-input-sm"
type="text"
@@ -580,14 +574,14 @@ function Opensigndrive() {
<div className="w-full h-[1px] bg-[#9f9f9f] my-[15px]"></div>
<div className="flex flex-row">
<button type="submit" className="op-btn op-btn-primary">
Add
{t("add")}
</button>
<button
type="button"
className="op-btn op-btn-ghost ml-1"
onClick={oncloseFolder}
>
Close
{t("close")}
</button>
</div>
</form>
@@ -655,21 +649,21 @@ function Opensigndrive() {
className="fa-light fa-plus mr-[5px]"
aria-hidden="true"
></i>
Create folder
{t("create-folder")}
</span>
<span
className="dropdown-item text-[10px] md:text-[13px]"
onClick={() => navigate("/form/sHAnZphf69")}
>
<i className="fa-light fa-pen-nib mr-[5px]"></i>
Sign Yourself
{t("form-name.Sign Yourself")}
</span>
<span
className="dropdown-item text-[10px] md:text-[13px]"
onClick={() => navigate("/form/8mZzFxbG1z")}
>
<i className="fa-light fa-file-signature mr-[5px]"></i>
Request Signatures
{t("form-name.Request Signatures")}
</span>
</div>
</div>
@@ -719,7 +713,9 @@ function Opensigndrive() {
aria-hidden="true"
></i>
)}
<span className="ml-[5px]">{value}</span>
<span className="ml-[5px]">
{t(`sort-order.${value}`)}
</span>
</span>
);
})}
@@ -744,7 +740,9 @@ function Opensigndrive() {
aria-hidden="true"
></i>
)}
<span className="ml-[5px]">{order}</span>
<span className="ml-[5px]">
{t(`sort-order.${order}`)}
</span>
</span>
);
})}
@@ -781,7 +779,7 @@ function Opensigndrive() {
{pdfData && pdfData.length === 0 ? (
<div className="flex justify-center items-center w-full h-[50vh]">
<span className="text-base-content font-bold">
No Data Found!
{t("no-data")}
</span>
</div>
) : (
@@ -803,7 +801,7 @@ function Opensigndrive() {
sortingData={sortingData}
/>
{loading && (
<div className="text-center pb-[20px]">Loading...</div>
<div className="text-center pb-[20px]">{t("loading")}</div>
)}
</React.Suspense>
</div>
File diff suppressed because it is too large Load Diff
+24 -22
View File
@@ -8,8 +8,10 @@ import { appInfo } from "../constant/appinfo";
import { showTenant } from "../redux/reducers/ShowTenant";
import { fetchAppInfo } from "../redux/reducers/infoReducer";
import Loader from "../primitives/Loader";
import { useTranslation } from "react-i18next";
const PgSignUp = () => {
const { t } = useTranslation();
const navigate = useNavigate();
const location = useLocation();
const dispatch = useDispatch();
@@ -71,9 +73,7 @@ const PgSignUp = () => {
if (res) {
localStorage.removeItem("userDetails");
try {
const extUser = await Parse.Cloud.run("getUserDetails", {
email: userDetails.email
});
const extUser = await Parse.Cloud.run("getUserDetails");
const userRole = extUser?.get("UserRole");
const _currentRole = userRole;
const _role = _currentRole.replace("contracts_", "");
@@ -168,11 +168,11 @@ const PgSignUp = () => {
} catch (error) {
console.log("err ", error);
if (error.message === "Account already exists for this username.") {
alert("Account already exists!");
alert(t("account-already-exists"));
navigate("/", { replace: true });
} else {
setIsLoader(false);
alert("Something went wrong, please try again later!");
alert(t("something-went-wrong-mssg"));
}
}
};
@@ -230,10 +230,7 @@ const PgSignUp = () => {
// Check extended class user role and tenentId
try {
const userSettings = appInfo.settings;
const currentUser = Parse.User.current();
const extUser = await Parse.Cloud.run("getUserDetails", {
email: currentUser.get("email")
});
const extUser = await Parse.Cloud.run("getUserDetails");
if (extUser) {
const IsDisabled = extUser?.get("IsDisabled") || false;
if (!IsDisabled) {
@@ -262,7 +259,7 @@ const PgSignUp = () => {
localStorage.setItem("defaultmenuid", menu.menuId);
localStorage.setItem("pageType", menu.pageType);
setIsLoader(false);
alert("Registered user successfully");
alert(t("registered-user-successfully"));
const redirectUrl =
location?.state?.from || `/${menu.pageType}/${menu.pageId}`;
// Redirect to the appropriate URL after successful login
@@ -294,27 +291,31 @@ const PgSignUp = () => {
>
<div className="p-[16px]">
<h1 className="text-2xl md:text-3xl font-bold">
Choose Password
{t("choose-password")}
</h1>
<hr className="border-[1px] border-[#cecece] mb-[5px]" />
<label htmlFor="password">
<b className="text-[13px]">Password</b>
<b className="text-[13px]">{t("password")}</b>
</label>
<input
type="password"
placeholder="Enter Password"
placeholder={t("enter-password")}
name="password"
className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs"
value={formData.password}
onChange={handlePassowordChange}
onInvalid={(e) =>
e.target.setCustomValidity(t("input-required"))
}
onInput={(e) => e.target.setCustomValidity("")}
required
/>
<label htmlFor="confirmPassword">
<b className="text-[13px]">Confirm Password</b>
<b className="text-[13px]">{t("confirm-password")}</b>
</label>
<input
type="password"
placeholder="Confirm Password"
placeholder={t("confirm-password")}
name="confirmPassword"
className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs"
style={{
@@ -326,6 +327,10 @@ const PgSignUp = () => {
}}
value={formData.confirmPassword}
onChange={handleConFirmPassowordChange}
onInvalid={(e) =>
e.target.setCustomValidity(t("input-required"))
}
onInput={(e) => e.target.setCustomValidity("")}
required
/>
<div
@@ -344,24 +349,21 @@ const PgSignUp = () => {
lengthValid ? "text-green-600" : "text-red-600"
}`}
>
{lengthValid ? "✓" : "✗"} Password should be 8 characters
long
{lengthValid ? "✓" : "✗"} {t("password-length")}
</p>
<p
className={`${
caseDigitValid ? "text-green-600" : "text-red-600"
}`}
>
{caseDigitValid ? "✓" : "✗"} Password should contain
uppercase letter, lowercase letter, digit
{caseDigitValid ? "✓" : "✗"} {t("password-case")}
</p>
<p
className={`${
specialCharValid ? "text-green-600" : "text-red-600"
}`}
>
{specialCharValid ? "✓" : "✗"} Password should contain
special character
{specialCharValid ? "✓" : "✗"} {t("password-special-char")}
</p>
</div>
)}
@@ -369,7 +371,7 @@ const PgSignUp = () => {
type="submit"
className="op-btn op-btn-primary w-full mt-[8px]"
>
Submit
{t("submit")}
</button>
</div>
</form>
File diff suppressed because it is too large Load Diff
+81 -15
View File
@@ -4,8 +4,9 @@ import checkmark from "../assets/images/checkmark.png";
import plansArr from "../json/plansArr";
import Title from "../components/Title";
import Parse from "parse";
import { openInNewTab } from "../constant/Utils";
import { openInNewTab, saveLanguageInLocal } from "../constant/Utils";
import Loader from "../primitives/Loader";
import { useTranslation } from "react-i18next";
const listItemStyle = {
paddingLeft: "20px", // Add padding to create space for the image
backgroundImage: `url(${checkmark})`, // Set your image as the list style image
@@ -15,6 +16,7 @@ const listItemStyle = {
};
const PlanSubscriptions = () => {
const { t, i18n } = useTranslation();
const navigate = useNavigate();
const [yearlyVisible, setYearlyVisible] = useState(true);
const [isLoader, setIsLoader] = useState(true);
@@ -51,19 +53,45 @@ const PlanSubscriptions = () => {
? "&mobile=" + encodeURIComponent(userDetails.phone)
: "";
const details =
"?shipping_country_code=US&billing_country_code=US&billing_state_code=CA&" +
name +
email +
company +
phone;
useEffect(() => {
setIsLoader(false);
detectLanguage();
// eslint-disable-next-line
}, []);
const detectLanguage = () => {
const detectedLanguage = i18n.language || "en";
i18n.changeLanguage(detectedLanguage);
localStorage.setItem("i18nextLng", detectedLanguage);
};
const handleFreePlan = async (item) => {
if (item.url) {
const code = yearlyVisible ? item.code.yearly : item.code.monthly;
const allowedUsers =
localStorage.getItem("allowedUsers") &&
localStorage.getItem("allowedUsers") > 0
? localStorage.getItem("allowedUsers") - 1
: "";
const teamperiod = {
"team-weekly": "monthly",
"team-yearly": "yearly",
"teams-monthly": "monthly",
"teams-yearly": "yearly"
};
const period = teamperiod[code] || "";
const quantity =
allowedUsers && period
? `addon_code%5B0%5D=extra-teams-users-${period}&addon_quantity%5B0%5D=${allowedUsers}&`
: "";
const details =
"?shipping_country_code=US&billing_country_code=US&billing_state_code=CA&" +
quantity +
name +
email +
company +
phone;
const url = yearlyVisible ? item.yearlyUrl + details : item.url + details;
if (user) {
localStorage.setItem("userDetails", JSON.stringify(user));
@@ -76,7 +104,7 @@ const PlanSubscriptions = () => {
const res = await Parse.Cloud.run("freesubscription", params);
if (res.status === "success" && res.result === "already subscribed!") {
setIsLoader(false);
alert("You have already subscribed to plan!");
alert(t("subscribed-alert"));
} else if (res.status === "success") {
setIsLoader(false);
navigate("/");
@@ -87,10 +115,34 @@ const PlanSubscriptions = () => {
} catch (err) {
setIsLoader(false);
console.log("err in free subscribe", err.message);
alert("Somenthing went wrong, please try again later!");
alert(t("something-went-wrong-mssg"));
}
}
};
const handleLogout = async () => {
try {
await Parse?.User?.logOut();
} catch (err) {
console.log("Err while logging out", err);
}
let appdata = localStorage.getItem("userSettings");
let applogo = localStorage.getItem("appLogo");
let defaultmenuid = localStorage.getItem("defaultmenuid");
let PageLanding = localStorage.getItem("PageLanding");
let baseUrl = localStorage.getItem("baseUrl");
let appid = localStorage.getItem("parseAppId");
localStorage.clear();
saveLanguageInLocal(i18n);
localStorage.setItem("appLogo", applogo);
localStorage.setItem("defaultmenuid", defaultmenuid);
localStorage.setItem("PageLanding", PageLanding);
localStorage.setItem("userSettings", appdata);
localStorage.setItem("baseUrl", baseUrl);
localStorage.setItem("parseAppId", appid);
navigate("/");
};
return (
<>
<Title title={"Subscriptions"} />
@@ -101,7 +153,13 @@ const PlanSubscriptions = () => {
) : (
<div className="overflow-y-auto max-h-full">
<div className="block my-2">
<div className="flex flex-col justify-center items-center w-full">
<div className="flex flex-col justify-center items-center w-full relative">
<button
className="md:hidden op-btn op-btn-primary op-btn-sm h-[40px] w-[250px] shadow-lg"
onClick={() => handleLogout()}
>
Log out
</button>
<div
role="tablist"
className="op-tabs op-tabs-boxed bg-base-100 my-2 shadow-lg transition-all"
@@ -111,17 +169,23 @@ const PlanSubscriptions = () => {
role="tab"
className={`${!yearlyVisible ? "op-tab-active" : ""} op-tab`}
>
Monthly
{t("monthly")}
</a>
<a
onClick={() => setYearlyVisible(true)}
role="tab"
className={`${yearlyVisible ? "op-tab-active" : ""} op-tab`}
>
Yearly (upto 66% off)
{t("yearly-upto")}
</a>
</div>
<ul className="op-card flex flex-col md:flex-row h-full bg-base-100 justify-center shadow-lg">
<button
className="hidden md:block -top-12 right-1 absolute w-[150px] h-[40px] op-btn op-btn-primary op-btn-sm shadow-lg"
onClick={() => handleLogout()}
>
{t("log-out")}
</button>
{plansArr.map((item) => (
<li
className="flex flex-col text-center border-collapse border-[1px] border-gray-300 max-w-[250px]"
@@ -170,7 +234,9 @@ const PlanSubscriptions = () => {
)}
</span>
<p className="font-semibold pt-2 text-sm">
{yearlyVisible ? "Billed Yearly" : "Billed Monthly"}
{yearlyVisible
? t("billed-yearly")
: t("billed-monthly")}
</p>
<div className="max-w-[250px] h-[40px] text-center text-sm my-2">
<div
@@ -228,7 +294,7 @@ const PlanSubscriptions = () => {
</div>
<div className="flex flex-col justify-center items-center">
<h3 className="text-[#002862] mt-1 mb-2">
Host it yourself for free
{t("plansubscription-1")}
</h3>
<div
className="op-btn op-btn-primary w-[200px]"
@@ -236,7 +302,7 @@ const PlanSubscriptions = () => {
openInNewTab("https://github.com/OpenSignLabs/OpenSign")
}
>
Visit Github
{t("visit-github")}
</div>
</div>
</div>
+218
View File
@@ -0,0 +1,218 @@
import React, { useEffect, useState } from "react";
import Title from "../components/Title";
import Alert from "../primitives/Alert";
import { useTranslation } from "react-i18next";
import Loader from "../primitives/Loader";
import Tooltip from "../primitives/Tooltip";
import {
getTenantDetails,
handleSignatureType,
signatureTypes
} from "../constant/Utils";
import Parse from "parse";
import { Tooltip as ReactTooltip } from "react-tooltip";
const Preferences = () => {
const { t } = useTranslation();
const [isalert, setIsAlert] = useState({ type: "success", msg: "" });
const [isTopLoader, setIsTopLoader] = useState(false);
const [isLoader, setIsLoader] = useState(false);
const [signatureType, setSignatureType] = useState([]);
const [errMsg, setErrMsg] = useState("");
useEffect(() => {
fetchSignType();
}, []);
const fetchSignType = async () => {
setIsTopLoader(true);
try {
const user = JSON.parse(
localStorage.getItem(
`Parse/${localStorage.getItem("parseAppId")}/currentUser`
)
);
const tenantDetails = await getTenantDetails(user?.objectId);
const signatureType = tenantDetails?.SignatureType || [];
const tenantSignTypes = signatureType?.filter((x) => x.enabled === true);
const getUser = await Parse.Cloud.run("getUserDetails");
if (getUser) {
const _getUser = JSON.parse(JSON.stringify(getUser));
if (tenantSignTypes?.length > 0) {
const signatureType = _getUser?.SignatureType || signatureTypes;
const updatedSignatureType = await handleSignatureType(
tenantSignTypes,
signatureType
);
setSignatureType(updatedSignatureType);
} else {
const SignatureType = _getUser?.SignatureType || signatureTypes;
setSignatureType(SignatureType);
}
}
} catch (err) {
console.log("err while getting user details", err);
setErrMsg("Something went wrong");
} finally {
setIsTopLoader(false);
}
};
// `handleCheckboxChange` is trigger when user enable/disable checkbox of respective type
const handleCheckboxChange = (index) => {
// Create a copy of the signatureType array
const updatedSignatureType = [...signatureType];
// Toggle the enabled value for the clicked item
updatedSignatureType[index].enabled = !updatedSignatureType[index].enabled;
// Update the state with the modified array
setSignatureType(updatedSignatureType);
};
// `handleSave` is used save updated value signature type
const handleSave = async () => {
setIsLoader(true);
const enabledSignTypes = signatureType?.filter((x) => x.enabled);
const isDefaultSignTypeOnly =
enabledSignTypes?.length === 1 && enabledSignTypes[0]?.name === "default";
if (enabledSignTypes.length === 0) {
setIsAlert({
type: "danger",
msg: t("at-least-one-signature-type")
});
} else if (isDefaultSignTypeOnly) {
setIsAlert({
type: "danger",
msg: t("expect-default-one-more-signature-type")
});
} else {
try {
const updateRes = await Parse.Cloud.run("updatesignaturetype", {
SignatureType: signatureType
});
if (updateRes) {
setIsAlert({ type: "success", msg: "Saved successfully." });
}
} catch (err) {
console.log("Error updating signature type", err);
setIsAlert({ type: "danger", msg: err.message });
}
}
setTimeout(() => setIsAlert({ type: "success", msg: "" }), 1500);
setIsLoader(false);
};
return (
<React.Fragment>
<Title title={"API Token"} />
{isalert.msg && <Alert type={isalert.type}>{isalert.msg}</Alert>}
{isTopLoader ? (
<div className="flex justify-center items-center h-screen">
<Loader />
</div>
) : (
<>
{errMsg ? (
<div className="flex justify-center items-center h-screen">
{errMsg}
</div>
) : (
<div className="relative bg-base-100 text-base-content flex flex-col justify-center shadow-md rounded-box mb-3">
{isLoader && (
<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">
OpenSign {t("Preferences")}{" "}
<span>
<Tooltip
message={`OpenSign™ ${t("Preferences")}`}
isSubscribe={true}
/>
</span>
</h1>
<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"
>
{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">Typed: </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}
</div>
</div>
))}
</div>
<button
className="op-btn op-btn-primary"
onClick={handleSave}
>
Save
</button>
</div>
</div>
</div>
)}
</>
)}
</React.Fragment>
);
};
export default Preferences;
+4 -4
View File
@@ -8,8 +8,10 @@ import Title from "../components/Title";
import PageNotFound from "./PageNotFound";
import TourContentWithBtn from "../primitives/TourContentWithBtn";
import Loader from "../primitives/Loader";
import { useTranslation } from "react-i18next";
const Report = () => {
const { t } = useTranslation();
const { id } = useParams();
const [List, setList] = useState([]);
const [isLoader, setIsLoader] = useState(true);
@@ -83,9 +85,7 @@ const Report = () => {
selector: "[data-tut=reactourFirst]",
content: () => (
<TourContentWithBtn
message={
"Click the 'Add' button to create a new template. Templates are reusable documents designed to quickly generate new documents with the same structure and varying signers. For example, an HR template for onboarding could have predefined roles like HR Manager and New Employee. Each time you use the template, you can assign the New Employee role to different incoming staff members, while the HR Manager role remains constant, facilitating a seamless onboarding process for each recruit. "
}
message={t("tour-mssg.report-1")}
isChecked={handleDontShow}
/>
),
@@ -100,7 +100,7 @@ const Report = () => {
selector: `[data-tut="${data?.selector}"]`,
content: () => (
<TourContentWithBtn
message={data?.message}
message={t(`tour-mssg.${data?.action}`)}
isChecked={handleDontShow}
/>
),
+37 -25
View File
@@ -8,8 +8,10 @@ import { useDispatch } from "react-redux";
import { showTenant } from "../redux/reducers/ShowTenant";
import ModalUi from "../primitives/ModalUi";
import Loader from "../primitives/Loader";
import { useTranslation } from "react-i18next";
const SSOVerify = () => {
const { t } = useTranslation();
const location = useLocation();
const navigate = useNavigate();
const dispatch = useDispatch();
@@ -48,6 +50,9 @@ const SSOVerify = () => {
console.log("err", err.message);
}
};
const handlePaidRoute = () => {
navigate("/subscription");
};
const checkExtUser = async (ssosign) => {
const params = { email: ssosign?.email };
try {
@@ -120,16 +125,16 @@ const SSOVerify = () => {
} catch (err) {
console.log("error in usersignup", err);
localStorage.removeItem("accesstoken");
alert("Something went wrong.");
alert(t("something-went-wrong-mssg"));
setIsLoader(false);
}
} else {
localStorage.removeItem("accesstoken");
alert("Internal server error.");
alert(t("server-error"));
setIsLoader(false);
}
} else {
alert("Please fill required details correctly.");
alert(t("filed-required-correctly"));
setIsLoader(false);
}
};
@@ -149,10 +154,7 @@ const SSOVerify = () => {
// Check extended class user role and tenentId
try {
const userSettings = appInfo.settings;
const currentUser = Parse.User.current();
await Parse.Cloud.run("getUserDetails", {
email: currentUser.get("email")
})
await Parse.Cloud.run("getUserDetails")
.then(async (extUser) => {
if (extUser) {
const IsDisabled = extUser?.get("IsDisabled") || false;
@@ -197,29 +199,25 @@ const SSOVerify = () => {
localStorage.removeItem("userDetails");
navigate(redirectUrl);
} else {
navigate(`/subscription`, { replace: true });
handlePaidRoute(plan);
}
} else {
navigate(`/subscription`, { replace: true });
handlePaidRoute(plan);
}
} else {
navigate(redirectUrl);
}
}
} else {
alert(
"Error: You don't have access, please contact the admin."
);
setMessage(
"Error: You don't have access, please contact the admin."
);
alert(t("do-not-access-contact-admin"));
setMessage(t("do-not-access-contact-admin"));
}
}
})
.catch((error) => {
console.error("Err in fetch extuser", error);
alert("user not exist.");
setMessage("Error: User not exist.");
alert(t("user-not-exist"));
setMessage(t("user-not-exist"));
});
} catch (err) {
console.log("err in getuserdetails", err);
@@ -230,10 +228,12 @@ const SSOVerify = () => {
}
};
// `handleCloseModal` is triggered when the user wants to close the new user flow modal
const handleCloseModal = () => {
const handleCloseModal = async () => {
setIsModal(false);
if (Parse?.User?.current()) {
Parse.User.logOut();
try {
await Parse.User.logOut();
} catch (err) {
console.log("Err while logging out", err);
}
};
@@ -265,7 +265,7 @@ const SSOVerify = () => {
>
<div className="mb-3">
<label htmlFor="Company" className="block text-xs font-semibold">
Phone <span className="text-[13px] text-[red]">*</span>
{t("phone")} <span className="text-[13px] text-[red]">*</span>
</label>
<input
type="tel"
@@ -279,6 +279,10 @@ const SSOVerify = () => {
})
}
disabled={isLoader}
onInvalid={(e) =>
e.target.setCustomValidity(t("input-required"))
}
onInput={(e) => e.target.setCustomValidity("")}
required
/>
<p className="text-[10px] text-[red] ml-2">
@@ -287,7 +291,7 @@ const SSOVerify = () => {
</div>
<div className="mb-3">
<label htmlFor="Company" className="block text-xs font-semibold">
Company <span className="text-[13px] text-[red]">*</span>
{t("company")} <span className="text-[13px] text-[red]">*</span>
</label>
<input
type="text"
@@ -301,12 +305,16 @@ const SSOVerify = () => {
})
}
disabled={isLoader}
onInvalid={(e) =>
e.target.setCustomValidity(t("input-required"))
}
onInput={(e) => e.target.setCustomValidity("")}
required
/>
</div>
<div className="mb-3">
<label htmlFor="JobTitle" className="block text-xs font-semibold">
Job Title
{t("job-title")}
<span className="text-[13px] text-[red]">*</span>
</label>
<input
@@ -321,19 +329,23 @@ const SSOVerify = () => {
})
}
disabled={isLoader}
onInvalid={(e) =>
e.target.setCustomValidity(t("input-required"))
}
onInput={(e) => e.target.setCustomValidity("")}
required
/>
</div>
<div className="mt-4">
<button type="submit" className="op-btn op-btn-primary">
Login
{t("login")}
</button>
<button
type="button"
className="op-btn op-btn-ghost ml-2"
onClick={handleCloseModal}
>
Cancel
{t("cancel")}
</button>
</div>
</form>
+155 -113
View File
@@ -10,11 +10,18 @@ import { appInfo } from "../constant/appinfo";
import { useDispatch } from "react-redux";
import { fetchAppInfo } from "../redux/reducers/infoReducer";
import { showTenant } from "../redux/reducers/ShowTenant";
import { isEnableSubscription } from "../constant/const";
import { getAppLogo, openInNewTab } from "../constant/Utils";
import { emailRegex, isEnableSubscription } from "../constant/const";
import {
getAppLogo,
openInNewTab,
saveLanguageInLocal
} from "../constant/Utils";
import Loader from "../primitives/Loader";
import { useTranslation } from "react-i18next";
import SelectLanguage from "../components/pdf/SelectLanguage";
const Signup = () => {
const { width } = useWindowSize();
const { t, i18n } = useTranslation();
const navigate = useNavigate();
const location = useLocation();
const dispatch = useDispatch();
@@ -38,8 +45,10 @@ const Signup = () => {
const togglePasswordVisibility = () => setShowPassword(!showPassword);
const clearStorage = async () => {
if (Parse.User.current()) {
try {
await Parse.User.logOut();
} catch (err) {
console.log("Err while logging out", err);
}
let baseUrl = localStorage.getItem("baseUrl");
let appid = localStorage.getItem("parseAppId");
@@ -49,7 +58,7 @@ const Signup = () => {
let userSettings = localStorage.getItem("userSettings");
localStorage.clear();
saveLanguageInLocal(i18n);
localStorage.setItem("baseUrl", baseUrl);
localStorage.setItem("parseAppId", appid);
localStorage.setItem("appLogo", applogo);
@@ -69,99 +78,101 @@ const Signup = () => {
}
} catch (err) {
console.log("err in free subscribe", err.message);
alert("Somenthing went wrong, please try again later!");
alert(t("something-went-wrong-mssg"));
}
};
const handleSubmit = (event) => {
event.preventDefault();
if (lengthValid && caseDigitValid && specialCharValid) {
clearStorage();
setState({ loading: true });
const userDetails = {
name: name,
email: email,
phone: phone,
company: company,
jobTitle: jobTitle
};
localStorage.setItem("userDetails", JSON.stringify(userDetails));
try {
event.preventDefault();
var user = new Parse.User();
user.set("name", name);
user.set("email", email);
user.set("password", password);
user.set("phone", phone);
user.set("username", email);
let res = user.save();
res
.then(async (r) => {
if (r) {
let roleData = appInfo.settings;
if (roleData && roleData.length > 0) {
const params = {
userDetails: {
jobTitle: jobTitle,
company: company,
name: name,
email: email,
phone: phone,
role: appInfo.defaultRole
}
};
try {
const usersignup = await Parse.Cloud.run(
"usersignup",
params
);
if (usersignup) {
const param = new URLSearchParams(location.search);
const isFreeplan =
param?.get("subscription") === "freeplan";
if (isFreeplan) {
await handleFreePlan(r.id);
if (!emailRegex.test(email)) {
alert("Please enter a valid email address.");
} else {
if (lengthValid && caseDigitValid && specialCharValid) {
clearStorage();
setState({ loading: true });
const userDetails = {
name: name,
email: email,
phone: phone,
company: company,
jobTitle: jobTitle
};
localStorage.setItem("userDetails", JSON.stringify(userDetails));
try {
event.preventDefault();
var user = new Parse.User();
user.set("name", name);
user.set("email", email);
user.set("password", password);
user.set("phone", phone);
user.set("username", email);
let res = user.save();
res
.then(async (r) => {
if (r) {
let roleData = appInfo.settings;
if (roleData && roleData.length > 0) {
const params = {
userDetails: {
jobTitle: jobTitle,
company: company,
name: name,
email: email,
phone: phone,
role: appInfo.defaultRole
}
handleNavigation(r.getSessionToken(), isFreeplan);
};
try {
const usersignup = await Parse.Cloud.run(
"usersignup",
params
);
if (usersignup) {
const param = new URLSearchParams(location.search);
const isFreeplan =
param?.get("subscription") === "freeplan";
if (isFreeplan) {
await handleFreePlan(r.id);
}
handleNavigation(r.getSessionToken(), isFreeplan);
}
} catch (err) {
alert(err.message);
setState({ loading: false });
}
}
}
})
.catch(async (err) => {
if (err.code === 202) {
const params = { email: email };
const res = await Parse.Cloud.run("getUserDetails", params);
// console.log("Res ", res);
if (res) {
alert(t("user-already-exist-name"));
setState({ loading: false });
} else {
// console.log("state.email ", email);
try {
await Parse.User.requestPasswordReset(email).then(
async function (res1) {
if (res1.data === undefined) {
alert(t("verification-code-sent"));
}
}
);
} catch (err) {
console.log(err);
}
} catch (err) {
alert(err.message);
setState({ loading: false });
}
}
}
})
.catch(async (err) => {
if (err.code === 202) {
const params = { email: email };
const res = await Parse.Cloud.run("getUserDetails", params);
// console.log("Res ", res);
if (res) {
alert("User already exists with this username!");
setState({ loading: false });
} else {
// console.log("state.email ", email);
try {
await Parse.User.requestPasswordReset(email).then(
async function (res1) {
if (res1.data === undefined) {
alert(
"Verification mail has been sent to your E-mail!"
);
}
}
);
} catch (err) {
console.log(err);
}
alert(err.message);
setState({ loading: false });
}
} else {
alert(err.message);
setState({ loading: false });
}
});
} catch (error) {
console.log("err ", error);
});
} catch (error) {
console.log("err ", error);
}
}
}
};
@@ -192,10 +203,7 @@ const Signup = () => {
// Check extended class user role and tenentId
try {
const userSettings = appInfo.settings;
const currentUser = Parse.User.current();
await Parse.Cloud.run("getUserDetails", {
email: currentUser.get("email")
})
await Parse.Cloud.run("getUserDetails")
.then(async (extUser) => {
if (extUser) {
const IsDisabled = extUser?.get("IsDisabled") || false;
@@ -233,14 +241,14 @@ const Signup = () => {
navigate(`/subscription`, { replace: true });
}
} else {
alert("Registered user successfully");
alert(t("registered-user-successfully"));
navigate(`/${menu.pageType}/${menu.pageId}`);
}
} else {
setState({
loading: false,
alertType: "danger",
alertMsg: "Role not found."
alertMsg: t("role-not-found")
});
setTimeout(() => {
setState({ loading: false, alertMsg: "" });
@@ -250,7 +258,7 @@ const Signup = () => {
setState({
loading: false,
alertType: "danger",
alertMsg: "You don't have access, please contact the admin."
alertMsg: t("do-not-access-contact-admin")
});
setTimeout(() => {
setState({ loading: false, alertMsg: "" });
@@ -263,7 +271,7 @@ const Signup = () => {
setState({
loading: false,
alertType: "danger",
alertMsg: "You don't have access, please contact the admin."
alertMsg: t("do-not-access-contact-admin")
});
setTimeout(() => {
setState({ loading: false, alertMsg: "" });
@@ -322,7 +330,7 @@ const Signup = () => {
<Loader />
</div>
)}
<Title title={"Signup page"} />
<Title title="Signup page" />
{appInfo && appInfo.applogo ? (
<div className="md:p-10 lg:p-16">
<div className="md:p-4 lg:p-10 p-4 bg-base-100 text-base-content op-card">
@@ -334,22 +342,28 @@ const Signup = () => {
<div className="grid grid-cols-1 md:grid-cols-2 gap-x-2">
<div>
<form onSubmit={handleSubmit}>
<h2 className="text-[30px] mt-6">Create Account !</h2>
<h2 className="text-[30px] mt-6">{t("create-account")}!</h2>
<div className="w-full my-4 op-card bg-base-100 shadow-md outline outline-1 outline-slate-300/50">
<div className="px-6 py-4 text-xs">
<label className="block ">
Name <span className="text-[red] text-[13px]">*</span>
{t("name")}{" "}
<span className="text-[red] text-[13px]">*</span>
</label>
<input
type="text"
className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs"
value={name}
onChange={(e) => setName(e.target.value)}
onInvalid={(e) =>
e.target.setCustomValidity(t("input-required"))
}
onInput={(e) => e.target.setCustomValidity("")}
required
/>
<hr className="my-2 border-none" />
<label>
Email <span className="text-[red] text-[13px]">*</span>
{t("email")}{" "}
<span className="text-[red] text-[13px]">*</span>
</label>
<input
id="email"
@@ -357,24 +371,35 @@ const Signup = () => {
className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs"
value={email}
onChange={(e) =>
setEmail(e.target.value?.toLowerCase())
setEmail(
e.target.value?.toLowerCase()?.replace(/\s/g, "")
)
}
onInvalid={(e) =>
e.target.setCustomValidity(t("input-required"))
}
onInput={(e) => e.target.setCustomValidity("")}
required
/>
<hr className="my-2 border-none" />
<label>
Phone <span className="text-[red] text-[13px]">*</span>
{t("phone")}{" "}
<span className="text-[red] text-[13px]">*</span>
</label>
<input
type="tel"
className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs"
value={phone}
onChange={(e) => setPhone(e.target.value)}
onInvalid={(e) =>
e.target.setCustomValidity(t("input-required"))
}
onInput={(e) => e.target.setCustomValidity("")}
required
/>
<hr className="my-2 border-none" />
<label>
Company{" "}
{t("company")}{" "}
<span className="text-[red] text-[13px]">*</span>
</label>
<input
@@ -382,11 +407,15 @@ const Signup = () => {
className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs"
value={company}
onChange={(e) => setCompany(e.target.value)}
onInvalid={(e) =>
e.target.setCustomValidity(t("input-required"))
}
onInput={(e) => e.target.setCustomValidity("")}
required
/>
<hr className="my-2 border-none" />
<label>
Job Title{" "}
{t("job-title")}{" "}
<span className="text-[red] text-[13px]">*</span>
</label>
<input
@@ -394,11 +423,15 @@ const Signup = () => {
className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs"
value={jobTitle}
onChange={(e) => setJobTitle(e.target.value)}
onInvalid={(e) =>
e.target.setCustomValidity(t("input-required"))
}
onInput={(e) => e.target.setCustomValidity("")}
required
/>
<hr className="my-2 border-none" />
<label>
Password{" "}
{t("password")}{" "}
<span className="text-[red] text-[13px]">*</span>
</label>
<div className="relative">
@@ -408,6 +441,10 @@ const Signup = () => {
name="password"
value={password}
onChange={(e) => handlePasswordChange(e)}
onInvalid={(e) =>
e.target.setCustomValidity(t("input-required"))
}
onInput={(e) => e.target.setCustomValidity("")}
required
/>
<span
@@ -428,16 +465,16 @@ const Signup = () => {
lengthValid ? "text-green-600" : "text-red-600"
}`}
>
{lengthValid ? "✓" : "✗"} Password should be 8
characters long
{lengthValid ? "✓" : "✗"}
{t("password-length")}
</p>
<p
className={`${
caseDigitValid ? "text-green-600" : "text-red-600"
}`}
>
{caseDigitValid ? "✓" : "✗"} Password should contain
uppercase letter, lowercase letter, digit
{caseDigitValid ? "✓" : "✗"}
{t("password-case")}
</p>
<p
className={`${
@@ -446,8 +483,8 @@ const Signup = () => {
: "text-red-600"
}`}
>
{specialCharValid ? "✓" : "✗"} Password should
contain special character
{specialCharValid ? "✓" : "✗"}{" "}
{t("password-special-char")}
</p>
</div>
)}
@@ -458,13 +495,17 @@ const Signup = () => {
id="termsandcondition"
checked={isAuthorize}
onChange={(e) => setIsAuthorize(e.target.checked)}
onInvalid={(e) =>
e.target.setCustomValidity(t("input-required"))
}
onInput={(e) => e.target.setCustomValidity("")}
required
/>
<label
className="text-xs cursor-pointer ml-1 mb-0"
htmlFor="termsandcondition"
>
I agree to the
{t("agreee")}
</label>
<span
className="underline cursor-pointer ml-1"
@@ -474,7 +515,7 @@ const Signup = () => {
)
}
>
Terms of Service
{t("term")}
</span>
<span>.</span>
</div>
@@ -486,7 +527,7 @@ const Signup = () => {
className="op-btn op-btn-primary"
disabled={state.loading}
>
{state.loading ? "Loading..." : "Register"}
{state.loading ? t("loading") : t("register")}
</button>
<button
type="button"
@@ -496,7 +537,7 @@ const Signup = () => {
navigate(location.search ? "/" + location.search : "/")
}
>
Login
{t("login")}
</button>
</div>
</form>
@@ -510,6 +551,7 @@ const Signup = () => {
)}
</div>
</div>
<SelectLanguage />
<Alert type={state.alertType}>{state.alertMsg}</Alert>
</div>
) : (
File diff suppressed because it is too large Load Diff

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