Merge branch 'staging' of https://github.com/OpenSignLabs/OpenSign into rotatepage_document

This commit is contained in:
RaktimaNXG
2024-09-03 12:27:37 +05:30
31 changed files with 397 additions and 237 deletions
+4 -4
View File
@@ -79,7 +79,7 @@
"eslint-plugin-react": "^7.34.3",
"lint-staged": "^15.2.8",
"mini-css-extract-plugin": "^2.9.1",
"postcss": "^8.4.41",
"postcss": "^8.4.44",
"prettier": "^3.3.3",
"pretty-quick": "^4.0.0",
"tailwindcss": "^3.4.10",
@@ -18207,9 +18207,9 @@
}
},
"node_modules/postcss": {
"version": "8.4.41",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.41.tgz",
"integrity": "sha512-TesUflQ0WKZqAvg52PWL6kHgLKP6xB6heTOdoYM0Wt2UHyxNa4K25EZZMgKns3BH1RLVbZCREPpLY0rhnNoHVQ==",
"version": "8.4.44",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.44.tgz",
"integrity": "sha512-Aweb9unOEpQ3ezu4Q00DPvvM2ZTUitJdNKeP/+uQgr1IBIqu574IaZoURId7BKtWMREwzKa9OgzPzezWGPWFQw==",
"funding": [
{
"type": "opencollective",
+1 -1
View File
@@ -111,7 +111,7 @@
"eslint-plugin-react": "^7.34.3",
"lint-staged": "^15.2.8",
"mini-css-extract-plugin": "^2.9.1",
"postcss": "^8.4.41",
"postcss": "^8.4.44",
"prettier": "^3.3.3",
"pretty-quick": "^4.0.0",
"tailwindcss": "^3.4.10",
@@ -41,6 +41,7 @@
"upgrade-now": "Upgrade now",
"upgrade-to": "Upgrade to",
"plan": "Plan",
"subscribe-card-teamplan":"Unlock the full power of collaboration! Create unlimited organizations, teams, and hierarchies. Share templates seamlessly across teams and assign custom user roles. Elevate your workflow today!",
"subscribe-card-plan": "Unlock premium features starting at just {{premiumPrice}}/month. Enjoy enhanced performance and only {{addonPrice}} per additional credit after your included premium credits.",
"user-name-limit-char": "To have a username less than 8 character please subscribe",
"tour-content": "Don't show this again",
@@ -217,8 +218,8 @@
"initials": "Initials",
"API": "API",
"api-token": "API Token",
"regenerate-token": "Regenerate Token",
"generate-token": "Generate Token",
"regenerate-token": "Regenerate Live Token",
"generate-token": "Generate Live Token",
"view-docs": "View Docs",
"generate-token-alert": "Are you sure you want to regenerate token it will expire old token?",
"yes": "Yes",
@@ -633,5 +634,11 @@
"generate-test-token":"Generate Test Token",
"regenerate-test-token":"Regenerate Test Token",
"help-test-token":"This token can be used to test the APIs at the https://sandbox.opensignlabs.com/api/v1 endpoint, allowing you to conduct unlimited document signatures. Please note that the sandbox API will sign your documents with self-signed certificates, which may not be recognized as valid by Adobe. Once youve completed your testing, you can upgrade to one of our paid plans to generate a production token.",
"help-api-token":"This token can be used to access the production APIs at the {{origin}}/api/v1 endpoint. It can only be generated on one of our paid plans."
"help-api-token":"This token can be used to access the production APIs at the {{origin}}/api/v1 endpoint. It can only be generated on one of our paid plans.",
"Add-Webhook":"Add Webhook",
"quotamailselfsign": "You've reached your limit of 20 emails for this month. Upgrade now to continue sending emails directly.",
"quotamail": "You've reached your limit of 20 signature request emails for this month. Upgrade now to continue sending emails directly.",
"quotamailTip":"Tip: You can still sign unlimited documents by manually sharing the signing request links below.",
"quotamailhead":"Quota Reached"
}
@@ -42,6 +42,7 @@
"upgrade-to": "Mettre à niveau vers",
"pro": "PRO",
"plan": "Offre",
"subscribe-card-teamplan":"Libérez toute la puissance de la collaboration ! Créez un nombre illimité d'organisations, d'équipes et de hiérarchies. Partagez des modèles de manière transparente entre les équipes et attribuez des rôles d'utilisateur personnalisés. Améliorez votre flux de travail dès aujourd'hui !",
"subscribe-card-plan": "Débloquez des fonctionnalités premium à partir de seulement {{premiumPrice}}/mois. Bénéficiez de performances améliorées et de seulement {{addonPrice}} par crédit supplémentaire après vos crédits premium inclus.",
"user-name-limit-char": "Pour avoir un nom d'utilisateur de moins de 8 caractères s'il vous plaît s'abonner",
"tour-content": "Ne plus afficher",
@@ -216,8 +217,8 @@
"initials": "Initiales",
"API": "API",
"api-token": "Jeton API",
"regenerate-token": "Régénérer le jeton",
"generate-token": "Générer un jeton",
"regenerate-token": "Régénérer en direct jeton",
"generate-token": "Générer en direct jeton",
"view-docs": "Afficher les documents",
"generate-token-alert": "Êtes-vous sûr de vouloir régénérer le jeton, votre ancien jeton sera supprimer?",
"yes": "Oui",
@@ -632,5 +633,11 @@
"generate-test-token": "Générer jeton de test",
"regenerate-test-token":"Régénérer le jeton de test",
"help-test-token":"Ce jeton peut être utilisé pour tester les API au niveau du point de terminaison https://sandbox.opensignlabs.com/api/v1, vous permettant ainsi d'effectuer un nombre illimité de signatures de documents. Veuillez noter que l'API sandbox signera vos documents avec des certificats auto-signés, qui peuvent ne pas être reconnus comme valides par Adobe. Une fois vos tests terminés, vous pouvez passer à lun de nos forfaits payants pour générer un jeton de production.",
"help-api-token":"Ce jeton peut être utilisé pour accéder aux API de production au point de terminaison {{origin}}/api/v1. Il ne peut être généré que sur l'un de nos forfaits payants."
"help-api-token":"Ce jeton peut être utilisé pour accéder aux API de production au point de terminaison {{origin}}/api/v1. Il ne peut être généré que sur l'un de nos forfaits payants.",
"Add-Webhook":"Ajouter Webhook",
"quotamailselfsign": "Vous avez atteint votre limite de 20 e-mails pour ce mois. Mettez à niveau maintenant pour continuer à envoyer des e-mails directement.",
"quotamail": "Vous avez atteint votre limite de 20 e-mails de demande de signature pour ce mois. Mettez à niveau maintenant pour continuer à envoyer des e-mails directement.",
"quotamailTip":"Astuce : Vous pouvez toujours signer un nombre illimité de documents en partageant manuellement les liens de demande de signature ci-dessous.",
"quotamailhead":"Quota atteint"
}
+1 -1
View File
@@ -262,7 +262,7 @@ const BulkSendUi = (props) => {
quantity: 500,
priceperbulksend: 0.15,
price: (75.0).toFixed(2),
totalcredits: _resAddon.addon
totalcredits: obj?.totalcredits + _resAddon.addon
}));
}
}
@@ -15,7 +15,8 @@ function EmailComponent({
sender,
setIsAlert,
extUserId,
activeMailAdapter
activeMailAdapter,
planCode
}) {
const { t } = useTranslation();
const [emailList, setEmailList] = useState([]);
@@ -34,7 +35,7 @@ function EmailComponent({
const imgPng =
"https://qikinnovation.ams3.digitaloceanspaces.com/logo.png";
let url = `${localStorage.getItem("baseUrl")}functions/sendmailv3/`;
let url = `${localStorage.getItem("baseUrl")}functions/sendmailv3`;
const headers = {
"Content-Type": "application/json",
"X-Parse-Application-Id": localStorage.getItem("parseAppId"),
@@ -50,6 +51,7 @@ function EmailComponent({
recipient: emailList[i],
subject: `${sender.name} has signed the doc - ${pdfName}`,
from: sender.email,
plan: planCode,
html:
"<html><head><meta http-equiv='Content-Type' content='text/html; charset=UTF-8' /></head><body> <div style='background-color:#f5f5f5;padding:20px'> <div style='box-shadow: rgba(0, 0, 0, 0.1) 0px 4px 12px;background-color:white;'> <div><img src=" +
imgPng +
@@ -74,24 +76,19 @@ function EmailComponent({
});
}
}
if (sendMail && sendMail.data.result.status === "success") {
if (sendMail?.data?.result?.status === "success") {
setSuccessEmail(true);
setIsEmail(false);
setTimeout(() => {
setSuccessEmail(false);
setIsEmail(false);
setEmailValue("");
setEmailList([]);
}, 1500);
setIsLoading(false);
} else if (sendMail && sendMail.data.result.status === "error") {
} else if (sendMail?.data?.result?.status === "quota-reached") {
setIsLoading(false);
setIsEmail(false);
setIsAlert({
isShow: true,
alertMessage: t("something-went-wrong-mssg")
});
setIsAlert({ isShow: true, alertMessage: "quotareached" });
setEmailValue("");
setEmailList([]);
} else {
+6 -6
View File
@@ -260,7 +260,7 @@ function GenerateToken() {
</div>
<button
onClick={handleGenerateTestToken}
className="op-btn op-btn-primary w-[200px] md:w-auto"
className="op-btn op-btn-primary w-[210px] md:w-auto"
>
{apitestToken
? t("regenerate-test-token")
@@ -301,7 +301,7 @@ function GenerateToken() {
</div>
<button
onClick={apiToken ? handleModal : handleSubmit}
className="op-btn op-btn-primary w-[200px] md:w-auto"
className="op-btn op-btn-primary w-[210px] md:w-auto"
>
{apiToken ? t("regenerate-token") : t("generate-token")}
</button>
@@ -332,14 +332,14 @@ function GenerateToken() {
"https://docs.opensignlabs.com/docs/API-docs/opensign-api-v-1"
)
}
className="op-btn op-btn-secondary mt-2 md:mb-3 px-8 w-[200px] md:w-auto"
className="op-btn op-btn-secondary mt-2 md:mb-3 px-8 w-[210px] md:w-auto"
>
{t("view-docs")}
</button>
<button
type="button"
onClick={() => handleBuyAPIsModal()}
className="op-btn op-btn-secondary mt-2 mb-3 px-8 w-[200px] md:w-auto"
className="op-btn op-btn-accent mt-2 mb-3 px-8 w-[210px] md:w-auto"
>
{t("buycredits")}
</button>
@@ -420,9 +420,9 @@ function GenerateToken() {
</form>
</ModalUi>
</div>
{isSubscribe?.plan === "freeplan" && isEnableSubscription && (
{isEnableSubscription && isSubscribe?.plan === "freeplan" && (
<div data-tut="apisubscribe">
<SubscribeCard plan_code={isSubscribe?.plan} />
<SubscribeCard />
</div>
)}
</>
@@ -133,6 +133,7 @@ function PdfRequestFiles(props) {
const [documentId, setDocumentId] = useState("");
const [isPublicContact, setIsPublicContact] = useState(false);
const [pdfArrayBuffer, setPdfArrayBuffer] = useState("");
const [plancode, setPlanCode] = useState("");
const isHeader = useSelector((state) => state.showHeader);
const divRef = useRef(null);
@@ -246,6 +247,7 @@ function PdfRequestFiles(props) {
const plan = res.plan;
const billingDate = res?.billingDate;
const status = res?.status;
setPlanCode(plan);
if (plan === "freeplan") {
return true;
} else if (billingDate) {
@@ -986,6 +988,7 @@ function PdfRequestFiles(props) {
? replaceVar?.subject
: `${pdfDetails?.[0].ExtUserPtr.Name} has requested you to sign "${pdfDetails?.[0].Name}"`,
from: senderEmail,
plan: plancode,
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=" +
+64 -45
View File
@@ -61,6 +61,7 @@ import PdfZoom from "../components/pdf/PdfZoom";
import LottieWithLoader from "../primitives/DotLottieReact";
import { useTranslation } from "react-i18next";
import RotateAlert from "../components/RotateAlert";
import QuotaCard from "../primitives/QuotaCard";
function PlaceHolderSign() {
const { t } = useTranslation();
@@ -150,8 +151,8 @@ function PlaceHolderSign() {
const [isCustomize, setIsCustomize] = useState(false);
const [zoomPercent, setZoomPercent] = useState(0);
const [scale, setScale] = useState(1);
const [pdfRotateBase64, setPdfRotatese64] = useState("");
const [planCode, setPlanCode] = useState("");
const isMobile = window.innerWidth < 767;
const [, drop] = useDrop({
accept: "BOX",
@@ -240,6 +241,7 @@ function PlaceHolderSign() {
const res = await fetchSubscription();
const plan = res.plan;
const billingDate = res.billingDate;
setPlanCode(plan);
if (plan === "freeplan") {
return true;
} else if (billingDate) {
@@ -1058,7 +1060,7 @@ function PlaceHolderSign() {
try {
const imgPng =
"https://qikinnovation.ams3.digitaloceanspaces.com/logo.png";
let url = `${localStorage.getItem("baseUrl")}functions/sendmailv3/`;
let url = `${localStorage.getItem("baseUrl")}functions/sendmailv3`;
const headers = {
"Content-Type": "application/json",
"X-Parse-Application-Id": localStorage.getItem("parseAppId"),
@@ -1113,6 +1115,7 @@ function PlaceHolderSign() {
? replaceVar?.subject
: `${senderName} has requested you to sign "${documentName}"`,
from: senderEmail,
plan: planCode,
html: isCustomize
? 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=" +
@@ -1143,7 +1146,7 @@ function PlaceHolderSign() {
console.log("error", error);
}
}
if (sendMail.data.result.status === "success") {
if (sendMail?.data?.result?.status === "success") {
setMailStatus("success");
try {
let data;
@@ -1156,9 +1159,8 @@ function PlaceHolderSign() {
} else {
data = { SendMail: true };
}
await axios
.put(
try {
await axios.put(
`${localStorage.getItem(
"baseUrl"
)}classes/contracts_Document/${documentId}`,
@@ -1170,21 +1172,21 @@ function PlaceHolderSign() {
"X-Parse-Session-Token": localStorage.getItem("accesstoken")
}
}
)
.then(() => {})
.catch((err) => {
console.log("axois err ", err);
});
);
} catch (err) {
console.log("axois err ", err);
}
} catch (e) {
console.log("error", e);
}
setIsSend(true);
setIsMailSend(true);
const loadObj = {
isLoad: false
};
setIsLoading(loadObj);
setIsLoading({ isLoad: false });
setIsUiLoading(false);
} else if (sendMail?.data?.result?.status === "quota-reached") {
setMailStatus("quotareached");
setIsSend(true);
setIsMailSend(true);
setIsUiLoading(false);
} else {
setMailStatus("failed");
@@ -1829,7 +1831,7 @@ function PlaceHolderSign() {
<span className="ml-[5px] mr-[5px]">{t("or")}</span>
<span className="h-[1px] w-[20%] bg-[#ccc]"></span>
</div>
<div className="mt-3 mb-3">{handleShareList()}</div>
<div className="my-3">{handleShareList()}</div>
</>
)}
</div>
@@ -1838,7 +1840,11 @@ function PlaceHolderSign() {
{/* this modal is used show send mail message and after send mail success message */}
<ModalUi
isOpen={isSend}
title={t("Mails Sent")}
title={
mailStatus === "quotareached"
? t("quotamailhead")
: t("Mails Sent")
}
handleClose={() => {
setIsSend(false);
setSignerPos([]);
@@ -1852,40 +1858,53 @@ function PlaceHolderSign() {
<p>{t("placeholder-alert-4")}</p>
{isCurrUser && <p>{t("placeholder-alert-5")}</p>}
</div>
) : mailStatus === "quotareached" ? (
<div className="flex flex-col gap-y-3">
<QuotaCard
handleClose={() => {
setIsSend(false);
setSignerPos([]);
navigate("/report/1MwEuxLEkF");
}}
/>
<div className="my-3">{handleShareList()}</div>
</div>
) : (
<p>{t("placeholder-alert-6")}</p>
)}
{!mailStatus && (
<div className="w-full h-[1px] bg-[#9f9f9f] my-[15px]"></div>
)}
<div
className={
mailStatus === "success"
? "flex justify-center mt-1"
: ""
}
>
{isCurrUser && (
<button
onClick={() => handleRecipientSign()}
type="button"
className="op-btn op-btn-primary mr-1"
>
{t("yes")}
</button>
)}
<button
onClick={() => {
setIsSend(false);
setSignerPos([]);
navigate("/report/1MwEuxLEkF");
}}
type="button"
className="op-btn op-btn-ghost"
{mailStatus !== "quotareached" && (
<div
className={
mailStatus === "success"
? "flex justify-center mt-1"
: ""
}
>
{isCurrUser ? t("no") : t("close")}
</button>
</div>
{isCurrUser && (
<button
onClick={() => handleRecipientSign()}
type="button"
className="op-btn op-btn-primary mr-1"
>
{t("yes")}
</button>
)}
<button
onClick={() => {
setIsSend(false);
setSignerPos([]);
navigate("/report/1MwEuxLEkF");
}}
type="button"
className="op-btn op-btn-ghost"
>
{isCurrUser ? t("no") : t("close")}
</button>
</div>
)}
</div>
</ModalUi>
<ModalUi
+38 -2
View File
@@ -4,7 +4,7 @@ import checkmark from "../assets/images/checkmark.png";
import plansArr from "../json/plansArr";
import Title from "../components/Title";
import Parse from "parse";
import { openInNewTab } from "../constant/Utils";
import { openInNewTab, saveLanguageInLocal } from "../constant/Utils";
import Loader from "../primitives/Loader";
import { useTranslation } from "react-i18next";
const listItemStyle = {
@@ -119,6 +119,30 @@ const PlanSubscriptions = () => {
}
}
};
const handleLogout = async () => {
try {
Parse?.User?.logOut();
} catch (err) {
console.log("Err", err);
}
let appdata = localStorage.getItem("userSettings");
let applogo = localStorage.getItem("appLogo");
let defaultmenuid = localStorage.getItem("defaultmenuid");
let PageLanding = localStorage.getItem("PageLanding");
let baseUrl = localStorage.getItem("baseUrl");
let appid = localStorage.getItem("parseAppId");
localStorage.clear();
saveLanguageInLocal(i18n);
localStorage.setItem("appLogo", applogo);
localStorage.setItem("defaultmenuid", defaultmenuid);
localStorage.setItem("PageLanding", PageLanding);
localStorage.setItem("userSettings", appdata);
localStorage.setItem("baseUrl", baseUrl);
localStorage.setItem("parseAppId", appid);
navigate("/");
};
return (
<>
<Title title={"Subscriptions"} />
@@ -129,7 +153,13 @@ const PlanSubscriptions = () => {
) : (
<div className="overflow-y-auto max-h-full">
<div className="block my-2">
<div className="flex flex-col justify-center items-center w-full">
<div className="flex flex-col justify-center items-center w-full relative">
<button
className="md:hidden op-btn op-btn-primary op-btn-sm h-[40px] w-[250px] shadow-lg"
onClick={() => handleLogout()}
>
Log out
</button>
<div
role="tablist"
className="op-tabs op-tabs-boxed bg-base-100 my-2 shadow-lg transition-all"
@@ -150,6 +180,12 @@ const PlanSubscriptions = () => {
</a>
</div>
<ul className="op-card flex flex-col md:flex-row h-full bg-base-100 justify-center shadow-lg">
<button
className="hidden md:block -top-12 right-1 absolute w-[150px] h-[40px] op-btn op-btn-primary op-btn-sm shadow-lg"
onClick={() => handleLogout()}
>
{t("log-out")}
</button>
{plansArr.map((item) => (
<li
className="flex flex-col text-center border-collapse border-[1px] border-gray-300 max-w-[250px]"
+38 -35
View File
@@ -57,6 +57,7 @@ import PdfZoom from "../components/pdf/PdfZoom";
import Loader from "../primitives/Loader";
import { useTranslation } from "react-i18next";
import RotateAlert from "../components/RotateAlert";
import QuotaCard from "../primitives/QuotaCard";
//For signYourself inProgress section signer can add sign and complete doc sign.
function SignYourSelf() {
const { t } = useTranslation();
@@ -128,56 +129,37 @@ function SignYourSelf() {
const isHeader = useSelector((state) => state.showHeader);
const [scale, setScale] = useState(1);
const [pdfRotateBase64, setPdfRotatese64] = useState("");
const [isRotate, setIsRotate] = useState({
status: false,
degree: 0
});
const [isRotate, setIsRotate] = useState({ status: false, degree: 0 });
const [isSubscribe, setIsSubscribe] = useState({ plan: "", isValid: true });
const divRef = useRef(null);
const nodeRef = useRef(null);
const [, drop] = useDrop({
accept: "BOX",
drop: (item, monitor) => addPositionOfSignature(item, monitor),
collect: (monitor) => ({
isOver: !!monitor.isOver()
})
collect: (monitor) => ({ isOver: !!monitor.isOver() })
});
const pdfRef = useRef();
const [{ isDragSign }, dragSignature] = useDrag({
type: "BOX",
item: {
id: 1,
text: "signature"
},
collect: (monitor) => ({
isDragSign: !!monitor.isDragging()
})
item: { id: 1, text: "signature" },
collect: (monitor) => ({ isDragSign: !!monitor.isDragging() })
});
const [{ isDragStamp }, dragStamp] = useDrag({
type: "BOX",
item: {
id: 2,
text: "stamp"
},
collect: (monitor) => ({
isDragStamp: !!monitor.isDragging()
})
item: { id: 2, text: "stamp" },
collect: (monitor) => ({ isDragStamp: !!monitor.isDragging() })
});
const index = xyPostion?.findIndex((object) => {
return object.pageNumber === pageNumber;
});
// rowlevel={JSON.parse(localStorage.getItem("rowlevel"))}
const rowLevel =
localStorage.getItem("rowlevel") &&
JSON.parse(localStorage.getItem("rowlevel"));
const signObjId =
rowLevel && rowLevel?.id
? rowLevel.id
: rowLevel?.objectId && rowLevel.objectId;
const documentId = docId ? docId : signObjId && signObjId;
const senderUser =
localStorage.getItem(
@@ -217,6 +199,12 @@ function SignYourSelf() {
//function for get document details for perticular signer with signer'object id
const getDocumentDetails = async (showComplete) => {
try {
const subscribe = await checkIsSubscribed();
setIsSubscribe(subscribe);
} catch (err) {
console.log("err in fetch sub", err);
}
try {
let isCompleted;
//getting document details
@@ -585,8 +573,7 @@ function SignYourSelf() {
docCls.id = documentId;
docCls.set("Placeholders", xyPostion);
docCls.set("IsSignyourself", true);
const res = await docCls.save();
console.log("Res", res);
await docCls.save();
} catch (e) {
console.log("error", e);
alert(t("something-went-wrong-mssg"));
@@ -730,7 +717,7 @@ function SignYourSelf() {
//function for get digital signature
const signPdfFun = async (base64Url, documentId) => {
let isCustomCompletionMail = false;
const getIsSubscribe = await checkIsSubscribed();
const tenantDetails = await getTenantDetails(jsonSender.objectId);
if (tenantDetails && tenantDetails === "user does not exist!") {
alert(t("user-not-exist"));
@@ -738,7 +725,7 @@ function SignYourSelf() {
if (
tenantDetails?.CompletionBody &&
tenantDetails?.CompletionSubject &&
getIsSubscribe.isValid
isSubscribe?.isValid
) {
isCustomCompletionMail = true;
}
@@ -1255,14 +1242,29 @@ function SignYourSelf() {
<div className="w-full md:w-[95%]">
<ModalUi
isOpen={isAlert.isShow}
title={isAlert?.header || t("alert")}
title={
isAlert.alertMessage === "quotareached"
? false
: isAlert?.header || t("alert")
}
handleClose={() =>
setIsAlert({ isShow: false, alertMessage: "" })
isAlert.alertMessage === "quotareached"
? false
: setIsAlert({ isShow: false, alertMessage: "" })
}
>
<div className="p-[20px] h-full">
<p>{isAlert.alertMessage}</p>
</div>
{isAlert.alertMessage === "quotareached" ? (
<QuotaCard
isSignyourself={true}
handlClose={() =>
setIsAlert({ isShow: false, alertMessage: "" })
}
/>
) : (
<div className="p-[20px] h-full">
<p>{isAlert.alertMessage}</p>
</div>
)}
</ModalUi>
{/* this modal is used show this document is already sign */}
@@ -1342,6 +1344,7 @@ function SignYourSelf() {
setIsAlert={setIsAlert}
extUserId={extUserId}
activeMailAdapter={activeMailAdapter}
planCode={isSubscribe?.plan}
/>
{/* pdf header which contain funish back button */}
<Header
+2 -6
View File
@@ -467,13 +467,9 @@ const TeamList = () => {
)}
</>
)}
{!validplan[isSubscribe.plan] && isEnableSubscription && !isLoader && (
{isEnableSubscription && !validplan[isSubscribe.plan] && !isLoader && (
<div data-tut="apisubscribe">
<SubscribeCard
plan={"TEAMS"}
price={"20"}
plan_code={isSubscribe.plan}
/>
<SubscribeCard plan="TEAMS" />
</div>
)}
</div>
@@ -21,7 +21,7 @@ const UpdateExistUserAdmin = () => {
try {
const isAdminExist = await Parse.Cloud.run("checkadminexist");
if (isAdminExist !== "not_exist") {
console.log("isAdminExist ", isAdminExist);
// console.log("isAdminExist ", isAdminExist);
setErrMsg("Admin already exists.");
}
} catch (err) {
+2 -6
View File
@@ -421,13 +421,9 @@ const UserList = () => {
)}
</>
)}
{!validplan[isSubscribe.plan] && isEnableSubscription && !isLoader && (
{isEnableSubscription && !validplan[isSubscribe.plan] && !isLoader && (
<div data-tut="apisubscribe">
<SubscribeCard
plan={"TEAMS"}
price={"20"}
plan_code={isSubscribe.plan}
/>
<SubscribeCard plan="TEAMS" />
</div>
)}
</div>
+4 -5
View File
@@ -10,7 +10,6 @@ import Tooltip from "../primitives/Tooltip";
import Loader from "../primitives/Loader";
import SubscribeCard from "../primitives/SubscribeCard";
import Tour from "reactour";
import { validplan } from "../json/plansArr";
import { useTranslation } from "react-i18next";
function Webhook() {
@@ -90,7 +89,7 @@ function Webhook() {
};
const handleModal = () => {
if (!validplan[isSubscribe.plan] && isEnableSubscription) {
if (!isSubscribe?.isValid && isEnableSubscription) {
setIsTour(true);
} else {
setIsModal(!isModal);
@@ -146,7 +145,7 @@ function Webhook() {
</div>
<ModalUi
isOpen={isModal}
title={"Regenerate Token"}
title={t("Add-Webhook")}
handleClose={handleModal}
>
{error && <Alert type="danger">{error}</Alert>}
@@ -178,9 +177,9 @@ function Webhook() {
</div>
</ModalUi>
</div>
{!validplan[isSubscribe.plan] && isEnableSubscription && (
{isEnableSubscription && !isSubscribe?.isValid && (
<div data-tut="webhooksubscribe">
<SubscribeCard plan_code={isSubscribe.plan} />
<SubscribeCard />
</div>
)}
</>
@@ -1661,8 +1661,8 @@ const ReportTable = (props) => {
)}
</>
)}
{!validplan[isSubscribe.plan] &&
isEnableSubscription && (
{isEnableSubscription &&
!validplan[isSubscribe.plan] && (
<>
<div
className="op-btn op-btn-sm op-btn-circle op-btn-ghost text-primary-content absolute right-2 top-2 z-40"
@@ -1670,14 +1670,11 @@ const ReportTable = (props) => {
>
</div>
<SubscribeCard
plan={"TEAMS"}
price={"20"}
/>
<SubscribeCard plan="TEAMS" />
</>
)}
{validplan[isSubscribe.plan] &&
!isEnableSubscription && (
{!isEnableSubscription &&
validplan[isSubscribe.plan] && (
<>
<h3 className="text-base-content font-bold text-lg pt-[15px] px-[20px]">
{t("share-with")}
+5 -3
View File
@@ -21,9 +21,11 @@ const ModalUi = ({
>
{showHeader && (
<>
<h3 className="text-base-content font-bold text-lg pt-[15px] px-[20px]">
{title}
</h3>
{title && (
<h3 className="text-base-content font-bold text-lg pt-[15px] px-[20px]">
{title}
</h3>
)}
{showClose && (
<button
className="op-btn op-btn-sm op-btn-circle op-btn-ghost text-base-content absolute right-2 top-2"
+53
View File
@@ -0,0 +1,53 @@
import React from "react";
import { useTranslation } from "react-i18next";
import { useNavigate } from "react-router-dom";
const QuotaCard = ({ isSignyourself, handlClose }) => {
const { t } = useTranslation();
const navigate = useNavigate();
return isSignyourself ? (
<>
<div
className="op-btn op-btn-sm op-btn-circle op-btn-ghost text-primary-content absolute right-2 top-2 z-40"
onClick={() => handlClose && handlClose()}
>
</div>
<div className="op-card op-bg-primary text-primary-content w-full shadow-lg">
<div className="op-card-body">
<h2 className="op-card-title">
{t("upgrade-to") + " Paid " + t("plan")}
</h2>
<p>{t("quotamailselfsign")}</p>
<div className="op-card-actions justify-end">
<button
onClick={() => navigate("/subscription")}
className="op-btn op-btn-accent"
>
{t("upgrade-now")}
</button>
</div>
</div>
</div>
</>
) : (
<>
<div className="op-card op-bg-primary text-primary-content w-full shadow-lg">
<div className="op-card-body">
<p>{t("quotamail")}</p>
<p>{t("quotamailTip")}</p>
<div className="op-card-actions justify-end">
<button
onClick={() => navigate("/subscription")}
className="op-btn op-btn-accent"
>
{t("upgrade-now")}
</button>
</div>
</div>
</div>
</>
);
};
export default QuotaCard;
@@ -5,18 +5,21 @@ import { useNavigate } from "react-router-dom";
const SubscribeCard = ({ plan, price }) => {
const { t } = useTranslation();
const navigate = useNavigate();
const handlePaidRoute = () => {
navigate("/subscription");
};
const handlePaidRoute = () => navigate("/subscription");
const premiumPrice = price ? "$" + price : "$9.99";
const addonPrice = "$0.15";
const plandName = plan ? plan.toLowerCase() : "Paid";
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">
{t("upgrade-to")} {plan ? plan : "Paid"} {t("plan")}
</h2>
<p>{t("subscribe-card-plan", { premiumPrice, addonPrice })}</p>
<p>
{plandName?.includes("team")
? t("subscribe-card-teamplan")
: t("subscribe-card-plan", { premiumPrice, addonPrice })}
</p>
<div className="op-card-actions justify-end">
<button
onClick={() => handlePaidRoute()}
@@ -215,8 +215,8 @@
"initials": "Initials",
"API": "API",
"api-token": "API Token",
"regenerate-token": "Regenerate Token",
"generate-token": "Generate Token",
"regenerate-token": "Regenerate Live Token",
"generate-token": "Generate Live Token",
"view-docs": "View Docs",
"generate-token-alert": "Are you sure you want to regenerate token it will expire old token?",
"yes": "Yes",
@@ -214,8 +214,8 @@
"initials": "Initiales",
"API": "API",
"api-token": "Jeton API",
"regenerate-token": "Régénérer le jeton",
"generate-token": "Générer un jeton",
"regenerate-token": "Régénérer en direct jeton",
"generate-token": "Générer en direct jeton",
"view-docs": "Afficher les documents",
"generate-token-alert": "Êtes-vous sûr de vouloir régénérer le jeton, votre ancien jeton sera supprimer?",
"yes": "Oui",
+17 -7
View File
@@ -91,7 +91,7 @@ const saveDataFile = async (size, fileUrl, tenantPtr) => {
}
};
export const updateMailCount = async extUserId => {
export const updateMailCount = async (extUserId, plan, monthchange) => {
// Update count in contracts_Users class
const query = new Parse.Query('contracts_Users');
query.equalTo('objectId', extUserId);
@@ -100,13 +100,23 @@ export const updateMailCount = async extUserId => {
const contractUser = await query.first({ useMasterKey: true });
if (contractUser) {
contractUser.increment('EmailCount', 1);
if (plan === 'freeplan') {
if (monthchange) {
contractUser.set('LastEmailCountReset', new Date());
contractUser.set('MontlyfreeEmails', 1);
} else {
if (contractUser?.get('MontlyfreeEmails')) {
contractUser.increment('MontlyfreeEmails', 1);
if (contractUser?.get('LastEmailCountReset')) {
contractUser.set('LastEmailCountReset', new Date());
}
} else {
contractUser.set('MontlyfreeEmails', 1);
contractUser.set('LastEmailCountReset', new Date());
}
}
}
await contractUser.save(null, { useMasterKey: true });
} else {
// Create new entry if not found
const ContractsUsers = Parse.Object.extend('contracts_Users');
const newContractUser = new ContractsUsers();
newContractUser.set('EmailCount', 1);
await newContractUser.save(null, { useMasterKey: true });
}
} catch (error) {
console.log('Error updating EmailCount in contracts_Users: ' + error.message);
@@ -81,7 +81,6 @@ export default async function createDocumentWithTemplate(request, response) {
objectId: extUser.get('TenantId').id,
});
subscription.include('ExtUserPtr');
subscription.greaterThan('AllowedApis', 0);
const resSub = await subscription.first({ useMasterKey: true });
if (resSub) {
const _resSub = JSON.parse(JSON.stringify(resSub));
@@ -406,7 +406,6 @@ export default async function createDocumentwithCoordinate(request, response) {
})),
message: 'Document sent successfully!',
});
// }
} else {
if (request.posthog) {
request.posthog?.capture({
@@ -67,7 +67,7 @@ export default async function BuyCredits(request) {
updateSub.set('AddonCredits', addonCredits);
const resupdateSub = await updateSub.save(null, { useMasterKey: true });
// console.log('resupdateSub ', resupdateSub);
return { status: 'success', addon: addonCredits };
return { status: 'success', addon: quantity };
}
} else {
throw new Parse.Error('400', 'Invalid access token.');
@@ -70,9 +70,9 @@ export default async function saveSubscription(request) {
if (existAddon > 0) {
updateSubscription.set('AllowedUsers', parseInt(existAddon));
}
const isSameAsPrevPlan = subscription?.get('PlanCode') === planCode;
const isSameAsPrevPlan = resSubscription?.get('PlanCode') === planCode;
if (isSameAsPrevPlan) {
const planCredits = subscription?.get('PlanCredits');
const planCredits = resSubscription?.get('PlanCredits');
if (planCredits) {
updateSubscription.set('AllowedCredits', planCredits);
} else {
@@ -142,8 +142,7 @@ export default async function sendMailGmailProvider(_extRes, template) {
raw: email,
},
});
// console.log('response ', response);
console.log('gmail provider res: ', response?.status);
return { code: 200, message: 'Email sent successfully' };
} catch (error) {
console.error('Error sending email:', error);
@@ -6,7 +6,7 @@ import Mailgun from 'mailgun.js';
import { smtpenable, smtpsecure, updateMailCount, useLocal } from '../../Utils.js';
import sendMailGmailProvider from './sendMailGmailProvider.js';
import { createTransport } from 'nodemailer';
async function sendMailProvider(req) {
async function sendMailProvider(req, plan, monthchange) {
const mailgunApiKey = process.env.MAILGUN_API_KEY;
try {
let transporterSMTP;
@@ -69,18 +69,23 @@ async function sendMailProvider(req) {
};
let attachment;
// `certificateBuffer` used to create buffer from pdf file
try {
const certificateBuffer = fs.readFileSync('./exports/certificate.pdf');
const certificate = {
filename: 'certificate.pdf',
content: smtpenable ? certificateBuffer : undefined, //fs.readFileSync('./exports/exported_file_1223.pdf'),
data: smtpenable ? undefined : certificateBuffer,
};
attachment = [file, certificate];
} catch (err) {
const certificatePath = './exports/certificate.pdf';
if (fs.existsSync(certificatePath)) {
try {
// `certificateBuffer` used to create buffer from pdf file
const certificateBuffer = fs.readFileSync(certificatePath);
const certificate = {
filename: 'certificate.pdf',
content: smtpenable ? certificateBuffer : undefined, //fs.readFileSync('./exports/exported_file_1223.pdf'),
data: smtpenable ? undefined : certificateBuffer,
};
attachment = [file, certificate];
} catch (err) {
attachment = [file];
console.log('Err in read certificate sendmailv3', err);
}
} else {
attachment = [file];
console.log('Err in read certificate sendmailv3', err);
}
const from = req.params.from || '';
const mailsender = smtpenable ? process.env.SMTP_USER_EMAIL : process.env.MAILGUN_SENDER;
@@ -96,38 +101,44 @@ async function sendMailProvider(req) {
};
if (transporterSMTP) {
const res = await transporterSMTP.sendMail(messageParams);
console.log('Res ', res);
console.log('smtp transporter res: ', res?.response);
if (!res.err) {
if (req.params?.extUserId) {
await updateMailCount(req.params.extUserId);
await updateMailCount(req.params.extUserId, plan, monthchange);
}
try {
fs.unlinkSync('./exports/certificate.pdf');
} catch (err) {
console.log('Err in unlink certificate sendmailv3');
if (fs.existsSync(certificatePath)) {
try {
fs.unlinkSync(certificatePath);
} catch (err) {
console.log('Err in unlink certificate sendmailv3');
}
}
return { status: 'success' };
}
} else {
if (mailgunApiKey) {
const res = await mailgunClient.messages.create(mailgunDomain, messageParams);
console.log('Res ', res);
console.log('mailgun res: ', res?.status);
if (res.status === 200) {
if (req.params?.extUserId) {
await updateMailCount(req.params.extUserId);
await updateMailCount(req.params.extUserId, plan, monthchange);
}
try {
fs.unlinkSync('./exports/certificate.pdf');
} catch (err) {
console.log('Err in unlink certificate sendmailv3');
if (fs.existsSync(certificatePath)) {
try {
fs.unlinkSync(certificatePath);
} catch (err) {
console.log('Err in unlink certificate sendmailv3');
}
}
return { status: 'success' };
}
} else {
try {
fs.unlinkSync('./exports/certificate.pdf');
} catch (err) {
console.log('Err in unlink certificate sendmailv3');
if (fs.existsSync(certificatePath)) {
try {
fs.unlinkSync(certificatePath);
} catch (err) {
console.log('Err in unlink certificate sendmailv3');
}
}
return { status: 'error' };
}
@@ -147,20 +158,20 @@ async function sendMailProvider(req) {
if (transporterSMTP) {
const res = await transporterSMTP.sendMail(messageParams);
console.log('Res ', res);
console.log('smtp transporter res: ', res?.response);
if (!res.err) {
if (req.params?.extUserId) {
await updateMailCount(req.params.extUserId);
await updateMailCount(req.params.extUserId, plan, monthchange);
}
return { status: 'success' };
}
} else {
if (mailgunApiKey) {
const res = await mailgunClient.messages.create(mailgunDomain, messageParams);
console.log('Res ', res);
console.log('mailgun res: ', res?.status);
if (res.status === 200) {
if (req.params?.extUserId) {
await updateMailCount(req.params.extUserId);
await updateMailCount(req.params.extUserId, plan, monthchange);
}
return { status: 'success' };
}
@@ -180,6 +191,7 @@ async function sendmailv3(req) {
const mailProvider = req.params.mailProvider || 'default';
if (mailProvider) {
try {
const Plan = req.params.plan;
const extUserId = req.params.extUserId || '';
const pdfName = req.params.pdfName || '';
const template = {
@@ -203,8 +215,31 @@ async function sendmailv3(req) {
return { status: 'error' };
}
} else {
const nonCustomMail = await sendMailProvider(req);
return nonCustomMail;
if (Plan && Plan === 'freeplan') {
let MontlyfreeEmails = _extRes?.MontlyfreeEmails || 0;
if (_extRes?.LastEmailCountReset?.iso) {
const lastDate = new Date(_extRes?.LastEmailCountReset?.iso);
const newDate = new Date();
const isMonthChange = newDate.getMonth() > lastDate.getMonth();
if (isMonthChange) {
const nonCustomMail = await sendMailProvider(req, Plan, true);
return nonCustomMail;
} else {
if (MontlyfreeEmails >= 20) {
return { status: 'quota-reached' };
} else {
const nonCustomMail = await sendMailProvider(req, Plan);
return nonCustomMail;
}
}
} else {
const nonCustomMail = await sendMailProvider(req, Plan);
return nonCustomMail;
}
} else {
const nonCustomMail = await sendMailProvider(req, '');
return nonCustomMail;
}
}
}
} catch (err) {
+35 -35
View File
@@ -15,8 +15,8 @@
"@signpdf/placeholder-pdf-lib": "^3.2.4",
"@signpdf/signer-p12": "^3.2.4",
"@signpdf/signpdf": "^3.2.4",
"aws-sdk": "^2.1681.0",
"axios": "^1.7.5",
"aws-sdk": "^2.1687.0",
"axios": "^1.7.7",
"cors": "^2.8.5",
"dotenv": "^16.4.5",
"express": "^4.19.2",
@@ -25,7 +25,7 @@
"googleapis": "^140.0.1",
"jsonschema": "^1.4.1",
"mailgun.js": "^10.2.3",
"mongoose": "^8.5.4",
"mongoose": "^8.6.0",
"multer": "^1.4.5-lts.1",
"multer-s3": "^3.0.1",
"node-forge": "^1.3.1",
@@ -35,14 +35,14 @@
"parse-server": "^7.2.0",
"parse-server-api-mail-adapter": "^4.0.0",
"pdf-lib": "^1.17.1",
"posthog-node": "^4.1.1",
"posthog-node": "^4.2.0",
"ws": "^8.18.0"
},
"devDependencies": {
"@babel/eslint-parser": "^7.25.1",
"eslint": "^9.9.1",
"jasmine": "^5.2.0",
"mongodb-runner": "^5.6.5",
"mongodb-runner": "^5.6.6",
"nodemon": "^3.1.4",
"nyc": "^17.0.0",
"prettier": "^3.3.3"
@@ -2315,9 +2315,9 @@
"deprecated": "This package has been decomissioned. See https://github.com/ldapjs/node-ldapjs/blob/8ffd0bc9c149088a10ec4c1ec6a18450f76ad05d/README.md"
},
"node_modules/@mongodb-js/mongodb-downloader": {
"version": "0.3.5",
"resolved": "https://registry.npmjs.org/@mongodb-js/mongodb-downloader/-/mongodb-downloader-0.3.5.tgz",
"integrity": "sha512-0tNik3E/eQxx8EkJpsa9+IIK5LtMle3N7M/1wtKQKMixJjZ1vsgAjJGguYbLfCyJqfnrw9KMyD1cwgaS37tvRA==",
"version": "0.3.6",
"resolved": "https://registry.npmjs.org/@mongodb-js/mongodb-downloader/-/mongodb-downloader-0.3.6.tgz",
"integrity": "sha512-Cu82TRmAP/OIRizx9o+fReQf8FfovI28rjY0pu8wHyCoUlG7q3Zkxb/lppB7a9/kzQfONeHAoXIOQkvSasKYrw==",
"dev": true,
"dependencies": {
"debug": "^4.3.4",
@@ -2328,9 +2328,9 @@
}
},
"node_modules/@mongodb-js/saslprep": {
"version": "1.1.8",
"resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.1.8.tgz",
"integrity": "sha512-qKwC/M/nNNaKUBMQ0nuzm47b7ZYWQHN3pcXq4IIcoSBc2hOIrflAxJduIvvqmhoz3gR2TacTAs8vlsCVPkiEdQ==",
"version": "1.1.9",
"resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.1.9.tgz",
"integrity": "sha512-tVkljjeEaAhCqTzajSdgbQ6gE6f3oneVwa3iXR6csiEwXXOFsiC6Uh9iAjAhXPtqa/XMDHWjjeNH/77m/Yq2dw==",
"dependencies": {
"sparse-bitfield": "^3.0.3"
}
@@ -4120,9 +4120,9 @@
}
},
"node_modules/aws-sdk": {
"version": "2.1681.0",
"resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.1681.0.tgz",
"integrity": "sha512-oeCr0muJraT+g7ceTMlJcidVayPMfT69EEvDIWMbeBIHqbLOJVtpsF577VZJNEh2Zkj+8DivR69kWdu+Y9JSyQ==",
"version": "2.1687.0",
"resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.1687.0.tgz",
"integrity": "sha512-Pk7RbIxJ8yDmFJRKzaapiUsAvz5cTPKCz7soomU+lASx1jvO29Z9KAPB6KJR22m7rDDMO/HNNN9OJRzfdvh7xQ==",
"hasInstallScript": true,
"dependencies": {
"buffer": "4.9.2",
@@ -4162,9 +4162,9 @@
"integrity": "sha512-u5w79Rd7SU4JaIlA/zFqG+gOiuq25q5VLyZ8E+ijJeILuTxVzZgp2CaGw/UTw6pXYN9XMO9yiqj/nEHmhTG5CA=="
},
"node_modules/axios": {
"version": "1.7.5",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.7.5.tgz",
"integrity": "sha512-fZu86yCo+svH3uqJ/yTdQ0QHpQu5oL+/QE+QPSv6BZSkDAoky9vytxp7u5qk83OJFS3kEBcesWni9WTZAv3tSw==",
"version": "1.7.7",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.7.7.tgz",
"integrity": "sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q==",
"dependencies": {
"follow-redirects": "^1.15.6",
"form-data": "^4.0.0",
@@ -8077,9 +8077,9 @@
}
},
"node_modules/mongodb-download-url": {
"version": "1.5.1",
"resolved": "https://registry.npmjs.org/mongodb-download-url/-/mongodb-download-url-1.5.1.tgz",
"integrity": "sha512-AJH2lqb7mBo7tT7RyFWK3P/ZMh7RC1qWJgOaAVrBdKeuPuCWGCESrti+ZMt6FA6mJ4eU58Lm7iG2rTkl94pBdQ==",
"version": "1.5.3",
"resolved": "https://registry.npmjs.org/mongodb-download-url/-/mongodb-download-url-1.5.3.tgz",
"integrity": "sha512-r/VulVz4Qgh9Y27h6rKoiUSFSZc1M0g5udBWfo+jLVKSVdrgw3X0RrojlwTcITbB9cYsW5DEVTXTh/7pn2Lbhg==",
"dev": true,
"dependencies": {
"debug": "^4.1.1",
@@ -8104,13 +8104,13 @@
}
},
"node_modules/mongodb-runner": {
"version": "5.6.5",
"resolved": "https://registry.npmjs.org/mongodb-runner/-/mongodb-runner-5.6.5.tgz",
"integrity": "sha512-joZJL5YKuwP7MNegz0CKt7rAPgAeUcWhOfJZPgifnKD+3tl4oMbRwP+HjcQjBieT1dr9lh+kI1MQuGInRtQzMw==",
"version": "5.6.6",
"resolved": "https://registry.npmjs.org/mongodb-runner/-/mongodb-runner-5.6.6.tgz",
"integrity": "sha512-PxmDhfY12GHiY/HoRgR0d4cJLs5lC9cd3ebnOdhNIxJdSiYDKcfgmJIAA0O+dPbrGOSv8AvxckfUEpYkp62W2w==",
"dev": true,
"dependencies": {
"@mongodb-js/mongodb-downloader": "^0.3.5",
"@mongodb-js/saslprep": "^1.1.8",
"@mongodb-js/mongodb-downloader": "^0.3.6",
"@mongodb-js/saslprep": "^1.1.9",
"debug": "^4.3.4",
"mongodb": "^6.8.0",
"mongodb-connection-string-url": "^3.0.0",
@@ -8228,13 +8228,13 @@
}
},
"node_modules/mongoose": {
"version": "8.5.4",
"resolved": "https://registry.npmjs.org/mongoose/-/mongoose-8.5.4.tgz",
"integrity": "sha512-nG3eehhWf9l1q80WuHvp5DV+4xDNFpDWLE5ZgcFD5tslUV2USJ56ogun8gaZ62MKAocJnoStjAdno08b8U57hg==",
"version": "8.6.0",
"resolved": "https://registry.npmjs.org/mongoose/-/mongoose-8.6.0.tgz",
"integrity": "sha512-p6VSbYKvD4ZIabqo8C0kS5eKX1Xpji+opTAIJ9wyuPJ8Y/FblgXSMnFRXnB40bYZLKPQT089K5KU8+bqIXtFdw==",
"dependencies": {
"bson": "^6.7.0",
"kareem": "2.6.3",
"mongodb": "6.7.0",
"mongodb": "6.8.0",
"mpath": "0.9.0",
"mquery": "5.0.0",
"ms": "2.1.3",
@@ -8306,9 +8306,9 @@
}
},
"node_modules/mongoose/node_modules/mongodb": {
"version": "6.7.0",
"resolved": "https://registry.npmjs.org/mongodb/-/mongodb-6.7.0.tgz",
"integrity": "sha512-TMKyHdtMcO0fYBNORiYdmM25ijsHs+Njs963r4Tro4OQZzqYigAzYQouwWRg4OIaiLRUEGUh/1UAcH5lxdSLIA==",
"version": "6.8.0",
"resolved": "https://registry.npmjs.org/mongodb/-/mongodb-6.8.0.tgz",
"integrity": "sha512-HGQ9NWDle5WvwMnrvUxsFYPd3JEbqD3RgABHBQRuoCEND0qzhsd0iH5ypHsf1eJ+sXmvmyKpP+FLOKY8Il7jMw==",
"dependencies": {
"@mongodb-js/saslprep": "^1.1.5",
"bson": "^6.7.0",
@@ -10095,9 +10095,9 @@
}
},
"node_modules/posthog-node": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/posthog-node/-/posthog-node-4.1.1.tgz",
"integrity": "sha512-hva26cNSz62H76blhWUF8mZmE3Q81KTrkkpHEZlD00qDov/phLQCrKQnxwjiAN3yI9pv/0/uwte6Gluy1xBmUA==",
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/posthog-node/-/posthog-node-4.2.0.tgz",
"integrity": "sha512-hgyCYMyzMvuF3qWMw6JvS8gT55v7Mtp5wKWcnDrw+nu39D0Tk9BXD7I0LOBp0lGlHEPaXCEVYUtviNKrhMALGA==",
"dependencies": {
"axios": "^1.7.4",
"rusha": "^0.8.14"
+5 -5
View File
@@ -24,8 +24,8 @@
"@signpdf/placeholder-pdf-lib": "^3.2.4",
"@signpdf/signer-p12": "^3.2.4",
"@signpdf/signpdf": "^3.2.4",
"aws-sdk": "^2.1681.0",
"axios": "^1.7.5",
"aws-sdk": "^2.1687.0",
"axios": "^1.7.7",
"cors": "^2.8.5",
"dotenv": "^16.4.5",
"express": "^4.19.2",
@@ -34,7 +34,7 @@
"googleapis": "^140.0.1",
"jsonschema": "^1.4.1",
"mailgun.js": "^10.2.3",
"mongoose": "^8.5.4",
"mongoose": "^8.6.0",
"multer": "^1.4.5-lts.1",
"multer-s3": "^3.0.1",
"node-forge": "^1.3.1",
@@ -44,7 +44,7 @@
"parse-server": "^7.2.0",
"parse-server-api-mail-adapter": "^4.0.0",
"pdf-lib": "^1.17.1",
"posthog-node": "^4.1.1",
"posthog-node": "^4.2.0",
"ws": "^8.18.0"
},
"type": "module",
@@ -52,7 +52,7 @@
"@babel/eslint-parser": "^7.25.1",
"eslint": "^9.9.1",
"jasmine": "^5.2.0",
"mongodb-runner": "^5.6.5",
"mongodb-runner": "^5.6.6",
"nodemon": "^3.1.4",
"nyc": "^17.0.0",
"prettier": "^3.3.3"
+1 -1
View File
@@ -9,7 +9,7 @@ services:
env_file: .env.prod
environment:
- NODE_ENV=production
- SERVER_URL=${HOST_URL:-https://localhost:3001/app}
- SERVER_URL=${HOST_URL:-https://localhost:3001}/app
networks:
- app-network
mongo: