Compare commits

...
71 Commits
Author SHA1 Message Date
RaktimaNXG 69308e22d8 fix: error in auto-sign feature unexpected issue encountered - something went wrong 2024-08-08 15:06:43 +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-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
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
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
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
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-opensignlabsandGitHub 375dc86f0a Merge pull request #998 from OpenSignLabs/input_text_darkmode
fix: type initials and signature looks blurry on download pdf
2024-08-01 18:47:01 +05:30
AndrewandGitHub d2f187f6c0 Merge pull request #1001 from OpenSignLabs/multiuser_issue 2024-08-01 18:42:51 +05:30
prafull-opensignlabs 5393ee9ba9 style: remove unncessary themes and change dropbox btn as per theme 2024-08-01 18:40:04 +05:30
AndrewandGitHub d4d2948455 Merge pull request #1000 from OpenSignLabs/multiuser_issue 2024-08-01 18:09:43 +05:30
prafull-opensignlabs 37617c04ad fix: x is not function and security issue 2024-08-01 18:08:34 +05:30
RaktimaNXG 10e0153018 fix: initial type signature bulry issue 2024-08-01 17:56:44 +05:30
RaktimaNXG 42cbe94af8 fix: initial type signature issue 2024-08-01 16:50:48 +05:30
AndrewandGitHub 8f95e53d9d Merge pull request #999 from OpenSignLabs/multiuser_issue 2024-08-01 16:49:44 +05:30
prafull-opensignlabs 0dae21dcf1 build(Deps): update depencencies and overide ws packge to resolve security issue 2024-08-01 16:39:37 +05:30
RaktimaNXG 912efeb5fd refactor-code 2024-08-01 15:50:48 +05:30
AmolandGitHub 3d9307f96d Merge pull request #997 from OpenSignLabs/multiuser_issue 2024-08-01 13:55:24 +05:30
prafull-opensignlabs 873f4b080a build(deps): update depencies 2024-08-01 13:52:07 +05:30
RaktimaNXG e337a79e2e fix: type initials and signature looks blurry on download pdf 2024-08-01 13:32:18 +05:30
AndrewandGitHub 980ce62bf6 Merge pull request #995 from OpenSignLabs/multiuser_issue 2024-07-31 22:10:21 +05:30
prafull-opensignlabs dccf757f56 fix: gmail adapter is not working 2024-07-31 21:26:14 +05:30
prafull-opensignlabsandGitHub 4a6b88328e Merge pull request #993 from OpenSignLabs/input_text_darkmode
fix: display wrong owner's ip address on certificate in bulk-send flow
2024-07-31 20:16:32 +05:30
RaktimaNXG 779a84cf0b fix: display wrong owner's ip addressin certificate in bulk-send flow 2024-07-31 20:15:07 +05:30
prafull-opensignlabsandGitHub aff409ba63 Merge pull request #992 from OpenSignLabs/input_text_darkmode
fix: all types of text widget background color issues in mobile dark mode.
2024-07-31 19:47:13 +05:30
RaktimaNXG 275167c0c4 fix: all types of text widget background color issues in mobile dark mode. 2024-07-31 16:56:11 +05:30
AndrewandGitHub 19b2af7f57 Merge pull request #990 from KrisIsNewxyz/staging 2024-07-31 03:02:57 +05:30
AndrewandGitHub 5050b9ee97 Merge pull request #991 from OpenSignLabs/multiuser_issue 2024-07-30 19:36:40 +05:30
prafull-opensignlabs 23da4be6b1 fix: err invalid protcol while sending file in mail 2024-07-30 18:15:16 +05:30
prafull-opensignlabs 299648b8e0 fix: getaddrinfo ENOTFOUND while creating admin 2024-07-30 16:53:36 +05:30
KrisIsNewxyz 86fa0c87ae repair broken conection to mongodb - Update .env.local_dev 2024-07-30 13:01:55 +02:00
prafull-opensignlabsandGitHub 9619eec40f Merge pull request #980 from OpenSignLabs/raktima-opensignlabs-patch-11
fix: issue with files opening in a new tab on download instead of direct download
2024-07-26 19:24:46 +05:30
RaktimaNXG 886161d65f refactor code 2024-07-26 18:47:57 +05:30
RaktimaNXG d5d646e6e0 fix: issue with files opening in a new tab on download instead of direct download 2024-07-26 18:37:48 +05:30
prafull-opensignlabsandGitHub 494103163c Merge pull request #978 from OpenSignLabs/raktima-opensignlabs-patch-11
fix: ip address missing issue in the completion certificate of document originator using public-sign flow
2024-07-26 15:28:21 +05:30
RaktimaNXG 72e9e4848b refactor code 2024-07-26 14:43:16 +05:30
RaktimaNXG 1181ba6f90 refactor code 2024-07-26 14:40:22 +05:30
RaktimaNXG b8d6ec5fe0 fix: ip address missing of document originator using public-sign 2024-07-26 14:06:47 +05:30
AndrewandGitHub 7335d7df0a Merge pull request #976 from OpenSignLabs/multiuser_issue 2024-07-25 21:01:24 +05:30
prafull-opensignlabs 44754095fb refactor: changes in cloud function 2024-07-25 20:34:44 +05:30
prafull-opensignlabsandGitHub 0f515bae01 Merge pull request #963 from OpenSignLabs/raktima-opensignlabs-patch-11
fix: text widget font size issue in large PDF documents
2024-07-25 16:23:38 +05:30
RaktimaNXG 76a11f6ee6 fix: something went wrong issue in public profile 2024-07-25 14:30:02 +05:30
prafull-opensignlabsandGitHub 5fb28feb65 Merge pull request #974 from OpenSignLabs/multiuser_issue
fix: not able to deactivate teams
2024-07-25 11:03:05 +05:30
prafull-opensignlabs e5f1524b10 fix: not able to deactivate teams 2024-07-25 11:00:55 +05:30
AmolandGitHub 8a875691fb Merge pull request #971 from OpenSignLabs/fix_selfhost 2024-07-25 01:22:00 +05:30
prafull-opensignlabs 0b2710b97d fix: docker config files 2024-07-25 01:20:42 +05:30
AmolandGitHub 57552a32b0 Merge pull request #969 from OpenSignLabs/multiuser_issue 2024-07-24 22:50:21 +05:30
prafull-opensignlabs 572ec3658e fix: teams are not available in dropdown when creating user 2024-07-24 22:49:26 +05:30
AmolandGitHub 6d5c791f61 Merge pull request #968 from OpenSignLabs/multiuser_issue 2024-07-24 17:53:01 +05:30
prafull-opensignlabs 168e479c0c refactor: plan changes 2024-07-24 17:51:32 +05:30
AmolandGitHub 927e1b7ef9 Merge pull request #966 from OpenSignLabs/multiuser_issue
refactor: plan changes
2024-07-24 17:45:56 +05:30
prafull-opensignlabs 76dccf804e refactor: plan changes 2024-07-24 17:42:20 +05:30
RaktimaNXG 4262e0e6eb fix: text input font size isssue in mobile view 2024-07-24 13:42:41 +05:30
RaktimaNXG 7d487420aa Merge branch 'staging' of https://github.com/OpenSignLabs/OpenSign into raktima-opensignlabs-patch-11 2024-07-24 12:25:28 +05:30
RaktimaNXG c422b11e3a fix: text widget font size issue in large pdf 2024-07-23 15:50:38 +05:30
98 changed files with 6058 additions and 10970 deletions
+1 -1
View File
@@ -20,7 +20,7 @@ appName=open_sign_server
# A 12 character long random secret key that allows access to all the data. It is used in Parse dashboard config to view all the data in the database.
MASTER_KEY=XnAadwKxxByMr
# Mongodb URI to connect to
MONGODB_URI=mongodb://mongo:27017/OpenSignDB
MONGODB_URI=mongodb://mongo-container:27017/OpenSignDB
# Path on which APIs should be mounted. Do not change this. This variable shall be removed & value hardcoded in the source code in coming versions.
PARSE_MOUNT=/app
# Set it to the URL from where APIs will be accessible to the NodeJS functions, for local development it should be localhost:3000/api/app (use your local port number instead)
+2092 -5798
View File
File diff suppressed because it is too large Load Diff
+15 -15
View File
@@ -4,10 +4,10 @@
"private": true,
"dependencies": {
"@formkit/auto-animate": "^0.8.2",
"@lottiefiles/dotlottie-react": "^0.7.2",
"@lottiefiles/dotlottie-react": "^0.8.6",
"@radix-ui/themes": "^3.1.1",
"@react-pdf/renderer": "^3.4.4",
"@reduxjs/toolkit": "^2.2.6",
"@reduxjs/toolkit": "^2.2.7",
"axios": "^1.7.2",
"file-saver": "^2.0.5",
"jwt-decode": "^4.0.0",
@@ -20,8 +20,8 @@
"react": "^18.2.0",
"react-bootstrap": "^2.10.4",
"react-confetti": "^6.1.0",
"react-cookie": "^7.1.4",
"react-datepicker": "^7.2.0",
"react-cookie": "^7.2.0",
"react-datepicker": "^7.3.0",
"react-dnd": "^16.0.1",
"react-dnd-html5-backend": "^16.0.1",
"react-dnd-multi-backend": "^8.0.3",
@@ -34,19 +34,19 @@
"react-quill": "^2.0.0",
"react-redux": "^9.1.2",
"react-rnd": "^10.4.11",
"react-router-dom": "^6.25.1",
"react-router-dom": "^6.26.0",
"react-scripts": "5.0.1",
"react-scrollbars-custom": "^4.1.1",
"react-select": "^5.8.0",
"react-signature-canvas": "^1.0.6",
"react-tooltip": "^5.27.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",
"styled-components": "^4.4.1",
"styled-components": "^5.3.0",
"web-vitals": "^4.2.2",
"ws": "^8.18.0"
},
@@ -88,10 +88,10 @@
}
},
"devDependencies": {
"@babel/core": "^7.24.6",
"@babel/preset-env": "^7.24.6",
"@babel/preset-react": "^7.24.6",
"@babel/runtime-corejs2": "^7.24.7",
"@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",
"clean-webpack-plugin": "^4.0.0",
@@ -102,14 +102,14 @@
"dotenv": "^16.4.5",
"dotenv-webpack": "^8.1.0",
"eslint": "^8.57.0",
"eslint-plugin-prettier": "^5.1.3",
"eslint-plugin-prettier": "^5.2.1",
"eslint-plugin-react": "^7.34.3",
"lint-staged": "^15.2.7",
"lint-staged": "^15.2.8",
"mini-css-extract-plugin": "^2.9.0",
"postcss": "^8.4.39",
"postcss": "^8.4.41",
"prettier": "^3.3.3",
"pretty-quick": "^4.0.0",
"tailwindcss": "^3.4.6",
"tailwindcss": "^3.4.7",
"terser-webpack-plugin": "^5.3.10",
"webpack-cli": "^5.1.4"
},
File diff suppressed because one or more lines are too long
Binary file not shown.
+3 -3
View File
@@ -17,7 +17,7 @@ const AddTeam = (props) => {
const getTeamList = async () => {
setIsLoader(true);
try {
const teams = await Parse.Cloud.run("getteams");
const teams = await Parse.Cloud.run("getteams", { active: true });
const teamRes = JSON.parse(JSON.stringify(teams));
if (teamRes.length > 0) {
const _teamRes = JSON.parse(JSON.stringify(teamRes));
@@ -125,10 +125,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>
)}
+1 -9
View File
@@ -35,15 +35,7 @@ const AddUser = (props) => {
const getTeamList = async () => {
setFormdata((prev) => ({ ...prev, password: generatePassword(12) }));
const extUser = JSON.parse(localStorage.getItem("Extand_Class"))?.[0];
const team = new Parse.Query("contracts_Teams");
team.equalTo("OrganizationId", {
__type: "Pointer",
className: "contracts_Organizations",
objectId: extUser.OrganizationId.objectId
});
team.notEqualTo("IsActive", false);
const teamRes = await team.find();
const teamRes = await Parse.Cloud.run("getteams", { active: true });
if (teamRes.length > 0) {
const _teamRes = JSON.parse(JSON.stringify(teamRes));
setTeamList(_teamRes);
+15 -2
View File
@@ -4,7 +4,12 @@ import FullScreenButton from "./FullScreenButton";
import { useNavigate } from "react-router-dom";
import Parse from "parse";
import { useWindowSize } from "../hook/useWindowSize";
import { checkIsSubscribed, getAppLogo, openInNewTab } from "../constant/Utils";
import {
checkIsSubscribed,
checkIsSubscribedTeam,
getAppLogo,
openInNewTab
} from "../constant/Utils";
import { isEnableSubscription, isStaging } from "../constant/const";
const Header = ({ showSidebar }) => {
@@ -15,6 +20,7 @@ const Header = ({ showSidebar }) => {
const [isOpen, setIsOpen] = useState(false);
const [isSubscribe, setIsSubscribe] = useState(true);
const [isPro, setIsPro] = useState(false);
const [isTeam, setIsTeam] = useState(false);
const [applogo, setAppLogo] = useState(
localStorage.getItem("appLogo") || " "
);
@@ -29,6 +35,7 @@ const Header = ({ showSidebar }) => {
async function checkSubscription() {
if (isEnableSubscription) {
const getIsSubscribe = await checkIsSubscribed();
const getIsTeam = await checkIsSubscribedTeam();
if (getIsSubscribe) {
const applogo = await getAppLogo();
if (applogo?.logo) {
@@ -38,6 +45,7 @@ const Header = ({ showSidebar }) => {
}
}
setIsPro(getIsSubscribe);
setIsTeam(getIsTeam);
setIsSubscribe(getIsSubscribe);
}
}
@@ -122,11 +130,16 @@ const Header = ({ showSidebar }) => {
</button>
</div>
)}
{isPro && (
{!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>
@@ -23,17 +23,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 +89,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 +211,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();
}
@@ -1,9 +1,7 @@
import React, { useState } from "react";
import { saveAs } from "file-saver";
import axios from "axios";
import { getBase64FromUrl } from "../../constant/Utils";
import { handleDownloadPdf, 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";
@@ -12,7 +10,7 @@ function EmailComponent({
pdfUrl,
setIsEmail,
setSuccessEmail,
pdfName,
pdfDetails,
sender,
setIsAlert,
extUserId,
@@ -22,8 +20,11 @@ function EmailComponent({
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;
@@ -138,43 +139,6 @@ 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 });
}
};
//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 */}
@@ -188,6 +152,11 @@ function EmailComponent({
</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!
@@ -195,7 +164,7 @@ function EmailComponent({
<div className="flex flex-row">
{!isAndroid && (
<button
onClick={handleToPrint}
onClick={(e) => handleToPrint(e, pdfUrl, setIsDownloading)}
className="op-btn op-btn-neutral op-btn-sm text-[15px]"
>
<i className="fa-light fa-print" aria-hidden="true"></i>
@@ -204,7 +173,9 @@ function EmailComponent({
)}
<button
className="op-btn op-btn-primary op-btn-sm text-[15px] ml-2"
onClick={() => handleDownloadPdf()}
onClick={() =>
handleDownloadPdf(pdfDetails, pdfUrl, setIsDownloading)
}
>
<i className="fa-light fa-download" aria-hidden="true"></i>
Download
+9 -13
View File
@@ -414,19 +414,15 @@ function Header({
</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()}
>
Sign Now
</button>
</div>
) : (
<div className="flex">
<button
@@ -4,6 +4,7 @@ import PlaceholderBorder from "./PlaceholderBorder";
import { Rnd } from "react-rnd";
import {
defaultWidthHeight,
getContainerScale,
handleCopyNextToWidget,
isTabAndMobile,
onChangeInput,
@@ -634,10 +635,11 @@ function Placeholder(props) {
);
};
const xPos = (pos, signYourself) => {
const getPdfPageWidth = props.pdfOriginalWH.find(
(data) => data.pageNumber === props.pageNumber
const containerScale = getContainerScale(
props.pdfOriginalWH,
props.pageNumber,
props.containerWH
);
const containerScale = props.containerWH.width / getPdfPageWidth?.width;
const resizePos = pos.xPosition;
if (signYourself) {
return resizePos * containerScale * props.scale;
@@ -659,10 +661,11 @@ function Placeholder(props) {
}
};
const yPos = (pos, signYourself) => {
const getPdfPageWidth = props.pdfOriginalWH.find(
(data) => data.pageNumber === props.pageNumber
const containerScale = getContainerScale(
props.pdfOriginalWH,
props.pageNumber,
props.containerWH
);
const containerScale = props.containerWH.width / getPdfPageWidth.width;
const resizePos = pos.yPosition;
if (signYourself) {
@@ -47,14 +47,11 @@ function PlaceholderBorder(props) {
onTouchEnd={() =>
props.pos.type === textWidget && props?.setDraggingEnabled(true)
}
className="absolute inline-block w-[14px] h-[14px] hover:cursor-sw-resize"
className="absolute inline-block w-[14px] h-[14px] border-[0.2px] overflow-hidden border-dashed"
style={{
borderColor: themeColor,
borderStyle: "dashed",
minWidth: handleMinWidth() || 0,
minHeight: handleMinHeight() || 0,
borderWidth: "0.2px",
overflow: "hidden"
minHeight: handleMinHeight() || 0
}}
></div>
);
@@ -15,7 +15,7 @@ import "../../styles/signature.css";
import RegexParser from "regex-parser";
import { emailRegex } from "../../constant/const";
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";
"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) {
@@ -140,8 +140,7 @@ function PlaceholderType(props) {
const ExampleCustomInput = forwardRef(({ value, onClick }, ref) => (
<div
className={`${selectWidgetCls} overflow-hidden`}
style={{ fontSize: calculateFontSize() }}
className={`${selectWidgetCls} text-[12px] overflow-hidden`}
onClick={onClick}
ref={ref}
>
@@ -172,12 +171,6 @@ function PlaceholderType(props) {
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [type]);
const calculateFontSize = () => {
const fontSize = 10 + Math.min(props.pos.Width, props.pos.Height) * 0.1;
const size = fontSize ? fontSize : 12;
return size + "px";
};
//function for show checked checkbox
const selectCheckbox = (ind) => {
const res = props.pos.options?.response;
@@ -427,7 +420,8 @@ function PlaceholderType(props) {
fontSize: props.pos.options?.fontSize
? props.pos.options?.fontSize + "px"
: "12px",
color: props.pos.options?.fontColor || "black"
color: props.pos.options?.fontColor || "black",
overflow: "hidden"
}}
>
<span>{type}</span>
@@ -436,7 +430,7 @@ function PlaceholderType(props) {
case "dropdown":
return props.data?.signerObjId === props.signerObjId ? (
<select
className={`${selectWidgetCls} text-[12px]`}
className={`${selectWidgetCls} text-[12px] bg-inherit`}
id="myDropdown"
value={selectOption}
onChange={(e) => {
@@ -466,10 +460,7 @@ function PlaceholderType(props) {
})}
</select>
) : (
<div
className={selectWidgetCls}
style={{ fontSize: calculateFontSize() }}
>
<div className="text-[12px] overflow-hidden">
{props.pos?.options?.name ? props.pos.options.name : type}
</div>
);
@@ -528,7 +519,9 @@ function PlaceholderType(props) {
fontSize: props.pos.options?.fontSize
? props.pos.options?.fontSize + "px"
: "12px",
color: props.pos.options?.fontColor || "black"
color: props.pos.options?.fontColor || "black",
fontFamily: "Arial, sans-serif",
overflow: "hidden"
}}
>
<span>{type}</span>
@@ -570,7 +563,9 @@ function PlaceholderType(props) {
fontSize: props.pos.options?.fontSize
? props.pos.options?.fontSize + "px"
: "12px",
color: props.pos.options?.fontColor || "black"
color: props.pos.options?.fontColor || "black",
overflow: "hidden",
fontFamily: "Arial, sans-serif"
}}
>
<span>{type}</span>
@@ -612,7 +607,9 @@ function PlaceholderType(props) {
fontSize: props.pos.options?.fontSize
? props.pos.options?.fontSize + "px"
: "12px",
color: props.pos.options?.fontColor || "black"
color: props.pos.options?.fontColor || "black",
fontFamily: "Arial, sans-serif",
overflow: "hidden"
}}
>
<span>{type}</span>
@@ -678,7 +675,7 @@ function PlaceholderType(props) {
/>
</div>
) : (
<div className="text-[12px] text-black uppercase items-center">
<div className="text-[12px] text-black items-center overflow-hidden">
<span>
{props.selectDate
? props.selectDate?.format
@@ -733,7 +730,8 @@ function PlaceholderType(props) {
fontSize: props.pos.options?.fontSize
? props.pos.options?.fontSize + "px"
: "12px",
color: props.pos.options?.fontColor || "black"
color: props.pos.options?.fontColor || "black",
fontFamily: "Arial, sans-serif"
}}
cols="50"
/>
@@ -743,7 +741,9 @@ function PlaceholderType(props) {
fontSize: props.pos.options?.fontSize
? props.pos.options?.fontSize + "px"
: "12px",
color: props.pos.options?.fontColor || "black"
color: props.pos.options?.fontColor || "black",
fontFamily: "Arial, sans-serif",
overflow: "hidden"
}}
>
<span>{type}</span>
@@ -802,6 +802,7 @@ function PlaceholderType(props) {
}}
className={textWidgetCls}
style={{
fontFamily: "Arial, sans-serif",
fontSize: props.pos.options?.fontSize
? props.pos.options?.fontSize + "px"
: "12px",
+10 -8
View File
@@ -3,6 +3,7 @@ import RSC from "react-scrollbars-custom";
import { Document, Page } from "react-pdf";
import {
defaultWidthHeight,
getContainerScale,
handleImageResize,
handleSignYourselfImageResize
} from "../../constant/Utils";
@@ -68,10 +69,11 @@ function RenderPdf({
// handle signature block width and height according to screen
const posWidth = (pos, signYourself) => {
const getPdfPageWidth = pdfOriginalWH.find(
(data) => data.pageNumber === pageNumber
const containerScale = getContainerScale(
pdfOriginalWH,
pageNumber,
containerWH
);
const containerScale = containerWH.width / getPdfPageWidth.width || 1;
const defaultWidth = defaultWidthHeight(pos.type).width;
const posWidth = pos.Width ? pos.Width : defaultWidth;
if (signYourself) {
@@ -97,11 +99,11 @@ function RenderPdf({
}
};
const posHeight = (pos, signYourself) => {
const getPdfPageWidth = pdfOriginalWH.find(
(data) => data.pageNumber === pageNumber
const containerScale = getContainerScale(
pdfOriginalWH,
pageNumber,
containerWH
);
const containerScale = containerWH.width / getPdfPageWidth?.width || 1;
const posHeight = pos.Height || defaultWidthHeight(pos.type).height;
if (signYourself) {
return posHeight * scale * containerScale;
@@ -577,7 +579,7 @@ function RenderPdf({
{/* this component for render pdf document is in middle of the component */}
<Document
onLoadError={() => {
pdfLoad(false);
setPdfLoad(false);
}}
loading={"Loading Document.."}
onLoadSuccess={pageDetails}
+10 -5
View File
@@ -1,6 +1,5 @@
import React, { useRef, useState, useEffect } from "react";
import SignatureCanvas from "react-signature-canvas";
function SignPad({
isSignPad,
isStamp,
@@ -99,7 +98,12 @@ function SignPad({
} else {
if (isTab === "type") {
setIsSignImg("");
onSaveSign(null, false, textWidth, textHeight);
onSaveSign(
null,
false,
!isInitial && textWidth > 150 ? 150 : textWidth,
!isInitial && textHeight > 35 ? 35 : textHeight
);
} else {
setIsSignImg("");
canvasRef.current.clear();
@@ -211,11 +215,11 @@ function SignPad({
: fontSelect
? fontSelect
: "Fasthand";
const fontSizeValue = "40px";
//creating span for getting text content width
const span = document.createElement("span");
span.textContent = textContent;
span.style.font = `20px ${fontfamily}`; // here put your text size and font family
span.style.font = `${fontSizeValue} ${fontfamily}`; // here put your text size and font family
span.style.color = color ? color : penColor;
span.style.display = "hidden";
document.body.appendChild(span); // Replace 'container' with the ID of the container element
@@ -225,7 +229,8 @@ function SignPad({
// Draw the text content on the canvas
const ctx = canvasElement.getContext("2d");
const pixelRatio = window.devicePixelRatio || 1;
const width = span.offsetWidth;
const addExtraWidth = isInitial ? 10 : 50;
const width = span.offsetWidth + addExtraWidth;
const height = span.offsetHeight;
setTextWidth(width);
setTextHeight(height);
@@ -54,7 +54,7 @@ export default function DropboxChooser({ children, onSuccess, onCancel }) {
return (
<div onClick={handleChoose}>
{children || (
<button className="px-2 py-[2px] text-2xl rounded border-[1px] text-blue-400 border-gray-300 w-full">
<button className="cursor-pointer op-input op-input-bordered focus:outline-none hover:border-base-content max-h-[35px] max-w-[45px] flex justify-center items-center">
<i className="fa-brands fa-dropbox"></i>
</button>
)}
+138 -81
View File
@@ -6,8 +6,9 @@ import Parse from "parse";
import { appInfo } from "./appinfo";
import { saveAs } from "file-saver";
import printModule from "print-js";
import { validplan } from "../json/plansArr";
export const fontsizeArr = [7, 8, 9, 10, 11, 12, 13, 14, 15, 18];
export const fontsizeArr = [2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28];
export const fontColorArr = ["red", "black", "blue", "yellow"];
export const isMobile = window.innerWidth < 767;
export const isTabAndMobile = window.innerWidth < 1023;
@@ -90,13 +91,7 @@ export async function checkIsSubscribedTeam() {
if (res.plan === "freeplan") {
return false;
} else if (res.billingDate) {
const plan =
res.plan === "team-weekly" ||
res.plan === "team-yearly" ||
res.plan === "teams-monthly" ||
res.plan === "teams-yearly" ||
res.plan === "enterprise-monthly" ||
res.plan === "enterprise-yearly";
const plan = validplan[res.plan] || false;
if (plan && new Date(res.billingDate) > new Date()) {
return true;
} else {
@@ -192,32 +187,19 @@ export const pdfNewWidthFun = (divRef) => {
};
//`contractUsers` function is used to get contract_User details
export const contractUsers = async (email) => {
const data = {
email: email
};
const userDetails = await axios
.post(`${localStorage.getItem("baseUrl")}functions/getUserDetails`, data, {
headers: {
"Content-Type": "application/json",
"X-Parse-Application-Id": localStorage.getItem("parseAppId"),
sessionToken: localStorage.getItem("accesstoken")
}
})
.then((Listdata) => {
const json = Listdata.data;
let data = [];
if (json && json.result) {
data.push(json.result);
}
return data;
})
.catch((err) => {
console.log("Err in getUserDetails cloud function", err);
return "Error: Something went wrong!";
});
return userDetails;
export const contractUsers = async () => {
try {
const userDetails = await Parse.Cloud.run("getUserDetails");
let data = [];
if (userDetails) {
const json = JSON.parse(JSON.stringify(userDetails));
data.push(json);
}
return data;
} catch (err) {
console.log("Err in getUserDetails cloud function", err);
return "Error: Something went wrong!";
}
};
//function for resize image and update width and height for mulitisigners
@@ -458,7 +440,7 @@ export const resizeBorderExtraWidth = () => {
return 20;
};
export async function getBase64FromUrl(url) {
export async function getBase64FromUrl(url, autosign) {
const data = await fetch(url);
const blob = await data.blob();
return new Promise((resolve) => {
@@ -466,8 +448,12 @@ export async function getBase64FromUrl(url) {
reader.readAsDataURL(blob);
reader.onloadend = function () {
const pdfBase = this.result;
const suffixbase64 = pdfBase.split(",").pop();
resolve(suffixbase64);
if (autosign) {
resolve(pdfBase);
} else {
const suffixbase64 = pdfBase.split(",").pop();
resolve(suffixbase64);
}
};
});
}
@@ -550,20 +536,17 @@ export const signPdfFun = async (
base64Url,
documentId,
signerObjectId,
setIsAlert,
objectId,
isSubscribed,
activeMailAdapter,
xyPosition
widgets
) => {
let singleSign,
isCustomCompletionMail = false;
let isCustomCompletionMail = false;
try {
//get tenant details
const tenantDetails = await getTenantDetails(objectId);
if (tenantDetails && tenantDetails === "user does not exist!") {
alert("User does not exist");
return { status: "error", message: "User does not exist." };
} else {
if (
tenantDetails?.CompletionBody &&
@@ -577,7 +560,7 @@ export const signPdfFun = async (
// below for loop is used to get first signature of user to send if to signpdf
// for adding it in completion certificate
let getSignature;
for (let item of xyPosition) {
for (let item of widgets) {
if (!getSignature) {
const typeExist = item.pos.some((data) => data?.type);
if (typeExist) {
@@ -596,14 +579,15 @@ export const signPdfFun = async (
base64Sign = await fetchImageBase64(base64Sign);
} catch (e) {
console.log("error", e);
return { status: "error", message: "something went wrong." };
}
}
//change image width and height to 104/44 in png base64
//change image width and height to 100/40 in png base64
const getNewse64 = await changeImageWH(base64Sign);
//remove suffiix of base64
const suffixbase64 = getNewse64 && getNewse64.split(",").pop();
singleSign = {
const params = {
mailProvider: activeMailAdapter,
pdfFile: base64Url,
docId: documentId,
@@ -611,34 +595,25 @@ export const signPdfFun = async (
isCustomCompletionMail: isCustomCompletionMail,
signature: suffixbase64
};
const response = await axios
.post(`${localStorage.getItem("baseUrl")}functions/signPdf`, singleSign, {
headers: {
"Content-Type": "application/json",
"X-Parse-Application-Id": localStorage.getItem("parseAppId"),
// sessionToken: localStorage.getItem("accesstoken")
"X-Parse-Session-Token": localStorage.getItem("accesstoken")
}
})
.then((Listdata) => {
const json = Listdata.data;
const res = json.result;
return res;
})
.catch((err) => {
console.log("Err in signPdf cloud function ", err);
setIsAlert({
isShow: true,
alertMessage: "something went wrong"
});
});
return response;
const resSignPdf = await Parse.Cloud.run("signPdf", params);
if (resSignPdf) {
const signedPdf = JSON.parse(JSON.stringify(resSignPdf));
return signedPdf;
}
} catch (e) {
setIsAlert({
isShow: true,
alertMessage: "something went wrong"
});
console.log("Err in signPdf cloud function ", e.message);
if (e && e?.message?.includes("is encrypted.")) {
return {
status: "error",
message: "Currently encrypted pdf files are not supported."
};
} else if (
e.message === "PKCS#12 MAC could not be verified. Invalid password?"
) {
return { status: "error", message: "PFX file password is invalid." };
} else {
return { status: "error", message: "something went wrong." };
}
}
};
@@ -1238,9 +1213,8 @@ export const changeImageWH = async (base64Image) => {
const ctx = canvas.getContext("2d");
canvas.width = newWidth;
canvas.height = newHeight;
ctx.imageSmoothingEnabled = false;
ctx.drawImage(img, 0, 0, newWidth, newHeight);
const resizedBase64 = canvas.toDataURL("image/png", 1);
const resizedBase64 = canvas.toDataURL("image/png", 1.0);
resolve(resizedBase64);
};
img.onerror = (error) => {
@@ -1249,14 +1223,30 @@ export const changeImageWH = async (base64Image) => {
});
};
//function to calculate font size of text area widgets
const calculateFontSize = (position, containerScale, signyourself) => {
const font = position?.options?.fontSize || 12;
if (!signyourself && position?.isMobile && position?.scale) {
return font / position?.scale / containerScale;
} else {
return font / containerScale;
}
};
//function for embed multiple signature using pdf-lib
export const multiSignEmbed = async (
xyPositionArray,
widgets,
pdfDoc,
signyourself,
scale
scale,
pdfOriginalWH,
containerWH
) => {
for (let item of xyPositionArray) {
for (let item of widgets) {
const containerScale = getContainerScale(
pdfOriginalWH,
item?.pageNumber,
containerWH
);
const typeExist = item.pos.some((data) => data?.type);
let updateItem;
@@ -1416,7 +1406,13 @@ export const multiSignEmbed = async (
}
} else if (widgetTypeExist) {
const font = await pdfDoc.embedFont("Helvetica");
const fontSize = parseInt(position?.options?.fontSize) || 12;
const fontSize = calculateFontSize(
position,
containerScale,
signyourself
);
parseInt(fontSize);
const color = position?.options?.fontColor;
let updateColorInRgb;
if (color === "red") {
@@ -1591,7 +1587,7 @@ export const multiSignEmbed = async (
});
}
const pdfBytes = await pdfDoc.saveAsBase64({ useObjectStreams: false });
// console.log("pdf", pdfBytes);
//console.log("pdf", pdfBytes);
return pdfBytes;
};
@@ -1957,6 +1953,20 @@ export const handleSendOTP = async (email) => {
alert(error.message);
}
};
export const fetchUrl = async (url, pdfName) => {
try {
const response = await fetch(url);
if (!response.ok) {
alert("something went wrong, please try again later.");
throw new Error("Network response was not ok");
}
const blob = await response.blob();
saveAs(blob, `${sanitizeFileName(pdfName)}_signed_by_OpenSign™.pdf`);
} catch (error) {
alert("something went wrong, please try again later.");
console.error("Error downloading the file:", error);
}
};
//handle download signed pdf
export const handleDownloadPdf = async (
pdfDetails,
@@ -1979,7 +1989,7 @@ export const handleDownloadPdf = async (
}
);
const url = axiosRes.data.result;
saveAs(url, `${sanitizeFileName(pdfName)}_signed_by_OpenSign™.pdf`);
await fetchUrl(url, pdfName);
setIsDownloading("");
} catch (err) {
console.log("err in getsignedurl", err);
@@ -2211,3 +2221,50 @@ function getImagePosition(page, image, sizeRatio) {
rotate: page.getRotation()
};
}
//function to use calculate pdf rendering scale in the container
export const getContainerScale = (pdfOriginalWH, pageNumber, containerWH) => {
const getPdfPageWidth = pdfOriginalWH.find(
(data) => data.pageNumber === pageNumber
);
const containerScale = containerWH?.width / getPdfPageWidth?.width || 1;
return containerScale;
};
//function to get default signatur eof current user from `contracts_Signature` class
export const getDefaultSignature = async (objectId) => {
try {
const result = await axios.get(
`${localStorage.getItem(
"baseUrl"
)}classes/contracts_Signature?where={"UserId": {"__type": "Pointer","className": "_User", "objectId":"${objectId}"}}`,
{
headers: {
"Content-Type": "application/json",
"X-Parse-Application-Id": localStorage.getItem("parseAppId"),
"X-Parse-Session-Token": localStorage.getItem("accesstoken")
}
}
);
const res = result.data?.results;
if (res[0] && res.length > 0) {
const defaultSignature = res[0]?.ImageURL
? await getBase64FromUrl(res[0]?.ImageURL, true)
: "";
const defaultInitial = res[0]?.Initials
? await getBase64FromUrl(res[0]?.Initials, true)
: "";
return {
status: "success",
res: {
defaultSignature: defaultSignature,
defaultInitial: defaultInitial
}
};
}
} catch (err) {
console.log("Error: error in fetch data in contracts_Signature", err);
return {
status: "error"
};
}
};
+7 -7
View File
@@ -4,10 +4,10 @@ export const documentCls = "contracts_Document";
export const themeColor = "#47a3ad";
export const iconColor = "#686968";
export const emailRegex = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;
export const isEnableSubscription = true;
// process.env.REACT_APP_ENABLE_SUBSCRIPTION &&
// process.env.REACT_APP_ENABLE_SUBSCRIPTION?.toLowerCase() === "true"
// ? true
// : false;
export const isStaging = "http://localhost:3001";
// window.location.origin === "https://staging-app.opensignlabs.com";
export const isEnableSubscription =
process.env.REACT_APP_ENABLE_SUBSCRIPTION &&
process.env.REACT_APP_ENABLE_SUBSCRIPTION?.toLowerCase() === "true"
? true
: false;
export const isStaging =
window.location.origin === "https://staging-app.opensignlabs.com";
+95 -31
View File
@@ -26,6 +26,27 @@ const plans = [
"Decline document support",
"Email notifications",
"Recipient authentication using OTP",
"Bulk send (upto 5 docs)",
"Public profiles",
"And much more"
],
yearlyBenefits: [
"Unlimited envelopes",
"Sign documents yourself",
"Request signatures from others",
"14 field types",
"Automatic e-signatures",
"Completion certificates",
"Send in order",
"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"
]
},
@@ -34,7 +55,7 @@ const plans = [
img: "professional.png",
currency: "$",
monthlyPrice: "29.99",
yearlyPrice: `10 <sup style="font-size: 17px;">/month/user</sup>`,
yearlyPrice: `9.99<sup style="font-size: 17px;">/month</sup>`,
subtitle: "Exclusive Access to advanced features.",
btn: { text: "Subscribe", color: "op-btn-primary" },
url: isStaging
@@ -53,9 +74,64 @@ const plans = [
"Zapier integration",
"API Access",
"100 API signatures included",
"DocumentId removal from signed docs",
"Custom email templates",
"Auto reminders"
"Auto reminders",
"Bulk send (upto 20 docs)",
"Premium Public profile usernames",
"Embedding (coming soon)"
],
yearlyBenefits: [
"Everything in OpenSign™ free",
"Field validations",
"Regular expression validations",
"Organize docs in OpenSign™ Drive",
"Webhooks",
"Zapier integration",
"API Access",
"240 API signatures included",
"Custom email templates",
"Auto reminders",
"Bulk send (upto 20 docs)",
"Premium Public profile usernames",
"Embedding (coming soon)"
]
},
{
planName: "OPENSIGN™ TEAMS",
img: "teams.png",
currency: "$",
monthlyPrice: `39.99<sup style="font-size: 17px;">/user</sup>`,
yearlyPrice: `19.99<sup style="font-size: 17px;">/user/month</sup>`,
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.opensignlabs.com/subscribe/ef798486e6a0a11ea65f2bae8f2af901237d0702bfaa959406306635d80f138c/teams-monthly",
yearlyUrl: isStaging
? "https://billing.zoho.in/subscribe/ed8097273a82b6bf39892c11a3bb3c381eb2705736014cfbdbde1ccf1c7a189d/team-weekly"
: "https://billing.opensignlabs.com/subscribe/ef798486e6a0a11ea65f2bae8f2af9011a864994bbeeec71fcf106188630199d/teams-yearly",
target: "_self",
benefits: [
"Everything in OpenSign™ professional",
"100 API signatures included",
"Teams and Organizations",
"Share Templates with teams",
"Share Templates with individuals",
"DocumentId removal from signed docs",
"Bulk send (upto 50 docs)",
"Request Payments (coming soon)",
"Mobile app (coming soon)"
],
yearlyBenefits: [
"Everything in OpenSign™ professional",
"500 API signatures included",
"Teams and Organizations",
"Share Templates with teams",
"Share Templates with individuals",
"DocumentId removal from signed docs",
"Bulk send (upto 50 docs)",
"Request Payments (coming soon)",
"Mobile app (coming soon)"
]
},
{
@@ -75,36 +151,24 @@ const plans = [
"Uptime SLA",
"SSO support",
"Priority support"
],
yearlyBenefits: [
"All features",
"Custom domain",
"Custom branding",
"Uptime SLA",
"SSO support",
"Priority support"
]
}
];
export const stagingPlan = {
planName: "OPENSIGN™ TEAMS",
img: "teams.png",
currency: "$",
monthlyPrice: "40",
yearlyPrice: `20 <sup style="font-size: 17px;">/month/user</sup>`,
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.opensignlabs.com/subscribe/ef798486e6a0a11ea65f2bae8f2af901d1a09dfa8085585cdd4ec4d7f32137f3/professional-monthly",
yearlyUrl: isStaging
? "https://billing.zoho.in/subscribe/ed8097273a82b6bf39892c11a3bb3c381eb2705736014cfbdbde1ccf1c7a189d/team-weekly"
: "https://billing.opensignlabs.com/subscribe/ef798486e6a0a11ea65f2bae8f2af901d8ad1135190dff951330360e47585a71/professional-yearly",
target: "_self",
benefits: [
"Everything in OpenSign™ free, professional",
"Field validations",
"Regular expression validations",
"Organize docs in OpenSign™ Drive",
"Webhooks",
"Zapier integration",
"API Access",
"100 API signatures included",
"DocumentId removal from signed docs",
"Custom email templates",
"Auto reminders"
]
export const validplan = {
"team-weekly": true,
"team-yearly": true,
"teams-monthly": true,
"teams-yearly": true,
"enterprise-monthly": true,
"enterprise-yearly": true
};
export default plans;
+3 -6
View File
@@ -40,7 +40,7 @@ const HomeLayout = () => {
try {
// Use the session token to validate the user
const userQuery = new Parse.Query(Parse.User);
const user = await userQuery.get(Parse.User.current().id, {
const user = await userQuery.get(Parse?.User?.current()?.id, {
sessionToken: localStorage.getItem("accesstoken")
});
if (user) {
@@ -212,10 +212,7 @@ const HomeLayout = () => {
};
async function checkTourStatus() {
const currentUser = Parse.User.current();
const cloudRes = await Parse.Cloud.run("getUserDetails", {
email: currentUser.get("email")
});
const cloudRes = await Parse.Cloud.run("getUserDetails");
const res = { data: cloudRes.toJSON() };
if (res.data && res.data.TourStatus && res.data.TourStatus.length > 0) {
const tourStatus = res.data.TourStatus;
@@ -246,7 +243,7 @@ const HomeLayout = () => {
const handleLoginBtn = () => {
try {
Parse.User.logOut();
Parse?.User?.logOut();
} catch (err) {
console.log("err ", err);
} finally {
+1 -4
View File
@@ -165,10 +165,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) {
+3 -3
View File
@@ -643,9 +643,9 @@ const Forms = (props) => {
<span className="text-red-500 text-[13px]">*</span>
</label>
{fileupload.length > 0 ? (
<div className="flex gap-2 justify-center items-center">
<div className="flex gap-1 justify-center items-center">
<div className="flex justify-between items-center op-input op-input-bordered op-input-sm w-full h-full text-[13px]">
<div className="break-all">
<div className="break-all cursor-default">
file selected: {getFileName(fileupload)}
</div>
<div
@@ -663,7 +663,7 @@ const Forms = (props) => {
)}
</div>
) : (
<div className="flex gap-2 justify-center items-center ">
<div className="flex gap-1 justify-center items-center">
<input
type="file"
className="op-file-input op-file-input-bordered op-file-input-sm focus:outline-none hover:border-base-content w-full text-xs"
+2 -1
View File
@@ -124,8 +124,9 @@ function GuestLogin() {
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`,
+10 -18
View File
@@ -44,16 +44,11 @@ function Login() {
const [isLoginSSO, setIsLoginSSO] = useState(false);
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") {
navigate("/addadmin");
@@ -63,6 +58,11 @@ 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;
@@ -93,10 +93,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;
@@ -279,10 +276,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;
@@ -408,9 +402,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) {
+1 -4
View File
@@ -496,10 +496,7 @@ 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 cloudRes = await Parse.Cloud.run("getUserDetails");
const res = { data: cloudRes.toJSON() };
if (res.data && res.data.TourStatus && res.data.TourStatus.length > 0) {
const tourStatus = res.data.TourStatus;
File diff suppressed because it is too large Load Diff
+2 -7
View File
@@ -71,9 +71,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_", "");
@@ -230,10 +228,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) {
+13 -11
View File
@@ -33,7 +33,8 @@ import {
replaceMailVaribles,
copytoData,
fetchSubscription,
convertPdfArrayBuffer
convertPdfArrayBuffer,
getContainerScale
} from "../constant/Utils";
import RenderPdf from "../components/pdf/RenderPdf";
import { useNavigate } from "react-router-dom";
@@ -403,8 +404,7 @@ function PlaceHolderSign() {
};
setIsLoading(loadObj);
}
const currentUserEmail = documentData[0]?.ExtUserPtr?.Email;
const res = await contractUsers(currentUserEmail);
const res = await contractUsers();
if (res === "Error: Something went wrong!") {
const loadObj = {
isLoad: false
@@ -452,10 +452,11 @@ function PlaceHolderSign() {
setZIndex(posZIndex);
const signer = signersdata.find((x) => x.Id === uniqueId);
const key = randomId();
const getPdfPageWidth = pdfOriginalWH.find(
(data) => data.pageNumber === pageNumber
const containerScale = getContainerScale(
pdfOriginalWH,
pageNumber,
containerWH
);
const containerScale = containerWH?.width / getPdfPageWidth?.width || 1;
let dropData = [];
let placeHolder;
const dragTypeValue = item?.text ? item.text : monitor.type;
@@ -676,11 +677,11 @@ function PlaceHolderSign() {
updateSignPos.splice(0, updateSignPos.length, ...dataNewPlace);
const signId = signerId ? signerId : uniqueId; //? signerId : signerObjId;
const keyValue = key ? key : dragKey;
const getPdfPageWidth = pdfOriginalWH.find(
(data) => data.pageNumber === pageNumber
const containerScale = getContainerScale(
pdfOriginalWH,
pageNumber,
containerWH
);
const containerScale = containerWH.width / getPdfPageWidth?.width;
if (keyValue >= 0) {
let filterSignerPos;
if (signId) {
@@ -851,13 +852,14 @@ function PlaceHolderSign() {
const pdfDoc = await PDFDocument.load(existingPdfBytes, {
ignoreEncryption: true
});
const isSignYourSelfFlow = false;
try {
const pdfBytes = await multiSignEmbed(
placeholder,
pdfDoc,
isSignYourSelfFlow,
scale,
pdfOriginalWH,
containerWH
);
+14 -12
View File
@@ -1,12 +1,11 @@
import React, { useState, useEffect } from "react";
import { useNavigate } from "react-router-dom";
import checkmark from "../assets/images/checkmark.png";
import plansArr, { stagingPlan } from "../json/plansArr";
import plansArr from "../json/plansArr";
import Title from "../components/Title";
import Parse from "parse";
import { openInNewTab } from "../constant/Utils";
import Loader from "../primitives/Loader";
import { isStaging } from "../constant/const";
const listItemStyle = {
paddingLeft: "20px", // Add padding to create space for the image
backgroundImage: `url(${checkmark})`, // Set your image as the list style image
@@ -17,7 +16,6 @@ const listItemStyle = {
const PlanSubscriptions = () => {
const navigate = useNavigate();
const isTeamPlan = plansArr.some((x) => x.planName === "OPENSIGN™ TEAMS");
const [yearlyVisible, setYearlyVisible] = useState(true);
const [isLoader, setIsLoader] = useState(true);
const extUser =
@@ -61,9 +59,6 @@ const PlanSubscriptions = () => {
phone;
useEffect(() => {
setIsLoader(false);
if (!isTeamPlan && isStaging) {
plansArr.splice(2, 0, stagingPlan);
}
// eslint-disable-next-line
}, []);
@@ -123,7 +118,7 @@ const PlanSubscriptions = () => {
role="tab"
className={`${yearlyVisible ? "op-tab-active" : ""} op-tab`}
>
Yearly (10% off)
Yearly (upto 66% off)
</a>
</div>
<ul className="op-card flex flex-col md:flex-row h-full bg-base-100 justify-center shadow-lg">
@@ -209,11 +204,18 @@ const PlanSubscriptions = () => {
</div>
<hr className="w-full bg-gray-300 h-[0.5px]" />
<ul className="mx-1 p-3 text-left break-words text-sm list-none">
{item.benefits.map((subitem, index) => (
<li style={listItemStyle} key={index} className="m-1">
<span className="relative">{subitem}</span>
</li>
))}
{!yearlyVisible &&
item.benefits.map((subitem, index) => (
<li style={listItemStyle} key={index} className="m-1">
<span className="relative">{subitem}</span>
</li>
))}
{yearlyVisible &&
item?.yearlyBenefits?.map((subitem, index) => (
<li style={listItemStyle} key={index} className="m-1">
<span className="relative">{subitem}</span>
</li>
))}
</ul>
</li>
))}
+1 -4
View File
@@ -149,10 +149,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;
+1 -4
View File
@@ -192,10 +192,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;
+156 -161
View File
@@ -32,7 +32,9 @@ import {
textInputWidget,
fetchImageBase64,
changeImageWH,
handleSendOTP
handleSendOTP,
getContainerScale,
getDefaultSignature
} from "../constant/Utils";
import { useParams } from "react-router-dom";
import Tour from "reactour";
@@ -204,131 +206,91 @@ function SignYourSelf() {
}, [divRef.current, isHeader]);
//function for get document details for perticular signer with signer'object id
const getDocumentDetails = async (showComplete) => {
let isCompleted;
//getting document details
const documentData = await contractDocument(documentId);
try {
let isCompleted;
//getting document details
const documentData = await contractDocument(documentId);
if (documentData && documentData.length > 0) {
setPdfDetails(documentData);
setExtUserId(documentData[0]?.ExtUserPtr?.objectId);
const url = documentData[0] && documentData[0]?.URL;
if (url) {
//convert document url in array buffer format to use embed widgets in pdf using pdf-lib
const arrayBuffer = await convertPdfArrayBuffer(url);
if (arrayBuffer === "Error") {
if (documentData && documentData.length > 0) {
setPdfDetails(documentData);
setExtUserId(documentData[0]?.ExtUserPtr?.objectId);
const url = documentData[0] && documentData[0]?.URL;
if (url) {
//convert document url in array buffer format to use embed widgets in pdf using pdf-lib
const arrayBuffer = await convertPdfArrayBuffer(url);
if (arrayBuffer === "Error") {
setHandleError("Error: Something went wrong!");
} else {
setPdfArrayBuffer(arrayBuffer);
}
} else {
setHandleError("Error: Something went wrong!");
} else {
setPdfArrayBuffer(arrayBuffer);
}
} else {
setHandleError("Error: Something went wrong!");
}
isCompleted = documentData[0].IsCompleted && documentData[0].IsCompleted;
if (isCompleted) {
setIsCelebration(true);
setTimeout(() => {
setIsCelebration(false);
}, 5000);
setIsCompleted(true);
setPdfUrl(documentData[0].SignedUrl);
const alreadySign = {
status: true,
mssg: "Congratulations! 🎉 This document has been successfully signed by you!"
};
if (showComplete) {
setShowAlreadySignDoc(alreadySign);
} else {
setIsUiLoading(false);
setIsSignPad(false);
setIsEmail(true);
setXyPostion([]);
setSignBtnPosition([]);
}
}
} else if (
documentData === "Error: Something went wrong!" ||
(documentData.result && documentData.result.error)
) {
const loadObj = {
isLoad: false
};
setHandleError("Error: Something went wrong!");
setIsLoading(loadObj);
} else {
setHandleError("No Data Found!");
const loadObj = {
isLoad: false
};
setIsLoading(loadObj);
}
await axios
.get(
`${localStorage.getItem(
"baseUrl"
)}classes/contracts_Signature?where={"UserId": {"__type": "Pointer","className": "_User", "objectId":"${
jsonSender.objectId
}"}}`,
{
headers: {
"Content-Type": "application/json",
"X-Parse-Application-Id": localStorage.getItem("parseAppId"),
"X-Parse-Session-Token": localStorage.getItem("accesstoken")
isCompleted =
documentData[0].IsCompleted && documentData[0].IsCompleted;
if (isCompleted) {
setIsCelebration(true);
setTimeout(() => {
setIsCelebration(false);
}, 5000);
setIsCompleted(true);
setPdfUrl(documentData[0].SignedUrl);
const alreadySign = {
status: true,
mssg: "Congratulations! 🎉 This document has been successfully signed by you!"
};
if (showComplete) {
setShowAlreadySignDoc(alreadySign);
} else {
setIsUiLoading(false);
setIsSignPad(false);
setIsEmail(true);
setXyPostion([]);
setSignBtnPosition([]);
}
}
)
.then((Listdata) => {
const json = Listdata.data;
const res = json.results;
if (res[0] && res.length > 0) {
setDefaultSignImg(res[0].ImageURL);
setMyInitial(res[0]?.Initials);
}
})
.catch((err) => {
console.log("Err ", err);
} else if (
documentData === "Error: Something went wrong!" ||
(documentData.result && documentData.result.error)
) {
const loadObj = {
isLoad: false
};
setHandleError("Error: Something went wrong!");
setIsLoading(loadObj);
});
const contractUsersRes = await contractUsers(jsonSender.email);
if (contractUsersRes === "Error: Something went wrong!") {
const loadObj = {
isLoad: false
};
setHandleError("Error: Something went wrong!");
setIsLoading(loadObj);
} else if (contractUsersRes[0] && contractUsersRes.length > 0) {
setActiveMailAdapter(contractUsersRes[0]?.active_mail_adapter);
setContractName("_Users");
setSignerUserId(contractUsersRes[0].objectId);
const tourstatuss =
contractUsersRes[0].TourStatus && contractUsersRes[0].TourStatus;
if (tourstatuss && tourstatuss.length > 0 && !isCompleted) {
setTourStatus(tourstatuss);
const checkTourRecipients = tourstatuss.filter(
(data) => data.signyourself
);
if (checkTourRecipients && checkTourRecipients.length > 0) {
setCheckTourStatus(checkTourRecipients[0].signyourself);
}
} else {
setCheckTourStatus(true);
setHandleError("No Data Found!");
const loadObj = {
isLoad: false
};
setIsLoading(loadObj);
}
const loadObj = {
isLoad: false
};
setIsLoading(loadObj);
} else if (contractUsersRes.length === 0) {
const contractContactBook = await contactBook(jsonSender.objectId);
if (contractContactBook && contractContactBook.length > 0) {
setContractName("_Contactbook");
setSignerUserId(contractContactBook[0].objectId);
const tourstatuss =
contractContactBook[0].TourStatus &&
contractContactBook[0].TourStatus;
//function to get default signatur eof current user from `contracts_Signature` class
const defaultSignRes = await getDefaultSignature(jsonSender.objectId);
console.log("defaultSignRes", defaultSignRes);
if (defaultSignRes?.status === "success") {
setDefaultSignImg(defaultSignRes?.res?.defaultSignature);
setMyInitial(defaultSignRes?.res?.defaultInitial);
} else if (defaultSignRes?.status === "error") {
setHandleError("Error: Something went wrong!");
setIsLoading({
isLoad: false
});
}
const contractUsersRes = await contractUsers();
if (contractUsersRes === "Error: Something went wrong!") {
const loadObj = {
isLoad: false
};
setHandleError("Error: Something went wrong!");
setIsLoading(loadObj);
} else if (contractUsersRes[0] && contractUsersRes.length > 0) {
setActiveMailAdapter(contractUsersRes[0]?.active_mail_adapter);
setContractName("_Users");
setSignerUserId(contractUsersRes[0].objectId);
const tourstatuss =
contractUsersRes[0].TourStatus && contractUsersRes[0].TourStatus;
if (tourstatuss && tourstatuss.length > 0 && !isCompleted) {
setTourStatus(tourstatuss);
const checkTourRecipients = tourstatuss.filter(
@@ -340,15 +302,47 @@ function SignYourSelf() {
} else {
setCheckTourStatus(true);
}
} else {
setHandleError("No Data Found!");
const loadObj = {
isLoad: false
};
setIsLoading(loadObj);
} else if (contractUsersRes.length === 0) {
const contractContactBook = await contactBook(jsonSender.objectId);
if (contractContactBook && contractContactBook.length > 0) {
setContractName("_Contactbook");
setSignerUserId(contractContactBook[0].objectId);
const tourstatuss =
contractContactBook[0].TourStatus &&
contractContactBook[0].TourStatus;
if (tourstatuss && tourstatuss.length > 0 && !isCompleted) {
setTourStatus(tourstatuss);
const checkTourRecipients = tourstatuss.filter(
(data) => data.signyourself
);
if (checkTourRecipients && checkTourRecipients.length > 0) {
setCheckTourStatus(checkTourRecipients[0].signyourself);
}
} else {
setCheckTourStatus(true);
}
} else {
setHandleError("No Data Found!");
}
const loadObj = {
isLoad: false
};
setIsLoading(loadObj);
}
const loadObj = {
} catch (err) {
console.log("Error: error in getDocumentDetails", err);
setHandleError("Error: Something went wrong!");
setIsLoading({
isLoad: false
};
setIsLoading(loadObj);
});
}
};
const getWidgetValue = (type) => {
switch (type) {
case "name":
@@ -442,6 +436,7 @@ function SignYourSelf() {
};
//function for setting position after drop signature button over pdf
const addPositionOfSignature = (item, monitor) => {
setCurrWidgetsDetails({});
const key = randomId();
let dropData = [];
let dropObj = {};
@@ -453,10 +448,11 @@ function SignYourSelf() {
const widgetTypeExist = ["name", "company", "job title", "email"].includes(
dragTypeValue
);
const getPdfPageWidth = pdfOriginalWH.find(
(data) => data.pageNumber === pageNumber
const containerScale = getContainerScale(
pdfOriginalWH,
pageNumber,
containerWH
);
const containerScale = containerWH?.width / getPdfPageWidth?.width || 1;
//adding and updating drop position in array when user drop signature button in div
if (item === "onclick") {
const getWidth = widgetTypeExist
@@ -694,7 +690,9 @@ function SignYourSelf() {
xyPostion,
pdfDoc,
isSignYourSelfFlow,
scale
scale,
pdfOriginalWH,
containerWH
);
// console.log("pdf", pdfBytes);
//function for call to embed signature in pdf and get digital signature pdf
@@ -705,15 +703,28 @@ function SignYourSelf() {
setIsUiLoading(false);
if (err && err.message.includes("is encrypted.")) {
setIsAlert({
header: "Error",
isShow: true,
alertMessage: `Currently encrypted pdf files are not supported.`
});
} else {
console.log("err in signing", err);
setIsAlert({
isShow: true,
alertMessage: `Something went wrong.`
});
console.log("err in signing", err.message);
if (
err.message ===
"PKCS#12 MAC could not be verified. Invalid password?"
) {
setIsAlert({
header: "Error",
isShow: true,
alertMessage: `PFX file password is invalid.`
});
} else {
setIsAlert({
header: "Error",
isShow: true,
alertMessage: `Something went wrong.`
});
}
}
}
}
@@ -721,6 +732,7 @@ function SignYourSelf() {
console.log("err in embedselfsign ", err);
setIsUiLoading(false);
setIsAlert({
header: "Error",
isShow: true,
alertMessage: "something went wrong, please try again later."
});
@@ -766,39 +778,24 @@ function SignYourSelf() {
console.log("error", e);
}
}
//change image width and height to 104/44 in png base64
//change image width and height to 100/40 in png base64
const getNewse64 = await changeImageWH(base64Sign);
//remove suffiix of base64
const suffixbase64 = getNewse64 && getNewse64.split(",").pop();
let singleSign = {
const params = {
pdfFile: base64Url,
docId: documentId,
isCustomCompletionMail: isCustomCompletionMail,
mailProvider: activeMailAdapter,
signature: suffixbase64
};
await axios
.post(`${localStorage.getItem("baseUrl")}functions/signPdf`, singleSign, {
headers: {
"Content-Type": "application/json",
"X-Parse-Application-Id": localStorage.getItem("parseAppId"),
// sessionToken: localStorage.getItem("accesstoken")
"X-Parse-Session-Token": localStorage.getItem("accesstoken")
}
})
.then((Listdata) => {
const json = Listdata.data;
setPdfUrl(json.result.data);
if (json.result.data) {
getDocumentDetails(false);
}
})
.catch((err) => {
console.log("axois err ", err);
});
const resSignPdf = await Parse.Cloud.run("signPdf", params);
if (resSignPdf) {
const signedpdf = JSON.parse(JSON.stringify(resSignPdf));
setPdfUrl(signedpdf);
getDocumentDetails(false);
}
};
//function for save x and y position and show signature tab on that position
@@ -812,10 +809,11 @@ function SignYourSelf() {
setFontColor();
if (isDragging && dragElement) {
event.preventDefault();
const getPdfPageWidth = pdfOriginalWH.find(
(data) => data.pageNumber === pageNumber
const containerScale = getContainerScale(
pdfOriginalWH,
pageNumber,
containerWH
);
const containerScale = containerWH.width / getPdfPageWidth?.width || 1;
if (dragKey >= 0) {
const filterDropPos = xyPostion.filter(
(data) => data.pageNumber === pageNumber
@@ -1224,16 +1222,13 @@ function SignYourSelf() {
setZoomPercent={setZoomPercent}
zoomPercent={zoomPercent}
/>
<div className=" w-full md:w-[95%] ">
<div className="w-full md:w-[95%]">
<ModalUi
isOpen={isAlert.isShow}
title={isAlert?.header || "Alert"}
handleClose={() => {
setIsAlert({
isShow: false,
alertMessage: ""
});
}}
handleClose={() =>
setIsAlert({ isShow: false, alertMessage: "" })
}
>
<div className="p-[20px] h-full">
<p>{isAlert.alertMessage}</p>
@@ -1308,12 +1303,12 @@ function SignYourSelf() {
isEmail={isEmail}
pdfUrl={pdfUrl}
setIsEmail={setIsEmail}
pdfName={pdfDetails[0] && pdfDetails[0].Name}
setSuccessEmail={setSuccessEmail}
sender={jsonSender}
setIsAlert={setIsAlert}
extUserId={extUserId}
activeMailAdapter={activeMailAdapter}
pdfDetails={pdfDetails}
/>
{/* pdf header which contain funish back button */}
<Header
+1 -1
View File
@@ -163,7 +163,7 @@ const TeamList = () => {
setTeamList(newArray);
try {
await Parse.Cloud.run("updateteam", {
IsActive: !IsActive,
IsActive: !IsActive === false ? "false" : "true",
TeamId: team.objectId
});
// console.log("teamRes ", teamRes);
+18 -33
View File
@@ -24,7 +24,8 @@ import {
addWidgetOptions,
textInputWidget,
radioButtonWidget,
fetchSubscription
fetchSubscription,
getContainerScale
} from "../constant/Utils";
import RenderPdf from "../components/pdf/RenderPdf";
import "../styles/AddUser.css";
@@ -152,14 +153,6 @@ const TemplatePlaceholder = () => {
const [fontColor, setFontColor] = useState();
const [zoomPercent, setZoomPercent] = useState(0);
const [scale, setScale] = useState(1);
const senderUser =
localStorage.getItem(
`Parse/${localStorage.getItem("parseAppId")}/currentUser`
) &&
localStorage.getItem(
`Parse/${localStorage.getItem("parseAppId")}/currentUser`
);
const jsonSender = JSON.parse(senderUser);
useEffect(() => {
fetchTemplate();
@@ -316,7 +309,7 @@ const TemplatePlaceholder = () => {
setHandleError("Error: Something went wrong!");
}
}
const res = await contractUsers(jsonSender.email);
const res = await contractUsers();
if (res[0] && res.length) {
setSignerUserId(res[0].objectId);
setCurrentEmail(res[0].Email);
@@ -364,10 +357,11 @@ const TemplatePlaceholder = () => {
if (signer) {
const posZIndex = zIndex + 1;
setZIndex(posZIndex);
const getPdfPageWidth = pdfOriginalWH.find(
(data) => data.pageNumber === pageNumber
const containerScale = getContainerScale(
pdfOriginalWH,
pageNumber,
containerWH
);
const containerScale = containerWH.width / getPdfPageWidth?.width || 1;
const key = randomId();
let filterSignerPos = signerPos.filter((data) => data.Id === uniqueId);
const dragTypeValue = item?.text ? item.text : monitor.type;
@@ -561,10 +555,11 @@ const TemplatePlaceholder = () => {
updateSignPos.splice(0, updateSignPos.length, ...dataNewPlace);
const signId = signerId; //? signerId : signerObjId;
const keyValue = key ? key : dragKey;
const getPdfPageWidth = pdfOriginalWH.find(
(data) => data.pageNumber === pageNumber
const containerScale = getContainerScale(
pdfOriginalWH,
pageNumber,
containerWH
);
const containerScale = containerWH.width / getPdfPageWidth?.width || 1;
if (keyValue >= 0) {
const filterSignerPos = updateSignPos.filter(
(data) => data.Id === signId
@@ -1314,7 +1309,7 @@ const TemplatePlaceholder = () => {
setZoomPercent={setZoomPercent}
zoomPercent={zoomPercent}
/>
<div className=" w-full md:w-[95%] ">
<div className="w-full md:w-[95%]">
{/* this modal is used show alert set placeholder for all signers before send mail */}
<ModalUi
isOpen={isSendAlert}
@@ -1351,9 +1346,7 @@ const TemplatePlaceholder = () => {
{currentEmail.length > 0 && (
<>
<button
onClick={() => {
handleCreateDocModal();
}}
onClick={() => handleCreateDocModal()}
type="button"
className="op-btn op-btn-primary"
>
@@ -1376,18 +1369,14 @@ const TemplatePlaceholder = () => {
{isCreateDoc && <LoaderWithMsg isLoading={isLoading} />}
<ModalUi
isOpen={isShowEmail}
title={"signers alert"}
handleClose={() => {
setIsShowEmail(false);
}}
title={"Signers alert"}
handleClose={() => setIsShowEmail(false)}
>
<div className="h-full p-[20px]">
<p>Please select signer for add placeholder!</p>
<div className="h-[1px] w-full my-[15px] bg-[#9f9f9f]"></div>
<button
onClick={() => {
setIsShowEmail(false);
}}
onClick={() => setIsShowEmail(false)}
type="button"
className="op-btn op-btn-primary"
>
@@ -1436,7 +1425,6 @@ const TemplatePlaceholder = () => {
allPages={allPages}
pageNumber={pageNumber}
signKey={signKey}
// signerObjId={signerObjId}
Id={uniqueId}
/>
{/* pdf header which contain funish back button */}
@@ -1548,10 +1536,8 @@ const TemplatePlaceholder = () => {
/>
</div>
) : (
<div
className={`w-[23%] bg-[#FFFFFF] min-h-screen overflow-y-auto hide-scrollbar`}
>
<div className={`max-h-screen`}>
<div className="w-[23%] bg-base-100 min-h-screen overflow-y-auto hide-scrollbar">
<div className="max-h-screen">
<SignerListPlace
isMailSend={isMailSend}
signerPos={signerPos}
@@ -1598,7 +1584,6 @@ const TemplatePlaceholder = () => {
</div>
</div>
)}
<div data-tut="reactourAddbtn--observe">
<AddRoleModal
isModalRole={isModalRole}
+3 -3
View File
@@ -221,9 +221,9 @@ const UserList = () => {
<thead className="text-[14px]">
<tr className="border-y-[1px]">
{heading?.map((item, index) => (
<React.Fragment key={index}>
<th className="px-4 py-2">{item}</th>
</React.Fragment>
<th key={index} className="px-4 py-2">
{item}
</th>
))}
</tr>
</thead>
+13 -10
View File
@@ -8,7 +8,11 @@ import sanitizeFileName from "../primitives/sanitizeFileName";
import axios from "axios";
import Tooltip from "../primitives/Tooltip";
import { isEnableSubscription } from "../constant/const";
import { checkIsSubscribed, handleSendOTP } from "../constant/Utils";
import {
checkIsSubscribed,
checkIsSubscribedTeam,
handleSendOTP
} from "../constant/Utils";
import Upgrade from "../primitives/Upgrade";
import ModalUi from "../primitives/ModalUi";
import Loader from "../primitives/Loader";
@@ -46,6 +50,7 @@ function UserProfile() {
const [tagLine, setTagLine] = useState(
extendUser && extendUser?.[0]?.Tagline
);
const [isTeam, setIsTeam] = useState(false);
useEffect(() => {
getUserDetail();
}, []);
@@ -57,7 +62,9 @@ function UserProfile() {
const HeaderDocId = jsonSender[0]?.HeaderDocId;
if (isEnableSubscription) {
const getIsSubscribe = await checkIsSubscribed();
const getIsTeam = await checkIsSubscribedTeam();
setIsSubscribe(getIsSubscribe);
setIsTeam(getIsTeam);
}
if (HeaderDocId) {
setIsDisableDocId(HeaderDocId);
@@ -306,9 +313,7 @@ function UserProfile() {
) : (
<div className="flex justify-center items-center w-full relative">
{userNameError && (
<div
className={`z-[1000] fixed top-[50%] transform border-[1px] text-sm border-[#f0a8a8] bg-[#f4bebe] text-[#c42121] rounded py-[.75rem] px-[1.25rem]`}
>
<div className="z-[1000] fixed top-[50%] transform border-[1px] text-sm border-[#f0a8a8] bg-[#f4bebe] text-[#c42121] rounded py-[.75rem] px-[1.25rem]">
{userNameError}
</div>
)}
@@ -511,9 +516,7 @@ function UserProfile() {
<div className="flex justify-between items-center py-2">
<span
className={
isSubscribe
? "font-semibold"
: "font-semibold text-gray-300"
isTeam ? "font-semibold" : "font-semibold text-gray-300"
}
>
Disable DocumentId :{" "}
@@ -522,17 +525,17 @@ function UserProfile() {
"https://docs.opensignlabs.com/docs/help/Settings/disabledocumentid"
}
/>
{!isSubscribe && isEnableSubscription && <Upgrade />}
{!isTeam && isEnableSubscription && <Upgrade />}
</span>
<label
className={`${
isSubscribe
isTeam
? `${editmode ? "cursor-pointer" : ""}`
: "pointer-events-none opacity-50"
} relative block items-center mb-0`}
>
<input
disabled={editmode ? false : true}
disabled={isTeam ? false : true}
type="checkbox"
className="op-toggle transition-all checked:[--tglbg:#3368ff] checked:bg-white"
checked={isDisableDocId}
+1 -3
View File
@@ -32,14 +32,12 @@ function Webhook() {
}, []);
const fetchWebhook = async () => {
const email = Parse.User.current().getEmail();
if (isEnableSubscription) {
const getIsSubscribe = await checkIsSubscribed();
setIsSubscribe(getIsSubscribe);
}
const params = { email: email };
try {
const extRes = await Parse.Cloud.run("getUserDetails", params);
const extRes = await Parse.Cloud.run("getUserDetails");
if (extRes) {
setWebhook(extRes.get("Webhook"));
}
@@ -10,10 +10,10 @@ import Tooltip from "./Tooltip";
import { RWebShare } from "react-web-share";
import Tour from "reactour";
import Parse from "parse";
import { saveAs } from "file-saver";
import {
checkIsSubscribedTeam,
copytoData,
fetchUrl,
replaceMailVaribles
} from "../constant/Utils";
import Confetti from "react-confetti";
@@ -145,7 +145,7 @@ const ReportTable = (props) => {
try {
const extUser = JSON.parse(localStorage.getItem("Extand_Class"))?.[0];
if (extUser?.OrganizationId?.objectId) {
const teamtRes = await Parse.Cloud.run("getteams");
const teamtRes = await Parse.Cloud.run("getteams", { active: true });
if (teamtRes.length > 0) {
const _teamRes = JSON.parse(JSON.stringify(teamtRes));
const formatedList = _teamRes.map((x) => ({
@@ -526,10 +526,7 @@ const ReportTable = (props) => {
};
async function checkTourStatus() {
const currentUser = Parse.User.current();
const cloudRes = await Parse.Cloud.run("getUserDetails", {
email: currentUser.get("email")
});
const cloudRes = await Parse.Cloud.run("getUserDetails");
const res = { data: cloudRes.toJSON() };
if (res.data && res.data.TourStatus && res.data.TourStatus.length > 0) {
const tourStatus = res.data.TourStatus;
@@ -595,14 +592,18 @@ const ReportTable = (props) => {
// `handleDownload` is used to get valid doc url available in completed report
const handleDownload = async (item) => {
setActLoader({ [`${item.objectId}`]: true });
const url = item?.SignedUrl || item?.URL || "";
const pdfName = item?.Name || "exported_file";
if (url) {
try {
const signedUrl = await Parse.Cloud.run("getsignedurl", { url: url });
saveAs(signedUrl);
await fetchUrl(signedUrl, pdfName);
setActLoader({});
} catch (err) {
console.log("err in getsignedurl", err);
alert("something went wrong, please try again later.");
setActLoader({});
}
}
};
+19 -18
View File
@@ -8,26 +8,27 @@ const Validate = () => {
const [isUserValid, setIsUserValid] = useState(true);
useEffect(() => {
(async () => {
try {
const userDetails = JSON.parse(
localStorage.getItem(
`Parse/${localStorage.getItem("parseAppId")}/currentUser`
)
);
// Use the session token to validate the user
const userQuery = new Parse.Query(Parse.User);
const user = await userQuery.get(userDetails?.objectId, {
sessionToken: localStorage.getItem("accesstoken")
});
if (user) {
setIsUserValid(true);
} else {
if (localStorage.getItem("accesstoken")) {
try {
const userDetails = JSON.parse(
localStorage.getItem(
`Parse/${localStorage.getItem("parseAppId")}/currentUser`
)
);
// Use the session token to validate the user
const userQuery = new Parse.Query(Parse.User);
const user = await userQuery.get(userDetails?.objectId, {
sessionToken: localStorage.getItem("accesstoken")
});
if (user) {
setIsUserValid(true);
} else {
setIsUserValid(false);
}
} catch (error) {
// Session token is invalid or there was an error
setIsUserValid(false);
}
} catch (error) {
// Session token is invalid or there was an error
setIsUserValid(false);
}
})();
+27 -17
View File
@@ -4,29 +4,39 @@ import { Outlet } from "react-router-dom";
const ValidateRoute = () => {
useEffect(() => {
(async () => {
try {
// Use the session token to validate the user
const userQuery = new Parse.Query(Parse.User);
const user = await userQuery.get(Parse.User.current().id, {
sessionToken: localStorage.getItem("accesstoken")
});
if (!user) {
if (localStorage.getItem("accesstoken")) {
try {
// Use the session token to validate the user
const userQuery = new Parse.Query(Parse.User);
const user = await userQuery.get(Parse?.User?.current()?.id, {
sessionToken: localStorage.getItem("accesstoken")
});
if (!user) {
handlelogout();
}
} catch (error) {
console.log("err in validate route", error);
handlelogout();
}
} catch (error) {
handlelogout();
}
})();
}, []);
const handlelogout = async () => {
try {
Parse.User.logOut();
localStorage.removeItem("accesstoken");
} catch (err) {
console.log("err ", err);
} finally {
localStorage.removeItem("accesstoken");
}
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();
localStorage.setItem("appLogo", applogo);
localStorage.setItem("defaultmenuid", defaultmenuid);
localStorage.setItem("PageLanding", PageLanding);
localStorage.setItem("userSettings", appdata);
localStorage.setItem("baseUrl", baseUrl);
localStorage.setItem("parseAppId", appid);
};
return <div>{<Outlet />}</div>;
};
-31
View File
@@ -8,38 +8,7 @@ module.exports = {
daisyui: {
// themes: true,
themes: [
"light",
"dark",
"cupcake",
"bumblebee",
"emerald",
"corporate",
"synthwave",
"retro",
"cyberpunk",
"valentine",
"halloween",
"garden",
"forest",
"aqua",
"lofi",
"pastel",
"fantasy",
"wireframe",
"black",
"luxury",
"dracula",
"cmyk",
"autumn",
"business",
"acid",
"lemonade",
"night",
"coffee",
"winter",
"dim",
"nord",
"sunset",
{
opensigncss: {
primary: "#002864",
+1 -1
View File
@@ -1,5 +1,5 @@
# Use an official Node runtime as the base image
FROM node:18
FROM node:20
# Set the working directory inside the container
WORKDIR /usr/src/app
+2 -1
View File
@@ -4,8 +4,9 @@ dotenv.config();
const appId = process.env.APP_ID;
const serverUrl = process.env.SERVER_URL;
export const cloudServerUrl = 'http://localhost:8080/app';
export function customAPIurl() {
const url = new URL(process.env.SERVER_URL);
const url = new URL(cloudServerUrl);
return url.pathname === '/api/app' ? url.origin + '/api' : url.origin;
}
@@ -1,4 +1,5 @@
import axios from 'axios';
import { cloudServerUrl } from '../../Utils.js';
// `replaceMailVaribles` is used to replace variables from mail with there actual values
function replaceMailVaribles(subject, body, variables) {
@@ -26,7 +27,7 @@ function replaceMailVaribles(subject, body, variables) {
async function sendMail(doc, signer) {
const subject = `{{sender_name}} has requested you to sign "{{document_title}}"`;
const body = `<html><head><meta http-equiv='Content-Type' content='text/html; charset=UTF-8' /></head><body><p>Hi {{receiver_name}},</p><br><p>We hope this email finds you well. {{sender_name}}&nbsp;has requested you to review and sign&nbsp;<b>"{{document_title}}"</b>.</p><p>Your signature is crucial to proceed with the next steps as it signifies your agreement and authorization.</p><br><p>{{signing_url}}</p><br><p>If you have any questions or need further clarification regarding the document or the signing process, please contact the sender.</p><br><p>Thanks</p><p> Team OpenSign™</p><br></body> </html>`;
const url = `${process.env.SERVER_URL}/functions/sendmailv3`;
const url = `${cloudServerUrl}/functions/sendmailv3`;
const headers = {
'Content-Type': 'application/json',
'X-Parse-Application-Id': process.env.APP_ID,
@@ -1,6 +1,7 @@
import axios from 'axios';
import { cloudServerUrl } from '../../Utils.js';
const appId = process.env.APP_ID;
const serverUrl = process.env.SERVER_URL;
const serverUrl = cloudServerUrl; //process.env.SERVER_URL;
export default async function gooogleauth(request, response) {
const code = request.body.code;
const baseUrl = new URL(process.env.SERVER_URL);
@@ -3,7 +3,7 @@ import multer from 'multer';
import multerS3 from 'multer-s3';
import aws from 'aws-sdk';
import dotenv from 'dotenv';
import { useLocal } from '../../Utils.js';
import { cloudServerUrl, useLocal } from '../../Utils.js';
dotenv.config();
function sanitizeFileName(fileName) {
@@ -49,7 +49,7 @@ async function uploadFile(req, res) {
const DO_SECRET_ACCESS_KEY = process.env.DO_SECRET_ACCESS_KEY;
const DO_SPACE = process.env.DO_SPACE;
const parseBaseUrl = process.env.SERVER_URL;
const parseBaseUrl = cloudServerUrl; //process.env.SERVER_URL;
const parseAppId = process.env.APP_ID;
let fileStorage;
if (useLocal === 'true') {
@@ -1,5 +1,5 @@
import axios from 'axios';
import { customAPIurl, replaceMailVaribles } from '../../../../Utils.js';
import { cloudServerUrl, customAPIurl, replaceMailVaribles } from '../../../../Utils.js';
// `sendDoctoWebhook` is used to send res data of document on webhook
async function sendDoctoWebhook(doc, WebhookUrl, userId) {
@@ -220,7 +220,7 @@ export default async function createDocumentWithTemplate(request, response) {
for (let i = 0; i < contactMail.length; i++) {
try {
const imgPng = 'https://qikinnovation.ams3.digitaloceanspaces.com/logo.png';
let url = `${process.env.SERVER_URL}/functions/sendmailv3/`;
let url = `${cloudServerUrl}/functions/sendmailv3/`;
const headers = {
'Content-Type': 'application/json',
'X-Parse-Application-Id': process.env.APP_ID,
@@ -6,6 +6,7 @@ import {
saveFileUsage,
formatWidgetOptions,
sanitizeFileName,
cloudServerUrl,
} from '../../../../Utils.js';
// `sendDoctoWebhook` is used to send res data of document on webhook
@@ -281,7 +282,7 @@ export default async function createDocumentwithCoordinate(request, response) {
for (let i = 0; i < contactMail.length; i++) {
try {
const imgPng = 'https://qikinnovation.ams3.digitaloceanspaces.com/logo.png';
let url = `${process.env.SERVER_URL}/functions/sendmailv3/`;
let url = `${cloudServerUrl}/functions/sendmailv3/`;
const headers = {
'Content-Type': 'application/json',
'X-Parse-Application-Id': process.env.APP_ID,
@@ -1,12 +1,13 @@
import axios from 'axios';
import reportJson from '../../../parsefunction/reportsJson.js';
import dotenv from 'dotenv';
import { cloudServerUrl } from '../../../../Utils.js';
dotenv.config();
export default async function getDocumentList(request, response) {
const reqToken = request.headers['x-api-token'];
const appId = process.env.APP_ID;
const serverUrl = process.env.SERVER_URL;
const serverUrl = cloudServerUrl; //process.env.SERVER_URL;
if (!reqToken) {
return response.status(400).json({ error: 'Please Provide API Token' });
}
@@ -1,10 +1,11 @@
import axios from 'axios';
import dotenv from 'dotenv';
import { cloudServerUrl } from '../../../../Utils.js';
dotenv.config();
export default async function getTemplatetList(request, response) {
const reqToken = request.headers['x-api-token'];
const appId = process.env.APP_ID;
const serverUrl = process.env.SERVER_URL;
const serverUrl = cloudServerUrl; //process.env.SERVER_URL;
if (!reqToken) {
return response.status(400).json({ error: 'Please Provide API Token' });
}
@@ -1,5 +1,5 @@
import axios from 'axios';
import { replaceMailVaribles } from '../../../../Utils.js';
import { cloudServerUrl, replaceMailVaribles } from '../../../../Utils.js';
export default async function resendMail(request, response) {
try {
@@ -44,7 +44,7 @@ export default async function resendMail(request, response) {
if (contact) {
try {
const imgPng = 'https://qikinnovation.ams3.digitaloceanspaces.com/logo.png';
let url = `${process.env.SERVER_URL}/functions/sendmailv3/`;
let url = `${cloudServerUrl}/functions/sendmailv3/`;
const headers = {
'Content-Type': 'application/json',
'X-Parse-Application-Id': process.env.APP_ID,
+4
View File
@@ -58,6 +58,8 @@ import updateOrganization from './parsefunction/updateOrganization.js';
import getTeams from './parsefunction/getTeams.js';
import addTeam from './parsefunction/addTeam.js';
import updateTeam from './parsefunction/updateTeam.js';
import getOrgAdmins from './parsefunction/getOrgAdmins.js';
import getAllUserTeamByOrg from './parsefunction/getAllUserTeamByOrg.js';
// This afterSave function triggers after an object is added or updated in the specified class, allowing for post-processing logic.
Parse.Cloud.afterSave('contracts_Document', DocumentAftersave);
@@ -125,3 +127,5 @@ Parse.Cloud.define('updateorganization', updateOrganization);
Parse.Cloud.define('getteams', getTeams);
Parse.Cloud.define('addteam', addTeam);
Parse.Cloud.define('updateteam', updateTeam);
Parse.Cloud.define('getorgadmins', getOrgAdmins);
Parse.Cloud.define('getalluserteambyorg', getAllUserTeamByOrg);
@@ -1,5 +1,6 @@
import axios from 'axios';
const serverUrl = process.env.SERVER_URL;
import { cloudServerUrl } from '../../Utils.js';
const serverUrl = cloudServerUrl; //process.env.SERVER_URL;
const APPID = process.env.APP_ID;
const masterKEY = process.env.MASTER_KEY;
async function addTeamAndOrg(extUser) {
@@ -1,8 +1,9 @@
import axios from 'axios';
import { cloudServerUrl } from '../../Utils.js';
async function AuthLoginAsMail(request) {
try {
//function for login user using user objectId without touching user's password
const serverUrl = process.env.SERVER_URL;
const serverUrl = cloudServerUrl; //process.env.SERVER_URL;
const APPID = process.env.APP_ID;
const masterKEY = process.env.MASTER_KEY;
@@ -5,6 +5,7 @@ async function DocumentAftersave(request) {
const createdAt = request.object.get('createdAt');
const Folder = request.object.get('Type');
const ip = request?.headers?.['x-real-ip'] || '';
const originIp = request?.object?.get('OriginIp') || '';
if (createdAt && Folder === undefined) {
// console.log("IN If condition")
const TimeToCompleteDays = request.object.get('TimeToCompleteDays') || 15;
@@ -13,7 +14,9 @@ async function DocumentAftersave(request) {
const documentQuery = new Parse.Query('contracts_Document');
const updateQuery = await documentQuery.get(request.object.id, { useMasterKey: true });
updateQuery.set('ExpiryDate', ExpiryDate);
updateQuery.set('OriginIp', ip);
if (!originIp) {
updateQuery.set('OriginIp', ip);
}
const AutoReminder = request?.object?.get('AutomaticReminders') || false;
if (AutoReminder) {
const RemindOnceInEvery = request?.object?.get('RemindOnceInEvery') || 5;
@@ -29,7 +32,9 @@ async function DocumentAftersave(request) {
const documentQuery = new Parse.Query('contracts_Document');
const updateQuery = await documentQuery.get(request.object.id, { useMasterKey: true });
updateQuery.set('ExpiryDate', ExpiryDate);
updateQuery.set('OriginIp', ip);
if (!originIp) {
updateQuery.set('OriginIp', ip);
}
const AutoReminder = request?.object?.get('AutomaticReminders') || false;
if (AutoReminder) {
const RemindOnceInEvery = request?.object?.get('RemindOnceInEvery') || 5;
@@ -1,6 +1,7 @@
import axios from 'axios';
import { cloudServerUrl } from '../../Utils.js';
const serverUrl = process.env.SERVER_URL;
const serverUrl = cloudServerUrl; //process.env.SERVER_URL;
const APPID = process.env.APP_ID;
const masterKEY = process.env.MASTER_KEY;
@@ -19,13 +19,19 @@ async function GetPublicTemplate(request) {
});
templatQuery.descending('updatedAt');
templatQuery.equalTo('IsPublic', true);
templatQuery.notEqualTo('IsArchive', true);
const getTemplate = await templatQuery.find({ useMasterKey: true });
const extend_Res = await Parse.Cloud.run('getUserDetails', {
email: user.get('email'),
});
if (extend_Res) {
return { template: getTemplate, user: user, extend_User: extend_Res };
const extcls = new Parse.Query('contracts_Users');
extcls.equalTo('email', user.get('email'));
const res = await extcls.first({ useMasterKey: true });
if (res) {
const _res = JSON.parse(JSON.stringify(_res));
return {
template: getTemplate,
user: user,
extend_User: { Tagline: _res?.Tagline || '', SearchIndex: _res?.SearchIndex || '' },
};
} else {
throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'Template not found');
}
@@ -1,7 +1,8 @@
import axios from 'axios';
import { cloudServerUrl } from '../../Utils.js';
export default async function GetTemplate(request) {
const serverUrl = process.env.SERVER_URL;
const serverUrl = cloudServerUrl; //process.env.SERVER_URL;
const templateId = request.params.templateId;
const ispublic = request.params.ispublic;
@@ -1,6 +1,7 @@
import axios from 'axios';
import { cloudServerUrl } from '../../Utils.js';
const serverUrl = process.env.SERVER_URL;
const serverUrl = cloudServerUrl; //process.env.SERVER_URL;
const APPID = process.env.APP_ID;
const masterKEY = process.env.MASTER_KEY;
@@ -54,13 +54,14 @@ const createDocumentFromTemplate = async (template, existContact, index) => {
object.set('Name', template?.Name);
object.set('Description', template?.Description);
object.set('Note', template?.Note);
object.set('TimeToCompleteDays', template.TimeToCompleteDays || 15);
object.set('TimeToCompleteDays', template?.TimeToCompleteDays || 15);
object.set('SendinOrder', template?.SendinOrder);
object.set('AutomaticReminders', template.AutomaticReminders);
object.set('RemindOnceInEvery', template?.RemindOnceInEvery);
object.set('AutomaticReminders', template?.AutomaticReminders || false);
object.set('RemindOnceInEvery', template?.RemindOnceInEvery || 5);
object.set('URL', template?.URL);
object.set('CreatedBy', template?.CreatedBy);
object.set('ExtUserPtr', template?.ExtUserPtr);
object.set('OriginIp', template?.OriginIp || '');
let signers = template?.Signers || [];
const signerobj = {
__type: 'Pointer',
@@ -212,11 +213,11 @@ const sendMailToAllSigners = async docId => {
throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'User not found.');
}
} catch (e) {
console.log('err in create document from template', err);
console.log('error in get partners_Tenant class details', err);
}
}
} catch (e) {
console.log('err in create document from template', err);
console.log('error in sendMailToAllSigners function', err);
}
};
@@ -5,13 +5,15 @@ export default async function TemplateAfterSave(request) {
// update acl of New Document If There are signers present in array
const signers = request.object.get('Signers');
const AutoReminder = request?.object?.get('AutomaticReminders') || false;
const ip = request?.headers?.['x-real-ip'] || '';
if (AutoReminder) {
const RemindOnceInEvery = request?.object?.get('RemindOnceInEvery') || 5;
const ReminderDate = new Date(request?.object?.get('createdAt'));
ReminderDate.setDate(ReminderDate.getDate() + RemindOnceInEvery);
request.object.set('NextReminderDate', ReminderDate);
await request.object.save(null, { useMasterKey: true });
}
request.object.set('OriginIp', ip);
await request.object.save(null, { useMasterKey: true });
if (signers && signers.length > 0) {
await updateAclDoc(request.object.id);
} else {
@@ -48,6 +48,15 @@ export default async function addOrganization(request) {
objectId: resExt.id,
});
const newResOrg = await newOrg.save(null, { useMasterKey: true });
const teamCls = new Parse.Object('contracts_Teams');
teamCls.set('Name', 'All Users');
teamCls.set('OrganizationId', {
__type: 'Pointer',
className: 'contracts_Organizations',
objectId: newResOrg.id,
});
teamCls.set('IsActive', true);
await teamCls.save(null, { useMasterKey: true });
if (newResOrg) {
return newResOrg;
}
@@ -1,10 +1,11 @@
import axios from 'axios';
import { cloudServerUrl } from '../../Utils.js';
export default async function callWebhook(request) {
const event = request.params.event;
const body = request.params.body;
const docId = body.objectId;
const contactId = request.params.contactId;
const serverUrl = process.env.SERVER_URL;
const serverUrl = cloudServerUrl; //process.env.SERVER_URL;
const appId = process.env.APP_ID;
const userRes = await axios.get(serverUrl + '/users/me', {
headers: {
@@ -1,6 +1,7 @@
import axios from 'axios';
import { cloudServerUrl } from '../../Utils.js';
const serverUrl = process.env.SERVER_URL;
const serverUrl = cloudServerUrl; //process.env.SERVER_URL;
const appId = process.env.APP_ID;
async function sendMail(document, sessionToken) {
@@ -1,7 +1,8 @@
import { generateApiKey } from 'generate-api-key';
import axios from 'axios';
import { cloudServerUrl } from '../../Utils.js';
export default async function generateApiToken(request) {
const serverUrl = process.env.SERVER_URL;
const serverUrl = cloudServerUrl; //process.env.SERVER_URL;
try {
const userRes = await axios.get(serverUrl + '/users/me', {
headers: {
@@ -0,0 +1,26 @@
export default async function getAllUserTeamByOrg(request) {
const OrgId = request.params.orgId;
if (!request?.user) {
throw new Parse.Error(Parse.Error.INVALID_SESSION_TOKEN, 'User is not authenticated.');
}
try {
const teamCls = new Parse.Query('contracts_Teams');
teamCls.equalTo('OrganizationId', {
__type: 'Pointer',
className: 'contracts_Organizations',
objectId: OrgId,
});
teamCls.equalTo('IsActive', true);
const teamRes = await teamCls.first({ useMasterKey: true });
if (teamRes) {
return teamRes;
} else {
throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'Team not found.');
}
} catch (err) {
console.log('err in getOrganizations', err);
const code = err?.code || 400;
const msg = err?.message || 'Something went wrong.';
throw new Parse.Error(code, msg);
}
}
@@ -1,7 +1,8 @@
import axios from 'axios';
import { cloudServerUrl } from '../../Utils.js';
export default async function getDocument(request) {
const serverUrl = process.env.SERVER_URL;
const serverUrl = cloudServerUrl; //process.env.SERVER_URL;
const docId = request.params.docId;
try {
@@ -1,6 +1,7 @@
import axios from 'axios';
import { cloudServerUrl } from '../../Utils.js';
export default async function getDrive(request) {
const serverUrl = process.env.SERVER_URL;
const serverUrl = cloudServerUrl; //process.env.SERVER_URL;
const appId = process.env.APP_ID;
const limit = request.params.limit;
const skip = request.params.skip;
@@ -1,5 +1,6 @@
import axios from 'axios';
const serverUrl = process.env.SERVER_URL;
import { cloudServerUrl } from '../../Utils.js';
const serverUrl = cloudServerUrl; //process.env.SERVER_URL;
const appId = process.env.APP_ID;
export default async function getInvoices(request) {
const limit = request.params.limit || 100;
@@ -0,0 +1,24 @@
export default async function getOrgAdmins(req) {
if (!req?.user) {
throw new Parse.Error(Parse.Error.INVALID_SESSION_TOKEN, 'User is not authenticated.');
} else {
try {
const extUser = new Parse.Query('contracts_Users');
extUser.equalTo('UserRole', 'contracts_OrgAdmin');
extUser.equalTo('CreatedBy', req?.user);
extUser.notEqualTo('UserId', req?.user);
extUser.include('TeamIds,OrganizationId');
extUser.descending('createdAt');
const userRes = await extUser.find({ useMasterKey: true });
if (userRes.length > 0) {
const _userRes = JSON.parse(JSON.stringify(userRes));
return _userRes;
} else {
return [];
}
} catch (err) {
console.log('err in getOrgAdmins', err);
throw err;
}
}
}
@@ -2,6 +2,7 @@ export default async function getOrganizations(request) {
const limit = request.params.limit || 200;
const skip = request.params.skip || 0;
const extUserId = request.params.extUserId;
const activeOrgs = request.params.active;
if (!request?.user) {
throw new Parse.Error(Parse.Error.INVALID_SESSION_TOKEN, 'User is not authenticated.');
}
@@ -17,7 +18,9 @@ export default async function getOrganizations(request) {
className: 'contracts_Users',
objectId: extUserId,
});
orgQuery.equalTo('IsActive', true);
if (activeOrgs) {
orgQuery.equalTo('IsActive', true);
}
orgQuery.exclude('ExtUserId');
orgQuery.limit(limit);
orgQuery.skip(skip);
@@ -1,5 +1,6 @@
import axios from 'axios';
const serverUrl = process.env.SERVER_URL;
import { cloudServerUrl } from '../../Utils.js';
const serverUrl = cloudServerUrl; //process.env.SERVER_URL;
const appId = process.env.APP_ID;
export default async function getPayments(request) {
const limit = request.params.limit || 100;
@@ -1,3 +1,4 @@
import { cloudServerUrl } from '../../Utils.js';
import reportJson from './reportsJson.js';
import axios from 'axios';
@@ -6,7 +7,7 @@ export default async function getReport(request) {
const limit = request.params.limit;
const skip = request.params.skip;
const serverUrl = process.env.SERVER_URL;
const serverUrl = cloudServerUrl; //process.env.SERVER_URL;
const appId = process.env.APP_ID;
const masterKey = process.env.MASTER_KEY;
try {
@@ -1,5 +1,6 @@
import axios from 'axios';
const serverUrl = process.env.SERVER_URL;
import { cloudServerUrl } from '../../Utils.js';
const serverUrl = cloudServerUrl; //process.env.SERVER_URL;
const appId = process.env.APP_ID;
export default async function getSubscription(request) {
const extUserId = request.params.extUserId || '';
@@ -1,4 +1,5 @@
export default async function getTeams(request) {
const activeTeams = request.params.active;
if (!request?.user) {
throw new Parse.Error(Parse.Error.INVALID_SESSION_TOKEN, 'User is not authenticated.');
}
@@ -18,7 +19,9 @@ export default async function getTeams(request) {
className: 'contracts_Organizations',
objectId: extUser.OrganizationId.objectId,
});
teamCls.equalTo('IsActive', true);
if (activeTeams) {
teamCls.equalTo('IsActive', true);
}
teamCls.descending('createdAt');
const teamRes = await teamCls.find({ useMasterKey: true });
if (teamRes && teamRes.length > 0) {
@@ -1,19 +1,39 @@
async function getUserDetails(request) {
try {
const userId = request.params.userId;
const userQuery = new Parse.Query('contracts_Users');
userQuery.equalTo('Email', request.params.email);
userQuery.include('TenantId');
userQuery.include('UserId');
userQuery.exclude('google_refresh_token')
if (userId) {
userQuery.equalTo('CreatedBy', { __type: 'Pointer', className: '_User', objectId: userId });
const reqEmail = request.params.email;
if (reqEmail || request.user) {
try {
const userId = request.params.userId;
const userQuery = new Parse.Query('contracts_Users');
if (request?.user) {
const email = request.user.get('email');
userQuery.equalTo('Email', email);
} else {
userQuery.equalTo('Email', reqEmail);
}
userQuery.include('TenantId');
userQuery.include('UserId');
userQuery.exclude('google_refresh_token');
if (userId) {
userQuery.equalTo('CreatedBy', { __type: 'Pointer', className: '_User', objectId: userId });
}
const res = await userQuery.first({ useMasterKey: true });
if (res) {
if (reqEmail) {
return { objectId: res.id };
} else {
return res;
}
} else {
return '';
}
} catch (err) {
console.log('Err ', err);
const code = err?.code || 400;
const msg = err?.message || 'Something went wrong.';
throw new Parse.Error(code, msg);
}
const res = await userQuery.first({ useMasterKey: true });
return res;
} catch (err) {
console.log('Err ', err);
return err;
} else {
throw new Parse.Error(Parse.Error.INVALID_SESSION_TOKEN, 'User is not authenticated.');
}
}
export default getUserDetails;
@@ -1,6 +1,7 @@
import axios from 'axios';
import { cloudServerUrl } from '../../Utils.js';
export default async function getapitoken(request) {
const serverUrl = process.env.SERVER_URL;
const serverUrl = cloudServerUrl; //process.env.SERVER_URL;
try {
const userRes = await axios.get(serverUrl + '/users/me', {
headers: {
@@ -4,9 +4,9 @@ import { SignPdf } from '@signpdf/signpdf';
import { P12Signer } from '@signpdf/signer-p12';
import { pdflibAddPlaceholder } from '@signpdf/placeholder-pdf-lib';
import { PDFDocument } from 'pdf-lib';
import { replaceMailVaribles, saveFileUsage } from '../../../Utils.js';
import { cloudServerUrl, replaceMailVaribles, saveFileUsage } from '../../../Utils.js';
import GenerateCertificate from './GenerateCertificate.js';
const serverUrl = process.env.SERVER_URL;
const serverUrl = cloudServerUrl; // process.env.SERVER_URL;
const APPID = process.env.APP_ID;
const masterKEY = process.env.MASTER_KEY;
const eSignName = 'opensign';
@@ -1,6 +1,7 @@
import axios from 'axios';
import { cloudServerUrl } from '../../Utils.js';
export default async function saveSubscription(request) {
const serverUrl = process.env.SERVER_URL;
const serverUrl = cloudServerUrl; //process.env.SERVER_URL;
const appId = process.env.APP_ID;
const subscription = request.params.subscription;
const SubscriptionId = subscription.data.subscription.subscription_id;
@@ -1,6 +1,7 @@
import axios from 'axios';
import { cloudServerUrl } from '../../Utils.js';
export default async function savewebhook(request) {
const serverUrl = process.env.SERVER_URL;
const serverUrl = cloudServerUrl; //process.env.SERVER_URL;
try {
const userRes = await axios.get(serverUrl + '/users/me', {
headers: {
@@ -2,6 +2,8 @@ import axios from 'axios';
import { google } from 'googleapis';
import fs from 'node:fs';
import https from 'https';
import http from 'http';
import { useLocal } from '../../Utils.js';
const clientId = process.env.GOOGLE_CLIENT_ID;
const clientSecret = process.env.GOOGLE_CLIENT_SECRET;
// Function to create a Gmail client
@@ -26,6 +28,7 @@ const refreshAccessToken = async refreshToken => {
// Function to create a raw email message
const makeEmail = async (to, from, subject, html, url, pdfName) => {
const protocol = new URL(process.env.SERVER_URL);
const htmlContent = html;
const boundary = 'boundary_' + Date.now().toString(16);
let str;
@@ -34,10 +37,17 @@ const makeEmail = async (to, from, subject, html, url, pdfName) => {
let Pdf = fs.createWriteStream('test.pdf');
const writeToLocalDisk = () => {
return new Promise((resolve, reject) => {
https.get(url, async function (response) {
response.pipe(Pdf);
response.on('end', () => resolve('success'));
});
if (useLocal !== 'true' && protocol.hostname !== 'localhost') {
https.get(url, async function (response) {
response.pipe(Pdf);
response.on('end', () => resolve('success'));
});
} else {
http.get(url, async function (response) {
response.pipe(Pdf);
response.on('end', () => resolve('success'));
});
}
});
};
// `writeToLocalDisk` is used to create pdf file from doc url
@@ -130,7 +140,7 @@ export default async function sendMailGmailProvider(_extRes, template) {
raw: email,
},
});
// console.log('response ', response);
// console.log('response ', response);
return { code: 200, message: 'Email sent successfully' };
} catch (error) {
@@ -1,11 +1,13 @@
import fs from 'node:fs';
import https from 'https';
import http from 'http';
import formData from 'form-data';
import Mailgun from 'mailgun.js';
import { smtpenable, smtpsecure, updateMailCount } from '../../Utils.js';
import { smtpenable, smtpsecure, updateMailCount, useLocal } from '../../Utils.js';
import sendMailGmailProvider from './sendMailGmailProvider.js';
import { createTransport } from 'nodemailer';
async function sendMailProvider(req) {
const protocol = new URL(process.env.SERVER_URL);
try {
let transporterSMTP;
let mailgunClient;
@@ -32,10 +34,17 @@ async function sendMailProvider(req) {
let Pdf = fs.createWriteStream('test.pdf');
const writeToLocalDisk = () => {
return new Promise((resolve, reject) => {
https.get(req.params.url, async function (response) {
response.pipe(Pdf);
response.on('end', () => resolve('success'));
});
if (useLocal !== 'true' && protocol.hostname !== 'localhost') {
https.get(req.params.url, async function (response) {
response.pipe(Pdf);
response.on('end', () => resolve('success'));
});
} else {
http.get(req.params.url, async function (response) {
response.pipe(Pdf);
response.on('end', () => resolve('success'));
});
}
});
};
// `writeToLocalDisk` is used to create pdf file from doc url
@@ -1,6 +1,7 @@
import axios from 'axios';
import { cloudServerUrl } from '../../Utils.js';
const serverUrl = process.env.SERVER_URL;
const serverUrl = cloudServerUrl; //process.env.SERVER_URL;
const APPID = process.env.APP_ID;
const masterKEY = process.env.MASTER_KEY;
const clientUrl = process.env.PUBLIC_URL;
@@ -33,7 +33,8 @@ export default async function updateTeam(request) {
updateteam.set('Name', Name);
}
if (IsActive) {
updateteam.set('IsActive', IsActive);
const active = IsActive === 'false' ? false : true;
updateteam.set('IsActive', active);
}
const updateTeamRes = await updateteam.save(null, { useMasterKey: true });
return updateTeamRes;
@@ -1,5 +1,6 @@
import axios from 'axios';
const serverUrl = process.env.SERVER_URL;
import { cloudServerUrl } from '../../Utils.js';
const serverUrl = cloudServerUrl; //process.env.SERVER_URL;
const APPID = process.env.APP_ID;
const masterKEY = process.env.MASTER_KEY;
@@ -0,0 +1,32 @@
/**
*
* @param {Parse} Parse
*/
exports.up = async (Parse) => {
// TODO: set className here
const className = 'contracts_Template';
const schema = new Parse.Schema(className);
schema.addString('OriginIp');
// TODO: Set the schema here
// Example:
// schema.addString('name').addNumber('cash');
return schema.update();
};
/**
*
* @param {Parse} Parse
*/
exports.down = async (Parse) => {
// TODO: set className here
const className = 'contracts_Template';
const schema = new Parse.Schema(className);
schema.deleteField('OriginIp');
// TODO: Set the schema here
// Example:
// schema.deleteField('name').deleteField('cash');
return schema.update();
};
+5 -5
View File
@@ -17,7 +17,7 @@ import { exec } from 'child_process';
import { createTransport } from 'nodemailer';
import { app as v1 } from './cloud/customRoute/v1/apiV1.js';
import { PostHog } from 'posthog-node';
import { smtpenable, smtpsecure, useLocal } from './Utils.js';
import { cloudServerUrl, smtpenable, smtpsecure, useLocal } from './Utils.js';
import { SSOAuth } from './auth/authadapter.js';
let fsAdapter;
if (useLocal !== 'true') {
@@ -98,9 +98,9 @@ export const config = {
maxUploadSize: '30mb',
masterKey: process.env.MASTER_KEY, //Add your master key here. Keep it secret!
masterKeyIps: ['0.0.0.0/0', '::/0'], // '::1'
serverURL: 'http://localhost:8080/app', // Don't forget to change to https if needed
serverURL: cloudServerUrl, // Don't forget to change to https if needed
verifyUserEmails: false,
publicServerURL: process.env.SERVER_URL || 'http://localhost:8080/app',
publicServerURL: process.env.SERVER_URL || cloudServerUrl,
// Your apps name. This will appear in the subject and body of the emails that are sent.
appName: 'Opensign',
allowClientClassCreation: false,
@@ -219,8 +219,8 @@ if (!process.env.TESTING) {
// console.log('isWindows', isWindows);
const migrate = isWindows
? `set APPLICATION_ID=${process.env.APP_ID}&& set SERVER_URL=http://localhost:8080/app&& set MASTER_KEY=${process.env.MASTER_KEY}&& npx parse-dbtool migrate`
: `APPLICATION_ID=${process.env.APP_ID} SERVER_URL=http://localhost:8080/app MASTER_KEY=${process.env.MASTER_KEY} npx parse-dbtool migrate`;
? `set APPLICATION_ID=${process.env.APP_ID}&& set SERVER_URL=${cloudServerUrl}&& set MASTER_KEY=${process.env.MASTER_KEY}&& npx parse-dbtool migrate`
: `APPLICATION_ID=${process.env.APP_ID} SERVER_URL=${cloudServerUrl} MASTER_KEY=${process.env.MASTER_KEY} npx parse-dbtool migrate`;
exec(migrate, (error, stdout, stderr) => {
if (error) {
console.error(`Error: ${error.message}`);
+2451 -2642
View File
File diff suppressed because it is too large Load Diff
+13 -9
View File
@@ -24,39 +24,43 @@
"@signpdf/placeholder-pdf-lib": "^3.2.4",
"@signpdf/signer-p12": "^3.2.4",
"@signpdf/signpdf": "^3.2.4",
"aws-sdk": "^2.1659.0",
"axios": "^1.7.2",
"aws-sdk": "^2.1667.0",
"axios": "^1.7.3",
"cors": "^2.8.5",
"dotenv": "^16.4.5",
"express": "^4.19.2",
"express-sse": "^0.5.3",
"form-data": "^4.0.0",
"generate-api-key": "^1.0.2",
"googleapis": "^140.0.1",
"jsonschema": "^1.4.1",
"mailgun.js": "^10.2.3",
"mongoose": "^8.5.1",
"mongoose": "^8.5.2",
"multer": "^1.4.5-lts.1",
"multer-s3": "^3.0.1",
"node-forge": "^1.3.1",
"nodemailer": "^6.9.14",
"parse": "^5.3.0",
"parse-dbtool": "^1.2.0",
"parse-server": "^7.1.0",
"parse-server": "^7.2.0",
"parse-server-api-mail-adapter": "^4.0.0",
"pdf-lib": "^1.17.1",
"posthog-node": "^4.0.1"
"posthog-node": "^4.0.1",
"ws": "^8.18.0"
},
"type": "module",
"devDependencies": {
"@babel/eslint-parser": "^7.24.8",
"eslint": "^9.7.0",
"jasmine": "^5.1.0",
"@babel/eslint-parser": "^7.25.1",
"eslint": "^9.8.0",
"jasmine": "^5.2.0",
"mongodb-runner": "^5.6.4",
"nodemon": "^3.1.4",
"nyc": "^17.0.0",
"prettier": "^3.3.3"
},
"overrides": {
"ws": "$ws",
"parse": "$parse"
},
"engines": {
"node": ">=12.22.10 <21"
}
-37
View File
@@ -1,37 +0,0 @@
// const { exec } = require('child_process');
import { exec } from 'child_process';
const migrate =
'APPLICATION_ID=legadranaxn SERVER_URL=http://localhost:8080/app MASTER_KEY=XnAwPDRQQyMr npx parse-dbtool migrate';
// `APPLICATION_ID=${process.env.APP_ID} SERVER_URL=${process.env.SERVER_URL} MASTER_KEY=${process.env.MASTER_KEY} npx parse-dbtool migrate`;
exec(migrate, (error, stdout, stderr) => {
if (error) {
console.error(`Error: ${error.message}`);
return;
}
if (stderr) {
console.error(`Error: ${stderr}`);
return;
}
console.log(`Command output: ${stdout}`);
});
// const seeder =
// 'APPLICATION_ID=legadranaxn SERVER_URL=http://localhost:8080/app MASTER_KEY=XnAwPDRQQyMr npx parse-dbtool seed';
// exec(seeder, (error, stdout, stderr) => {
// if (error) {
// console.error(`Error: ${error.message}`);
// return;
// }
// if (stderr) {
// console.error(`Error: ${stderr}`);
// return;
// }
// console.log(`Command output: ${stdout}`);
// });
+1 -1
View File
@@ -5,7 +5,7 @@ FROM mongo:latest
RUN mkdir -p /docker-entrypoint-initdb.d
# Copy default data JSON files to the initialization directory
COPY ./default-data/*.json /docker-entrypoint-initdb.d/
# COPY ./default-data/*.json /docker-entrypoint-initdb.d/
# Execute the initialization script during container startup
CMD ["mongod"]
@@ -1,70 +0,0 @@
[{
"_id": "lpm8ijrwod",
"name": "contracts_Admin",
"_wperm": [
"*"
],
"_rperm": [
"*"
],
"_acl": {
"*": {
"r": true,
"w": true
}
},
"_created_at": {
"$date": "2023-09-19T09:25:20.205Z"
},
"_updated_at": {
"$date": "2023-09-28T09:47:03.968Z"
}
},
{
"_id": "Bz90QJSYMw",
"name": "contracts_Guest",
"_wperm": [
"ZhOmhqvw7S"
],
"_rperm": [
"*",
"ZhOmhqvw7S"
],
"_acl": {
"ZhOmhqvw7S": {
"w": true,
"r": true
},
"*": {
"r": true
}
},
"_created_at": {
"$date": "2023-10-20T07:56:10.094Z"
},
"_updated_at": {
"$date": "2023-10-20T10:50:36.229Z"
}
},
{
"_id": "Tb14x04JK2",
"name": "contracts_User",
"_wperm": [
"*"
],
"_rperm": [
"*"
],
"_acl": {
"*": {
"r": true,
"w": true
}
},
"_created_at": {
"$date": "2023-09-19T09:25:20.205Z"
},
"_updated_at": {
"$date": "2023-10-20T06:54:09.836Z"
}
}]
@@ -1,657 +0,0 @@
[{
"_id": "_Role",
"objectId": "string",
"updatedAt": "date",
"createdAt": "date",
"name": "string",
"users": "relation<_User>",
"roles": "relation<_Role>",
"_metadata": {
"indexes": {
"name_1": {
"name": 1
},
"_id_": {
"_id": 1
}
},
"class_permissions": {
"get": {
"*": true
},
"find": {
"*": true
},
"count": {
"*": true
},
"create": {
"*": true
},
"update": {
"*": true
},
"delete": {
"*": true
},
"addField": {},
"protectedFields": {
"*": []
}
}
}
},
{
"_id": "_Session",
"objectId": "string",
"updatedAt": "date",
"createdAt": "date",
"user": "*_User",
"installationId": "string",
"sessionToken": "string",
"expiresAt": "date",
"createdWith": "object",
"_metadata": {
"indexes": {
"_id_": {
"_id": 1
}
}
}
},
{
"_id": "_User",
"objectId": "string",
"updatedAt": "date",
"createdAt": "date",
"username": "string",
"email": "string",
"emailVerified": "boolean",
"authData": "object",
"_metadata": {
"indexes": {
"phone_1": {
"phone": 1
},
"username_1": {
"username": 1
},
"case_insensitive_username": {
"username": 1
},
"email_1": {
"email": 1
},
"case_insensitive_email": {
"email": 1
},
"_id_": {
"_id": 1
}
},
"class_permissions": {
"get": {
"*": true
},
"find": {
"*": true
},
"count": {
"*": true
},
"create": {
"*": true
},
"update": {
"*": true
},
"delete": {
"*": true
},
"addField": {},
"protectedFields": {
"*": [
"email"
]
}
}
},
"name": "string",
"phone": "string",
"ProfilePic": "string"
},
{
"_id": "contracts_Contactbook",
"objectId": "string",
"updatedAt": "date",
"createdAt": "date",
"Phone": "string",
"Email": "string",
"Name": "string",
"UserRole": "string",
"UserId": "*_User",
"CreatedBy": "*_User",
"_metadata": {
"indexes": {
"_id_": {
"_id": 1
}
}
},
"TenantId": "*partners_Tenant",
"TourStatus": "array"
},
{
"_id": "contracts_Document",
"objectId": "string",
"updatedAt": "date",
"createdAt": "date",
"_metadata": {
"fields_options": {
"EnablePhoneOTP": {
"required": "false"
},
"IsCompleted": {
"required": "false",
"defaultValue": false
},
"IsDeclined": {
"required": "false",
"defaultValue": false
},
"SendinOrder": {
"required": "false",
"defaultValue": false
},
"ExpiryDate": {
"required": "false"
},
"Signers": {
"required": "false"
},
"Name": {
"required": "false"
},
"AgreementValidUntil": {
"required": "false"
},
"URL": {
"required": "false"
},
"RemindOnceInEvery": {
"required": "false",
"defaultValue": 5
},
"EnableEmailOTP": {
"required": "false"
},
"AutomaticReminders": {
"required": "false",
"defaultValue": false
},
"SentToOthers": {
"required": "false",
"defaultValue": false
},
"TimeToCompleteDays": {
"required": "false",
"defaultValue": 15
},
"Recipients": {
"required": "false"
},
"Type": {
"required": "false"
},
"Description": {
"required": "false"
},
"ExtUserPtr": {
"required": "false"
},
"SignedUrl": {
"required": "false"
},
"AuditTrail": {
"required": "false"
},
"Placeholders": {
"required": "false"
},
"Folder": {
"required": "false"
},
"Note": {
"required": false
},
"Clauses": {
"required": false
},
"AgreementDelta": {
"required": false
}
},
"indexes": {
"_id_": {
"_id": 1
}
},
"class_permissions": {
"get": {
"*": true
},
"find": {
"*": true
},
"count": {
"*": true
},
"create": {
"*": true
},
"update": {
"*": true
},
"delete": {
"*": true
},
"addField": {},
"protectedFields": {
"*": []
}
}
},
"EnablePhoneOTP": "boolean",
"IsCompleted": "boolean",
"IsDeclined": "boolean",
"SendinOrder": "boolean",
"ExpiryDate": "date",
"Signers": "array",
"Name": "string",
"AgreementValidUntil": "date",
"URL": "string",
"RemindOnceInEvery": "number",
"EnableEmailOTP": "boolean",
"AutomaticReminders": "boolean",
"SentToOthers": "boolean",
"TimeToCompleteDays": "number",
"Recipients": "array",
"Type": "string",
"Description": "string",
"ExtUserPtr": "*contracts_Users",
"SignedUrl": "string",
"AuditTrail": "array",
"Placeholders": "array",
"Folder": "*contracts_Document",
"Note": "string",
"CreatedBy": "*_User",
"Clauses": "array",
"AgreementDelta": "array"
},
{
"_id": "contracts_Signature",
"objectId": "string",
"updatedAt": "date",
"createdAt": "date",
"_metadata": {
"fields_options": {
"SignatureName": {
"required": "false"
},
"SignText": {
"required": "false"
},
"ImageURL": {
"required": "false"
},
"SignTextFont": {
"required": "false"
},
"InitialsText": {
"required": "false"
},
"InitialsFont": {
"required": "false"
},
"UserId": {
"required": false
}
},
"indexes": {
"_id_": {
"_id": 1
}
},
"class_permissions": {
"get": {
"*": true
},
"find": {
"*": true
},
"count": {
"*": true
},
"create": {
"*": true
},
"update": {
"*": true
},
"delete": {
"*": true
},
"addField": {},
"protectedFields": {
"*": []
}
}
},
"SignatureName": "string",
"SignText": "string",
"ImageURL": "string",
"SignTextFont": "string",
"InitialsText": "string",
"InitialsFont": "string",
"Initials": "string",
"UserId": "*_User"
},
{
"_id": "contracts_Users",
"objectId": "string",
"updatedAt": "date",
"createdAt": "date",
"_metadata": {
"fields_options": {
"Name": {
"required": "false"
},
"Phone": {
"required": "false"
},
"JobTitle": {
"required": "false"
},
"Email": {
"required": "false"
},
"Company": {
"required": "false"
},
"UserId": {
"required": "false"
},
"TenantId": {
"required": "false"
},
"TourStatus": {
"required": false
},
"IsContactEntry": {
"required": false,
"defaultValue": false
},
"ShareWithTeam": {
"required": false
}
},
"indexes": {
"_id_": {
"_id": 1
}
},
"class_permissions": {
"get": {
"*": true
},
"find": {
"*": true
},
"count": {
"*": true
},
"create": {
"*": true
},
"update": {
"*": true
},
"delete": {
"*": true
},
"addField": {},
"protectedFields": {
"*": []
}
}
},
"Name": "string",
"Phone": "string",
"JobTitle": "string",
"Email": "string",
"Company": "string",
"UserId": "*_User",
"TenantId": "*partners_Tenant",
"TourStatus": "array",
"Plan": "object",
"UserRole": "string",
"Next_billing_date": "date",
"Customer_id": "string",
"Subscription_id": "string",
"CreatedBy": "*_User",
"IsContactEntry": "boolean",
"ShareWithTeam": "boolean"
},
{
"_id": "partners_DataFiles",
"objectId": "string",
"updatedAt": "date",
"createdAt": "date",
"FileSize": "number",
"FileUrl": "string",
"_metadata": {
"indexes": {
"_id_": {
"_id": 1
}
}
}
},
{
"_id": "partners_Subscriptions",
"objectId": "string",
"updatedAt": "date",
"createdAt": "date"
},
{
"_id": "partners_Tenant",
"objectId": "string",
"updatedAt": "date",
"createdAt": "date",
"EmailAddress": "string",
"TenantName": "string",
"IsActive": "boolean",
"CreatedBy": "*_User",
"ContactNumber": "string",
"UserId": "*_User",
"_metadata": {
"indexes": {
"_id_": {
"_id": 1
}
}
}
},
{
"_id": "partners_TenantCredits",
"objectId": "string",
"updatedAt": "date",
"createdAt": "date",
"usedStorage": "number",
"PartnersTenant": "*partners_Tenant",
"_metadata": {
"indexes": {
"_id_": {
"_id": 1
}
}
}
},
{
"_id": "w_appinfo",
"objectId": "string",
"updatedAt": "date",
"createdAt": "date",
"orgId": "string",
"forgetpassFormId": "string",
"mainformObjId": "string",
"applogo": "string",
"fbAppId": "string",
"appname": "string",
"loginFormId": "string",
"baseurl": "string",
"org_name": "string",
"signUpFormId": "string",
"defaultmenuid": "string",
"version": "string",
"formTitle": "string",
"googleClietId": "string",
"_metadata": {
"indexes": {
"_id_": {
"_id": 1
}
},
"class_permissions": {
"get": {
"*": true
},
"find": {
"*": true
},
"count": {
"*": true
},
"create": {
"*": true
},
"update": {
"*": true
},
"delete": {
"*": true
},
"addField": {
"*": true
}
},
"fields_options": {
"uploadUrl": {
"required": false
}
}
},
"class": "string",
"LandingPageId": "string",
"accessType": "string",
"settings": "array",
"appTitle": "string",
"metaDescription": "string",
"branding_image": "string",
"fev_Icon": "string",
"defaultRole": "string",
"results": "array",
"loginType": "string",
"createdBy": "*_User",
"domain": "string",
"enableWebNotification": "boolean",
"allowWhiteLabel": "boolean",
"uploadUrl": "string"
},
{
"_id": "w_dashboard",
"objectId": "string",
"updatedAt": "date",
"createdAt": "date",
"dbDescription": "string",
"dbTitle": "string",
"bgColor": "string",
"rows": "array",
"_metadata": {
"indexes": {
"_id_": {
"_id": 1
}
}
},
"appId": "*w_appinfo"
},
{
"_id": "w_formV3",
"objectId": "string",
"updatedAt": "date",
"createdAt": "date",
"description": "string",
"uiSchema": "object",
"jsonSchema": "object",
"_metadata": {
"indexes": {
"_id_": {
"_id": 1
}
}
},
"class": "string",
"success_message": "string",
"restrict_form_entry": "object",
"send_email": "boolean",
"restrict_form_access": "object",
"email_template": "object",
"form_permission": "string",
"success_redirect": "string",
"form_buttons": "object",
"buttons": "object",
"appId": "*w_appinfo",
"rpTitle": "string",
"rpDescription": "string",
"rpType": "string",
"bgColor": "string",
"rows": "array",
"redirect_id": "string",
"formACL": "object",
"userSchema": "object",
"isRegisterForm": "boolean",
"liveValidate": "boolean",
"noValidate": "boolean",
"validFunction": "string",
"help": "object",
"name": "string",
"phone": "string",
"email": "string",
"password": "string",
"username": "string",
"role": "string",
"helpText": "object",
"helpTextForm": "object",
"hideActionsAfter": "number",
"rules": "array",
"extraActions": "object",
"persistentFields": "array"
},
{
"_id": "w_menu",
"objectId": "string",
"updatedAt": "date",
"createdAt": "date",
"menuTitle": "string",
"menuType": "string",
"menuItems": "array",
"_metadata": {
"indexes": {
"_id_": {
"_id": 1
}
}
},
"appId": "*w_appinfo"
}]
File diff suppressed because one or more lines are too long
@@ -1,104 +0,0 @@
[{
"_id": "35KBoSgoAK",
"rows": [
{
"columns": [
{
"colxs": "12",
"colmd": "6",
"collg": "6",
"widget": {
"type": "Card",
"icon": "fas fa-signature",
"bgColor": "#f0058e",
"label": "Need your Signature",
"description": null,
"data": {
"id": "e04ee9dc-932d-6b80-0202-703fd154eb74",
"queryType": "",
"class": "contracts_Document",
"query": "where={\"$and\":[{\"AuditTrail.UserPtr\":{\"$ne\":{\"__type\":\"Pointer\",\"className\": \"contracts_Users\",\"objectId\":\"#objectId#\"}}},{\"AuditTrail.Activity\":{\"$ne\":\"Signed\"}}],\"Signers\":{\"$in\":[{\"__type\":\"Pointer\",\"className\":\"contracts_Users\",\"objectId\":\"#objectId#\"}]},\"IsDeclined\":{\"$ne\":true},\"IsCompleted\":{\"$ne\":true},\"Type\":{\"$ne\":\"Folder\"},\"Placeholders\":{\"$ne\":null},\"ExpiryDate\":{\"#*gt\":{\"__type\":\"#Date#\",\"iso\":\"#today#\"}}}&count=1",
"key": "count",
"Redirect_type": "Report",
"Redirect_id": "4Hhwbp482K",
"tourSection": "tourcard1",
"tourMessage": "This card shows the aggregate count of documents that are awaiting your signature. Clicking on this card will seamlessly take you to the detailed list of such documents for your review and action."
}
}
},
{
"colxs": "12",
"colmd": "6",
"collg": "6",
"widget": {
"type": "Card",
"icon": "fas fa-sign-out-alt",
"bgColor": "#g0058e",
"label": "Out for signatures",
"description": null,
"data": {
"id": "c1935cc0-28d4-3d73-b72a-8c1e3d18a17f",
"queryType": "",
"class": "contracts_Document",
"query": "where={\"IsDeclined\":{\"$ne\":true},\"IsCompleted\":{\"$ne\":true},\"Type\":{\"$ne\":\"Folder\"},\"Placeholders\":{\"$ne\":null},\"ExpiryDate\":{\"#*gt\":{\"__type\":\"#Date#\",\"iso\":\"#today#\"}}}&include=Signers,AuditTrail.UserPtr",
"key": "count",
"Redirect_type": "Report",
"Redirect_id": "1MwEuxLEkF",
"tourSection": "tourcard2",
"tourMessage": "This card indicates the total number of documents you've sent out for signatures. A single click on this card will navigate you to a comprehensive list of these documents, allowing you to monitor their status."
}
}
},
{
"colxs": "12",
"colmd": "6",
"collg": "6",
"widget": {
"type": "report",
"reportId": "5Go51Q7T8r",
"data": {
"tourSection": "tourreport1",
"tourMessage": "Here lies a curated list of documents that are pending your signature. These are requests from other users that require your immediate attention for completion."
}
}
},
{
"colxs": "12",
"colmd": "6",
"collg": "6",
"widget": {
"type": "report",
"reportId": "d9k3UfYHBc",
"data": {
"tourSection": "tourreport2",
"tourMessage": "This area displays all the documents you've dispatched for signatures from other parties. It serves as a real-time tracker for documents pending external approval."
}
}
},
{
"colxs": "12",
"colmd": "12",
"collg": "12",
"widget": {
"type": "report",
"reportId": "kC5mfynCi4",
"data": {
"tourSection": "tourreport3",
"tourMessage": "In this section, you'll find your draft documents awaiting completion. These are the documents you've initiated but haven't yet finalized for sending."
}
}
}
]
}
],
"_p_appId": "w_appinfo$aIPmIvMzGM",
"dbTitle": "Dashboard",
"dbDescription": null,
"bgColor": "#ffffff",
"_created_at": {
"$date": "2023-09-04T13:17:26.707Z"
},
"_updated_at": {
"$date": "2023-09-27T04:53:20.395Z"
}
}]
@@ -1,290 +0,0 @@
[
{
"_id": "H9vRfEYKhT",
"_created_at": {
"$date": "2023-09-04T14:04:00.669Z"
},
"_updated_at": {
"$date": "2023-10-20T06:27:02.314Z"
},
"_p_appId": "w_appinfo$aIPmIvMzGM",
"menuItems": [
{
"icon": "fas fa-tachometer-alt",
"title": "Dashboard",
"target": "",
"pageType": "dashboard",
"description": "",
"objectId": "35KBoSgoAK"
},
{
"icon": "far fa-newspaper",
"title": "New Document",
"target": "_self",
"pageType": null,
"description": null,
"objectId": null,
"children": [
{
"icon": "fas fa-pen-nib",
"title": "Sign yourself",
"target": "_self",
"pageType": "form",
"description": "",
"objectId": "sHAnZphf69"
},
{
"icon": "fas fa-file-signature",
"title": "Request signatures",
"target": "_self",
"pageType": "form",
"description": "",
"objectId": "8mZzFxbG1z"
}
]
},
{
"icon": "fas fa-folder",
"title": "OpenSignDrive™",
"target": "_self",
"pageType": "mf",
"description": "",
"objectId": "remoteUrl=aHR0cHM6Ly9xaWstYWktb3JnLmdpdGh1Yi5pby9TaWduLU1pY3JvYXBwVjIvcmVtb3RlRW50cnkuanM=&moduleToLoad=AppRoutes&remoteName=signmicroapp/legadrive"
},
{
"icon": "fas fa-address-card",
"title": "Reports",
"target": "_self",
"pageType": null,
"description": "",
"objectId": null,
"children": [
{
"icon": "fas fa-signature",
"title": "Need your sign",
"target": "_self",
"pageType": "report",
"description": "",
"objectId": "4Hhwbp482K"
},
{
"icon": "fas fa-tasks",
"title": "In Progress",
"target": "_self",
"pageType": "report",
"description": "",
"objectId": "1MwEuxLEkF"
},
{
"icon": "fas fa-check-circle",
"title": "Completed",
"target": "_self",
"pageType": "report",
"description": "",
"objectId": "kQUoW4hUXz"
},
{
"icon": "fas fa-edit",
"title": "Drafts",
"target": "_self",
"pageType": "report",
"description": "",
"objectId": "ByHuevtCFY"
},
{
"icon": "fas fa-times-circle",
"title": "Declined",
"target": "_self",
"pageType": "report",
"description": "",
"objectId": "UPr2Fm5WY3"
},
{
"icon": "fas fa-hourglass-end",
"title": "Expired",
"target": "_self",
"pageType": "report",
"description": "",
"objectId": "zNqBHXHsYH"
},
{
"icon": "fa-solid fa-address-book",
"title": "Contactbook",
"target": "_self",
"pageType": "report",
"description": "",
"objectId": "5KhaPr482K"
}
]
},
{
"icon": "fas fa-cog",
"title": "Settings",
"target": "_self",
"pageType": null,
"description": "",
"objectId": null,
"children": [
{
"icon": "fas fa-pen-fancy",
"title": "My Signature",
"target": "_self",
"pageType": "mf",
"description": "",
"objectId": "remoteUrl=aHR0cHM6Ly9xaWstYWktb3JnLmdpdGh1Yi5pby9TaWduLU1pY3JvYXBwVjIvcmVtb3RlRW50cnkuanM=&moduleToLoad=AppRoutes&remoteName=signmicroapp/managesign"
}
]
}
],
"menuTitle": "Default Menu",
"menuType": "Side Menu"
},
{
"_id": "VPh91h0ZHk",
"_created_at": {
"$date": "2023-09-04T14:16:15.424Z"
},
"_updated_at": {
"$date": "2023-10-20T06:25:59.660Z"
},
"_p_appId": "w_appinfo$aIPmIvMzGM",
"menuItems": [
{
"icon": "fas fa-tachometer-alt",
"title": "Dashboard",
"target": "",
"pageType": "dashboard",
"description": "",
"objectId": "35KBoSgoAK"
},
{
"icon": "far fa-newspaper",
"title": "New Document",
"target": "_self",
"pageType": null,
"description": null,
"objectId": null,
"children": [
{
"icon": "fas fa-pen-nib",
"title": "Sign yourself",
"target": "_self",
"pageType": "form",
"description": "",
"objectId": "sHAnZphf69"
},
{
"icon": "fas fa-file-signature",
"title": "Request signatures",
"target": "_self",
"pageType": "form",
"description": "",
"objectId": "8mZzFxbG1z"
}
]
},
{
"icon": "fas fa-folder",
"title": "OpenSignDrive™",
"target": "_self",
"pageType": "mf",
"description": "",
"objectId": "remoteUrl=aHR0cHM6Ly9xaWstYWktb3JnLmdpdGh1Yi5pby9TaWduLU1pY3JvYXBwVjIvcmVtb3RlRW50cnkuanM=&moduleToLoad=AppRoutes&remoteName=signmicroapp/legadrive"
},
{
"icon": "fas fa-address-card",
"title": "Reports",
"target": "_self",
"pageType": null,
"description": "",
"objectId": null,
"children": [
{
"icon": "fas fa-signature",
"title": "Need your sign",
"target": "_self",
"pageType": "report",
"description": "",
"objectId": "4Hhwbp482K"
},
{
"icon": "fas fa-tasks",
"title": "In Progress",
"target": "_self",
"pageType": "report",
"description": "",
"objectId": "1MwEuxLEkF"
},
{
"icon": "fas fa-check-circle",
"title": "Completed",
"target": "_self",
"pageType": "report",
"description": "",
"objectId": "kQUoW4hUXz"
},
{
"icon": "fas fa-edit",
"title": "Drafts",
"target": "_self",
"pageType": "report",
"description": "",
"objectId": "ByHuevtCFY"
},
{
"icon": "fas fa-times-circle",
"title": "Declined",
"target": "_self",
"pageType": "report",
"description": "",
"objectId": "UPr2Fm5WY3"
},
{
"icon": "fas fa-hourglass-end",
"title": "Expired",
"target": "_self",
"pageType": "report",
"description": "",
"objectId": "zNqBHXHsYH"
},
{
"icon": "fa-solid fa-address-book",
"title": "Contactbook",
"target": "_self",
"pageType": "report",
"description": "",
"objectId": "5KhaPr482K"
}
]
},
{
"icon": "fas fa-cog",
"title": "Settings",
"target": "_self",
"pageType": null,
"description": "",
"objectId": null,
"children": [
{
"icon": "fas fa-pen-fancy",
"title": "My Signature",
"target": "_self",
"pageType": "mf",
"description": "",
"objectId": "remoteUrl=aHR0cHM6Ly9xaWstYWktb3JnLmdpdGh1Yi5pby9TaWduLU1pY3JvYXBwVjIvcmVtb3RlRW50cnkuanM=&moduleToLoad=AppRoutes&remoteName=signmicroapp/managesign"
},
{
"icon": "far fa-user",
"title": "Add User",
"target": "_self",
"pageType": "form",
"description": "",
"objectId": "lM0xRnM3iE"
}
]
}
],
"menuTitle": "Admin Menu",
"menuType": "Side Menu"
}
]
+1 -2
View File
@@ -28,9 +28,8 @@ services:
image: opensign-mongo
volumes:
- data-volume:/data/db
- ./apps/mongo/mongo-init.sh:/docker-entrypoint-initdb.d/mongo-init.sh:ro
ports:
- "27017:27017"
- "27018:27017"
networks:
- app-network
client: