Merge pull request #548 from OpenSignLabs/staging

v1.4.1
This commit is contained in:
Amol
2024-04-01 11:48:17 +05:30
committed by GitHub
19 changed files with 233 additions and 175 deletions
+11 -11
View File
@@ -42,24 +42,24 @@ Please star ⭐ the repo to support us! 😀
### Introduction
Welcome to OpenSign, the premier open-source docusign alternative - document e-signing solution designed to provide a secure, reliable, and free alternative to commercial platforms like DocuSign, PandaDoc, SignNow, Adobe Sign, Smartwaiver, SignRequest, HelloSign & Zoho sign. Developed under the OpenSignLabs organization, our mission is to democratize the e-signing process, making it accessible and straightforward for everyone.
Welcome to OpenSign, the premier open source docusign alternative - document e-signing solution designed to provide a secure, reliable and free alternative to commercial esign platforms like DocuSign, PandaDoc, SignNow, Adobe Sign, Smartwaiver, SignRequest, HelloSign & Zoho sign. Our mission is to democratize the e-signing process, making it accessible and straightforward for everyone.
---
### Features
- **Secure PDF E-Signing:** With the help of Robust encryption algorithms, OpenSign™ ensures maximum security, privacy & compatibility.
- **Annotate Documents:** OpenSign™ allows you to annotate PDF documents with an advanced signing pad that comes with hand drawn signatures support as well as uploaded images & saved signatures for the simplest signing experience.
- **User-Friendly Interface:** OpenSign™ was built while keeping Intuitive design in mind for ease of use. Features like "Sign yourself", "One click signatures" and "OpenSign Drive" makes it stand out of the crowd and even makes it better than a lot of so-called industry leaders.
- **Multi-signer Support:** OpenSign's ability to invite multiple signers for signing along with the ability to invite witnesses & being able to enforce signing in a sequence makes it the only open source solution that is fully loaded and allows it to compete head-to-head with established players.
- **Secure PDF E-Signing:** With the help of robust encryption algorithms, OpenSign™ ensures maximum security, privacy & compatibility.
- **Annotate Documents:** OpenSign™ allows you to annotate PDF documents with an advanced signing pad that allows hand drawn signatures, uploaded images, typed signatures & saved signatures for the simplest signing experience ever.
- **User-Friendly Interface:** OpenSign™ was built while keeping Intuitive design in mind for ease of use. Features like "Sign yourself", "Templates", "One click signatures" and "OpenSign Drive" makes it stand out of the crowd and even makes it better than a lot of so-called industry leaders.
- **Multi-signer Support:** OpenSign's ability to invite multiple signers for signing along with the ability to invite witnesses & being able to enforce signing in a sequence makes it the only open source solution that is fully loaded and allows it to compete head-to-head with established players in e-signature space.
- **Email Unique Code(OTP) verification support for guest signers:** With OpenSign™, your documents are fully secure even when being signed by guest users. Guest signers can only sign the document after entering a unique code sent to their email address. 
- **"Expiring Docs" & "Rejection":** You can set documents to expire after certain number of days after which nobody will be able to sign it. Not just this, OpenSign also allows signers to reject signing a document.
- **"Expiring Docs" & "Rejection":** You can set documents to expire after certain number of days after which nobody will be able to sign. Not just this, OpenSign also allows signers to reject signing a document.
- **Beautiful email templates:** All document signing invitations, completion notifications & reminders are formatted using great looking email templates.
- **PDF Template Creation(coming soon):** OpenSign™ allows you to create and store PDF document templates for repeated use thereby saving you a lot of time.
- **OpenSign™ Drive:** It is a centralised secure vault for your signed documents that makes storing, signing, organizing, sharing & achieving your docs a breeze.
- **PDF Template Creation:** OpenSign™ allows you to create and store PDF document templates for repeated use thereby saving you a lot of time & collect e-signatures seamlessly.
- **OpenSign™ Drive:** It is a centralised secure vault for your digital documents that makes storing, signing, organizing, sharing & achieving your docs a breeze.
- **Audit Trails & completion certificate:** Being a security focused solution, OpenSign™ makes it a top priority to save detailed logs for tracking document activities along with time-stamps, IP addresses, email IDs & phone numbers. A completion certificate is generated as soon as document is completed which contains all the document related logs for added safety.
- **API Support(coming soon):** OpenSign™ API allows seamless integration into existing systems and software. APIs will soon be available as a cloud hosted solution.
- **Integrations:** Seamless integrations with various Cloud storage systems, CRMs & enterprise platforms is coming soon.
- **API Support:** OpenSign™ API allows seamless integration into existing systems and software. You can generate an API key from the app and refer the [docs](https://docs.opensignlabs.com) to start integrating it in your existing applications.
- **Integrations:** Seamless integrations with various Cloud storage systems, CRMs & enterprise platforms is available. We also have a Zapier integration that allows you to integrate it with virtually any application.
<img src=https://github.com/OpenSignLabs/OpenSign/assets/5486116/b37ff443-7099-4273-9aeb-21c46d7154cf height='200'>
<img src=https://github.com/OpenSignLabs/OpenSign/assets/5486116/86db91b7-6c2f-4885-a33c-58f4fd35ec89 height='200'>
@@ -76,7 +76,7 @@ Please refer to the [Installation Guide](INSTALLATION.md) for detailed instructi
### Usage
For comprehensive guidelines on how to use OpenSign, please consult our [User Manual](USAGE.md).
For comprehensive guidelines on how to use OpenSign, please consult our [User Manual](USAGE.md).
---
@@ -353,7 +353,7 @@ const DashboardCard = (props) => {
</div>
</div>
</div>
<div className="text-xs absolute top-1 right-1">
<div className="text-xs absolute top-2 right-1">
<Tooltip id={props.Label} iconColor={"white"} message={props?.Data?.tourMessage} />
</div>
</div>
@@ -275,6 +275,7 @@ function Placeholder(props) {
}
};
const handleOnClickPlaceholder = () => {
props.setCurrWidgetsDetails && props.setCurrWidgetsDetails(props.pos);
if (!props.isNeedSign) {
props.setWidgetType(props.pos.type);
}
@@ -307,6 +307,7 @@ function PlaceholderType(props) {
return props.pos.SignUrl ? (
<img
alt="signimg"
draggable="false"
src={props.pos.SignUrl}
style={{
width: "99%",
@@ -328,6 +329,7 @@ function PlaceholderType(props) {
return props.pos.SignUrl ? (
<img
alt="signimg"
draggable="false"
src={props.pos.SignUrl}
style={{
width: "99%",
@@ -483,6 +485,7 @@ function PlaceholderType(props) {
return props.pos.SignUrl ? (
<img
alt="signimg"
draggable="false"
src={props.pos.SignUrl}
style={{
width: "99%",
@@ -668,6 +671,7 @@ function PlaceholderType(props) {
return props.pos.SignUrl ? (
<img
alt="signimg"
draggable="false"
src={props.pos.SignUrl}
style={{
width: "99%",
@@ -787,6 +791,7 @@ function PlaceholderType(props) {
<div style={{ pointerEvents: "none" }}>
<img
alt="signimg"
draggable="false"
src={props.pos.SignUrl}
style={{
width: "99%",
@@ -116,7 +116,13 @@ const RecipientList = (props) => {
data-tut="reactourFirst"
onMouseEnter={() => setIsHover(ind)}
onMouseLeave={() => setIsHover(null)}
className={props.sendInOrder && "dragCursor"}
className={
props.sendInOrder
? props.isMailSend
? "disabled"
: "dragCursor"
: props.isMailSend && "disabled"
}
style={
(!isMobile && isHover === ind) || props.isSelectListId === ind
? onHoverStyle(ind, obj?.blockColor)
@@ -272,6 +272,7 @@ function RenderPdf({
unSignedWidgetId={unSignedWidgetId}
setSelectWidgetId={setSelectWidgetId}
selectWidgetId={selectWidgetId}
setCurrWidgetsDetails={setCurrWidgetsDetails}
/>
</React.Fragment>
)
+36 -19
View File
@@ -20,7 +20,9 @@ function SignPad({
isInitial,
setIsInitial,
setIsStamp,
widgetType
widgetType,
currWidgetsDetails,
setCurrWidgetsDetails
}) {
const [penColor, setPenColor] = useState("blue");
const allColor = ["blue", "red", "black"];
@@ -31,6 +33,7 @@ function SignPad({
const [signValue, setSignValue] = useState("");
const [textWidth, setTextWidth] = useState(null);
const [textHeight, setTextHeight] = useState(null);
const [signatureType, setSignatureType] = useState("draw");
const fontOptions = [
{ value: "Fasthand" },
{ value: "Dancing Script" },
@@ -48,19 +51,11 @@ function SignPad({
`Parse/${localStorage.getItem("parseAppId")}/currentUser`
);
const jsonSender = JSON.parse(senderUser);
const currentUserName = jsonSender && jsonSender.name;
useEffect(() => {
const trimmedName = currentUserName.trim();
const firstCharacter = trimmedName.charAt(0);
const userName = isInitial ? firstCharacter : currentUserName;
setSignValue(userName);
setFontSelect("Fasthand");
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
//function for clear signature image
const handleClear = () => {
setCurrWidgetsDetails({});
if (isTab === "draw") {
if (canvasRef.current) {
canvasRef.current.clear();
@@ -72,7 +67,7 @@ function SignPad({
} else if (isTab === "uploadImage") {
setImage("");
}
setIsInitial(false);
// setIsInitial(false);
};
//function for set signature url
const handleSignatureChange = () => {
@@ -100,27 +95,28 @@ function SignPad({
<button
onClick={() => {
setCurrWidgetsDetails({});
if (!image) {
if (isTab === "mysignature") {
setIsSignImg("");
if (isInitial) {
onSaveSign("initials");
onSaveSign(signatureType, "initials");
} else {
onSaveSign("default");
onSaveSign(null, "default");
}
} else {
if (isTab === "type") {
setIsSignImg("");
onSaveSign(false, textWidth, textHeight);
onSaveSign(null, false, textWidth, textHeight);
} else {
onSaveSign();
onSaveSign(signatureType);
}
}
setPenColor("blue");
} else {
setIsSignImg("");
onSaveImage();
onSaveImage(signatureType);
}
setIsSignPad(false);
setIsInitial(false);
@@ -150,11 +146,27 @@ function SignPad({
</div>
);
};
//useEffect for set already draw or save signature url/text url of signature text type and draw type for initial type and signature type widgets
useEffect(() => {
if (canvasRef.current && isSignImg) {
canvasRef.current.fromDataURL(isSignImg);
if (currWidgetsDetails && canvasRef.current) {
const isWidgetType = currWidgetsDetails?.type;
const signatureType = currWidgetsDetails?.signatureType;
const url = currWidgetsDetails?.SignUrl;
//checking widget type and draw type signature url
if (isInitial) {
if (isWidgetType === "initials" && signatureType === "draw" && url) {
canvasRef.current.fromDataURL(url);
}
} else if (
isWidgetType === "signature" &&
signatureType === "draw" &&
url
) {
canvasRef.current.fromDataURL(url);
}
}
const trimmedName = currentUserName.trim();
const firstCharacter = trimmedName.charAt(0);
const userName = isInitial ? firstCharacter : currentUserName;
@@ -349,6 +361,7 @@ function SignPad({
setIsDefaultSign(false);
setIsImageSelect(true);
setIsTab("uploadImage");
setSignatureType("");
}}
style={{
color:
@@ -373,6 +386,7 @@ function SignPad({
setIsDefaultSign(false);
setIsImageSelect(false);
setIsTab("type");
setSignatureType("");
setImage();
}}
style={{
@@ -400,6 +414,7 @@ function SignPad({
setIsDefaultSign(true);
setIsImageSelect(true);
setIsTab("mysignature");
setSignatureType("");
setImage();
}}
style={{
@@ -430,6 +445,7 @@ function SignPad({
setIsDefaultSign(true);
setIsImageSelect(true);
setIsTab("mysignature");
setSignatureType("");
setImage();
}}
style={{
@@ -469,6 +485,7 @@ function SignPad({
setIsDefaultSign(false);
setImage();
setIsTab("draw");
setSignatureType("draw");
setSignValue("");
setIsStamp(false);
}}
@@ -23,6 +23,10 @@ function SignerListPlace(props) {
data-tut="reactourAddbtn"
className="p-[10px] my-[2px] flex flex-row items-center justify-center border-[1px] border-[#47a3ad] hover:bg-[#47a3ad] text-[#47a3ad] hover:text-white cursor-pointer"
onClick={() => props.handleAddSigner()}
style={{
opacity: props.isMailSend && "0.5",
pointerEvents: props.isMailSend && "none"
}}
>
<i className="fa-solid fa-plus"></i>
<span style={{ marginLeft: 2 }}>Add role</span>
@@ -364,7 +364,12 @@ function WidgetComponent({
</div>
)
) : (
<div data-tut={dataTut} className="signerComponent">
<div
data-tut={dataTut}
className={
isMailSend ? "disabled signerComponent " : "signerComponent"
}
>
<div
style={{
background: themeColor,
@@ -196,7 +196,7 @@ const SelectFolder = ({ required, onSuccess, folderCls, isReset }) => {
{selectFolder && selectFolder.Name ? `(${folderPath})` : ""}
</p>
</div>
<div className="absolute top-1 right-1 cursor-pointer">
<div className="absolute top-2 right-1 cursor-pointer">
<Tooltip
message={
"If you do not select a folder, your signed document will be saved in the Main OpenSign drive folder."
@@ -105,7 +105,7 @@ const SignersInput = (props) => {
return (
<div className="text-xs mt-2 ">
<label className="block">
<label className="block relative">
Signers
{props.required && <span className="text-red-500 text-[13px]">*</span>}
<span className="absolute ml-1 text-xs z-50">
+2
View File
@@ -935,6 +935,7 @@ export const embedDocId = async (pdfDoc, documentId, allPages) => {
//function for save button to save signature or image url
export function onSaveSign(
type,
xyPostion,
index,
signKey,
@@ -975,6 +976,7 @@ export function onSaveSign(
Width: posWidth,
Height: posHeight,
SignUrl: signatureImg,
signatureType: type && type,
options: {
...position.options,
response: signatureImg
+83 -110
View File
@@ -35,7 +35,7 @@ function Opensigndrive() {
const scrollRef = useRef(null);
const [isList, setIsList] = useState(false);
const [selectedSort, setSelectedSort] = useState("Date");
const [sortingOrder, setSortingOrder] = useState("Decending");
const [sortingOrder, setSortingOrder] = useState("Descending");
const [pdfData, setPdfData] = useState([]);
const [isFolder, setIsFolder] = useState(false);
const [newFolderName, setNewFolderName] = useState();
@@ -54,6 +54,14 @@ function Opensigndrive() {
const [skip, setSkip] = useState(0);
const limit = 100;
const [loading, setLoading] = useState(false);
const sortOrder = ["Ascending", "Descending"];
const sortingValue = ["Name", "Date"];
const orderName = {
Ascending: "Ascending",
Descending: "Descending",
Name: "Name",
Date: "Date"
};
const currentUser =
localStorage.getItem(
`Parse/${localStorage.getItem("parseAppId")}/currentUser`
@@ -80,7 +88,7 @@ function Opensigndrive() {
setHandleError("Error: Something went wrong!");
} else if (driveDetails && driveDetails.length > 0) {
setSkip((prevSkip) => prevSkip + limit);
sortApps("Date", "Decending", driveDetails, true);
sortingData(null, null, driveDetails, true);
}
if (!docId) {
setFolderName([{ name: "OpenSign™ Drive", objectId: "" }]);
@@ -114,6 +122,7 @@ function Opensigndrive() {
//disableLoading is used disable initial loader
const disableLoading = true;
// If the fetched data length is less than the limit, it means there's no more data to fetch
if (!loading && pdfData.length % 100 === 0) {
getPdfDocumentList(disableLoading);
}
@@ -129,7 +138,7 @@ function Opensigndrive() {
};
}
// eslint-disable-next-line
}, [loading]); // Add/remove scroll event listener when loading changes
}, [loading, sortingOrder, selectedSort]); // Add/remove scroll event listener when loading changes
//function for handle folder name path
const handleRoute = (index) => {
@@ -210,35 +219,38 @@ function Opensigndrive() {
}
};
const sortingApp = (appInfo, type, order) => {
if (type === "Name") {
if (order === "Accending") {
//function to use sorting document list according to type and order
const sortedBy = (appInfo, type, order) => {
if (type === orderName.Name) {
if (order === orderName.Ascending) {
return appInfo.sort((a, b) => (a.Name > b.Name ? 1 : -1));
} else if (order === "Decending") {
} else if (order === orderName.Descending) {
return appInfo.sort((a, b) => (a.Name > b.Name ? -1 : 1));
}
} else if (type === "Date") {
if (order === "Accending") {
} else if (type === orderName.Date) {
if (order === orderName.Ascending) {
return appInfo.sort((a, b) => (a.createdAt > b.createdAt ? 1 : -1));
} else if (order === "Decending") {
} else if (order === orderName.Descending) {
return appInfo.sort((a, b) => (a.createdAt > b.createdAt ? -1 : 1));
}
}
};
const sortApps = (type, order, driveDetails, isInitial) => {
const selectedSortType = type ? type : selectedSort ? selectedSort : "Date";
const sortOrder = order ? order : sortingOrder ? sortingOrder : "Decending";
if (selectedSortType === "Name") {
sortingApp(driveDetails, "Name", sortOrder);
} else if (selectedSortType === "Date") {
sortingApp(driveDetails, "Date", sortOrder);
}
if (isInitial) {
setPdfData([...pdfData, ...driveDetails]);
} else {
setPdfData(driveDetails);
//function to use get sorting type, order and document list to sort
const sortingData = (type, order, driveDetails, isInitial) => {
const selectedSortType = type ? type : selectedSort;
const sortOrder = order ? order : sortingOrder;
//check isInitial true it means sort previous 20 and get on scrolling 20 = 40 document list
const allPdfData = isInitial ? [...pdfData, ...driveDetails] : driveDetails;
//call sortedBy function according to selected Type and order
if (selectedSortType === orderName.Name) {
sortedBy(allPdfData, orderName.Name, sortOrder);
} else if (selectedSortType === orderName.Date) {
sortedBy(allPdfData, orderName.Date, sortOrder);
}
setPdfData(allPdfData);
};
//function for handle auto scroll on folder path
@@ -611,95 +623,56 @@ function Opensigndrive() {
aria-labelledby="dropdownMenuButton"
aria-expanded={isShowSort ? "true" : "false"}
>
<span
onClick={() => {
setSelectedSort("Name");
sortApps("Name", null, pdfData);
}}
className="dropdown-item itemColor"
>
{selectedSort !== "Name" ? (
<i
className="fa fa-arrow-up"
aria-hidden="true"
style={{ marginRight: "5px" }}
></i>
) : (
<i
className="fa fa-check"
aria-hidden="true"
style={{ marginRight: "5px" }}
></i>
)}
Name
</span>
<span
onClick={() => {
setSelectedSort("Date");
sortApps("Date", null, pdfData);
}}
className="dropdown-item itemColor"
>
{selectedSort !== "Date" ? (
<i
className="fa fa-arrow-up"
aria-hidden="true"
style={{ marginRight: "5px" }}
></i>
) : (
<i
className="fa fa-check"
aria-hidden="true"
style={{ marginRight: "5px" }}
></i>
)}
Date
</span>
{sortingValue.map((value, ind) => {
return (
<span
key={ind}
onClick={() => {
setSelectedSort(value);
sortingData(value, null, pdfData);
}}
className="dropdown-item itemColor"
style={{
paddingLeft: selectedSort !== value && "33px"
}}
>
{selectedSort === value && (
<i
className="fa fa-check"
aria-hidden="true"
style={{ marginRight: "5px" }}
></i>
)}
{value}
</span>
);
})}
<hr className="hrStyle" />
<span
onClick={() => {
setSortingOrder("Accending");
sortApps(null, "Accending", pdfData);
}}
className="dropdown-item itemColor"
>
{sortingOrder !== "Accending" ? (
<i
className="fa fa-arrow-up"
aria-hidden="true"
style={{ marginRight: "5px" }}
></i>
) : (
<i
className="fa fa-check"
aria-hidden="true"
style={{ marginRight: "5px" }}
></i>
)}
Accending
</span>
<span
onClick={() => {
setSortingOrder("Decending");
sortApps(null, "Decending", pdfData);
}}
className="dropdown-item itemColor"
>
{sortingOrder !== "Decending" ? (
<i
className="fa fa-arrow-up"
aria-hidden="true"
style={{ marginRight: "5px" }}
></i>
) : (
<i
className="fa fa-check"
aria-hidden="true"
style={{ marginRight: "5px" }}
></i>
)}
Decending
</span>
{sortOrder.map((order, ind) => {
return (
<span
key={ind}
onClick={() => {
setSortingOrder(order);
sortingData(null, order, pdfData);
}}
className="dropdown-item itemColor"
style={{
paddingLeft: sortingOrder !== order && "33px"
}}
>
{sortingOrder === order && (
<i
className="fa fa-check"
aria-hidden="true"
style={{ marginRight: "5px" }}
></i>
)}
{order}
</span>
);
})}
</div>
</div>
+24 -4
View File
@@ -10,6 +10,7 @@ import { useParams } from "react-router-dom";
import SignPad from "../components/pdf/SignPad";
import RenderAllPdfPage from "../components/pdf/RenderAllPdfPage";
import Tour from "reactour";
import moment from "moment";
import {
contractDocument,
multiSignEmbed,
@@ -65,6 +66,7 @@ function PdfRequestFiles() {
const [currentSigner, setCurrentSigner] = useState(false);
const [isAlert, setIsAlert] = useState({ isShow: false, alertMessage: "" });
const [unSignedWidgetId, setUnSignedWidgetId] = useState("");
const [expiredDate, setExpiredDate] = useState("");
const [defaultSignAlert, setDefaultSignAlert] = useState({
isShow: false,
alertMessage: ""
@@ -87,6 +89,7 @@ function PdfRequestFiles() {
const [widgetsTour, setWidgetsTour] = useState(false);
const [minRequiredCount, setminRequiredCount] = useState();
const [sendInOrder, setSendInOrder] = useState(false);
const [currWidgetsDetails, setCurrWidgetsDetails] = useState({});
const divRef = useRef(null);
const isMobile = window.innerWidth < 767;
const rowLevel =
@@ -167,7 +170,11 @@ function PdfRequestFiles() {
};
setIsDecline(currentDecline);
} else if (currDate > expireUpdateDate) {
const expireDateFormat = moment(new Date(expireDate)).format(
"MMM DD, YYYY"
);
setIsExpired(true);
setExpiredDate(expireDateFormat);
}
if (documentData.length > 0) {
@@ -367,7 +374,6 @@ function PdfRequestFiles() {
return true;
}
};
//function for embed signature or image url in pdf
async function embedWidgetsData() {
const validateSigning = checkSendInOrder();
@@ -731,7 +737,7 @@ function PdfRequestFiles() {
};
//function for save button to save signature or image url
const saveSign = (isDefaultSign, width, height) => {
const saveSign = (type, isDefaultSign, width, height) => {
const isTypeText = width && height ? true : false;
const signatureImg = isDefaultSign
? isDefaultSign === "initials"
@@ -767,6 +773,7 @@ function PdfRequestFiles() {
const placeholderPosition = currentSigner[0].placeHolder;
//function of save signature image and get updated position with signature image url
const getUpdatePosition = onSaveSign(
type,
placeholderPosition,
getIndex,
signKey,
@@ -926,7 +933,17 @@ function PdfRequestFiles() {
</div>
)}
<div className="signatureContainer" ref={divRef}>
<div
className="signatureContainer"
style={{
pointerEvents:
isExpired ||
(isDecline.isDeclined && isDecline.currnt === "another")
? "none"
: "auto"
}}
ref={divRef}
>
<ModalUi
headerColor={"#dc3545"}
isOpen={isAlert.isShow}
@@ -999,7 +1016,7 @@ function PdfRequestFiles() {
containerWH={containerWH}
show={isExpired}
headMsg="Document Expired!"
bodyMssg="This Document is no longer available."
bodyMssg={`This document expired on ${expiredDate} and is no longer available to sign.`}
/>
<ModalUi
@@ -1133,6 +1150,8 @@ function PdfRequestFiles() {
isInitial={isInitial}
setIsInitial={setIsInitial}
setIsStamp={setIsStamp}
currWidgetsDetails={currWidgetsDetails}
setCurrWidgetsDetails={setCurrWidgetsDetails}
/>
{/* pdf header which contain funish back button */}
<Header
@@ -1179,6 +1198,7 @@ function PdfRequestFiles() {
unSignedWidgetId={unSignedWidgetId}
setSelectWidgetId={setSelectWidgetId}
selectWidgetId={selectWidgetId}
setCurrWidgetsDetails={setCurrWidgetsDetails}
/>
)}
</div>
+8 -5
View File
@@ -97,7 +97,7 @@ function PlaceHolderSign() {
const [widgetType, setWidgetType] = useState("");
const [isUiLoading, setIsUiLoading] = useState(false);
const [isRadio, setIsRadio] = useState(false);
const [currWidgetsDetails, setCurrWidgetsDetails] = useState([]);
const [currWidgetsDetails, setCurrWidgetsDetails] = useState({});
const [selectWidgetId, setSelectWidgetId] = useState("");
const [isCheckbox, setIsCheckbox] = useState(false);
const [isNameModal, setIsNameModal] = useState(false);
@@ -1450,7 +1450,7 @@ function PlaceHolderSign() {
{isSendAlert.mssg === "sure" ? (
<p>Please add field for all recipients.</p>
) : isSendAlert.mssg === textWidget ? (
<p>Please confirm that you have filled label widget.</p>
<p>Please confirm that you have filled the text field.</p>
) : (
isSendAlert.mssg === "confirm" && (
<p>
@@ -1716,9 +1716,11 @@ function PlaceHolderSign() {
</div>
) : (
<div>
<div className="signerComponent">
<div className="signerComponent" aria-disabled>
<div
style={{ maxHeight: window.innerHeight - 70 + "px" }}
style={{
maxHeight: window.innerHeight - 70 + "px"
}}
className="autoSignScroll"
>
<SignerListPlace
@@ -1734,11 +1736,12 @@ function PlaceHolderSign() {
setSignersData={setSignersData}
blockColor={blockColor}
setBlockColor={setBlockColor}
isMailSend={isMailSend}
// handleAddSigner={handleAddSigner}
/>
<div data-tut="reactourSecond">
<WidgetComponent
pdfUrl={isMailSend}
isMailSend={isMailSend}
dragSignature={dragSignature}
signRef={signRef}
handleDivClick={handleDivClick}
+15 -7
View File
@@ -90,7 +90,7 @@ function SignYourSelf() {
const [showAlreadySignDoc, setShowAlreadySignDoc] = useState({
status: false
});
const [currWidgetsDetails, setCurrWidgetsDetails] = useState([]);
const [currWidgetsDetails, setCurrWidgetsDetails] = useState({});
const [isCheckbox, setIsCheckbox] = useState(false);
const [widgetType, setWidgetType] = useState("");
const [pdfLoadFail, setPdfLoadFail] = useState({
@@ -180,14 +180,14 @@ function SignYourSelf() {
//function for get document details for perticular signer with signer'object id
const getDocumentDetails = async (showComplete) => {
let isCompleted;
//getting document details
const documentData = await contractDocument(documentId);
if (documentData && documentData.length > 0) {
setPdfDetails(documentData);
const isCompleted =
documentData[0].IsCompleted && documentData[0].IsCompleted;
isCompleted = documentData[0].IsCompleted && documentData[0].IsCompleted;
if (isCompleted) {
const docStatus = {
isCompleted: isCompleted
@@ -263,8 +263,7 @@ function SignYourSelf() {
setSignerUserId(contractUsersRes[0].objectId);
const tourstatuss =
contractUsersRes[0].TourStatus && contractUsersRes[0].TourStatus;
if (tourstatuss && tourstatuss.length > 0) {
if (tourstatuss && tourstatuss.length > 0 && !isCompleted) {
setTourStatus(tourstatuss);
const checkTourRecipients = tourstatuss.filter(
(data) => data.signyourself
@@ -272,6 +271,8 @@ function SignYourSelf() {
if (checkTourRecipients && checkTourRecipients.length > 0) {
setCheckTourStatus(checkTourRecipients[0].signyourself);
}
} else {
setCheckTourStatus(true);
}
const loadObj = {
isLoad: false
@@ -291,7 +292,8 @@ function SignYourSelf() {
const tourstatuss =
contractContactBook[0].TourStatus &&
contractContactBook[0].TourStatus;
if (tourstatuss && tourstatuss.length > 0) {
if (tourstatuss && tourstatuss.length > 0 && !isCompleted) {
setTourStatus(tourstatuss);
const checkTourRecipients = tourstatuss.filter(
(data) => data.signyourself
@@ -299,6 +301,8 @@ function SignYourSelf() {
if (checkTourRecipients && checkTourRecipients.length > 0) {
setCheckTourStatus(checkTourRecipients[0].signyourself);
}
} else {
setCheckTourStatus(true);
}
} else {
setHandleError("No Data Found!");
@@ -704,7 +708,7 @@ function SignYourSelf() {
};
//function for save button to save signature or image url
const saveSign = (isDefaultSign, width, height) => {
const saveSign = (type, isDefaultSign, width, height) => {
const isTypeText = width && height ? true : false;
const signatureImg = isDefaultSign
? isDefaultSign === "initials"
@@ -727,6 +731,7 @@ function SignYourSelf() {
}
}
const getUpdatePosition = onSaveSign(
type,
xyPostion,
index,
signKey,
@@ -763,6 +768,7 @@ function SignYourSelf() {
//function for delete signature block
const handleDeleteSign = (key) => {
setCurrWidgetsDetails({});
const updateResizeData = [];
let filterData = xyPostion[index].pos.filter((data) => data.key !== key);
@@ -1101,6 +1107,8 @@ function SignYourSelf() {
setIsInitial={setIsInitial}
setIsStamp={setIsStamp}
widgetType={widgetType}
currWidgetsDetails={currWidgetsDetails}
setCurrWidgetsDetails={setCurrWidgetsDetails}
/>
{/*render email component to send email after finish signature on document */}
<EmailComponent
@@ -1464,6 +1464,7 @@ const TemplatePlaceholder = () => {
className="autoSignScroll"
>
<SignerListPlace
isMailSend={isMailSend}
signerPos={signerPos}
signersdata={signersdata}
isSelectListId={isSelectListId}
@@ -1484,7 +1485,7 @@ const TemplatePlaceholder = () => {
/>
<div data-tut="reactourSecond">
<WidgetComponent
pdfUrl={isMailSend}
isMailSend={isMailSend}
dragSignature={dragSignature}
signRef={signRef}
handleDivClick={handleDivClick}
+20 -12
View File
@@ -1,14 +1,21 @@
import React from "react";
import { Tooltip as ReactTooltip } from "react-tooltip";
import { openInNewTab } from "../constant/Utils";
const Tooltip = ({ children, id, message, url, iconColor }) =>
const Tooltip = ({ id, message, url, iconColor }) =>
url ? (
<button onClick={() => openInNewTab(url)} className="text-center">
{children ? (
children
) : (
<i className="fa-solid fa-question text-xs border-[1.5px] px-1 rounded-full border-[#33bbff] text-[#33bbff]"></i>
)}
<sup>
<i
className="fa-solid fa-question rounded-full"
style={{
borderColor: iconColor ? iconColor : "#33bbff",
color: iconColor ? iconColor : "#33bbff",
fontSize: 13,
borderWidth: 1.5,
padding: "1.5px 4px"
}}
></i>
</sup>
</button>
) : (
<>
@@ -17,17 +24,18 @@ const Tooltip = ({ children, id, message, url, iconColor }) =>
data-tooltip-content={message}
className="z-50"
>
{children ? (
children
) : (
<sup>
<i
className="fa-solid fa-question text-xs border-[1.5px] px-1 rounded-full border-[#33bbff] text-[#33bbff]"
className="fa-solid fa-question rounded-full"
style={{
borderColor: iconColor ? iconColor : "#33bbff",
color: iconColor ? iconColor : "#33bbff"
color: iconColor ? iconColor : "#33bbff",
fontSize: 13,
borderWidth: 1.5,
padding: "1.5px 4px"
}}
></i>
)}
</sup>
</a>
<ReactTooltip id={id ? id : "my-tooltip"} className="max-w-[200px]" />
</>
+5 -1
View File
@@ -496,7 +496,11 @@
overflow: hidden !important;
text-overflow: ellipsis;
}
.disabled {
opacity: 0.5; /* Example: reduce opacity to visually indicate disabled state */
pointer-events: none; /* Prevents mouse clicks and other events */
/* background-color: #888; */
}
.useEmail {
font-size: 10px;
color: #424242;