mirror of
https://github.com/OpenSignLabs/OpenSign.git
synced 2026-08-21 15:12:34 +02:00
Merge pull request #695 from OpenSignLabs/login_to_sandbox
refactor: handle conditions of sandbox
This commit is contained in:
@@ -1,25 +0,0 @@
|
||||
# Use an official Node runtime as the base image
|
||||
FROM node:18
|
||||
|
||||
# Set the working directory inside the container
|
||||
WORKDIR /usr/src/app
|
||||
|
||||
# Copy package.json and package-lock.json first to leverage Docker cache
|
||||
COPY ./package*.json ./
|
||||
|
||||
# Install application dependencies
|
||||
RUN npm install
|
||||
|
||||
# Copy the current directory contents into the container
|
||||
COPY ./ .
|
||||
COPY ./.husky .
|
||||
|
||||
# Make port 3000 available to the world outside this container
|
||||
EXPOSE 3000
|
||||
|
||||
# Define environment variables if needed
|
||||
# ENV NODE_ENV production
|
||||
|
||||
# Run the application
|
||||
ENTRYPOINT npm run start
|
||||
|
||||
@@ -13,6 +13,10 @@ RUN npm install
|
||||
# Copy the current directory contents into the container
|
||||
COPY apps/OpenSign/ .
|
||||
COPY apps/OpenSign/.husky .
|
||||
COPY apps/OpenSign/entrypoint.sh .
|
||||
|
||||
# make the entrypoint.sh file executable
|
||||
RUN chmod +x entrypoint.sh
|
||||
|
||||
# Define environment variables if needed
|
||||
ENV NODE_ENV=production
|
||||
@@ -20,8 +24,13 @@ ENV GENERATE_SOURCEMAP=false
|
||||
# build
|
||||
RUN npm run build
|
||||
|
||||
# Inject env.js loader into index.html
|
||||
RUN sed -i '/<head>/a\<script src="/env.js"></script>' build/index.html
|
||||
|
||||
# Make port 3000 available to the world outside this container
|
||||
EXPOSE 3000
|
||||
|
||||
ENTRYPOINT ["./entrypoint.sh"]
|
||||
|
||||
# Run the application
|
||||
CMD ["npm", "start"]
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
#!/bin/sh
|
||||
|
||||
ENV_FILE=./build/env.js
|
||||
DOTENV_FILE=./.env.prod # ✅ use .env.prod
|
||||
|
||||
echo "Generating runtime env file at $ENV_FILE..."
|
||||
|
||||
echo "window.RUNTIME_ENV = {" > $ENV_FILE
|
||||
|
||||
# List of keys to include
|
||||
RUNTIME_KEYS="REACT_APP_SERVERURL"
|
||||
|
||||
for key in $RUNTIME_KEYS; do
|
||||
# First check docker env (-e), fallback to .env file
|
||||
value=$(printenv "$key")
|
||||
|
||||
if [ -z "$value" ] && [ -f "$DOTENV_FILE" ]; then
|
||||
# fallback: read from .env
|
||||
value=$(grep "^$key=" "$DOTENV_FILE" | cut -d '=' -f2- | tr -d '\r\n' | sed 's/"/\\"/g')
|
||||
else
|
||||
value=$(echo "$value" | sed 's/"/\\"/g')
|
||||
fi
|
||||
|
||||
echo " $key: \"$value\"," >> $ENV_FILE
|
||||
done
|
||||
|
||||
echo "};" >> $ENV_FILE
|
||||
|
||||
exec "$@"
|
||||
@@ -1,6 +1,7 @@
|
||||
{
|
||||
"header-news": "Neue Funktion: Benutzer des Teams-Plans können jetzt ihre eigenen AWS S3-Buckets für die Dateispeicherung integrieren",
|
||||
"header-news-btn": "Jetzt einrichten",
|
||||
"sandbox-news": "Dies ist eine Sandbox-Umgebung. Bitte nicht für produktive Zwecke verwenden.",
|
||||
"create-account": "Konto erstellen",
|
||||
"login": "Anmelden",
|
||||
"language": "Sprache",
|
||||
@@ -675,7 +676,7 @@
|
||||
"public-template-mssg-1": "Um OpenSign in Ihr React- oder Next.js-Projekt zu integrieren, führen Sie einfach den folgenden Befehl aus:",
|
||||
"public-template-mssg-2": "Stellen Sie sicher, dass npm oder yarn in Ihrem Projekt eingerichtet ist. Wenn Sie Yarn verwenden, können Sie npm install durch yarn add @opensign/react ersetzen.",
|
||||
"public-template-mssg-3": "Benötigen Sie weitere Details oder Beispiele?",
|
||||
"public-template-mssg-4": "Besuchen Sie die",
|
||||
"public-template-mssg-4": "Besuchen Sie die ",
|
||||
"public-template-mssg-5": " npm für die neuesten Updates, detaillierte Dokumentationen und Versionshistorie.",
|
||||
"public-template-mssg-6": "Bevor Sie diesen Code-Schnipsel verwenden können, müssen Sie diese Vorlage öffentlich machen.",
|
||||
"public-template-mssg-7": "Bevor Sie einen öffentlichen Link generieren können, müssen Sie diese Vorlage öffentlich machen.",
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
{
|
||||
"header-news": "New feature: Protect your account with Two-Factor Authentication (2FA) and enjoy the future of login with Passkeys — no passwords needed.",
|
||||
"header-news-btn": "Setup now",
|
||||
"sandbox-news": "This is a sandbox environment. Please do not use it for production purposes.",
|
||||
"create-account": "Create account",
|
||||
"login": "Login",
|
||||
"language": "Language",
|
||||
@@ -675,7 +676,7 @@
|
||||
"public-template-mssg-1": "To integrate OpenSign into your React or Next.js project, simply run the following command:",
|
||||
"public-template-mssg-2": "Ensure you have npm or yarn set up in your project. If you're using Yarn, you can replace npm install with yarn add @opensign/react.",
|
||||
"public-template-mssg-3": "Need more details or examples?",
|
||||
"public-template-mssg-4": "Visit the",
|
||||
"public-template-mssg-4": "Visit the ",
|
||||
"public-template-mssg-5": " npm for the latest updates, detailed documentation, and version history.",
|
||||
"public-template-mssg-6": "Before you can use this code snippet, you must make this template public.",
|
||||
"public-template-mssg-7": "Before you can generate a public link you must make this template public.",
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
{
|
||||
"header-news": "Nueva característica: los usuarios del plan Teams ahora pueden integrar sus propios depósitos de AWS S3 para el almacenamiento de archivos",
|
||||
"header-news-btn": "Configurar ahora",
|
||||
"sandbox-news": "Este es un entorno sandbox. Por favor, no lo utilice con fines de producción.",
|
||||
"create-account": "Crear cuenta",
|
||||
"login": "Iniciar sesión",
|
||||
"language": "Idioma",
|
||||
@@ -675,7 +676,7 @@
|
||||
"public-template-mssg-1": "Para integrar OpenSign a tu proyecto React o Next.js, simplemente ejecuta los siguientes comandos:",
|
||||
"public-template-mssg-2": "Asegúrate de tener «npm» o «yarn» configurado en tu proyecto. Si estás usando «yarn», puedes reemplazar «npm install» con «yarn add @opensign/react».",
|
||||
"public-template-mssg-3": "¿Necesitas más detalles o ejemplos?",
|
||||
"public-template-mssg-4": "Visita la",
|
||||
"public-template-mssg-4": "Visita la ",
|
||||
"public-template-mssg-5": " «npm» para las últimas actualizaciones, documentación detallada e historial de versiones.",
|
||||
"public-template-mssg-6": "Antes de que puedas usar este fragmento de código, debes convertir esta plantilla en pública.",
|
||||
"public-template-mssg-7": "Antes de poder generar un enlace público, debes hacer que esta plantilla sea pública.",
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
{
|
||||
"header-news": "Nouvelle fonctionnalité : les utilisateurs du forfait Teams peuvent désormais intégrer leurs propres compartiments AWS S3 pour le stockage de fichiers",
|
||||
"header-news-btn": "Configurer maintenant",
|
||||
"sandbox-news": "Ceci est un environnement sandbox. Veuillez ne pas l'utiliser à des fins de production.",
|
||||
"create-account": "Créer un compte",
|
||||
"login": "Se Connecter",
|
||||
"language": "Langue",
|
||||
@@ -675,7 +676,7 @@
|
||||
"public-template-mssg-1": "Pour intégrer OpenSign dans votre projet React ou Next.js, exécutez simplement la commande suivante :",
|
||||
"public-template-mssg-2": "Assurez-vous que npm ou Yarn est configuré dans votre projet. Si vous utilisez Yarn, vous pouvez remplacer npm install par Yarn Add @opensign/react.",
|
||||
"public-template-mssg-3": "Besoin de plus de détails ou d'exemples ?",
|
||||
"public-template-mssg-4": "Visitez le",
|
||||
"public-template-mssg-4": "Visitez le ",
|
||||
"public-template-mssg-5": "npm pour les dernières mises à jour, une documentation détaillée et l'historique des versions.",
|
||||
"public-template-mssg-6": "Avant de pouvoir utiliser cet extrait de code, vous devez rendre ce modèle public.",
|
||||
"public-template-mssg-7": "Avant de pouvoir générer un lien public, vous devez rendre ce modèle public.",
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
{
|
||||
"header-news": "Nuova funzionalità: Gli utenti del piano Teams possono ora integrare i propri bucket AWS S3 per l'archiviazione dei file",
|
||||
"header-news-btn": "Configura Ora",
|
||||
"sandbox-news": "Questo è un ambiente sandbox. Si prega di non utilizzarlo per scopi di produzione.",
|
||||
"create-account": "Crea Account",
|
||||
"login": "Accedi",
|
||||
"language": "Lingua",
|
||||
@@ -675,7 +676,7 @@
|
||||
"public-template-mssg-1": "Per integrare OpenSign nel tuo progetto React o Next.js, esegui semplicemente il seguente comando:",
|
||||
"public-template-mssg-2": "Assicurati di avere npm o yarn configurato nel tuo progetto. Se usi Yarn, puoi sostituire npm install con yarn add @opensign/react.",
|
||||
"public-template-mssg-3": "Hai bisogno di maggiori dettagli o esempi?",
|
||||
"public-template-mssg-4": "Visita il",
|
||||
"public-template-mssg-4": "Visita il ",
|
||||
"public-template-mssg-5": " npm per gli aggiornamenti più recenti, documentazione dettagliata e cronologia delle versioni.",
|
||||
"public-template-mssg-6": "Prima di poter utilizzare questo frammento di codice, devi rendere questo modello pubblico.",
|
||||
"public-template-mssg-7": "Prima di poter generare un link pubblico, devi rendere questo modello pubblico.",
|
||||
|
||||
@@ -106,10 +106,10 @@ function App() {
|
||||
element={<LazyPage Page={GuestLogin} />}
|
||||
/>
|
||||
<Route path="/debugpdf" element={<LazyPage Page={DebugPdf} />} />
|
||||
<Route
|
||||
path="/forgetpassword"
|
||||
element={<LazyPage Page={ForgetPassword} />}
|
||||
/>
|
||||
<Route
|
||||
path="/forgetpassword"
|
||||
element={<LazyPage Page={ForgetPassword} />}
|
||||
/>
|
||||
<Route
|
||||
element={
|
||||
<ValidateSession>
|
||||
@@ -165,7 +165,7 @@ function App() {
|
||||
path="/recipientSignPdf/:docId"
|
||||
element={<PdfRequestFiles />}
|
||||
/>
|
||||
<Route path="/users" element={<UserList />} />
|
||||
<Route path="/users" element={<UserList />} />
|
||||
<Route
|
||||
path="/preferences"
|
||||
element={<LazyPage Page={Preferences} />}
|
||||
|
||||
@@ -22,7 +22,7 @@ function DropdownWidgetOption(props) {
|
||||
|
||||
const resetState = () => {
|
||||
setDropdownOptionList(["option-1", "option-2"]);
|
||||
setDropdownName( props.currWidgetsDetails?.options?.name || props.type);
|
||||
setDropdownName(props.currWidgetsDetails?.options?.name || props.type);
|
||||
setIsReadOnly(false);
|
||||
setIsHideLabel(false);
|
||||
setMinCount(0);
|
||||
@@ -115,7 +115,7 @@ function DropdownWidgetOption(props) {
|
||||
defaultData,
|
||||
isHideLabel
|
||||
);
|
||||
resetState()
|
||||
resetState();
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, {
|
||||
import {
|
||||
useState,
|
||||
useRef,
|
||||
} from "react";
|
||||
|
||||
@@ -168,34 +168,34 @@ function PlaceholderType(props) {
|
||||
<div style={{ zIndex: props.isSignYourself && "99" }}>
|
||||
{props.pos.options?.values?.map((data, ind) => {
|
||||
return (
|
||||
<div
|
||||
key={ind}
|
||||
className="select-none-cls flex items-center text-center gap-0.5 pointer-events-none"
|
||||
>
|
||||
<input
|
||||
id={`checkbox-${props.pos.key + ind}`}
|
||||
style={{ width: fontSize, height: fontSize }}
|
||||
className={`${
|
||||
ind === 0 ? "mt-0" : "mt-[5px]"
|
||||
} flex justify-center op-checkbox rounded-[1px] `}
|
||||
disabled={
|
||||
props.isNeedSign &&
|
||||
(props.pos.options?.isReadOnly ||
|
||||
props.data?.signerObjId !== props.signerObjId)
|
||||
}
|
||||
type="checkbox"
|
||||
readOnly
|
||||
checked={!!selectCheckbox(ind, selectedCheckbox)}
|
||||
/>
|
||||
{!props.pos.options?.isHideLabel && (
|
||||
<label
|
||||
htmlFor={`checkbox-${props.pos.key + ind}`}
|
||||
style={{ fontSize: fontSize, color: fontColor }}
|
||||
className="text-xs mb-0 text-center"
|
||||
>
|
||||
{data}
|
||||
</label>
|
||||
)}
|
||||
<div key={ind} className="select-none-cls pointer-events-none">
|
||||
<label
|
||||
htmlFor={`checkbox-${props.pos.key + ind}`}
|
||||
style={{ fontSize: fontSize, color: fontColor }}
|
||||
className={`mb-0 flex items-center gap-1 ${
|
||||
ind > 0 ? "mt-[3px]" : "mt-[0px]"
|
||||
}`}
|
||||
>
|
||||
<input
|
||||
id={`checkbox-${props.pos.key + ind}`}
|
||||
style={{
|
||||
width: fontSize,
|
||||
height: fontSize
|
||||
}}
|
||||
className="op-checkbox rounded-[1px]"
|
||||
disabled={
|
||||
props.isNeedSign &&
|
||||
(props.pos.options?.isReadOnly ||
|
||||
props.data?.signerObjId !== props.signerObjId)
|
||||
}
|
||||
type="checkbox"
|
||||
readOnly
|
||||
checked={!!selectCheckbox(ind, selectedCheckbox)}
|
||||
/>
|
||||
{!props.pos.options?.isHideLabel && (
|
||||
<span className="leading-none">{data}</span>
|
||||
)}
|
||||
</label>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
@@ -243,7 +243,6 @@ function PlaceholderType(props) {
|
||||
<i className="fa-light fa-circle-chevron-down mr-1 "></i>
|
||||
</div>
|
||||
);
|
||||
|
||||
case "initials":
|
||||
return props.pos.SignUrl ? (
|
||||
<img
|
||||
@@ -444,36 +443,40 @@ function PlaceholderType(props) {
|
||||
return (
|
||||
<div
|
||||
key={ind}
|
||||
className="select-none-cls flex items-center text-center gap-0.5 pointer-events-none"
|
||||
className="select-none-cls pointer-events-none"
|
||||
>
|
||||
<input
|
||||
readOnly
|
||||
id={`radio-${props.pos.key + ind}`}
|
||||
<label
|
||||
htmlFor={`radio-${props.pos.key + ind}`}
|
||||
style={{
|
||||
width: fontSize,
|
||||
height: fontSize,
|
||||
marginTop: ind > 0 ? "10px" : "0px"
|
||||
fontSize: fontSize,
|
||||
color: fontColor,
|
||||
marginTop: ind > 0 ? "5px" : "0px"
|
||||
}}
|
||||
className={`op-radio rounded-full border- border-black appearance-none bg-white inline-block align-middle relative ${
|
||||
handleRadioCheck(data) ? "checked-radio" : ""
|
||||
}`}
|
||||
type="radio"
|
||||
disabled={
|
||||
props.isNeedSign &&
|
||||
(props.pos.options?.isReadOnly ||
|
||||
props.data?.signerObjId !== props.signerObjId)
|
||||
}
|
||||
checked={handleRadioCheck(data)}
|
||||
/>
|
||||
{!props.pos.options?.isHideLabel && (
|
||||
<label
|
||||
htmlFor={`radio-${props.pos.key + ind}`}
|
||||
style={{ fontSize: fontSize, color: fontColor }}
|
||||
className="text-xs mb-0"
|
||||
>
|
||||
{data}
|
||||
</label>
|
||||
)}
|
||||
className="text-xs mb-0 flex items-center gap-1 "
|
||||
>
|
||||
<input
|
||||
readOnly
|
||||
id={`radio-${props.pos.key + ind}`}
|
||||
style={{
|
||||
width: fontSize,
|
||||
height: fontSize,
|
||||
lineHeight: 2
|
||||
}}
|
||||
className={`op-radio rounded-full border- border-black appearance-none bg-white inline-block align-middle relative ${
|
||||
handleRadioCheck(data) ? "checked-radio" : ""
|
||||
}`}
|
||||
type="radio"
|
||||
disabled={
|
||||
props.isNeedSign &&
|
||||
(props.pos.options?.isReadOnly ||
|
||||
props.data?.signerObjId !== props.signerObjId)
|
||||
}
|
||||
checked={handleRadioCheck(data)}
|
||||
/>
|
||||
{!props.pos.options?.isHideLabel && (
|
||||
<span className="leading-none">{data}</span>
|
||||
)}
|
||||
</label>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
|
||||
@@ -231,7 +231,9 @@ function WidgetsValueModal(props) {
|
||||
setXyPosition,
|
||||
uniqueId,
|
||||
false,
|
||||
data?.format
|
||||
data?.format,
|
||||
currWidgetsDetails?.options?.fontSize || 12,
|
||||
currWidgetsDetails?.options?.fontColor || "black"
|
||||
);
|
||||
setSelectDate({ date: date, format: data?.format });
|
||||
};
|
||||
@@ -1327,47 +1329,42 @@ function WidgetsValueModal(props) {
|
||||
<div className="border-[1px] border-gray-300 rounded-[2px] p-1 px-3">
|
||||
{currWidgetsDetails?.options?.values?.map((data, ind) => {
|
||||
return (
|
||||
<div
|
||||
key={ind}
|
||||
className=" select-none-cls flex items-center text-center gap-0.5"
|
||||
>
|
||||
<input
|
||||
id={`checkbox-${currWidgetsDetails?.key + ind}`}
|
||||
className={`${
|
||||
ind === 0 ? "mt-0" : "mt-[5px]"
|
||||
} op-checkbox op-checkbox-sm rounded-[1px] `}
|
||||
type="checkbox"
|
||||
checked={!!selectCheckbox(ind, selectedCheckbox)}
|
||||
onChange={(e) => {
|
||||
if (e.target.checked) {
|
||||
const maxRequired =
|
||||
currWidgetsDetails?.options?.validation
|
||||
?.maxRequiredCount;
|
||||
const maxCountInt =
|
||||
maxRequired && parseInt(maxRequired);
|
||||
if (maxCountInt > 0) {
|
||||
if (
|
||||
selectedCheckbox &&
|
||||
selectedCheckbox?.length <= maxCountInt - 1
|
||||
) {
|
||||
<div key={ind} className=" select-none-cls">
|
||||
<label
|
||||
htmlFor={`checkbox-${currWidgetsDetails?.key + ind}`}
|
||||
className="text-xs flex items-center gap-1"
|
||||
>
|
||||
<input
|
||||
id={`checkbox-${currWidgetsDetails?.key + ind}`}
|
||||
className={`${
|
||||
ind === 0 ? "mt-0" : "mt-[5px]"
|
||||
} op-checkbox op-checkbox-xs rounded-[1px] `}
|
||||
type="checkbox"
|
||||
checked={!!selectCheckbox(ind, selectedCheckbox)}
|
||||
onChange={(e) => {
|
||||
if (e.target.checked) {
|
||||
const maxRequired =
|
||||
currWidgetsDetails?.options?.validation
|
||||
?.maxRequiredCount;
|
||||
const maxCountInt =
|
||||
maxRequired && parseInt(maxRequired);
|
||||
if (maxCountInt > 0) {
|
||||
if (
|
||||
selectedCheckbox &&
|
||||
selectedCheckbox?.length <= maxCountInt - 1
|
||||
) {
|
||||
handleCheckboxValue(e.target.checked, ind);
|
||||
}
|
||||
} else {
|
||||
handleCheckboxValue(e.target.checked, ind);
|
||||
}
|
||||
} else {
|
||||
handleCheckboxValue(e.target.checked, ind);
|
||||
}
|
||||
} else {
|
||||
handleCheckboxValue(e.target.checked, ind);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
{!currWidgetsDetails?.options?.isHideLabel && (
|
||||
<label
|
||||
htmlFor={`checkbox-${currWidgetsDetails?.key + ind}`}
|
||||
className="text-xs mb-0 text-center"
|
||||
>
|
||||
{data}
|
||||
</label>
|
||||
)}
|
||||
}}
|
||||
/>
|
||||
{data}
|
||||
</label>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
@@ -1515,32 +1512,23 @@ function WidgetsValueModal(props) {
|
||||
<div className="border-[1px] border-gray-300 rounded-[2px] p-1 px-3">
|
||||
{currWidgetsDetails?.options?.values.map((data, ind) => {
|
||||
return (
|
||||
<div
|
||||
key={ind}
|
||||
className="select-none-cls flex items-center text-center gap-0.5"
|
||||
>
|
||||
<input
|
||||
id={`radio-${currWidgetsDetails?.key + ind}`}
|
||||
style={{
|
||||
marginTop: ind > 0 ? "10px" : "0px"
|
||||
}}
|
||||
className={`flex justify-center op-radio`}
|
||||
type="radio"
|
||||
value={data}
|
||||
checked={handleRadioCheck(data)}
|
||||
onChange={(e) => {
|
||||
handleCheckRadio(e.target.value);
|
||||
}}
|
||||
/>
|
||||
{!currWidgetsDetails?.options?.isHideLabel && (
|
||||
<label
|
||||
htmlFor={`radio-${currWidgetsDetails?.key + ind}`}
|
||||
// style={{ fontSize: fontSize, color: fontColor }}
|
||||
className="text-xs mb-0"
|
||||
>
|
||||
{data}
|
||||
</label>
|
||||
)}
|
||||
<div key={ind} className="select-none-cls">
|
||||
<label
|
||||
htmlFor={`radio-${currWidgetsDetails?.key + ind}`}
|
||||
className="cursor-pointer flex items-center text-sm gap-1"
|
||||
>
|
||||
<input
|
||||
id={`radio-${currWidgetsDetails?.key + ind}`}
|
||||
className={`op-radio op-radio-xs`}
|
||||
type="radio"
|
||||
value={data}
|
||||
checked={handleRadioCheck(data)}
|
||||
onChange={(e) => {
|
||||
handleCheckRadio(e.target.value);
|
||||
}}
|
||||
/>
|
||||
{data}
|
||||
</label>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
@@ -1652,7 +1640,7 @@ function WidgetsValueModal(props) {
|
||||
const validateExpression = (regexValidation) => {
|
||||
if (widgetValue && regexValidation) {
|
||||
let regexObject = regexValidation;
|
||||
if (props.pos?.options?.validation?.type === "regex") {
|
||||
if (currWidgetsDetails?.options?.validation?.type === "regex") {
|
||||
regexObject = RegexParser(regexValidation);
|
||||
}
|
||||
let isValidate = regexObject.test(widgetValue);
|
||||
@@ -1675,7 +1663,8 @@ function WidgetsValueModal(props) {
|
||||
validateExpression(regexValidation);
|
||||
break;
|
||||
default:
|
||||
regexValidation = props.pos?.options?.validation?.pattern || "";
|
||||
regexValidation =
|
||||
currWidgetsDetails?.options?.validation?.pattern || "";
|
||||
validateExpression(regexValidation);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -2,9 +2,19 @@ import React, { useEffect, useState } from "react";
|
||||
import AsyncSelect from "react-select/async";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import axios from "axios";
|
||||
import { handleUnlinkSigner } from "../../../constant/Utils";
|
||||
|
||||
const SelectSigners = (props) => {
|
||||
const { t } = useTranslation();
|
||||
const {
|
||||
signerPos,
|
||||
setSignerPos,
|
||||
signersData,
|
||||
setSignersData,
|
||||
uniqueId,
|
||||
isRemove,
|
||||
handleAddUser
|
||||
} = props;
|
||||
const [userList, setUserList] = useState([]);
|
||||
const [selected, setSelected] = useState();
|
||||
const [userData, setUserData] = useState({});
|
||||
@@ -30,7 +40,7 @@ const SelectSigners = (props) => {
|
||||
//checking if user select no signer option from dropdown
|
||||
if (item) {
|
||||
//checking selected signer is already assign to the document or not
|
||||
const alreadyAssign = props.signersData.some(
|
||||
const alreadyAssign = signersData.some(
|
||||
(item2) => item2.objectId === item.value
|
||||
);
|
||||
if (alreadyAssign) {
|
||||
@@ -49,7 +59,7 @@ const SelectSigners = (props) => {
|
||||
};
|
||||
const handleAdd = () => {
|
||||
if (userData && userData.objectId) {
|
||||
props.details(userData);
|
||||
handleAddUser(userData);
|
||||
if (props.closePopup) {
|
||||
props.closePopup();
|
||||
}
|
||||
@@ -60,7 +70,13 @@ const SelectSigners = (props) => {
|
||||
};
|
||||
//function to use remove signer from assigned widgets in create template flow
|
||||
const handleRemove = () => {
|
||||
props.handleUnlinkSigner();
|
||||
handleUnlinkSigner(
|
||||
signerPos,
|
||||
setSignerPos,
|
||||
signersData,
|
||||
setSignersData,
|
||||
uniqueId
|
||||
);
|
||||
if (props.closePopup) {
|
||||
props.closePopup();
|
||||
}
|
||||
@@ -161,7 +177,7 @@ const SelectSigners = (props) => {
|
||||
<button className="op-btn op-btn-primary" onClick={() => handleAdd()}>
|
||||
{t("submit")}
|
||||
</button>
|
||||
{props.isExistSigner && props.handleUnlinkSigner && (
|
||||
{props.isExistSigner && isRemove && (
|
||||
<button
|
||||
className="op-btn op-btn-accent op-btn-outline"
|
||||
onClick={() => handleRemove()}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import axios from "axios";
|
||||
import moment from "moment";
|
||||
import React from "react";
|
||||
import { PDFDocument, rgb, degrees } from "pdf-lib";
|
||||
import Parse from "parse";
|
||||
import { appInfo } from "./appinfo";
|
||||
@@ -21,7 +20,9 @@ export const isTabAndMobile = window.innerWidth < 1023;
|
||||
export const textInputWidget = "text input";
|
||||
export const textWidget = "text";
|
||||
export const radioButtonWidget = "radio button";
|
||||
|
||||
export function getEnv() {
|
||||
return window?.RUNTIME_ENV || {};
|
||||
}
|
||||
|
||||
//function for create list of year for date widget
|
||||
export const range = (start, end, step) => {
|
||||
@@ -1665,10 +1666,11 @@ export const multiSignEmbed = async (widgets, pdfDoc, signyourself, scale) => {
|
||||
].includes(position.type);
|
||||
if (position.type === "checkbox") {
|
||||
let checkboxGapFromTop, isCheck;
|
||||
let y = yPos(position);
|
||||
const optionsFontSize = fontSize || 13;
|
||||
const checkboxSize = fontSize;
|
||||
const checkboxTextGapFromLeft = fontSize + 5 || 22;
|
||||
let y = yPos(position) + 2;
|
||||
//calculate checkbox size to draw on pdf
|
||||
const checkboxSize = fontSize - 1;
|
||||
//calculate gap between checkbox and options
|
||||
const checkboxTextGapFromLeft = fontSize + 5;
|
||||
if (position?.options?.values.length > 0) {
|
||||
position?.options?.values.forEach((item, ind) => {
|
||||
const checkboxRandomId = "checkbox" + randomId();
|
||||
@@ -1680,13 +1682,11 @@ export const multiSignEmbed = async (widgets, pdfDoc, signyourself, scale) => {
|
||||
} else if (position?.options?.defaultValue) {
|
||||
isCheck = position?.options?.defaultValue?.includes(ind);
|
||||
}
|
||||
|
||||
const checkbox = form.createCheckBox(checkboxRandomId);
|
||||
|
||||
if (ind > 0) {
|
||||
y = y + checkboxGapFromTop;
|
||||
} else {
|
||||
checkboxGapFromTop = fontSize + 5 || 26;
|
||||
checkboxGapFromTop = fontSize + 3.2;
|
||||
}
|
||||
|
||||
if (!position?.options?.isHideLabel) {
|
||||
@@ -1694,10 +1694,10 @@ export const multiSignEmbed = async (widgets, pdfDoc, signyourself, scale) => {
|
||||
const optionsPosition = compensateRotation(
|
||||
page.getRotation().angle,
|
||||
xPos(position) + checkboxTextGapFromLeft,
|
||||
y,
|
||||
y - 3,
|
||||
1,
|
||||
page.getSize(),
|
||||
optionsFontSize,
|
||||
fontSize,
|
||||
updateColorInRgb,
|
||||
font,
|
||||
page
|
||||
@@ -1780,7 +1780,7 @@ export const multiSignEmbed = async (widgets, pdfDoc, signyourself, scale) => {
|
||||
: NewbreakTextIntoLines(textContent, fixedWidth);
|
||||
// Set initial y-coordinate for the first line
|
||||
let x = xPos(position);
|
||||
let y = yPos(position);
|
||||
let y = yPos(position) - 4;
|
||||
// Embed each line on the page
|
||||
for (const line of lines) {
|
||||
const textPosition = compensateRotation(
|
||||
@@ -1830,28 +1830,33 @@ export const multiSignEmbed = async (widgets, pdfDoc, signyourself, scale) => {
|
||||
} else if (position.type === radioButtonWidget) {
|
||||
const radioRandomId = "radio" + randomId();
|
||||
const radioGroup = form.createRadioGroup(radioRandomId);
|
||||
let radioOptionGapFromTop;
|
||||
const optionsFontSize = fontSize || 13;
|
||||
const radioTextGapFromLeft = fontSize + 5 || 20;
|
||||
//draw radio button on document and options if hide label is enable
|
||||
let radioButtonFromTop;
|
||||
//getting radio buttons options text font size
|
||||
const optionsFontSize = fontSize;
|
||||
//calculate value of gap between radio button and options
|
||||
const radioTextGapFromLeft = fontSize + 6;
|
||||
//getting radio button font size
|
||||
const radioSize = fontSize;
|
||||
//getting position of radio widget in y direction
|
||||
let y = yPos(position);
|
||||
//on the basic of option's length create radio button and message
|
||||
if (position?.options?.values.length > 0) {
|
||||
position?.options?.values.forEach((item, ind) => {
|
||||
if (ind > 0) {
|
||||
y = y + radioOptionGapFromTop;
|
||||
y = y + radioButtonFromTop;
|
||||
} else {
|
||||
radioOptionGapFromTop = fontSize + 10 || 25;
|
||||
radioButtonFromTop = fontSize + 6;
|
||||
}
|
||||
if (!position?.options?.isHideLabel) {
|
||||
// below line of code is used to embed label with radio button in pdf
|
||||
|
||||
const optionsPosition = compensateRotation(
|
||||
page.getRotation().angle,
|
||||
xPos(position) + radioTextGapFromLeft,
|
||||
y,
|
||||
y - 2,
|
||||
1,
|
||||
page.getSize(),
|
||||
optionsFontSize,
|
||||
fontSize,
|
||||
updateColorInRgb,
|
||||
font,
|
||||
page
|
||||
@@ -1860,7 +1865,7 @@ export const multiSignEmbed = async (widgets, pdfDoc, signyourself, scale) => {
|
||||
page.drawText(item, optionsPosition);
|
||||
}
|
||||
let radioObj = {
|
||||
x: xPos(position),
|
||||
x: xPos(position) + 2,
|
||||
y: y,
|
||||
width: radioSize,
|
||||
height: radioSize
|
||||
@@ -3066,7 +3071,7 @@ export const mailTemplate = (param) => {
|
||||
"</td></tr><tr><td style='font-weight:bold;font-family:sans-serif;font-size:15px'>Note</td><td></td><td style='color:#626363;font-weight:bold'>" +
|
||||
param.note +
|
||||
"</td></tr><tr><td></td><td></td></tr></table></div> <div style='margin-left:70px'><a target=_blank href=" +
|
||||
param.sigingUrl +
|
||||
param.signingUrl +
|
||||
"><button style='padding:12px;background-color:#d46b0f;color:white;border:0px;font-weight:bold;margin-top:30px'>Sign here</button></a></div><div style='display:flex;justify-content:center;margin-top:10px'></div></div></div><div><p> This is an automated email from " +
|
||||
appName +
|
||||
". For any queries regarding this email, please contact the sender " +
|
||||
@@ -3161,3 +3166,22 @@ export const checkRegularExpress = (validateType, setValidatePlaceholder) => {
|
||||
setValidatePlaceholder("please enter value");
|
||||
}
|
||||
};
|
||||
//function to use unlink signer from widgets
|
||||
export const handleUnlinkSigner = (signerPos,setSignerPos,signersdata,setSignersData,uniqueId) => {
|
||||
//remove existing signer's details from 'signerPos' array
|
||||
const updatePlaceHolder = signerPos.map((x) => {
|
||||
if (x.Id === uniqueId) {
|
||||
return { ...x, signerPtr: {}, signerObjId: "" };
|
||||
}
|
||||
return { ...x };
|
||||
});
|
||||
setSignerPos(updatePlaceHolder);
|
||||
//remove existing signer's details from 'signersdata' array and keep role and id
|
||||
const updateSigner = signersdata.map((item) => {
|
||||
if (item.Id == uniqueId) {
|
||||
return { Role: item.Role, Id: item.Id, blockColor: item.blockColor };
|
||||
}
|
||||
return item;
|
||||
});
|
||||
setSignersData(updateSigner);
|
||||
};
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
import logo from "../assets/images/logo.png";
|
||||
import { getEnv } from "./Utils";
|
||||
|
||||
export function serverUrl_fn() {
|
||||
let baseUrl = process.env.REACT_APP_SERVERURL
|
||||
? process.env.REACT_APP_SERVERURL
|
||||
: window.location.origin + "/api/app";
|
||||
const env = getEnv();
|
||||
const serverurl = env?.REACT_APP_SERVERURL
|
||||
? env.REACT_APP_SERVERURL // env.REACT_APP_SERVERURL is used for prod
|
||||
: process.env.REACT_APP_SERVERURL; // process.env.REACT_APP_SERVERURL is used for dev (locally)
|
||||
let baseUrl = serverurl ? serverurl : window.location.origin + "/api/app";
|
||||
return baseUrl;
|
||||
}
|
||||
export const appInfo = {
|
||||
|
||||
@@ -1,3 +1,13 @@
|
||||
const userssetting = [
|
||||
{
|
||||
icon: "fa-light fa-users fa-fw",
|
||||
title: "Users",
|
||||
target: "_self",
|
||||
pageType: "",
|
||||
description: "",
|
||||
objectId: "users"
|
||||
}
|
||||
];
|
||||
export const subSetting = [
|
||||
{
|
||||
icon: "fa-light fa-sliders",
|
||||
@@ -7,14 +17,7 @@ export const subSetting = [
|
||||
description: "",
|
||||
objectId: "preferences"
|
||||
},
|
||||
{
|
||||
icon: "fa-light fa-users fa-fw",
|
||||
title: "Users",
|
||||
target: "_self",
|
||||
pageType: "",
|
||||
description: "",
|
||||
objectId: "users"
|
||||
}
|
||||
...userssetting
|
||||
];
|
||||
|
||||
const sidebarList = [
|
||||
@@ -65,7 +68,7 @@ const sidebarList = [
|
||||
pageType: "report",
|
||||
description: "",
|
||||
objectId: "6TeaPr321t"
|
||||
},
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
|
||||
@@ -68,6 +68,7 @@ function Login() {
|
||||
setState({ ...state, loading: false, alertType: type, alertMsg: msg });
|
||||
setTimeout(() => setState({ ...state, alertMsg: "" }), 2000);
|
||||
};
|
||||
|
||||
const checkUserExt = async () => {
|
||||
const app = await getAppLogo();
|
||||
if (app?.error === "invalid_json") {
|
||||
@@ -82,11 +83,11 @@ function Login() {
|
||||
} else {
|
||||
setImage(appInfo?.applogo || undefined);
|
||||
}
|
||||
dispatch(fetchAppInfo());
|
||||
if (localStorage.getItem("accesstoken")) {
|
||||
setState({ ...state, loading: true });
|
||||
GetLoginData();
|
||||
}
|
||||
dispatch(fetchAppInfo());
|
||||
};
|
||||
const handleChange = (event) => {
|
||||
let { name, value } = event.target;
|
||||
@@ -96,20 +97,15 @@ function Login() {
|
||||
setState({ ...state, [name]: value });
|
||||
};
|
||||
|
||||
const handleSubmit = async (event) => {
|
||||
localStorage.removeItem("accesstoken");
|
||||
event.preventDefault();
|
||||
const handleLogin = async (
|
||||
) => {
|
||||
const email = state?.email
|
||||
const password = state?.password
|
||||
|
||||
if (!emailRegex.test(state.email)) {
|
||||
alert("Please enter a valid email address.");
|
||||
return;
|
||||
}
|
||||
|
||||
const { email, password } = state;
|
||||
if (!email || !password) {
|
||||
return;
|
||||
}
|
||||
|
||||
localStorage.removeItem("accesstoken");
|
||||
try {
|
||||
setState({ ...state, loading: true });
|
||||
localStorage.setItem("appLogo", appInfo.applogo);
|
||||
@@ -132,6 +128,14 @@ function Login() {
|
||||
showToast("danger", "Invalid username/password or region");
|
||||
}
|
||||
};
|
||||
const handleLoginBtn = async (event) => {
|
||||
event.preventDefault();
|
||||
if (!emailRegex.test(state.email)) {
|
||||
alert("Please enter a valid email address.");
|
||||
return;
|
||||
}
|
||||
await handleLogin();
|
||||
};
|
||||
|
||||
const setThirdpartyLoader = (value) => {
|
||||
setState({ ...state, thirdpartyLoader: value });
|
||||
@@ -275,7 +279,6 @@ function Login() {
|
||||
const userInformation = JSON.parse(
|
||||
localStorage.getItem("UserInformation")
|
||||
);
|
||||
// console.log("payload ", payload);
|
||||
if (payload && payload.sessionToken) {
|
||||
const params = {
|
||||
userDetails: {
|
||||
@@ -289,7 +292,6 @@ function Login() {
|
||||
}
|
||||
};
|
||||
const userSignUp = await Parse.Cloud.run("usersignup", params);
|
||||
// console.log("userSignUp ", userSignUp);
|
||||
if (userSignUp && userSignUp.sessionToken) {
|
||||
const LocalUserDetails = {
|
||||
name: userInformation.name,
|
||||
@@ -430,7 +432,7 @@ function Login() {
|
||||
</div>
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-x-2">
|
||||
<div>
|
||||
<form onSubmit={handleSubmit} aria-label="Login Form">
|
||||
<form onSubmit={handleLoginBtn} aria-label="Login Form">
|
||||
<h1 className="text-[30px] mt-6">{t("welcome")}</h1>
|
||||
<fieldset>
|
||||
<legend className="text-[12px] text-[#878787]">
|
||||
@@ -488,15 +490,14 @@ function Login() {
|
||||
)}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div className="relative mt-1">
|
||||
<NavLink
|
||||
to="/forgetpassword"
|
||||
className="text-[13px] op-link op-link-primary underline-offset-1 focus:outline-none ml-1"
|
||||
>
|
||||
{t("forgot-password")}
|
||||
</NavLink>
|
||||
</div>
|
||||
<div className="relative mt-1">
|
||||
<NavLink
|
||||
to="/forgetpassword"
|
||||
className="text-[13px] op-link op-link-primary underline-offset-1 focus:outline-none ml-1"
|
||||
>
|
||||
{t("forgot-password")}
|
||||
</NavLink>
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-2 text-center text-xs font-bold mt-2">
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { useState, useRef, useEffect } from "react";
|
||||
import { useState, useRef, useEffect } from "react";
|
||||
import { PDFDocument } from "pdf-lib";
|
||||
import "../styles/signature.css";
|
||||
import Parse from "parse";
|
||||
@@ -916,7 +916,7 @@ function PdfRequestFiles(
|
||||
const htmlReqBody =
|
||||
"<html><head><meta http-equiv='Content-Type' content='text/html; charset=UTF-8' /></head><body>" +
|
||||
replacedRequestBody +
|
||||
"</body> </html>";
|
||||
"</body></html>";
|
||||
|
||||
const variables = {
|
||||
document_title: documentName,
|
||||
@@ -929,7 +929,7 @@ function PdfRequestFiles(
|
||||
receiver_phone: user?.Phone || "",
|
||||
expiry_date: localExpireDate,
|
||||
company_name: orgName,
|
||||
signing_url: `<a href=${signPdf} target=_blank>Sign here</a>`
|
||||
signing_url: signPdf
|
||||
};
|
||||
replaceVar = replaceMailVaribles(
|
||||
requestSubject,
|
||||
@@ -944,7 +944,7 @@ function PdfRequestFiles(
|
||||
title: documentName,
|
||||
organization: orgName,
|
||||
localExpireDate: localExpireDate,
|
||||
sigingUrl: signPdf
|
||||
signingUrl: signPdf
|
||||
};
|
||||
let params = {
|
||||
replyto: senderEmail || "",
|
||||
|
||||
@@ -1220,7 +1220,7 @@ function PlaceHolderSign() {
|
||||
receiver_phone: signerMail[i]?.Phone || "",
|
||||
expiry_date: localExpireDate,
|
||||
company_name: orgName,
|
||||
signing_url: `<a href=${signPdf} target=_blank>Sign here</a>`
|
||||
signing_url: signPdf
|
||||
};
|
||||
replaceVar = replaceMailVaribles(
|
||||
requestSubject,
|
||||
@@ -1249,7 +1249,7 @@ function PlaceHolderSign() {
|
||||
receiver_phone: signerMail[i]?.Phone || "",
|
||||
expiry_date: localExpireDate,
|
||||
company_name: orgName,
|
||||
signing_url: `<a href=${signPdf} target=_blank>Sign here</a>`
|
||||
signing_url: signPdf
|
||||
};
|
||||
replaceVar = replaceMailVaribles(mailSubject, htmlReqBody, variables);
|
||||
}
|
||||
@@ -1260,7 +1260,7 @@ function PlaceHolderSign() {
|
||||
title: documentName,
|
||||
organization: orgName,
|
||||
localExpireDate: localExpireDate,
|
||||
sigingUrl: signPdf
|
||||
signingUrl: signPdf
|
||||
};
|
||||
let params = {
|
||||
extUserId: owner?.objectId,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { useState, useRef, useEffect } from "react";
|
||||
import { useState, useRef, useEffect } from "react";
|
||||
import { PDFDocument } from "pdf-lib";
|
||||
import "../styles/signature.css";
|
||||
import Parse from "parse";
|
||||
|
||||
@@ -1149,25 +1149,6 @@ const TemplatePlaceholder = () => {
|
||||
const handleLinkUser = (id) => {
|
||||
setIsAddUser({ [id]: true });
|
||||
};
|
||||
//function to use unlink signer from widgets
|
||||
const handleUnlinkSigner = () => {
|
||||
//remove existing signer's details from 'signerPos' array
|
||||
const updatePlaceHolder = signerPos.map((x) => {
|
||||
if (x.Id === uniqueId) {
|
||||
return { ...x, signerPtr: {}, signerObjId: "" };
|
||||
}
|
||||
return { ...x };
|
||||
});
|
||||
setSignerPos(updatePlaceHolder);
|
||||
//remove existing signer's details from 'signersdata' array and keep role and id
|
||||
const updateSigner = signersdata.map((item) => {
|
||||
if (item.Id == uniqueId) {
|
||||
return { Role: item.Role, Id: item.Id, blockColor: item.blockColor };
|
||||
}
|
||||
return item;
|
||||
});
|
||||
setSignersData(updateSigner);
|
||||
};
|
||||
// `handleAddUser` is used to adduser
|
||||
const handleAddUser = (data) => {
|
||||
const signerPtr = {
|
||||
@@ -1950,7 +1931,9 @@ const TemplatePlaceholder = () => {
|
||||
closePopup={closePopup}
|
||||
signersData={signersdata}
|
||||
signerPos={signerPos}
|
||||
handleUnlinkSigner={handleUnlinkSigner}
|
||||
setSignerPos={setSignerPos}
|
||||
setSignersData={setSignersData}
|
||||
isRemove={true}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -679,7 +679,7 @@ const ReportTable = (props) => {
|
||||
receiver_phone: userDetails?.Phone || "",
|
||||
expiry_date: localExpireDate,
|
||||
company_name: doc.ExtUserPtr.Company,
|
||||
signing_url: `<a href=${signPdf} target=_blank>Sign here</a>`
|
||||
signing_url: signPdf
|
||||
};
|
||||
const res = replaceMailVaribles(subject, "", variables);
|
||||
setMail((prev) => ({ ...prev, subject: res.subject }));
|
||||
@@ -710,7 +710,7 @@ const ReportTable = (props) => {
|
||||
receiver_phone: userDetails?.Phone || "",
|
||||
expiry_date: localExpireDate,
|
||||
company_name: doc.ExtUserPtr.Company,
|
||||
signing_url: `<a href=${signPdf} target=_blank>Sign here</a>`
|
||||
signing_url: signPdf
|
||||
};
|
||||
const res = replaceMailVaribles("", body, variables);
|
||||
|
||||
@@ -754,7 +754,7 @@ const ReportTable = (props) => {
|
||||
receiver_phone: user?.signerPtr?.Phone || "",
|
||||
expiry_date: localExpireDate,
|
||||
company_name: doc?.ExtUserPtr?.Company || "",
|
||||
signing_url: `<a href=${signPdf} target=_blank>Sign here</a>`
|
||||
signing_url: signPdf
|
||||
};
|
||||
const subject =
|
||||
doc?.RequestSubject ||
|
||||
|
||||
@@ -25,12 +25,10 @@ const LinkUserModal = (props) => {
|
||||
handleClose={props.closePopup}
|
||||
>
|
||||
<SelectSigners
|
||||
details={props.handleAddUser}
|
||||
{...props}
|
||||
closePopup={props.closePopup}
|
||||
signersData={props?.signersData}
|
||||
isContact={isContact}
|
||||
setIsContact={setIsContact}
|
||||
handleUnlinkSigner={props.handleUnlinkSigner}
|
||||
isExistSigner={isExistSigner}
|
||||
/>
|
||||
{isContact && (
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
# Use an official Node runtime as the base image
|
||||
FROM node:20
|
||||
|
||||
# Set the working directory inside the container
|
||||
WORKDIR /usr/src/app
|
||||
|
||||
# Copy package.json and package-lock.json first to leverage Docker cache
|
||||
COPY ./package*.json ./
|
||||
|
||||
# Install application dependencies
|
||||
RUN npm install
|
||||
|
||||
# If you have native dependencies, you'll need extra tools. Uncomment the following line if needed.
|
||||
# RUN apk add --no-cache make gcc g++ python3
|
||||
|
||||
# Copy the current directory contents into the container
|
||||
COPY ./ .
|
||||
|
||||
# Make port 8080 available to the world outside this container
|
||||
EXPOSE 8080
|
||||
|
||||
# Define environment variables if needed
|
||||
# ENV NODE_ENV production
|
||||
# ENV DATABASE_URL mongodb://db:27017
|
||||
|
||||
# Run the application
|
||||
ENTRYPOINT npm start
|
||||
@@ -252,7 +252,7 @@ export const mailTemplate = param => {
|
||||
"</td></tr><tr><td style='font-weight:bold;font-family:sans-serif;font-size:15px'>Note</td><td></td><td style='color:#626363;font-weight:bold'>" +
|
||||
param.note +
|
||||
"</td></tr><tr><td></td><td></td></tr></table></div> <div style='margin-left:70px'><a target=_blank href=" +
|
||||
param.sigingUrl +
|
||||
param.signingUrl +
|
||||
"><button style='padding:12px;background-color:#d46b0f;color:white;border:0px;font-weight:bold;margin-top:30px'>Sign here</button></a></div><div style='display:flex;justify-content:center;margin-top:10px'></div></div></div><div><p> This is an automated email from " +
|
||||
AppName +
|
||||
'. For any queries regarding this email, please contact the sender ' +
|
||||
|
||||
@@ -4,9 +4,9 @@ export default async function Newsletter(request) {
|
||||
const email = request.params?.email?.toLowerCase()?.replace(/\s/g, '');
|
||||
const domain = request.params.domain;
|
||||
try {
|
||||
const envAppId = process.env.REACT_APP_APPID || 'opensign';
|
||||
const envAppId = 'opensign';
|
||||
const headers = { 'Content-Type': 'application/json', 'X-Parse-Application-Id': envAppId };
|
||||
const envProdServer = process.env.REACT_APP_SERVERURL || 'https://app.opensignlabs.com/api/app';
|
||||
const envProdServer = 'https://app.opensignlabs.com/api/app';
|
||||
const newsletter = await axios.post(
|
||||
`${envProdServer}/classes/Newsletter`,
|
||||
{ Name: name, Email: email, Domain: domain },
|
||||
|
||||
@@ -14,7 +14,7 @@ async function deductcount(docsCount, extUserId) {
|
||||
}
|
||||
async function sendMail(document, publicUrl) {
|
||||
//sessionToken
|
||||
const baseUrl = new URL(publicUrl); //process.env.PUBLIC_URL
|
||||
const baseUrl = new URL(publicUrl);
|
||||
|
||||
// console.log("pdfDetails", pdfDetails);
|
||||
const timeToCompleteDays = document?.TimeToCompleteDays || 15;
|
||||
@@ -71,7 +71,7 @@ async function sendMail(document, publicUrl) {
|
||||
receiver_phone: existSigner?.Phone || '',
|
||||
expiry_date: localExpireDate,
|
||||
company_name: orgName,
|
||||
signing_url: `<a href=${signPdf} target=_blank>Sign here</a>`,
|
||||
signing_url: signPdf,
|
||||
};
|
||||
replaceVar = replaceMailVaribles(mailSubject, htmlReqBody, variables);
|
||||
}
|
||||
@@ -82,7 +82,7 @@ async function sendMail(document, publicUrl) {
|
||||
title: document.Name,
|
||||
organization: orgName,
|
||||
localExpireDate: localExpireDate,
|
||||
sigingUrl: signPdf,
|
||||
signingUrl: signPdf,
|
||||
};
|
||||
let params = {
|
||||
extUserId: document.ExtUserPtr.objectId,
|
||||
|
||||
@@ -116,7 +116,7 @@ async function sendNotifyMail(doc, signUser, mailProvider, publicUrl) {
|
||||
const creatorEmail = doc.ExtUserPtr.Email;
|
||||
const signerName = signUser.Name;
|
||||
const signerEmail = signUser.Email;
|
||||
const viewDocUrl = `${publicUrl}/recipientSignPdf/${doc.objectId}`; // ` ${process.env.PUBLIC_URL}/recipientSignPdf/${doc.objectId}`;
|
||||
const viewDocUrl = `${publicUrl}/recipientSignPdf/${doc.objectId}`;
|
||||
const subject = `Document "${pdfName}" has been signed by ${signerName}`;
|
||||
const body =
|
||||
"<html><head><meta http-equiv='Content-Type' content='text/html; charset=UTF-8'/></head><body><div style='background-color:#f5f5f5;padding:20px'><div style='background-color:white'>" +
|
||||
|
||||
@@ -161,7 +161,7 @@ app.use(express.urlencoded({ limit: '50mb', extended: true }));
|
||||
app.use(function (req, res, next) {
|
||||
req.headers['x-real-ip'] = getUserIP(req);
|
||||
const publicUrl = 'https://' + req?.get('host');
|
||||
req.headers['public_url'] = publicUrl; // process.env.PUBLIC_URL
|
||||
req.headers['public_url'] = publicUrl;
|
||||
next();
|
||||
});
|
||||
function getUserIP(request) {
|
||||
|
||||
Generated
+2
-2
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "open_sign_server",
|
||||
"version": "1.4.0",
|
||||
"version": "2.21.1",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "open_sign_server",
|
||||
"version": "1.4.0",
|
||||
"version": "2.21.1",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@aws-sdk/client-s3": "^3.812.0",
|
||||
|
||||
Reference in New Issue
Block a user