diff --git a/.env.local_dev b/.env.local_dev
index 71635fd48..bf88879c4 100644
--- a/.env.local_dev
+++ b/.env.local_dev
@@ -40,7 +40,7 @@ DO_SECRET_ACCESS_KEY=
# Digital ocean spaces region or AWS s3 region
DO_REGION=us-west
# local storage
-USE_LOCAL=TRUE
+USE_LOCAL=true
# Email mailgun or set SMTP_ENABLE true to use SMTP config (The app will not initialize if any of these 3 variables are not set) *********************************************************************************************************************
MAILGUN_API_KEY=
diff --git a/README.md b/README.md
index 24e1046fc..ede88954f 100644
--- a/README.md
+++ b/README.md
@@ -136,7 +136,7 @@ We would like to thank all our contributors and users for their support and feed
@@ -278,14 +294,12 @@ const AddSigner = (props) => {
className="block text-xs text-gray-700 font-semibold"
>
Phone
-
*
setPhone(e.target.value)}
- required
disabled={addYourself}
className="px-3 py-2 w-full border-[1px] border-gray-300 rounded focus:outline-none text-xs"
/>
diff --git a/apps/OpenSign/src/components/AddUser.js b/apps/OpenSign/src/components/AddUser.js
index d812a1cd0..8d40db895 100644
--- a/apps/OpenSign/src/components/AddUser.js
+++ b/apps/OpenSign/src/components/AddUser.js
@@ -62,8 +62,10 @@ const AddUser = (props) => {
_user.set("name", name);
_user.set("username", email);
_user.set("email", email);
- _user.set("phone", phone);
- _user.set("password", phone);
+ _user.set("password", email);
+ if (phone) {
+ _user.set("phone", phone);
+ }
const user = await _user.save();
if (user) {
diff --git a/apps/OpenSign/src/components/BulkSendUi.js b/apps/OpenSign/src/components/BulkSendUi.js
new file mode 100644
index 000000000..6e4aa5e76
--- /dev/null
+++ b/apps/OpenSign/src/components/BulkSendUi.js
@@ -0,0 +1,261 @@
+import React, { useState, useEffect, useRef } from "react";
+import axios from "axios";
+import SuggestionInput from "./shared/fields/SuggestionInput";
+
+const BulkSendUi = (props) => {
+ const [forms, setForms] = useState([]);
+ const [formId, setFormId] = useState(2);
+ const formRef = useRef(null);
+ const [scrollOnNextUpdate, setScrollOnNextUpdate] = useState(false);
+ const [isSubmit, setIsSubmit] = useState(false);
+ const [allowedForm, setAllowedForm] = useState(0);
+ const [isSignatureExist, setIsSignatureExist] = useState();
+ const allowedSigners = 50;
+ useEffect(() => {
+ signatureExist();
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, []);
+
+ //function to check atleast one signature field exist
+ const signatureExist = () => {
+ const getPlaceholder = props.item?.Placeholders;
+ const checkIsSignatureExistt = getPlaceholder?.every((placeholderObj) =>
+ placeholderObj?.placeHolder?.some((holder) =>
+ holder?.pos?.some((posItem) => posItem?.type === "signature")
+ )
+ );
+ setIsSignatureExist(checkIsSignatureExistt);
+ };
+ useEffect(() => {
+ if (scrollOnNextUpdate && formRef.current) {
+ formRef.current.scrollIntoView({
+ behavior: "smooth",
+ block: "end",
+ inline: "nearest"
+ });
+ setScrollOnNextUpdate(false);
+ }
+ }, [forms, scrollOnNextUpdate]);
+
+ useEffect(() => {
+ (() => {
+ if (props?.Placeholders?.length > 0) {
+ let users = [];
+ props?.Placeholders?.forEach((element) => {
+ if (!element.signerObjId) {
+ users = [
+ ...users,
+ {
+ fieldId: element.Id,
+ email: "",
+ label: element.Role,
+ signer: {}
+ }
+ ];
+ }
+ });
+ setForms((prevForms) => [...prevForms, { Id: 1, fields: users }]);
+ const totalForms = Math.floor(allowedSigners / users?.length);
+ setAllowedForm(totalForms);
+ }
+ })();
+ // eslint-disable-next-line
+ }, []);
+ const handleInputChange = (index, signer, fieldIndex) => {
+ const newForms = [...forms];
+ newForms[index].fields[fieldIndex].email = signer?.Email
+ ? signer?.Email
+ : signer || "";
+ newForms[index].fields[fieldIndex].signer = signer?.objectId ? signer : "";
+ setForms(newForms);
+ };
+
+ const handleAddForm = (e) => {
+ e.preventDefault();
+ // Check if the quick send limit has been reached
+ if (forms?.length < allowedForm) {
+ if (props?.Placeholders.length > 0) {
+ let newForm = [];
+ props?.Placeholders?.forEach((element) => {
+ if (!element.signerObjId) {
+ newForm = [
+ ...newForm,
+ {
+ fieldId: element.Id,
+ email: "",
+ label: element.Role,
+ signer: {}
+ }
+ ];
+ }
+ });
+ setForms([...forms, { Id: formId, fields: newForm }]);
+ }
+ setFormId(formId + 1);
+ setScrollOnNextUpdate(true);
+ } else {
+ // If the limit has been reached, throw an error with the appropriate message
+ alert("Quick send reached limit.");
+ }
+ };
+
+ const handleRemoveForm = (index) => {
+ const updatedForms = forms.filter((_, i) => i !== index);
+ setForms(updatedForms);
+ };
+ const handleSubmit = async (e) => {
+ e.preventDefault();
+ e.stopPropagation();
+ setIsSubmit(true);
+
+ // Create a copy of Placeholders array from props.item
+ let Placeholders = [...props.item.Placeholders];
+ // Initialize an empty array to store updated documents
+ let Documents = [];
+
+ // Loop through each form
+ forms.forEach((form) => {
+ // Map through the copied Placeholders array to update email values
+ const updatedPlaceholders = Placeholders.map((placeholder) => {
+ // Find the field in the current form that matches the placeholder Id
+ const field = form.fields.find(
+ (element) => parseInt(element.fieldId) === placeholder.Id
+ );
+ // If a matching field is found, update the email value in the placeholder
+ const signer = field?.signer?.objectId ? field.signer : {};
+ if (field) {
+ return {
+ ...placeholder,
+ email: field.email,
+ signerObjId: field?.signer?.objectId || "",
+ signerPtr: signer
+ };
+ }
+ // If no matching field is found, keep the placeholder as is
+ return placeholder;
+ });
+
+ // Push a new document object with updated Placeholders into the Documents array
+ Documents.push({ ...props.item, Placeholders: updatedPlaceholders });
+ });
+ // console.log("Documents ", Documents);
+ await batchQuery(Documents);
+ };
+
+ const batchQuery = async (Documents) => {
+ const serverUrl = localStorage.getItem("baseUrl");
+ const functionsUrl = `${serverUrl}functions/batchdocuments`;
+ const headers = {
+ "Content-Type": "application/json",
+ "X-Parse-Application-Id": localStorage.getItem("parseAppId"),
+ sessionToken: localStorage.getItem("accesstoken")
+ };
+ const params = {
+ Documents: JSON.stringify(Documents)
+ };
+ try {
+ const res = await axios.post(functionsUrl, params, { headers: headers });
+ // console.log("res ", res);
+ if (res.data && res.data.result) {
+ props.handleClose("success", Documents?.length);
+ }
+ } catch (err) {
+ console.log("Err ", err);
+ props.handleClose("error", 0);
+ } finally {
+ setIsSubmit(false);
+ }
+ };
+
+ return (
+ <>
+ {isSubmit && (
+
+ )}
+ {props.Placeholders?.length > 0 ? (
+ isSignatureExist ? (
+ <>
+ {props.Placeholders?.some((x) => !x.signerObjId) ? (
+
+ ) : (
+
+ All roles in this document are currently linked to contacts. To
+ 'quick send' copies of this template to multiple
+ signers, please ensure that at least one role is not linked to
+ any contact.
+
+ )}
+ >
+ ) : (
+
+ Please ensure there's at least one signature widget added for
+ all recipients.
+
+ )
+ ) : (
+
+ Please add at least one role to this template in order to 'quick
+ send' copies of it to multiple signers.
+
+ )}
+ >
+ );
+};
+
+export default BulkSendUi;
diff --git a/apps/OpenSign/src/components/Header.js b/apps/OpenSign/src/components/Header.js
index 2b1a477cb..90563aac5 100644
--- a/apps/OpenSign/src/components/Header.js
+++ b/apps/OpenSign/src/components/Header.js
@@ -44,7 +44,9 @@ const Header = ({ showSidebar }) => {
const closeDropdown = () => {
setIsOpen(false);
- Parse.User.logOut();
+ if (Parse?.User?.current()) {
+ Parse.User.logOut();
+ }
let appdata = localStorage.getItem("userSettings");
let applogo = localStorage.getItem("appLogo");
let appName = localStorage.getItem("appName");
diff --git a/apps/OpenSign/src/components/LoginFacebook.js b/apps/OpenSign/src/components/LoginFacebook.js
index 033208d57..f9ca16a30 100644
--- a/apps/OpenSign/src/components/LoginFacebook.js
+++ b/apps/OpenSign/src/components/LoginFacebook.js
@@ -49,7 +49,7 @@ const LoginFacebook = ({
const extRes = await Parse.Cloud.run("getUserDetails", params);
// console.log("extRes ", extRes);
if (extRes) {
- const params = { ...details, Phone: extRes.get("Phone") };
+ const params = { ...details, Phone: extRes?.get("Phone") || "" };
const payload = await Parse.Cloud.run("facebooksign", params);
// console.log("payload ", payload);
if (payload && payload.sessiontoken) {
@@ -59,7 +59,7 @@ const LoginFacebook = ({
const LocalUserDetails = {
name: details.Name,
email: details.Email,
- phone: extRes.get("Phone"),
+ phone: extRes?.get("Phone") || "",
company: extRes.get("Company")
};
localStorage.setItem("userDetails", JSON.stringify(LocalUserDetails));
@@ -75,7 +75,7 @@ const LoginFacebook = ({
const handleSubmitbtn = async () => {
if (userDetails.Phone && userDetails.Company) {
setThirdpartyLoader(true);
- const params = { ...fBDetails, Phone: userDetails.Phone };
+ const params = { ...fBDetails, Phone: userDetails?.Phone || "" };
const payload = await Parse.Cloud.run("facebooksign", params);
// console.log("payload ", payload);
@@ -85,7 +85,7 @@ const LoginFacebook = ({
name: userDetails.Name,
email: userDetails.Email,
// "passsword":userDetails.Phone,
- phone: userDetails.Phone,
+ phone: userDetails?.Phone || "",
role: "contracts_User",
company: userDetails.Company
}
@@ -96,7 +96,7 @@ const LoginFacebook = ({
const LocalUserDetails = {
name: userDetails.Name,
email: userDetails.Email,
- phone: userDetails.Phone,
+ phone: userDetails?.Phone || "",
company: userDetails.Company
};
localStorage.setItem("userDetails", JSON.stringify(LocalUserDetails));
diff --git a/apps/OpenSign/src/components/LoginGoogle.js b/apps/OpenSign/src/components/LoginGoogle.js
index 469352b52..7bb53017b 100644
--- a/apps/OpenSign/src/components/LoginGoogle.js
+++ b/apps/OpenSign/src/components/LoginGoogle.js
@@ -110,7 +110,7 @@ const GoogleSignInBtn = ({
const extRes = await Parse.Cloud.run("getUserDetails", params);
// console.log("extRes ", extRes);
if (extRes) {
- const params = { ...details, Phone: extRes.get("Phone") };
+ const params = { ...details, Phone: extRes?.get("Phone") || "" };
const payload = await Parse.Cloud.run("googlesign", params);
// console.log("payload ", payload);
if (payload && payload.sessiontoken) {
@@ -121,7 +121,7 @@ const GoogleSignInBtn = ({
const LocalUserDetails = {
name: details.Name,
email: details.Gmail,
- phone: extRes.get("Phone"),
+ phone: extRes?.get("Phone") || "",
company: extRes.get("Company")
};
localStorage.setItem("userDetails", JSON.stringify(LocalUserDetails));
@@ -139,7 +139,7 @@ const GoogleSignInBtn = ({
setThirdpartyLoader(true);
// e.preventDefault()
// console.log("handelSubmit", userDetails);
- const params = { ...googleDetails, Phone: userDetails.Phone };
+ const params = { ...googleDetails, Phone: userDetails?.Phone };
const payload = await Parse.Cloud.run("googlesign", params);
// console.log("payload ", payload);
@@ -149,7 +149,7 @@ const GoogleSignInBtn = ({
name: userDetails.Name,
email: userDetails.Email,
// "passsword":userDetails.Phone,
- phone: userDetails.Phone,
+ phone: userDetails?.Phone || "",
role: "contracts_User",
company: userDetails.Company,
jobTitle: userDetails.Destination
@@ -161,7 +161,7 @@ const GoogleSignInBtn = ({
const LocalUserDetails = {
name: userDetails.Name,
email: userDetails.Email,
- phone: userDetails.Phone,
+ phone: userDetails?.Phone || "",
company: userDetails.Company
// jobTitle: userDetails.JobTitle
};
diff --git a/apps/OpenSign/src/components/pdf/DefaultSignature.js b/apps/OpenSign/src/components/pdf/DefaultSignature.js
index a440e807e..1887d5164 100644
--- a/apps/OpenSign/src/components/pdf/DefaultSignature.js
+++ b/apps/OpenSign/src/components/pdf/DefaultSignature.js
@@ -17,7 +17,7 @@ function DefaultSignature({ defaultSignImg, xyPostion, setDefaultSignAlert }) {
};
return (
-
+
{
@@ -9,9 +12,21 @@ const EditTemplate = ({ template, onSuccess }) => {
Name: template?.Name || "",
Note: template?.Note || "",
Description: template?.Description || "",
- SendinOrder: template?.SendinOrder ? `${template?.SendinOrder}` : "false"
+ SendinOrder: template?.SendinOrder ? `${template?.SendinOrder}` : "false",
+ AutomaticReminders: template?.AutomaticReminders || false,
+ RemindOnceInEvery: template?.RemindOnceInEvery || 5
});
-
+ const [isSubscribe, setIsSubscribe] = useState(false);
+ useEffect(() => {
+ fetchSubscription();
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, []);
+ const fetchSubscription = async () => {
+ if (isEnableSubscription) {
+ const getIsSubscribe = await checkIsSubscribed();
+ setIsSubscribe(getIsSubscribe);
+ }
+ };
const handleStrInput = (e) => {
setFormData({ ...formData, [e.target.name]: e.target.value });
};
@@ -25,12 +40,26 @@ const EditTemplate = ({ template, onSuccess }) => {
e.preventDefault();
e.stopPropagation();
const isChecked = formData.SendinOrder === "true" ? true : false;
- const data = { ...formData, SendinOrder: isChecked };
+ const AutoReminder = formData?.AutomaticReminders || false;
+
+ let reminderDate = {};
+ if (AutoReminder) {
+ const RemindOnceInEvery = parseInt(formData?.RemindOnceInEvery);
+ const ReminderDate = new Date(template?.createdAt);
+ ReminderDate.setDate(ReminderDate.getDate() + RemindOnceInEvery);
+ reminderDate = { NextReminderDate: ReminderDate };
+ }
+ const data = { ...formData, SendinOrder: isChecked, ...reminderDate };
onSuccess(data);
};
-
+ const handleAutoReminder = () => {
+ setFormData((prev) => ({
+ ...prev,
+ AutomaticReminders: !formData.AutomaticReminders
+ }));
+ };
return (
-
+
+
+ {!isEnableSubscription && (
+
+ )}
+
+ Auto reminder{" "}
+ {!isSubscribe && isEnableSubscription && }
+
+
+
+
+
+
+ {isSubscribe && formData?.AutomaticReminders === true && (
+
+
+ Remind once in every (Days)
+ *
+
+
+
+ )}
{/*
*/}
diff --git a/apps/OpenSign/src/components/pdf/EmailComponent.js b/apps/OpenSign/src/components/pdf/EmailComponent.js
index b1e905719..66c4cc682 100644
--- a/apps/OpenSign/src/components/pdf/EmailComponent.js
+++ b/apps/OpenSign/src/components/pdf/EmailComponent.js
@@ -10,7 +10,6 @@ import loader from "../../assets/images/loader2.gif";
function EmailComponent({
isEmail,
pdfUrl,
- isCeleb,
setIsEmail,
setSuccessEmail,
pdfName,
@@ -22,6 +21,7 @@ function EmailComponent({
const [emailList, setEmailList] = useState([]);
const [emailValue, setEmailValue] = useState();
const [isLoading, setIsLoading] = useState(false);
+ const [isEmailCelebration, setIsEmailCelebration] = useState(false);
//function for send email
const sendEmail = async () => {
setIsLoading(true);
@@ -62,6 +62,10 @@ function EmailComponent({
" target=_blank>here