mirror of
https://github.com/OpenSignLabs/OpenSign.git
synced 2026-08-28 18:59:44 +02:00
fix: implement feature to detect lagunage from browser, resolve conflict
This commit is contained in:
+1
-1
@@ -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://host.docker.internal:27018/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)
|
||||
|
||||
Generated
+2064
-5770
File diff suppressed because it is too large
Load Diff
+12
-12
@@ -4,10 +4,10 @@
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"@formkit/auto-animate": "^0.8.2",
|
||||
"@lottiefiles/dotlottie-react": "^0.7.2",
|
||||
"@lottiefiles/dotlottie-react": "^0.8.5",
|
||||
"@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",
|
||||
"i18next": "^23.12.2",
|
||||
@@ -23,8 +23,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",
|
||||
@@ -50,7 +50,7 @@
|
||||
"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"
|
||||
},
|
||||
@@ -92,10 +92,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",
|
||||
@@ -106,14 +106,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",
|
||||
"mini-css-extract-plugin": "^2.9.0",
|
||||
"postcss": "^8.4.39",
|
||||
"postcss": "^8.4.40",
|
||||
"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"
|
||||
},
|
||||
|
||||
@@ -35,10 +35,15 @@
|
||||
"save":"Save",
|
||||
"cancel":"Cancel",
|
||||
"upgrade-now":"Upgrade now",
|
||||
"upgrade-to":"Upgrade to",
|
||||
"plan":"Plan",
|
||||
"subscribe-card-plan":"Sign 100 docs using API. Only $0.15/doc after that.",
|
||||
"tour-content":"Don't show this again",
|
||||
"pro":"PRO",
|
||||
"team":"TEAM",
|
||||
"user":"User",
|
||||
"docs":"Docs",
|
||||
"session-expired":"Your session has expired.",
|
||||
"public-profile-help":"This is your public URL. Copy or share it with the signer, and you will be able to see all your publicly set templates.",
|
||||
"tagline-help":"This Tagline will appear on your OpenSign public profile for ex. https://opensign.me/alex",
|
||||
"welcome":"Welcome Back!",
|
||||
@@ -108,6 +113,7 @@
|
||||
},
|
||||
"btnLabel":{
|
||||
"sign":"sign",
|
||||
"Sign":"SIGN",
|
||||
"Resend":"Resend",
|
||||
"Revoke":"Revoke",
|
||||
"Delete":"Delete",
|
||||
@@ -134,7 +140,11 @@
|
||||
"Active":"Active",
|
||||
"Role":"Role",
|
||||
"Team":"Team",
|
||||
"Name":"Name"
|
||||
"Name":"Name",
|
||||
"Status":"Status",
|
||||
"created-date":"Created Date",
|
||||
"Type":"Type"
|
||||
|
||||
},
|
||||
"report-help":{
|
||||
"Draft Documents": "These are documents you have started but have not finalized for sending.",
|
||||
@@ -270,27 +280,27 @@
|
||||
"document-sent-alert" : "Document sent successfully!",
|
||||
"template-share-alert" :"Template Shared successfully.",
|
||||
"template-public-alert-1" :"You have successfully made the template public.",
|
||||
"template-public-alert-2" :"You have successfully made the template private.",
|
||||
"template-public-alert-3" :"You need to select a role for the public signers.",
|
||||
"template-public-alert-2" :"You have successfully made the template private.",
|
||||
"template-public-alert-3" :"You need to select a role for the public signers.",
|
||||
"template-public-alert-4": "Please ensure there's at least one signature widget added for all signers.",
|
||||
"template-public-alert-5" : "Since this template has send-in-order enabled, the public role must be positioned at the top.",
|
||||
"template-public-alert-6" :"Please attach signers to all roles except for the public role user.",
|
||||
"template-public-alert-7" : "Please assign at least one public role to make this template public.",
|
||||
"loader":" This might take some time",
|
||||
"pages":"Pages",
|
||||
"document-signed":"Document signed",
|
||||
"close":"Close",
|
||||
"validation-alert":"Validation alert",
|
||||
"validate-alert-mssg" :" The input does not meet the criteria set by the regular expression.",
|
||||
"otp-verification":"OTP verification",
|
||||
"enter-otp":"Enter OTP",
|
||||
"verify":"Verify",
|
||||
"resend":"Resend",
|
||||
"verify-email":"Please verify your email !",
|
||||
"send-otp":" Send OTP",
|
||||
"otp-placeholder":"Enter OTP received over email",
|
||||
"loading-doc":"Loading Document..",
|
||||
"widgets-name":{
|
||||
"template-public-alert-6" :"Please attach signers to all roles except for the public role user.",
|
||||
"template-public-alert-7" : "Please assign at least one public role to make this template public.",
|
||||
"loader":" This might take some time",
|
||||
"pages":"Pages",
|
||||
"document-signed":"Document signed",
|
||||
"close":"Close",
|
||||
"validation-alert":"Validation alert",
|
||||
"validate-alert-mssg" :" The input does not meet the criteria set by the regular expression.",
|
||||
"otp-verification":"OTP verification",
|
||||
"enter-otp":"Enter OTP",
|
||||
"verify":"Verify",
|
||||
"resend":"Resend",
|
||||
"verify-email":"Please verify your email !",
|
||||
"send-otp":" Send OTP",
|
||||
"otp-placeholder":"Enter OTP received over email",
|
||||
"loading-doc":"Loading Document..",
|
||||
"widgets-name":{
|
||||
"signature":"signature",
|
||||
"stamp":"stamp",
|
||||
"initials":"initials",
|
||||
@@ -331,6 +341,11 @@
|
||||
"signature-tab":"Signature",
|
||||
"your-signature":"Your signature",
|
||||
"copy-to-all-pages":"Copy to all pages",
|
||||
"contact-delete-alert":"Are you sure you want to delete this contact?",
|
||||
"reset-password-alert-1":"Reset password link has been sent to your email id",
|
||||
"reset-password-alert-2":"Please setup email adapter ",
|
||||
"reset-password-alert-3":"Reset Your Password",
|
||||
"faild-animation" :"Failed to load animation",
|
||||
"apply":"Apply",
|
||||
"copy-type":{
|
||||
"All pages":"All pages",
|
||||
@@ -493,6 +508,20 @@
|
||||
"master-key":" Master key",
|
||||
"profile-update-alert" :"Profile updated successfully.",
|
||||
"date":"Date",
|
||||
"report-not-found":"Report Not Found",
|
||||
"please-wait":"please wait",
|
||||
"select-foler":"Select Folder",
|
||||
"generated-on":"Generated On",
|
||||
"text-field":"Text field",
|
||||
"font-size":"Font size",
|
||||
"all-right":"All Rights Reserved",
|
||||
"version":"version",
|
||||
"social-media":{
|
||||
"github":"Github",
|
||||
"linked-in":"LinkedIn",
|
||||
"twitter":"Twitter",
|
||||
"discord":"Discord"
|
||||
},
|
||||
"tour-mssg":{
|
||||
"home-layout-1":"You have logged in successfully! Let's take a look.",
|
||||
"home-layout-2":"To upload documents for self-signing or to request others’ signatures, simply select the respective buttons.",
|
||||
@@ -523,7 +552,14 @@
|
||||
"template-placeholder-3":"Drag or click on a field to add it to the document.",
|
||||
"template-placeholder-4":"Drag the placeholder for a role anywhere on the document.Remember, it will appear in the same colour as the name of the recipient for easy reference.",
|
||||
"template-placeholder-5":"Clicking 'Next' will store the current template. After saving, you’ll be prompted to create a new document from this template if you wish.",
|
||||
"webhook-1":"Upgrade now to set webhook"
|
||||
"webhook-1":"Upgrade now to set webhook",
|
||||
"Need your Signature":"Clicking on this card will take you to the list of documents awaiting your review.",
|
||||
"Out for signatures":"Clicking on this card will take you to a list of documents awaiting signature.",
|
||||
"Recent signature requests": "This is a list of documents that are waiting for your signature.",
|
||||
"Recently sent for signatures":"This is a list of documents you've sent to other parties for signature.",
|
||||
"Drafts":"This are documents you have started but have not finalized for sending."
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -35,9 +35,14 @@
|
||||
"save":"Sauvegarder",
|
||||
"cancel":"Annuler",
|
||||
"upgrade-now":"Mettre à jour maintenant",
|
||||
"upgrade-to" :"Mettre à niveau vers",
|
||||
"pro":"PRO",
|
||||
"plan":"Plan",
|
||||
"subscribe-card-plan":"Signez 100 documents à l'aide de l'API. Seulement 0,15 $/doc par la suite.",
|
||||
"tour-content":"Ne montre plus ça",
|
||||
"team":"ÉQUIPE",
|
||||
"docs":"Documents",
|
||||
"session-expired" :"Votre session a expiré.",
|
||||
"user":"Utilisateur",
|
||||
"public-profile-help":"Il s'agit de votre URL publique. Copiez-le ou partagez-le avec le signataire et vous pourrez voir tous vos modèles définis publiquement.",
|
||||
"tagline-help":"Ce slogan apparaîtra sur votre profil public OpenSign par exemple. https://opensign.me/alex",
|
||||
@@ -121,7 +126,10 @@
|
||||
"Active":"Actif",
|
||||
"Role":"Rôle",
|
||||
"Team":"Équipe",
|
||||
"Name":"Nom"
|
||||
"Name":"Nom",
|
||||
"Status":"Statut",
|
||||
"created-date":"Date de création",
|
||||
"Type":"Taper"
|
||||
},
|
||||
"btnLabel":{
|
||||
"sign":"signe",
|
||||
@@ -331,6 +339,11 @@
|
||||
"signature-tab":"Signature",
|
||||
"your-signature" :"Votre signature",
|
||||
"copy-to-all-pages" :"Copier sur toutes les pages",
|
||||
"contact-delete-alert" :"Êtes-vous sûr de vouloir supprimer ce contact ?",
|
||||
"reset-password" :"Le lien de réinitialisation du mot de passe a été envoyé à votre identifiant de messagerie",
|
||||
"reset-password-alert-2" :"Veuillez configurer l'adaptateur de messagerie",
|
||||
"reset-password-alert-3" :"Réinitialisez votre mot de passe",
|
||||
"faild-animation" :"Échec du chargement de l'animation",
|
||||
"apply" :"Appliquer",
|
||||
"copy-type":{
|
||||
"All pages":"Toutes les pages",
|
||||
@@ -493,6 +506,20 @@
|
||||
"master-key" :"La clef maitresse",
|
||||
"profile-update-alert" :"Mise à jour du profil réussie.",
|
||||
"date":"Date",
|
||||
"report-not-found" :"Rapport introuvable",
|
||||
"please-wait" :"S'il vous plaît, attendez",
|
||||
"select-foler":"Sélectionner le dossier",
|
||||
"generated-on" :"Généré le",
|
||||
"text-field" :"Champ de texte",
|
||||
"font-size" :"Taille de police",
|
||||
"all-right" :"Tous droits réservés",
|
||||
"version" :"version",
|
||||
"social-media":{
|
||||
"github":"Github",
|
||||
"linked-in":"LinkedIn",
|
||||
"twitter":"Twitter",
|
||||
"discord":"Discorde"
|
||||
},
|
||||
"tour-mssg":{
|
||||
"home-layout-1":"Vous vous êtes connecté avec succès ! Jetons un coup d'oeil.",
|
||||
"home-layout-2": "Pour télécharger des documents à auto-signature ou pour demander la signature d'autres personnes, sélectionnez simplement les boutons correspondants.",
|
||||
@@ -523,8 +550,12 @@
|
||||
"template-placeholder-3":"Faites glisser ou cliquez sur un champ pour l'ajouter au document.",
|
||||
"template-placeholder-4":"Faites glisser l'espace réservé pour un rôle n'importe où sur le document. N'oubliez pas qu'il apparaîtra dans la même couleur que le nom du destinataire pour une référence facile.",
|
||||
"template-placeholder-5":"Cliquer sur 'Suivant' stockera le modèle actuel. Après l'enregistrement, vous serez invité à créer un nouveau document à partir de ce modèle si vous le souhaitez.",
|
||||
"webhook-1":"Mettez à niveau maintenant pour définir le webhook"
|
||||
|
||||
"webhook-1":"Mettez à niveau maintenant pour définir le webhook",
|
||||
"Need your Signature":"En cliquant sur cette carte, vous accéderez à la liste des documents en attente de révision.",
|
||||
"Out for signatures":"En cliquant sur cette carte, vous accéderez à une liste de documents en attente de signature.",
|
||||
"Recent signature requests": "Voici une liste de documents qui attendent votre signature.",
|
||||
"Recently sent for signatures":"Il s'agit d'une liste de documents que vous avez envoyés à d'autres parties pour signature.",
|
||||
"Drafts":"Il s'agit de documents que vous avez commencés mais que vous n'avez pas finalisés pour envoi."
|
||||
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -2,7 +2,9 @@ import React, { useEffect, useState } from "react";
|
||||
import Package from "../../package.json";
|
||||
import axios from "axios";
|
||||
import { openInNewTab } from "../constant/Utils";
|
||||
import { useTranslation } from "react-i18next";
|
||||
const Footer = () => {
|
||||
const { t } = useTranslation();
|
||||
const [showButton, setShowButton] = useState(false);
|
||||
const [version, setVersion] = useState("");
|
||||
useEffect(() => {
|
||||
@@ -48,9 +50,10 @@ const Footer = () => {
|
||||
<footer className="op-footer op-footer-center py-3 bg-base-300 text-base-content text-center text-[13px]">
|
||||
<aside>
|
||||
<p>
|
||||
All Rights Reserved © {new Date().getFullYear()}
|
||||
{t("all-right")} © {new Date().getFullYear()}
|
||||
<span onClick={openUrl} className="hover:underline cursor-pointer">
|
||||
{appName} ( version: {version ? version : `${Package.version} `})
|
||||
{appName} ( {t("version")}:{" "}
|
||||
{version ? version : `${Package.version} `})
|
||||
</span>
|
||||
</p>
|
||||
</aside>
|
||||
|
||||
@@ -341,6 +341,7 @@ const DashboardCard = (props) => {
|
||||
} text-[25px] lg:text-[30px]`}
|
||||
></i>
|
||||
</span>
|
||||
|
||||
<div className="font-medium">
|
||||
<div className="text-base lg:text-lg">
|
||||
{t(`dashboard-card.${props.Label}`)}
|
||||
@@ -354,7 +355,8 @@ const DashboardCard = (props) => {
|
||||
<Tooltip
|
||||
id={props.Label}
|
||||
iconColor={"white"}
|
||||
message={props?.Data?.tourMessage}
|
||||
message={t(`tour-mssg.${props.Label}`)}
|
||||
// {props?.Data?.tourMessage}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -4,7 +4,9 @@ import ReportTable from "../../primitives/GetReportDisplay";
|
||||
import reportJson from "../../json/ReportJson";
|
||||
import axios from "axios";
|
||||
import Loader from "../../primitives/Loader";
|
||||
import { useTranslation } from "react-i18next";
|
||||
function DashboardReport(props) {
|
||||
const { t } = useTranslation();
|
||||
// console.log("props ", props)
|
||||
const [List, setList] = useState([]);
|
||||
const [isLoader, setIsLoader] = useState(true);
|
||||
@@ -141,7 +143,7 @@ function DashboardReport(props) {
|
||||
) : (
|
||||
<div className="flex items-center justify-center h-[100px] w-full bg-white rounded">
|
||||
<div className="text-center">
|
||||
<p className="text-xl text-black">Report Not Found</p>
|
||||
<p className="text-xl text-black">{t("report-not-found")}</p>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import React, { Suspense, lazy } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
const DashboardButton = lazy(() => import("./DashboardButton"));
|
||||
const DashboardCard = lazy(() => import("./DashboardCard"));
|
||||
const DashboardReport = lazy(() => import("./DashboardReport"));
|
||||
@@ -17,6 +18,7 @@ const buttonList = [
|
||||
}
|
||||
];
|
||||
const GetDashboard = (props) => {
|
||||
const { t } = useTranslation();
|
||||
const Button = ({ label, redirectId, redirectType, icon }) => (
|
||||
<DashboardButton
|
||||
Icon={icon}
|
||||
@@ -37,7 +39,7 @@ const GetDashboard = (props) => {
|
||||
<Suspense
|
||||
fallback={
|
||||
<div className="h-[150px] w-full flex justify-center items-center">
|
||||
loading...
|
||||
{t("loading")}
|
||||
</div>
|
||||
}
|
||||
>
|
||||
|
||||
@@ -506,7 +506,7 @@ function DriveBody(props) {
|
||||
>
|
||||
<i className={menu.icon}></i>
|
||||
<span className="ml-[8px]">
|
||||
{t(`context-menu${menu.type}`)}
|
||||
{t(`context-menu.${menu.type}`)}
|
||||
</span>
|
||||
</ContextMenu.Item>
|
||||
);
|
||||
@@ -518,18 +518,26 @@ function DriveBody(props) {
|
||||
</HoverCard.Trigger>
|
||||
<HoverCard.Portal>
|
||||
<HoverCard.Content className="HoverCardContent" sideOffset={5}>
|
||||
<strong className="text-[13px]">Title: </strong>
|
||||
<strong className="text-[13px]">
|
||||
{t("report-heading.Title")}:{" "}
|
||||
</strong>
|
||||
<span className="text-[12px] font-medium mb-0"> {data.Name}</span>
|
||||
<br />
|
||||
<strong className="text-[13px]">Status: </strong>
|
||||
<strong className="text-[13px]">
|
||||
{t("report-heading.Status")}:{" "}
|
||||
</strong>
|
||||
<span className="text-[12px] font-medium"> {status}</span>
|
||||
<br />
|
||||
<strong className="text-[13px]">Created Date: </strong>
|
||||
<strong className="text-[13px]">
|
||||
{t("report-heading.created-date")}:{" "}
|
||||
</strong>
|
||||
<span className="text-[12px] font-medium">{createddate}</span>
|
||||
<br />
|
||||
{signerExist && (
|
||||
<>
|
||||
<strong className="text-[13px]">Signers: </strong>
|
||||
<strong className="text-[13px]">
|
||||
{t("report-heading.Signers")}:{" "}
|
||||
</strong>
|
||||
{signersName()}
|
||||
</>
|
||||
)}
|
||||
@@ -549,11 +557,11 @@ function DriveBody(props) {
|
||||
<Table striped bordered hover>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Created Date</th>
|
||||
<th>Type</th>
|
||||
<th>Status</th>
|
||||
<th>Action</th>
|
||||
<th>{t("report-heading.Name")}</th>
|
||||
<th>{t("report-heading.created-date")}</th>
|
||||
<th>{t("report-heading.Type")}</th>
|
||||
<th>{t("report-heading.Status")}</th>
|
||||
<th>{t("action")}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@@ -586,25 +594,25 @@ function DriveBody(props) {
|
||||
)}
|
||||
<ModalUi
|
||||
isOpen={isDeleteDoc}
|
||||
title={"Delete Document"}
|
||||
title={t("delete-document")}
|
||||
handleClose={() => setIsDeleteDoc(false)}
|
||||
>
|
||||
<div className="h-full p-[20px] text-base-content">
|
||||
<p>Are you sure you want to delete this document?</p>
|
||||
<p>{t("delete-document-alert")}</p>
|
||||
<div className="h-[1px] w-full bg-[#9f9f9f] my-[15px]"></div>
|
||||
<button
|
||||
onClick={() => handleDeleteDocument(selectDoc)}
|
||||
type="button"
|
||||
className="op-btn op-btn-primary mr-2"
|
||||
>
|
||||
Yes
|
||||
{t("yes")}
|
||||
</button>
|
||||
<button
|
||||
onClick={() => setIsDeleteDoc(false)}
|
||||
type="button"
|
||||
className="op-btn op-btn-neutral"
|
||||
>
|
||||
No
|
||||
{t("no")}
|
||||
</button>
|
||||
</div>
|
||||
</ModalUi>
|
||||
|
||||
@@ -419,19 +419,17 @@ function Header({
|
||||
</button>
|
||||
</div>
|
||||
) : isPublicTemplate ? (
|
||||
<>
|
||||
<div className="flex">
|
||||
<button
|
||||
type="button"
|
||||
className="op-btn op-btn-primary op-btn-sm shadow"
|
||||
onClick={() => {
|
||||
embedWidgetsData();
|
||||
}}
|
||||
>
|
||||
{t("sign-now")}
|
||||
</button>
|
||||
</div>
|
||||
</>
|
||||
<div className="flex">
|
||||
<button
|
||||
type="button"
|
||||
className="op-btn op-btn-primary op-btn-sm shadow"
|
||||
onClick={() => {
|
||||
embedWidgetsData();
|
||||
}}
|
||||
>
|
||||
{t("sign-now")}
|
||||
</button>
|
||||
</div>
|
||||
) : (
|
||||
<div className="flex">
|
||||
<button
|
||||
|
||||
@@ -16,7 +16,7 @@ import RegexParser from "regex-parser";
|
||||
import { emailRegex } from "../../constant/const";
|
||||
import { useTranslation } from "react-i18next";
|
||||
const textWidgetCls =
|
||||
"w-full h-full md:min-w-full md:min-h-full z-[999] text-[12px] rounded-[2px] border-[1px] border-[#007bff] overflow-hidden resize-none outline-none text-base-content item-center whitespace-pre-wrap";
|
||||
"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) {
|
||||
@@ -433,7 +433,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) => {
|
||||
|
||||
@@ -579,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}
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
import React, { useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
function SelectLanguage() {
|
||||
const { i18n } = useTranslation();
|
||||
const languages = [
|
||||
{ value: "en", text: "English" },
|
||||
{ value: "fr", text: "Français" }
|
||||
];
|
||||
const [lang, setLang] = useState("en");
|
||||
// This function put query that helps to
|
||||
// change the language
|
||||
const handleChangeLang = (e) => {
|
||||
setLang(e.target.value);
|
||||
i18n.changeLanguage(e.target.value);
|
||||
};
|
||||
return (
|
||||
<div className={`flex justify-center items-center mt-4`}>
|
||||
<select
|
||||
value={lang}
|
||||
onChange={handleChangeLang}
|
||||
className="op-select op-select-bordered w-[15%] bg-white pt-0"
|
||||
>
|
||||
<option disabled selected>
|
||||
select
|
||||
</option>
|
||||
{languages.map((item) => {
|
||||
return (
|
||||
<option key={item.value} value={item.value}>
|
||||
{item.text}
|
||||
</option>
|
||||
);
|
||||
})}
|
||||
</select>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default SelectLanguage;
|
||||
@@ -1,7 +1,6 @@
|
||||
import React, { useRef, useState, useEffect } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import SignatureCanvas from "react-signature-canvas";
|
||||
|
||||
function SignPad({
|
||||
isSignPad,
|
||||
isStamp,
|
||||
@@ -101,7 +100,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();
|
||||
@@ -213,11 +217,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
|
||||
@@ -227,7 +231,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);
|
||||
|
||||
@@ -1,19 +1,21 @@
|
||||
import React from "react";
|
||||
import ModalUi from "../../primitives/ModalUi";
|
||||
import { fontColorArr, fontsizeArr } from "../../constant/Utils";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
function TextFontSetting(props) {
|
||||
const { t } = useTranslation();
|
||||
return (
|
||||
<ModalUi
|
||||
headerColor={"#dc3545"}
|
||||
isOpen={props.isTextSetting}
|
||||
reduceWidth={"max-w-[350px]"}
|
||||
title={"Text field"}
|
||||
title={t("text-field")}
|
||||
handleClose={() => props.setIsTextSetting(false)}
|
||||
>
|
||||
<div className="h-full p-[20px]">
|
||||
<div className="flex items-center">
|
||||
<span>Font size:</span>
|
||||
<span>{t("font-size")} :</span>
|
||||
<select
|
||||
className="ml-[7px] op-select op-select-bordered op-select-sm focus:outline-none hover:border-base-content text-xs"
|
||||
value={
|
||||
@@ -32,7 +34,7 @@ function TextFontSetting(props) {
|
||||
})}
|
||||
</select>
|
||||
<div className="flex flex-row gap-1 items-center ml-4">
|
||||
<span>color: </span>
|
||||
<span>{t("color")}: </span>
|
||||
<select
|
||||
value={
|
||||
props.fontColor ||
|
||||
@@ -67,7 +69,7 @@ function TextFontSetting(props) {
|
||||
type="button"
|
||||
className="op-btn op-btn-primary mt-2"
|
||||
>
|
||||
save
|
||||
{t("save")}
|
||||
</button>
|
||||
</div>
|
||||
</ModalUi>
|
||||
|
||||
@@ -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>
|
||||
)}
|
||||
|
||||
@@ -2,8 +2,10 @@ import React, { useEffect, useState } from "react";
|
||||
import Parse from "parse";
|
||||
import CreateFolder from "./CreateFolder";
|
||||
import ModalUi from "../../../primitives/ModalUi";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
const FolderModal = (props) => {
|
||||
const { t } = useTranslation();
|
||||
const [clickFolder, setClickFolder] = useState("");
|
||||
const [folderList, setFolderList] = useState([]);
|
||||
const [tabList, setTabList] = useState([]);
|
||||
@@ -147,7 +149,7 @@ const FolderModal = (props) => {
|
||||
return (
|
||||
<div className="text-xs mt-2">
|
||||
<ModalUi
|
||||
title={"Select Folder"}
|
||||
title={t("select-foler")}
|
||||
isOpen={props.isOpenModal}
|
||||
handleClose={handleCancel}
|
||||
>
|
||||
@@ -158,7 +160,7 @@ const FolderModal = (props) => {
|
||||
title="OpenSign™ Drive"
|
||||
onClick={(e) => removeTabListItem(e)}
|
||||
>
|
||||
OpenSign™ Drive /{" "}
|
||||
{t("OpenSign-drive")} /{" "}
|
||||
</span>
|
||||
{tabList &&
|
||||
tabList.map((tab, i) => (
|
||||
@@ -214,7 +216,7 @@ const FolderModal = (props) => {
|
||||
))
|
||||
: !isLoader && (
|
||||
<div className="text-base-content text-center my-2">
|
||||
No data found
|
||||
{t("no-data")}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
@@ -236,27 +238,28 @@ const FolderModal = (props) => {
|
||||
<div className="flex justify-between items-center py-[.75rem] px-[1.25rem]">
|
||||
<div
|
||||
className="op-btn op-btn-seconday op-btn-sm"
|
||||
title="Save Here"
|
||||
title={t("save-here")}
|
||||
onClick={handleCreate}
|
||||
>
|
||||
{isAdd ? (
|
||||
<>
|
||||
<i className="fa-light fa-arrow-left" aria-hidden="true"></i>
|
||||
<span className="text-xs">Back</span>
|
||||
<span className="text-xs">{t("back")}</span>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<i className="fa-light fa-square-plus" aria-hidden="true"></i>
|
||||
<span className="">Add folder</span>
|
||||
<span className="">{t("add-folder")}</span>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
<div
|
||||
className="op-btn op-btn-primary op-btn-sm"
|
||||
title="Save Here"
|
||||
title={t("save-here")}
|
||||
onClick={handleSubmit}
|
||||
>
|
||||
<i className="fa-light fa-save" aria-hidden="true"></i>Save here
|
||||
<i className="fa-light fa-save" aria-hidden="true"></i>
|
||||
{t("save-here")}
|
||||
</div>
|
||||
</div>
|
||||
</ModalUi>
|
||||
|
||||
@@ -1,27 +1,54 @@
|
||||
import React from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { NavLink } from "react-router-dom";
|
||||
|
||||
const SocialMedia = () => {
|
||||
return (
|
||||
<React.Fragment>
|
||||
<NavLink to="https://github.com/opensignlabs/opensign" target="_blank" rel="noopener noreferrer">
|
||||
<i aria-hidden="true" className="fa-brands fa-github"></i>
|
||||
<span className="fa-sr-only">OpenSign's Github</span>
|
||||
</NavLink>
|
||||
<NavLink to="https://www.linkedin.com/company/opensign%E2%84%A2/" target="_blank" rel="noopener noreferrer">
|
||||
<i aria-hidden="true" className="fa-brands fa-linkedin"></i>
|
||||
<span className="fa-sr-only">OpenSign's LinkedIn</span>
|
||||
</NavLink>
|
||||
<NavLink to="https://www.twitter.com/opensignlabs" target="_blank" rel="noopener noreferrer">
|
||||
<i aria-hidden="true" className="fa-brands fa-square-x-twitter"></i>
|
||||
<span className="fa-sr-only">OpenSign's Twitter</span>
|
||||
</NavLink>
|
||||
<NavLink to="https://discord.com/invite/xe9TDuyAyj" target="_blank" rel="noopener noreferrer">
|
||||
<i aria-hidden="true" className="fa-brands fa-discord"></i>
|
||||
<span className="fa-sr-only">OpenSign's Discord</span>
|
||||
</NavLink>
|
||||
</React.Fragment>
|
||||
)
|
||||
}
|
||||
const { t } = useTranslation();
|
||||
|
||||
export default SocialMedia;
|
||||
return (
|
||||
<React.Fragment>
|
||||
<NavLink
|
||||
to="https://github.com/opensignlabs/opensign"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
<i aria-hidden="true" className="fa-brands fa-github"></i>
|
||||
<span className="fa-sr-only">
|
||||
OpenSign's {t("social-media.github")}
|
||||
</span>
|
||||
</NavLink>
|
||||
<NavLink
|
||||
to="https://www.linkedin.com/company/opensign%E2%84%A2/"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
<i aria-hidden="true" className="fa-brands fa-linkedin"></i>
|
||||
<span className="fa-sr-only">
|
||||
OpenSign's {t("social-media.linked-in")}
|
||||
</span>
|
||||
</NavLink>
|
||||
<NavLink
|
||||
to="https://www.twitter.com/opensignlabs"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
<i aria-hidden="true" className="fa-brands fa-square-x-twitter"></i>
|
||||
<span className="fa-sr-only">
|
||||
OpenSign's {t("social-media.twitter")}
|
||||
</span>
|
||||
</NavLink>
|
||||
<NavLink
|
||||
to="https://discord.com/invite/xe9TDuyAyj"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
<i aria-hidden="true" className="fa-brands fa-discord"></i>
|
||||
<span className="fa-sr-only">
|
||||
OpenSign's {t("social-media.discord")}
|
||||
</span>
|
||||
</NavLink>
|
||||
</React.Fragment>
|
||||
);
|
||||
};
|
||||
|
||||
export default SocialMedia;
|
||||
|
||||
@@ -549,20 +549,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 &&
|
||||
@@ -576,7 +573,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) {
|
||||
@@ -595,14 +592,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,
|
||||
@@ -610,34 +608,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." };
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1237,9 +1226,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) => {
|
||||
@@ -1259,14 +1247,14 @@ const calculateFontSize = (position, containerScale, signyourself) => {
|
||||
};
|
||||
//function for embed multiple signature using pdf-lib
|
||||
export const multiSignEmbed = async (
|
||||
xyPositionArray,
|
||||
widgets,
|
||||
pdfDoc,
|
||||
signyourself,
|
||||
scale,
|
||||
pdfOriginalWH,
|
||||
containerWH
|
||||
) => {
|
||||
for (let item of xyPositionArray) {
|
||||
for (let item of widgets) {
|
||||
const containerScale = getContainerScale(
|
||||
pdfOriginalWH,
|
||||
item?.pageNumber,
|
||||
|
||||
@@ -5,11 +5,16 @@ import LanguageDetector from "i18next-browser-languagedetector";
|
||||
|
||||
i18n
|
||||
.use(Backend)
|
||||
.use(LanguageDetector)
|
||||
.use(LanguageDetector) // Use LanguageDetector directly without creating an instance
|
||||
.use(initReactI18next)
|
||||
.init({
|
||||
lng: "en", // Set English as the default language
|
||||
fallbackLng: "en", // Fallback to English if no other language is detected
|
||||
detection: {
|
||||
// Order and from where user language should be detected
|
||||
order: ["navigator", "htmlTag", "path", "subdomain"],
|
||||
// Cache user language on
|
||||
caches: ["localStorage", "cookie"]
|
||||
},
|
||||
debug: true,
|
||||
interpolation: {
|
||||
escapeValue: false // Not needed for react as it escapes by default
|
||||
|
||||
@@ -18,6 +18,7 @@ import TagManager from "react-gtm-module";
|
||||
import Parse from "parse";
|
||||
import "./polyfills";
|
||||
import "./i18n";
|
||||
|
||||
const appId = process.env.REACT_APP_APPID
|
||||
? process.env.REACT_APP_APPID
|
||||
: "opensign";
|
||||
|
||||
@@ -19,9 +19,7 @@ const dashboardJson = [
|
||||
key: "count",
|
||||
Redirect_type: "Report",
|
||||
Redirect_id: "4Hhwbp482K",
|
||||
tourSection: "tourcard1",
|
||||
tourMessage:
|
||||
"Clicking on this card will take you to the list of documents awaiting your review."
|
||||
tourSection: "tourcard1"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -42,9 +40,7 @@ const dashboardJson = [
|
||||
key: "count",
|
||||
Redirect_type: "Report",
|
||||
Redirect_id: "1MwEuxLEkF",
|
||||
tourSection: "tourcard2",
|
||||
tourMessage:
|
||||
"Clicking on this card will take you to a list of documents awaiting signature."
|
||||
tourSection: "tourcard2"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -53,10 +49,9 @@ const dashboardJson = [
|
||||
widget: {
|
||||
type: "report",
|
||||
reportId: "5Go51Q7T8r",
|
||||
label: "Recent signature requests",
|
||||
data: {
|
||||
tourSection: "tourreport1",
|
||||
tourMessage:
|
||||
"This is a list of documents that are waiting for your signature."
|
||||
tourSection: "tourreport1"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -65,10 +60,9 @@ const dashboardJson = [
|
||||
widget: {
|
||||
type: "report",
|
||||
reportId: "d9k3UfYHBc",
|
||||
label: "Recently sent for signatures",
|
||||
data: {
|
||||
tourSection: "tourreport2",
|
||||
tourMessage:
|
||||
"This is a list of documents you've sent to other parties for signature."
|
||||
tourSection: "tourreport2"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -77,10 +71,9 @@ const dashboardJson = [
|
||||
widget: {
|
||||
type: "report",
|
||||
reportId: "kC5mfynCi4",
|
||||
label: "Drafts",
|
||||
data: {
|
||||
tourSection: "tourreport3",
|
||||
tourMessage:
|
||||
"This are documents you have started but have not finalized for sending."
|
||||
tourSection: "tourreport3"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -300,7 +300,7 @@ const HomeLayout = () => {
|
||||
<div className="flex flex-col justify-center items-center py-4 md:py-5 gap-5">
|
||||
<p className="text-xl font-medium">Your session has expired.</p>
|
||||
<button onClick={handleLoginBtn} className="op-btn op-btn-neutral">
|
||||
Login
|
||||
{t("login")}
|
||||
</button>
|
||||
</div>
|
||||
</ModalUi>
|
||||
|
||||
@@ -251,7 +251,7 @@ const AddAdmin = () => {
|
||||
};
|
||||
return (
|
||||
<div className="h-screen flex justify-center">
|
||||
<Title title={t("add-admin")} />
|
||||
<Title title="Add admin" />
|
||||
{state.loading ? (
|
||||
<div className="text-[grey] flex justify-center items-center text-lg md:text-2xl">
|
||||
<Loader />
|
||||
|
||||
@@ -6,8 +6,10 @@ import { useDispatch } from "react-redux";
|
||||
import { saveTourSteps } from "../redux/reducers/TourStepsReducer";
|
||||
import dashboardJson from "../json/dashboardJson";
|
||||
import Loader from "../primitives/Loader";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
const Dashboard = () => {
|
||||
const { t } = useTranslation();
|
||||
const navigate = useNavigate();
|
||||
const dispatch = useDispatch();
|
||||
const { id } = useParams();
|
||||
@@ -40,7 +42,7 @@ const Dashboard = () => {
|
||||
.map((col) => {
|
||||
return {
|
||||
selector: `[data-tut=${col.widget.data.tourSection}]`,
|
||||
content: col.widget.data.tourMessage,
|
||||
content: t(`tour-mssg.${col.widget.data.label}`),
|
||||
position: "top"
|
||||
// style: { backgroundColor: "#abd4d2" },
|
||||
};
|
||||
|
||||
@@ -9,8 +9,10 @@ import { useDispatch } from "react-redux";
|
||||
import { fetchAppInfo } from "../redux/reducers/infoReducer";
|
||||
import { isEnableSubscription } from "../constant/const";
|
||||
import { getAppLogo } from "../constant/Utils";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
function ForgotPassword() {
|
||||
const { t } = useTranslation();
|
||||
const dispatch = useDispatch();
|
||||
const navigate = useNavigate();
|
||||
const [state, setState] = useState({
|
||||
@@ -75,12 +77,10 @@ function ForgotPassword() {
|
||||
<div>
|
||||
<Title title="Forgot password page" />
|
||||
{sentStatus === "success" && (
|
||||
<Alert type="success">
|
||||
Reset password link has been sent to your email id
|
||||
</Alert>
|
||||
<Alert type="success">{t("reset-password-alert-1")}</Alert>
|
||||
)}
|
||||
{sentStatus === "failed" && (
|
||||
<Alert type={"danger"}>Please setup email adapter </Alert>
|
||||
<Alert type={"danger"}>{t("reset-password-alert-2")}</Alert>
|
||||
)}
|
||||
<div className="md:p-10 lg:p-16">
|
||||
<div className="md:p-4 lg:p-10 p-4 bg-base-100 text-base-content op-card">
|
||||
@@ -96,13 +96,13 @@ function ForgotPassword() {
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-x-2">
|
||||
<div>
|
||||
<form onSubmit={handleSubmit}>
|
||||
<h2 className="text-[30px] mt-6">Welcome Back !</h2>
|
||||
<h2 className="text-[30px] mt-6">{t("welcome")}</h2>
|
||||
<span className="text-[12px] text-[#878787]">
|
||||
Reset Your Password
|
||||
{t("reset-password-alert-3")}
|
||||
</span>
|
||||
<div className="w-full my-4 op-card bg-base-100 shadow-md outline outline-1 outline-slate-300/50">
|
||||
<div className="px-6 py-4">
|
||||
<label className="block text-xs">Email</label>
|
||||
<label className="block text-xs">{t("email")}</label>
|
||||
<input
|
||||
type="email"
|
||||
name="email"
|
||||
@@ -116,13 +116,13 @@ function ForgotPassword() {
|
||||
</div>
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-2 text-center text-xs font-bold">
|
||||
<button type="submit" className="op-btn op-btn-primary">
|
||||
Submit
|
||||
{t("submit")}
|
||||
</button>
|
||||
<button
|
||||
onClick={() => navigate("/", { replace: true })}
|
||||
className="op-btn op-btn-secondary"
|
||||
>
|
||||
Login
|
||||
{t("login")}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
@@ -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">
|
||||
{t("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"
|
||||
|
||||
@@ -17,6 +17,7 @@ import { showTenant } from "../redux/reducers/ShowTenant";
|
||||
import { fetchSubscription, getAppLogo, openInNewTab } from "../constant/Utils";
|
||||
import Loader from "../primitives/Loader";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import SelectLanguage from "../components/pdf/SelectLanguage";
|
||||
function Login() {
|
||||
const { t } = useTranslation();
|
||||
const navigate = useNavigate();
|
||||
@@ -605,9 +606,10 @@ function Login() {
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Title title={t("login-page")} />
|
||||
<Title title="Login Page" />
|
||||
{state.loading && (
|
||||
<div
|
||||
aria-live="assertive"
|
||||
@@ -766,6 +768,7 @@ function Login() {
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<SelectLanguage />
|
||||
{state.alertMsg && (
|
||||
<Alert type={state.alertType}>
|
||||
<div className="ml-3">{state.alertMsg}</div>
|
||||
|
||||
@@ -820,8 +820,8 @@ function PdfRequestFiles(props) {
|
||||
setWidgetsTour(true);
|
||||
} else {
|
||||
setIsUiLoading(true);
|
||||
|
||||
const pngUrl = checkUser[0].placeHolder;
|
||||
// `widgets` is Used to return widgets details with page number of current user
|
||||
const widgets = checkUser?.[0]?.placeHolder;
|
||||
let pdfArrBuffer;
|
||||
//`contractDocument` function used to get updated SignedUrl
|
||||
//resolved issue of sign document by multiple signers simultaneously
|
||||
@@ -859,14 +859,14 @@ function PdfRequestFiles(props) {
|
||||
}
|
||||
//embed multi signature in pdf
|
||||
const pdfBytes = await multiSignEmbed(
|
||||
pngUrl,
|
||||
widgets,
|
||||
pdfDoc,
|
||||
isSignYourSelfFlow,
|
||||
scale,
|
||||
pdfOriginalWH,
|
||||
containerWH
|
||||
);
|
||||
// console.log("pdfte", pdfBytes);
|
||||
// console.log("pdfte", pdfBytes);
|
||||
//get ExistUserPtr object id of user class to get tenantDetails
|
||||
const objectId = pdfDetails?.[0]?.ExtUserPtr?.UserId?.objectId;
|
||||
//get ExistUserPtr email to get userDetails
|
||||
@@ -875,178 +875,166 @@ function PdfRequestFiles(props) {
|
||||
let activeMailAdapter = "";
|
||||
if (res === "Error: Something went wrong!") {
|
||||
setHandleError(t("something-went-wrong-mssg"));
|
||||
setIsLoading({
|
||||
isLoad: false
|
||||
});
|
||||
setIsLoading({ isLoad: false });
|
||||
} else if (!res || res?.length === 0) {
|
||||
activeMailAdapter = "";
|
||||
} else if (res[0] && res.length) {
|
||||
activeMailAdapter = res[0]?.active_mail_adapter;
|
||||
}
|
||||
//function for call to embed signature in pdf and get digital signature pdf
|
||||
try {
|
||||
const res = await signPdfFun(
|
||||
pdfBytes,
|
||||
documentId,
|
||||
signerObjectId,
|
||||
setIsAlert,
|
||||
objectId,
|
||||
isSubscribed,
|
||||
activeMailAdapter,
|
||||
pngUrl
|
||||
const resSign = await signPdfFun(
|
||||
pdfBytes,
|
||||
documentId,
|
||||
signerObjectId,
|
||||
objectId,
|
||||
isSubscribed,
|
||||
activeMailAdapter,
|
||||
widgets
|
||||
);
|
||||
if (resSign && resSign.status === "success") {
|
||||
setPdfUrl(res.data);
|
||||
setIsSigned(true);
|
||||
setSignedSigners([]);
|
||||
setUnSignedSigners([]);
|
||||
getDocumentDetails(true);
|
||||
const index = pdfDetails?.[0].Signers.findIndex(
|
||||
(x) => x.Email === currentUser?.email
|
||||
);
|
||||
if (res && res.status === "success") {
|
||||
setPdfUrl(res.data);
|
||||
setIsSigned(true);
|
||||
setSignedSigners([]);
|
||||
setUnSignedSigners([]);
|
||||
getDocumentDetails(true);
|
||||
const index = pdfDetails?.[0].Signers.findIndex(
|
||||
(x) => x.Email === currentUser?.email
|
||||
);
|
||||
const newIndex = index + 1;
|
||||
const usermail = {
|
||||
Email: pdfDetails?.[0]?.Placeholders[newIndex]?.email || ""
|
||||
};
|
||||
const user = usermail?.Email
|
||||
? usermail
|
||||
: pdfDetails?.[0]?.Signers[newIndex];
|
||||
if (sendmail !== "false" && sendInOrder) {
|
||||
const requestBody = pdfDetails?.[0]?.RequestBody;
|
||||
const requestSubject = pdfDetails?.[0]?.RequestSubject;
|
||||
if (user) {
|
||||
const expireDate = pdfDetails?.[0].ExpiryDate.iso;
|
||||
const newDate = new Date(expireDate);
|
||||
const localExpireDate = newDate.toLocaleDateString(
|
||||
"en-US",
|
||||
{
|
||||
day: "numeric",
|
||||
month: "long",
|
||||
year: "numeric"
|
||||
}
|
||||
);
|
||||
let senderEmail = pdfDetails?.[0].ExtUserPtr.Email;
|
||||
let senderPhone = pdfDetails?.[0]?.ExtUserPtr?.Phone;
|
||||
const senderName = `${pdfDetails?.[0].ExtUserPtr.Name}`;
|
||||
|
||||
try {
|
||||
const imgPng =
|
||||
"https://qikinnovation.ams3.digitaloceanspaces.com/logo.png";
|
||||
let url = `${localStorage.getItem(
|
||||
"baseUrl"
|
||||
)}functions/sendmailv3`;
|
||||
const headers = {
|
||||
"Content-Type": "application/json",
|
||||
"X-Parse-Application-Id":
|
||||
localStorage.getItem("parseAppId"),
|
||||
sessionToken: localStorage.getItem("accesstoken")
|
||||
};
|
||||
const objectId = user?.objectId;
|
||||
const hostUrl = window.location.origin;
|
||||
//encode this url value `${pdfDetails?.[0].objectId}/${user.Email}/${objectId}` to base64 using `btoa` function
|
||||
let encodeBase64;
|
||||
if (objectId) {
|
||||
encodeBase64 = btoa(
|
||||
`${pdfDetails?.[0].objectId}/${user.Email}/${objectId}`
|
||||
);
|
||||
} else {
|
||||
encodeBase64 = btoa(
|
||||
`${pdfDetails?.[0].objectId}/${user.Email}`
|
||||
);
|
||||
}
|
||||
const hostPublicUrl = isStaging
|
||||
? "https://staging-app.opensignlabs.com"
|
||||
: "https://app.opensignlabs.com";
|
||||
let signPdf = props?.templateId
|
||||
? `${hostPublicUrl}/login/${encodeBase64}`
|
||||
: `${hostUrl}/login/${encodeBase64}`;
|
||||
const openSignUrl =
|
||||
"https://www.opensignlabs.com/contact-us";
|
||||
const orgName = pdfDetails[0]?.ExtUserPtr.Company
|
||||
? pdfDetails[0].ExtUserPtr.Company
|
||||
: "";
|
||||
const themeBGcolor = themeColor;
|
||||
let replaceVar;
|
||||
if (requestBody && requestSubject && isSubscribed) {
|
||||
const replacedRequestBody = requestBody.replace(
|
||||
/"/g,
|
||||
"'"
|
||||
);
|
||||
const htmlReqBody =
|
||||
"<html><head><meta http-equiv='Content-Type' content='text/html; charset=UTF-8' /></head><body>" +
|
||||
replacedRequestBody +
|
||||
"</body> </html>";
|
||||
|
||||
const variables = {
|
||||
document_title: pdfDetails?.[0].Name,
|
||||
sender_name: senderName,
|
||||
sender_mail: senderEmail,
|
||||
sender_phone: senderPhone,
|
||||
receiver_name: user.Name,
|
||||
receiver_email: user.Email,
|
||||
receiver_phone: user.Phone,
|
||||
expiry_date: localExpireDate,
|
||||
company_name: orgName,
|
||||
signing_url: `<a href=${signPdf}>Sign here</a>`
|
||||
};
|
||||
replaceVar = replaceMailVaribles(
|
||||
requestSubject,
|
||||
htmlReqBody,
|
||||
variables
|
||||
);
|
||||
}
|
||||
|
||||
let params = {
|
||||
mailProvider: activeMailAdapter,
|
||||
extUserId: extUserId,
|
||||
recipient: user.Email,
|
||||
subject: requestSubject
|
||||
? replaceVar?.subject
|
||||
: `${pdfDetails?.[0].ExtUserPtr.Name} has requested you to sign "${pdfDetails?.[0].Name}"`,
|
||||
from: senderEmail,
|
||||
html: requestBody
|
||||
? replaceVar?.body
|
||||
: "<html><head><meta http-equiv='Content-Type' content='text/html; charset=UTF-8' /> </head> <body> <div style='background-color: #f5f5f5; padding: 20px'=> <div style=' box-shadow: rgba(0, 0, 0, 0.1) 0px 4px 12px;background: white;padding-bottom: 20px;'> <div style='padding:10px 10px 0 10px'><img src=" +
|
||||
imgPng +
|
||||
" height='50' style='padding: 20px,width:170px,height:40px' /></div> <div style=' padding: 2px;font-family: system-ui;background-color:" +
|
||||
themeBGcolor +
|
||||
";'><p style='font-size: 20px;font-weight: 400;color: white;padding-left: 20px;' > Digital Signature Request</p></div><div><p style='padding: 20px;font-family: system-ui;font-size: 14px; margin-bottom: 10px;'> " +
|
||||
pdfDetails?.[0].ExtUserPtr.Name +
|
||||
" has requested you to review and sign <strong> " +
|
||||
pdfDetails?.[0].Name +
|
||||
"</strong>.</p><div style='padding: 5px 0px 5px 25px;display: flex;flex-direction: row;justify-content: space-around;'><table> <tr> <td style='font-weight:bold;font-family:sans-serif;font-size:15px'>Sender</td> <td> </td> <td style='color:#626363;font-weight:bold'>" +
|
||||
senderEmail +
|
||||
"</td></tr><tr><td style='font-weight:bold;font-family:sans-serif;font-size:15px'>Organization</td> <td> </td><td style='color:#626363;font-weight:bold'> " +
|
||||
orgName +
|
||||
"</td></tr> <tr> <td style='font-weight:bold;font-family:sans-serif;font-size:15px'>Expires on</td><td> </td> <td style='color:#626363;font-weight:bold'>" +
|
||||
localExpireDate +
|
||||
"</td></tr><tr> <td></td> <td> </td></tr></table> </div> <div style='margin-left:70px'><a href=" +
|
||||
signPdf +
|
||||
"> <button style='padding: 12px 12px 12px 12px;background-color: #d46b0f;color: white; border: 0px;box-shadow: rgba(0, 0, 0, 0.05) 0px 6px 24px 0px,rgba(0, 0, 0, 0.08) 0px 0px 0px 1px;font-weight:bold;margin-top:30px'>Sign here</button></a> </div> <div style='display: flex; justify-content: center;margin-top: 10px;'> </div></div></div><div><p> This is an automated email from OpenSign™. For any queries regarding this email, please contact the sender " +
|
||||
senderEmail +
|
||||
" directly.If you think this email is inappropriate or spam, you may file a complaint with OpenSign™ <a href= " +
|
||||
openSignUrl +
|
||||
" target=_blank>here</a>.</p> </div></div></body> </html>"
|
||||
};
|
||||
await axios.post(url, params, {
|
||||
headers: headers
|
||||
});
|
||||
} catch (error) {
|
||||
console.log("error", error);
|
||||
const newIndex = index + 1;
|
||||
const usermail = {
|
||||
Email: pdfDetails?.[0]?.Placeholders[newIndex]?.email || ""
|
||||
};
|
||||
const user = usermail?.Email
|
||||
? usermail
|
||||
: pdfDetails?.[0]?.Signers[newIndex];
|
||||
if (sendmail !== "false" && sendInOrder) {
|
||||
const requestBody = pdfDetails?.[0]?.RequestBody;
|
||||
const requestSubject = pdfDetails?.[0]?.RequestSubject;
|
||||
if (user) {
|
||||
const expireDate = pdfDetails?.[0].ExpiryDate.iso;
|
||||
const newDate = new Date(expireDate);
|
||||
const localExpireDate = newDate.toLocaleDateString(
|
||||
"en-US",
|
||||
{
|
||||
day: "numeric",
|
||||
month: "long",
|
||||
year: "numeric"
|
||||
}
|
||||
);
|
||||
let senderEmail = pdfDetails?.[0].ExtUserPtr.Email;
|
||||
let senderPhone = pdfDetails?.[0]?.ExtUserPtr?.Phone;
|
||||
const senderName = `${pdfDetails?.[0].ExtUserPtr.Name}`;
|
||||
|
||||
try {
|
||||
const imgPng =
|
||||
"https://qikinnovation.ams3.digitaloceanspaces.com/logo.png";
|
||||
let url = `${localStorage.getItem(
|
||||
"baseUrl"
|
||||
)}functions/sendmailv3`;
|
||||
const headers = {
|
||||
"Content-Type": "application/json",
|
||||
"X-Parse-Application-Id":
|
||||
localStorage.getItem("parseAppId"),
|
||||
sessionToken: localStorage.getItem("accesstoken")
|
||||
};
|
||||
const objectId = user?.objectId;
|
||||
const hostUrl = window.location.origin;
|
||||
//encode this url value `${pdfDetails?.[0].objectId}/${user.Email}/${objectId}` to base64 using `btoa` function
|
||||
let encodeBase64;
|
||||
if (objectId) {
|
||||
encodeBase64 = btoa(
|
||||
`${pdfDetails?.[0].objectId}/${user.Email}/${objectId}`
|
||||
);
|
||||
} else {
|
||||
encodeBase64 = btoa(
|
||||
`${pdfDetails?.[0].objectId}/${user.Email}`
|
||||
);
|
||||
}
|
||||
const hostPublicUrl = isStaging
|
||||
? "https://staging-app.opensignlabs.com"
|
||||
: "https://app.opensignlabs.com";
|
||||
let signPdf = props?.templateId
|
||||
? `${hostPublicUrl}/login/${encodeBase64}`
|
||||
: `${hostUrl}/login/${encodeBase64}`;
|
||||
const openSignUrl =
|
||||
"https://www.opensignlabs.com/contact-us";
|
||||
const orgName = pdfDetails[0]?.ExtUserPtr.Company
|
||||
? pdfDetails[0].ExtUserPtr.Company
|
||||
: "";
|
||||
const themeBGcolor = themeColor;
|
||||
let replaceVar;
|
||||
if (requestBody && requestSubject && isSubscribed) {
|
||||
const replacedRequestBody = requestBody.replace(
|
||||
/"/g,
|
||||
"'"
|
||||
);
|
||||
const htmlReqBody =
|
||||
"<html><head><meta http-equiv='Content-Type' content='text/html; charset=UTF-8' /></head><body>" +
|
||||
replacedRequestBody +
|
||||
"</body> </html>";
|
||||
|
||||
const variables = {
|
||||
document_title: pdfDetails?.[0].Name,
|
||||
sender_name: senderName,
|
||||
sender_mail: senderEmail,
|
||||
sender_phone: senderPhone,
|
||||
receiver_name: user.Name,
|
||||
receiver_email: user.Email,
|
||||
receiver_phone: user.Phone,
|
||||
expiry_date: localExpireDate,
|
||||
company_name: orgName,
|
||||
signing_url: `<a href=${signPdf}>Sign here</a>`
|
||||
};
|
||||
replaceVar = replaceMailVaribles(
|
||||
requestSubject,
|
||||
htmlReqBody,
|
||||
variables
|
||||
);
|
||||
}
|
||||
|
||||
let params = {
|
||||
mailProvider: activeMailAdapter,
|
||||
extUserId: extUserId,
|
||||
recipient: user.Email,
|
||||
subject: requestSubject
|
||||
? replaceVar?.subject
|
||||
: `${pdfDetails?.[0].ExtUserPtr.Name} has requested you to sign "${pdfDetails?.[0].Name}"`,
|
||||
from: senderEmail,
|
||||
html: requestBody
|
||||
? replaceVar?.body
|
||||
: "<html><head><meta http-equiv='Content-Type' content='text/html; charset=UTF-8' /> </head> <body> <div style='background-color: #f5f5f5; padding: 20px'=> <div style=' box-shadow: rgba(0, 0, 0, 0.1) 0px 4px 12px;background: white;padding-bottom: 20px;'> <div style='padding:10px 10px 0 10px'><img src=" +
|
||||
imgPng +
|
||||
" height='50' style='padding: 20px,width:170px,height:40px' /></div> <div style=' padding: 2px;font-family: system-ui;background-color:" +
|
||||
themeBGcolor +
|
||||
";'><p style='font-size: 20px;font-weight: 400;color: white;padding-left: 20px;' > Digital Signature Request</p></div><div><p style='padding: 20px;font-family: system-ui;font-size: 14px; margin-bottom: 10px;'> " +
|
||||
pdfDetails?.[0].ExtUserPtr.Name +
|
||||
" has requested you to review and sign <strong> " +
|
||||
pdfDetails?.[0].Name +
|
||||
"</strong>.</p><div style='padding: 5px 0px 5px 25px;display: flex;flex-direction: row;justify-content: space-around;'><table> <tr> <td style='font-weight:bold;font-family:sans-serif;font-size:15px'>Sender</td> <td> </td> <td style='color:#626363;font-weight:bold'>" +
|
||||
senderEmail +
|
||||
"</td></tr><tr><td style='font-weight:bold;font-family:sans-serif;font-size:15px'>Organization</td> <td> </td><td style='color:#626363;font-weight:bold'> " +
|
||||
orgName +
|
||||
"</td></tr> <tr> <td style='font-weight:bold;font-family:sans-serif;font-size:15px'>Expires on</td><td> </td> <td style='color:#626363;font-weight:bold'>" +
|
||||
localExpireDate +
|
||||
"</td></tr><tr> <td></td> <td> </td></tr></table> </div> <div style='margin-left:70px'><a href=" +
|
||||
signPdf +
|
||||
"> <button style='padding: 12px 12px 12px 12px;background-color: #d46b0f;color: white; border: 0px;box-shadow: rgba(0, 0, 0, 0.05) 0px 6px 24px 0px,rgba(0, 0, 0, 0.08) 0px 0px 0px 1px;font-weight:bold;margin-top:30px'>Sign here</button></a> </div> <div style='display: flex; justify-content: center;margin-top: 10px;'> </div></div></div><div><p> This is an automated email from OpenSign™. For any queries regarding this email, please contact the sender " +
|
||||
senderEmail +
|
||||
" directly.If you think this email is inappropriate or spam, you may file a complaint with OpenSign™ <a href= " +
|
||||
openSignUrl +
|
||||
" target=_blank>here</a>.</p> </div></div></body> </html>"
|
||||
};
|
||||
await axios.post(url, params, {
|
||||
headers: headers
|
||||
});
|
||||
} catch (error) {
|
||||
console.log("error", error);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
setIsAlert({
|
||||
isShow: true,
|
||||
alertMessage: t("something-went-wrong-mssg")
|
||||
});
|
||||
}
|
||||
} catch (err) {
|
||||
setIsAlert({
|
||||
isShow: true,
|
||||
alertMessage: t("something-went-wrong-mssg")
|
||||
});
|
||||
} else {
|
||||
setIsUiLoading(false);
|
||||
setIsAlert({ isShow: true, alertMessage: resSign.message });
|
||||
}
|
||||
} catch (err) {
|
||||
setIsUiLoading(false);
|
||||
@@ -1659,25 +1647,18 @@ function PdfRequestFiles(props) {
|
||||
<ModalUi
|
||||
isOpen={isAlert.isShow}
|
||||
title={t("alert-message")}
|
||||
handleClose={() => {
|
||||
setIsAlert({
|
||||
isShow: false,
|
||||
alertMessage: ""
|
||||
});
|
||||
}}
|
||||
handleClose={() =>
|
||||
setIsAlert({ isShow: false, alertMessage: "" })
|
||||
}
|
||||
>
|
||||
<div className="h-full p-[20px]">
|
||||
<p>{isAlert.alertMessage}</p>
|
||||
<div className="h-[1px] w-full my-[15px] bg-[#9f9f9f]"></div>
|
||||
<button
|
||||
onClick={() => {
|
||||
setIsAlert({
|
||||
isShow: false,
|
||||
alertMessage: ""
|
||||
});
|
||||
}}
|
||||
onClick={() =>
|
||||
setIsAlert({ isShow: false, alertMessage: "" })
|
||||
}
|
||||
type="button"
|
||||
className="op-btn op-btn-primary"
|
||||
className="op-btn op-btn-primary mt-3 px-4"
|
||||
>
|
||||
{t("ok")}
|
||||
</button>
|
||||
|
||||
@@ -14,6 +14,7 @@ import { isEnableSubscription } from "../constant/const";
|
||||
import { getAppLogo, openInNewTab } from "../constant/Utils";
|
||||
import Loader from "../primitives/Loader";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import SelectLanguage from "../components/pdf/SelectLanguage";
|
||||
const Signup = () => {
|
||||
const { width } = useWindowSize();
|
||||
const { t } = useTranslation();
|
||||
@@ -322,7 +323,7 @@ const Signup = () => {
|
||||
<Loader />
|
||||
</div>
|
||||
)}
|
||||
<Title title={t("signup-page")} />
|
||||
<Title title="Signup page" />
|
||||
{appInfo && appInfo.applogo ? (
|
||||
<div className="md:p-10 lg:p-16">
|
||||
<div className="md:p-4 lg:p-10 p-4 bg-base-100 text-base-content op-card">
|
||||
@@ -513,6 +514,7 @@ const Signup = () => {
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<SelectLanguage />
|
||||
<Alert type={state.alertType}>{state.alertMsg}</Alert>
|
||||
</div>
|
||||
) : (
|
||||
|
||||
@@ -710,15 +710,28 @@ function SignYourSelf() {
|
||||
setIsUiLoading(false);
|
||||
if (err && err.message.includes("is encrypted.")) {
|
||||
setIsAlert({
|
||||
header: "Error",
|
||||
isShow: true,
|
||||
alertMessage: t("encrypted-pdf-alert")
|
||||
});
|
||||
} else {
|
||||
console.log("err in signing", err);
|
||||
setIsAlert({
|
||||
isShow: true,
|
||||
alertMessage: t("something-went-wrong-mssg")
|
||||
});
|
||||
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: t("something-went-wrong-mssg")
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -726,6 +739,7 @@ function SignYourSelf() {
|
||||
console.log("err in embedselfsign ", err);
|
||||
setIsUiLoading(false);
|
||||
setIsAlert({
|
||||
header: "Error",
|
||||
isShow: true,
|
||||
alertMessage: t("something-went-wrong-mssg")
|
||||
});
|
||||
@@ -772,40 +786,24 @@ function SignYourSelf() {
|
||||
alert(t("something-went-wrong-mssg"));
|
||||
}
|
||||
}
|
||||
//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);
|
||||
alert(t("something-went-wrong-mssg"));
|
||||
});
|
||||
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
|
||||
@@ -1233,16 +1231,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 || t("alert")}
|
||||
handleClose={() => {
|
||||
setIsAlert({
|
||||
isShow: false,
|
||||
alertMessage: ""
|
||||
});
|
||||
}}
|
||||
handleClose={() =>
|
||||
setIsAlert({ isShow: false, alertMessage: "" })
|
||||
}
|
||||
>
|
||||
<div className="p-[20px] h-full">
|
||||
<p>{isAlert.alertMessage}</p>
|
||||
|
||||
@@ -1319,7 +1319,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 +1351,7 @@ const TemplatePlaceholder = () => {
|
||||
{currentEmail.length > 0 && (
|
||||
<>
|
||||
<button
|
||||
onClick={() => {
|
||||
handleCreateDocModal();
|
||||
}}
|
||||
onClick={() => handleCreateDocModal()}
|
||||
type="button"
|
||||
className="op-btn op-btn-primary"
|
||||
>
|
||||
@@ -1377,17 +1375,13 @@ const TemplatePlaceholder = () => {
|
||||
<ModalUi
|
||||
isOpen={isShowEmail}
|
||||
title={t("signers-alert")}
|
||||
handleClose={() => {
|
||||
setIsShowEmail(false);
|
||||
}}
|
||||
handleClose={() => setIsShowEmail(false)}
|
||||
>
|
||||
<div className="h-full p-[20px]">
|
||||
<p>{t("template-creation-alert-1")}</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 +1430,6 @@ const TemplatePlaceholder = () => {
|
||||
allPages={allPages}
|
||||
pageNumber={pageNumber}
|
||||
signKey={signKey}
|
||||
// signerObjId={signerObjId}
|
||||
Id={uniqueId}
|
||||
/>
|
||||
{/* pdf header which contain funish back button */}
|
||||
@@ -1548,9 +1541,7 @@ const TemplatePlaceholder = () => {
|
||||
/>
|
||||
</div>
|
||||
) : (
|
||||
<div
|
||||
className={`w-[23%] bg-[#FFFFFF] min-h-screen overflow-y-auto hide-scrollbar`}
|
||||
>
|
||||
<div className="w-[23%] bg-[#FFFFFF] min-h-screen overflow-y-auto hide-scrollbar">
|
||||
<div className={`max-h-screen`}>
|
||||
<SignerListPlace
|
||||
isMailSend={isMailSend}
|
||||
|
||||
@@ -65,7 +65,7 @@ const UpdateExistUserAdmin = () => {
|
||||
};
|
||||
return (
|
||||
<div className="h-screen flex justify-center">
|
||||
<Title title={t("add-admin")} />
|
||||
<Title title="Add admin" />
|
||||
{isAlert.msg && (
|
||||
<Alert type={isAlert.type}>
|
||||
<div className="ml-3">{isAlert.msg}</div>
|
||||
|
||||
@@ -20,7 +20,7 @@ import { useTranslation } from "react-i18next";
|
||||
|
||||
function UserProfile() {
|
||||
const navigate = useNavigate();
|
||||
const { t, i18n } = useTranslation();
|
||||
const { t } = useTranslation();
|
||||
let UserProfile = JSON.parse(localStorage.getItem("UserInformation"));
|
||||
let extendUser = JSON.parse(localStorage.getItem("Extand_Class"));
|
||||
const [parseBaseUrl] = useState(localStorage.getItem("baseUrl"));
|
||||
@@ -53,11 +53,6 @@ function UserProfile() {
|
||||
extendUser && extendUser?.[0]?.Tagline
|
||||
);
|
||||
const [isTeam, setIsTeam] = useState(false);
|
||||
const languages = [
|
||||
{ value: "en", text: "English" },
|
||||
{ value: "fr", text: "French" }
|
||||
];
|
||||
const [lang, setLang] = useState("en");
|
||||
|
||||
useEffect(() => {
|
||||
getUserDetail();
|
||||
@@ -311,12 +306,7 @@ function UserProfile() {
|
||||
setJobTitle(extendUser?.[0]?.JobTitle);
|
||||
setIsDisableDocId(extendUser?.[0]?.HeaderDocId);
|
||||
};
|
||||
// This function put query that helps to
|
||||
// change the language
|
||||
const handleChangeLang = (e) => {
|
||||
setLang(e.target.value);
|
||||
i18n.changeLanguage(e.target.value);
|
||||
};
|
||||
|
||||
return (
|
||||
<React.Fragment>
|
||||
<Title title={"Profile"} />
|
||||
@@ -369,29 +359,6 @@ function UserProfile() {
|
||||
</div>
|
||||
</div>
|
||||
<ul className="w-full flex flex-col p-2 text-sm">
|
||||
<li
|
||||
className={`flex justify-between items-center border-t-[1px] border-gray-300 break-all ${
|
||||
editmode ? "py-1.5" : "py-2"
|
||||
}`}
|
||||
>
|
||||
<span className="font-semibold">{t("language")}:</span>{" "}
|
||||
<select
|
||||
value={lang}
|
||||
onChange={handleChangeLang}
|
||||
className="select select-bordered w-[30%] border-[1px] rounded-lg p-2 max-w-xs"
|
||||
>
|
||||
<option disabled selected>
|
||||
select
|
||||
</option>
|
||||
{languages.map((item) => {
|
||||
return (
|
||||
<option key={item.value} value={item.value}>
|
||||
{item.text}
|
||||
</option>
|
||||
);
|
||||
})}
|
||||
</select>
|
||||
</li>
|
||||
<li
|
||||
className={`flex justify-between items-center border-t-[1px] border-gray-300 break-all ${
|
||||
editmode ? "py-1.5" : "py-2"
|
||||
@@ -406,10 +373,7 @@ function UserProfile() {
|
||||
onChange={(e) => SetName(e.target.value)}
|
||||
/>
|
||||
) : (
|
||||
<span>
|
||||
{/* {localStorage.getItem("username")} */}
|
||||
<p>{t("greeting", { name })}</p>
|
||||
</span>
|
||||
<span>{localStorage.getItem("username")}</span>
|
||||
)}
|
||||
</li>
|
||||
<li
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
import React, { useState, useEffect } from "react";
|
||||
import { DotLottieReact } from "@lottiefiles/dotlottie-react";
|
||||
import Loader from "./Loader";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
const LottieWithLoader = () => {
|
||||
const { t } = useTranslation();
|
||||
const [isLoaded, setIsLoaded] = useState(false);
|
||||
const [hasError, setHasError] = useState(false);
|
||||
const [animationSrc, setAnimationSrc] = useState(null);
|
||||
@@ -34,7 +36,7 @@ const LottieWithLoader = () => {
|
||||
<Loader />
|
||||
</div>
|
||||
)}
|
||||
{hasError && <div className="error">Failed to load animation</div>}
|
||||
{hasError && <div className="error">{t("faild-animation")}</div>}
|
||||
{isLoaded && animationSrc && (
|
||||
<DotLottieReact
|
||||
src={animationSrc}
|
||||
|
||||
@@ -1137,7 +1137,7 @@ const ReportTable = (props) => {
|
||||
<button
|
||||
key={index}
|
||||
onClick={() => handleActionBtn(act, item)}
|
||||
title={act.hoverLabel}
|
||||
title={t(`btnLabel.${act.hoverLabel}`)}
|
||||
className={`${
|
||||
act?.btnColor ? act.btnColor : ""
|
||||
} op-btn op-btn-sm`}
|
||||
@@ -1153,7 +1153,7 @@ const ReportTable = (props) => {
|
||||
>
|
||||
<div className="m-[20px]">
|
||||
<div className="text-lg font-normal text-black">
|
||||
Are you sure you want to delete this contact?
|
||||
{t("contact-delete-alert")}
|
||||
</div>
|
||||
<hr className="bg-[#ccc] mt-4 " />
|
||||
<div className="flex items-center mt-3 gap-2 text-white">
|
||||
@@ -1161,13 +1161,13 @@ const ReportTable = (props) => {
|
||||
onClick={() => handleDelete(item)}
|
||||
className="op-btn op-btn-primary"
|
||||
>
|
||||
Yes
|
||||
{t("yes")}
|
||||
</button>
|
||||
<button
|
||||
onClick={handleClose}
|
||||
className="op-btn op-btn-secondary"
|
||||
>
|
||||
No
|
||||
{t("no")}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1363,7 +1363,7 @@ const ReportTable = (props) => {
|
||||
onClick={() =>
|
||||
handleActionBtn(act, item)
|
||||
}
|
||||
title={t(`btnLabel.${act.btnLabel}`)}
|
||||
title={t(`btnLabel.${act.hoverLabel}`)}
|
||||
className={
|
||||
act.action !== "option"
|
||||
? `${
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import React, { useState } from "react";
|
||||
import "../styles/signature.css";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
function CustomModal({
|
||||
show,
|
||||
@@ -9,6 +10,7 @@ function CustomModal({
|
||||
declineDoc,
|
||||
setIsDecline
|
||||
}) {
|
||||
const { t } = useTranslation();
|
||||
const [reason, setReason] = useState("");
|
||||
return (
|
||||
show && (
|
||||
@@ -41,7 +43,7 @@ function CustomModal({
|
||||
declineDoc(reason);
|
||||
}}
|
||||
>
|
||||
Yes
|
||||
{t("yes")}
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
@@ -51,7 +53,7 @@ function CustomModal({
|
||||
setIsDecline({ isDeclined: false });
|
||||
}}
|
||||
>
|
||||
Close
|
||||
{t("close")}
|
||||
</button>
|
||||
</div>
|
||||
</>
|
||||
|
||||
@@ -1,22 +1,25 @@
|
||||
import React from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
|
||||
const SubscribeCard = ({ plan, price }) => {
|
||||
const { t } = useTranslation();
|
||||
const navigate = useNavigate();
|
||||
return (
|
||||
<div className="op-card op-bg-primary text-primary-content w-full shadow-lg">
|
||||
<div className="op-card-body">
|
||||
<h2 className="op-card-title">Upgrade to {plan ? plan : "PRO"} Plan</h2>
|
||||
<h2 className="op-card-title">
|
||||
{t("upgrade-to")} {plan ? plan : "PRO"} {t("plan")}
|
||||
</h2>
|
||||
<p>
|
||||
${price ? price : "29.99"}/month: Sign 100 docs using API. Only
|
||||
$0.15/doc after that.
|
||||
${price ? price : "29.99"}/month: {t("subscribe-card-plan")}
|
||||
</p>
|
||||
<div className="op-card-actions justify-end">
|
||||
<button
|
||||
onClick={() => navigate("/subscription")}
|
||||
className="op-btn op-btn-accent"
|
||||
>
|
||||
Upgrade Now
|
||||
{t("upgrade-now")}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import React, { useState } from "react";
|
||||
|
||||
import { useTranslation } from "react-i18next";
|
||||
export default function TourContentWithBtn({ message, isChecked }) {
|
||||
const { t } = useTranslation();
|
||||
const [isCheck, setIsCheck] = useState(false);
|
||||
|
||||
const handleCheck = () => {
|
||||
@@ -19,7 +20,7 @@ export default function TourContentWithBtn({ message, isChecked }) {
|
||||
checked={isCheck}
|
||||
onChange={handleCheck}
|
||||
/>
|
||||
<span className="#787878 text-[12px]">Don't show this again</span>
|
||||
<span className="#787878 text-[12px]">{t("tour-content")}</span>
|
||||
</label>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -2,8 +2,10 @@ import React, { useState, useEffect } from "react";
|
||||
import Parse from "parse";
|
||||
import { Outlet, useNavigate, useLocation } from "react-router-dom";
|
||||
import ModalUi from "./ModalUi";
|
||||
import { useTranslation } from "react-i18next";
|
||||
const Validate = () => {
|
||||
const navigate = useNavigate();
|
||||
const { t } = useTranslation();
|
||||
const location = useLocation();
|
||||
const [isUserValid, setIsUserValid] = useState(true);
|
||||
useEffect(() => {
|
||||
@@ -51,9 +53,9 @@ const Validate = () => {
|
||||
) : (
|
||||
<ModalUi showHeader={false} isOpen={true} showClose={false}>
|
||||
<div className="flex flex-col justify-center items-center py-4 md:py-5 gap-5">
|
||||
<p className="text-xl font-medium">Your session has expired.</p>
|
||||
<p className="text-xl font-medium">{this("session-expired")}</p>
|
||||
<button onClick={handleLoginBtn} className="op-btn op-btn-neutral">
|
||||
Login
|
||||
{t("login")}
|
||||
</button>
|
||||
</div>
|
||||
</ModalUi>
|
||||
|
||||
@@ -20,15 +20,21 @@ const ValidateRoute = () => {
|
||||
})();
|
||||
}, []);
|
||||
const handlelogout = async () => {
|
||||
try {
|
||||
// if (Parse?.User?.current()) {
|
||||
// Parse?.User?.logOut();
|
||||
// }
|
||||
localStorage.removeItem("accesstoken");
|
||||
} catch (err) {
|
||||
console.log("err ", err);
|
||||
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>;
|
||||
};
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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}} has requested you to review and sign <b>"{{document_title}}"</b>.</p><p>Your signature is crucial to proceed with the next steps as it signifies your agreement and authorization.</p><br><p>{{signing_url}}</p><br><p>If you have any questions or need further clarification regarding the document or the signing process, please contact the sender.</p><br><p>Thanks</p><p> Team OpenSign™</p><br></body> </html>`;
|
||||
const 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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -4,7 +4,8 @@ async function DocumentAftersave(request) {
|
||||
console.log('new entry is insert in contracts_Document');
|
||||
const createdAt = request.object.get('createdAt');
|
||||
const Folder = request.object.get('Type');
|
||||
const ip = request?.headers?.['x-real-ip'] || request.object?.get('OriginIp') || '';
|
||||
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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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: {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
Generated
+2447
-2638
File diff suppressed because it is too large
Load Diff
@@ -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",
|
||||
"aws-sdk": "^2.1665.0",
|
||||
"axios": "^1.7.2",
|
||||
"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"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user