From a06723ff3f0d19bb1a092e4c68d6aeaa059170fa Mon Sep 17 00:00:00 2001 From: prafull-opensignlabs Date: Wed, 27 Mar 2024 11:05:24 +0530 Subject: [PATCH 01/10] refactor: reduce size of tooltip and adjust it's position --- .../src/components/dashboard/DashboardCard.js | 2 +- .../components/shared/fields/SelectFolder.js | 2 +- .../components/shared/fields/SignersInput.js | 2 +- apps/OpenSign/src/primitives/Tooltip.js | 32 ++++++++++++------- 4 files changed, 23 insertions(+), 15 deletions(-) diff --git a/apps/OpenSign/src/components/dashboard/DashboardCard.js b/apps/OpenSign/src/components/dashboard/DashboardCard.js index 9b54c273e..b6e12579e 100644 --- a/apps/OpenSign/src/components/dashboard/DashboardCard.js +++ b/apps/OpenSign/src/components/dashboard/DashboardCard.js @@ -353,7 +353,7 @@ const DashboardCard = (props) => { -
+
diff --git a/apps/OpenSign/src/components/shared/fields/SelectFolder.js b/apps/OpenSign/src/components/shared/fields/SelectFolder.js index 138648f03..dcf24e95f 100644 --- a/apps/OpenSign/src/components/shared/fields/SelectFolder.js +++ b/apps/OpenSign/src/components/shared/fields/SelectFolder.js @@ -196,7 +196,7 @@ const SelectFolder = ({ required, onSuccess, folderCls, isReset }) => { {selectFolder && selectFolder.Name ? `(${folderPath})` : ""}

-
+
{ return (
-
) ) : ( -
+
0) { setSkip((prevSkip) => prevSkip + limit); - sortApps("Date", "Decending", driveDetails, true); + sortApps(orderName.Date, orderName.Descending, driveDetails, true); } if (!docId) { setFolderName([{ name: "OpenSign™ Drive", objectId: "" }]); @@ -211,34 +219,40 @@ function Opensigndrive() { }; const sortingApp = (appInfo, type, order) => { - if (type === "Name") { - if (order === "Accending") { + 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); + const selectedSortType = type + ? type + : selectedSort + ? selectedSort + : orderName.Date; + const sortOrder = order + ? order + : sortingOrder + ? sortingOrder + : orderName.Descending; + const allPdfData = isInitial ? [...pdfData, ...driveDetails] : driveDetails; + if (selectedSortType === orderName.Name) { + sortingApp(driveDetails, orderName.Name, sortOrder); + } else if (selectedSortType === orderName.Date) { + sortingApp(allPdfData, orderName.Date, sortOrder); } + + setPdfData(allPdfData); }; //function for handle auto scroll on folder path @@ -611,95 +625,56 @@ function Opensigndrive() { aria-labelledby="dropdownMenuButton" aria-expanded={isShowSort ? "true" : "false"} > - { - setSelectedSort("Name"); - sortApps("Name", null, pdfData); - }} - className="dropdown-item itemColor" - > - {selectedSort !== "Name" ? ( - - ) : ( - - )} - Name - - { - setSelectedSort("Date"); - sortApps("Date", null, pdfData); - }} - className="dropdown-item itemColor" - > - {selectedSort !== "Date" ? ( - - ) : ( - - )} - Date - + {sortingValue.map((value, ind) => { + return ( + { + setSelectedSort(value); + sortApps(value, null, pdfData); + }} + className="dropdown-item itemColor" + style={{ + marginLeft: selectedSort !== value && "15px" + }} + > + {selectedSort === value && ( + + )} + {value} + + ); + })} +
- { - setSortingOrder("Accending"); - sortApps(null, "Accending", pdfData); - }} - className="dropdown-item itemColor" - > - {sortingOrder !== "Accending" ? ( - - ) : ( - - )} - Accending - - { - setSortingOrder("Decending"); - sortApps(null, "Decending", pdfData); - }} - className="dropdown-item itemColor" - > - {sortingOrder !== "Decending" ? ( - - ) : ( - - )} - Decending - + {sortOrder.map((order, ind) => { + return ( + { + setSortingOrder(order); + sortApps(null, order, pdfData); + }} + className="dropdown-item itemColor" + style={{ + marginLeft: sortingOrder !== order && "15px" + }} + > + {sortingOrder === order && ( + + )} + {order} + + ); + })}
diff --git a/apps/OpenSign/src/pages/PlaceHolderSign.js b/apps/OpenSign/src/pages/PlaceHolderSign.js index 3228e963b..3dbdce63b 100644 --- a/apps/OpenSign/src/pages/PlaceHolderSign.js +++ b/apps/OpenSign/src/pages/PlaceHolderSign.js @@ -1450,7 +1450,7 @@ function PlaceHolderSign() { {isSendAlert.mssg === "sure" ? (

Please add field for all recipients.

) : isSendAlert.mssg === textWidget ? ( -

Please confirm that you have filled label widget.

+

Please confirm that you have filled the text field.

) : ( isSendAlert.mssg === "confirm" && (

@@ -1716,9 +1716,11 @@ function PlaceHolderSign() {

) : (
-
+
{ className="autoSignScroll" > { />
); }; - + //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 (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 +359,7 @@ function SignPad({ setIsDefaultSign(false); setIsImageSelect(true); setIsTab("uploadImage"); + setSignatureType(""); }} style={{ color: @@ -373,6 +384,7 @@ function SignPad({ setIsDefaultSign(false); setIsImageSelect(false); setIsTab("type"); + setSignatureType(""); setImage(); }} style={{ @@ -400,6 +412,7 @@ function SignPad({ setIsDefaultSign(true); setIsImageSelect(true); setIsTab("mysignature"); + setSignatureType(""); setImage(); }} style={{ @@ -430,6 +443,7 @@ function SignPad({ setIsDefaultSign(true); setIsImageSelect(true); setIsTab("mysignature"); + setSignatureType(""); setImage(); }} style={{ @@ -469,6 +483,7 @@ function SignPad({ setIsDefaultSign(false); setImage(); setIsTab("draw"); + setSignatureType("draw"); setSignValue(""); setIsStamp(false); }} diff --git a/apps/OpenSign/src/constant/Utils.js b/apps/OpenSign/src/constant/Utils.js index 40b71434b..044d6c0d6 100644 --- a/apps/OpenSign/src/constant/Utils.js +++ b/apps/OpenSign/src/constant/Utils.js @@ -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 diff --git a/apps/OpenSign/src/pages/PdfRequestFiles.js b/apps/OpenSign/src/pages/PdfRequestFiles.js index 7f2bf551d..4b430c934 100644 --- a/apps/OpenSign/src/pages/PdfRequestFiles.js +++ b/apps/OpenSign/src/pages/PdfRequestFiles.js @@ -87,6 +87,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 = @@ -731,7 +732,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 +768,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, @@ -1133,6 +1135,8 @@ function PdfRequestFiles() { isInitial={isInitial} setIsInitial={setIsInitial} setIsStamp={setIsStamp} + currWidgetsDetails={currWidgetsDetails} + setCurrWidgetsDetails={setCurrWidgetsDetails} /> {/* pdf header which contain funish back button */}
)}
diff --git a/apps/OpenSign/src/pages/PlaceHolderSign.js b/apps/OpenSign/src/pages/PlaceHolderSign.js index 3dbdce63b..b152c8cf8 100644 --- a/apps/OpenSign/src/pages/PlaceHolderSign.js +++ b/apps/OpenSign/src/pages/PlaceHolderSign.js @@ -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); diff --git a/apps/OpenSign/src/pages/SignyourselfPdf.js b/apps/OpenSign/src/pages/SignyourselfPdf.js index 69915f333..4a28e7313 100644 --- a/apps/OpenSign/src/pages/SignyourselfPdf.js +++ b/apps/OpenSign/src/pages/SignyourselfPdf.js @@ -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({ @@ -708,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" @@ -731,6 +731,7 @@ function SignYourSelf() { } } const getUpdatePosition = onSaveSign( + type, xyPostion, index, signKey, @@ -1105,6 +1106,8 @@ function SignYourSelf() { setIsInitial={setIsInitial} setIsStamp={setIsStamp} widgetType={widgetType} + currWidgetsDetails={currWidgetsDetails} + setCurrWidgetsDetails={setCurrWidgetsDetails} /> {/*render email component to send email after finish signature on document */} Date: Wed, 27 Mar 2024 18:09:06 +0530 Subject: [PATCH 05/10] fix: expired document message --- apps/OpenSign/src/pages/PdfRequestFiles.js | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/apps/OpenSign/src/pages/PdfRequestFiles.js b/apps/OpenSign/src/pages/PdfRequestFiles.js index 4b430c934..e810cf503 100644 --- a/apps/OpenSign/src/pages/PdfRequestFiles.js +++ b/apps/OpenSign/src/pages/PdfRequestFiles.js @@ -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: "" @@ -168,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) { @@ -368,7 +374,6 @@ function PdfRequestFiles() { return true; } }; - //function for embed signature or image url in pdf async function embedWidgetsData() { const validateSigning = checkSendInOrder(); @@ -928,7 +933,17 @@ function PdfRequestFiles() {
)} -
+
Date: Wed, 27 Mar 2024 20:31:30 +0530 Subject: [PATCH 06/10] fix: drive details sorting, signature and intial widgets signature url isuue --- .../src/components/pdf/PlaceholderType.js | 5 +++++ apps/OpenSign/src/components/pdf/SignPad.js | 8 +++++--- apps/OpenSign/src/pages/Opensigndrive.js | 19 ++++++++++++------- apps/OpenSign/src/pages/SignyourselfPdf.js | 1 + 4 files changed, 23 insertions(+), 10 deletions(-) diff --git a/apps/OpenSign/src/components/pdf/PlaceholderType.js b/apps/OpenSign/src/components/pdf/PlaceholderType.js index 00e927429..58bdd0f14 100644 --- a/apps/OpenSign/src/components/pdf/PlaceholderType.js +++ b/apps/OpenSign/src/components/pdf/PlaceholderType.js @@ -307,6 +307,7 @@ function PlaceholderType(props) { return props.pos.SignUrl ? ( signimg signimg { @@ -154,8 +154,10 @@ function SignPad({ const url = currWidgetsDetails?.SignUrl; //checking widget type and draw type signature url - if (isWidgetType === "initials" && signatureType === "draw" && url) { - canvasRef.current.fromDataURL(url); + if (isInitial) { + if (isWidgetType === "initials" && signatureType === "draw" && url) { + canvasRef.current.fromDataURL(url); + } } else if ( isWidgetType === "signature" && signatureType === "draw" && diff --git a/apps/OpenSign/src/pages/Opensigndrive.js b/apps/OpenSign/src/pages/Opensigndrive.js index 93079a69d..82773faa9 100644 --- a/apps/OpenSign/src/pages/Opensigndrive.js +++ b/apps/OpenSign/src/pages/Opensigndrive.js @@ -88,7 +88,7 @@ function Opensigndrive() { setHandleError("Error: Something went wrong!"); } else if (driveDetails && driveDetails.length > 0) { setSkip((prevSkip) => prevSkip + limit); - sortApps(orderName.Date, orderName.Descending, driveDetails, true); + sortingData(null, null, driveDetails, true); } if (!docId) { setFolderName([{ name: "OpenSign™ Drive", objectId: "" }]); @@ -218,7 +218,8 @@ function Opensigndrive() { } }; - const sortingApp = (appInfo, type, order) => { + //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)); @@ -234,7 +235,8 @@ function Opensigndrive() { } }; - const sortApps = (type, order, driveDetails, isInitial) => { + //function to use get sorting type, order and document list to sort + const sortingData = (type, order, driveDetails, isInitial) => { const selectedSortType = type ? type : selectedSort @@ -245,11 +247,14 @@ function Opensigndrive() { : sortingOrder ? sortingOrder : orderName.Descending; + + //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) { - sortingApp(driveDetails, orderName.Name, sortOrder); + sortedBy(driveDetails, orderName.Name, sortOrder); } else if (selectedSortType === orderName.Date) { - sortingApp(allPdfData, orderName.Date, sortOrder); + sortedBy(allPdfData, orderName.Date, sortOrder); } setPdfData(allPdfData); @@ -631,7 +636,7 @@ function Opensigndrive() { key={ind} onClick={() => { setSelectedSort(value); - sortApps(value, null, pdfData); + sortingData(value, null, pdfData); }} className="dropdown-item itemColor" style={{ @@ -657,7 +662,7 @@ function Opensigndrive() { key={ind} onClick={() => { setSortingOrder(order); - sortApps(null, order, pdfData); + sortingData(null, order, pdfData); }} className="dropdown-item itemColor" style={{ diff --git a/apps/OpenSign/src/pages/SignyourselfPdf.js b/apps/OpenSign/src/pages/SignyourselfPdf.js index 4a28e7313..4538732f8 100644 --- a/apps/OpenSign/src/pages/SignyourselfPdf.js +++ b/apps/OpenSign/src/pages/SignyourselfPdf.js @@ -768,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); From 6d5e07dac7d1cec021ccb840c48738011074ef3b Mon Sep 17 00:00:00 2001 From: RaktimaNXG Date: Thu, 28 Mar 2024 11:03:54 +0530 Subject: [PATCH 07/10] fix: sorting issue in open-sign drive --- apps/OpenSign/src/pages/Opensigndrive.js | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/apps/OpenSign/src/pages/Opensigndrive.js b/apps/OpenSign/src/pages/Opensigndrive.js index 82773faa9..377b5f286 100644 --- a/apps/OpenSign/src/pages/Opensigndrive.js +++ b/apps/OpenSign/src/pages/Opensigndrive.js @@ -122,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); } @@ -137,7 +138,7 @@ function Opensigndrive() { }; } // eslint-disable-next-line - }, [loading]); // Add/remove scroll event listener when loading changes + }, [loading, sortingOrder]); // Add/remove scroll event listener when loading changes //function for handle folder name path const handleRoute = (index) => { @@ -237,16 +238,8 @@ function Opensigndrive() { //function to use get sorting type, order and document list to sort const sortingData = (type, order, driveDetails, isInitial) => { - const selectedSortType = type - ? type - : selectedSort - ? selectedSort - : orderName.Date; - const sortOrder = order - ? order - : sortingOrder - ? sortingOrder - : orderName.Descending; + 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; @@ -640,7 +633,7 @@ function Opensigndrive() { }} className="dropdown-item itemColor" style={{ - marginLeft: selectedSort !== value && "15px" + paddingLeft: selectedSort !== value && "33px" }} > {selectedSort === value && ( @@ -666,7 +659,7 @@ function Opensigndrive() { }} className="dropdown-item itemColor" style={{ - marginLeft: sortingOrder !== order && "15px" + paddingLeft: sortingOrder !== order && "33px" }} > {sortingOrder === order && ( From 1f50368259f96816c5ee400a69f3004925714ed0 Mon Sep 17 00:00:00 2001 From: RaktimaNXG Date: Thu, 28 Mar 2024 12:30:28 +0530 Subject: [PATCH 08/10] fix: open-sign drive sorting issue by date and name --- apps/OpenSign/src/pages/Opensigndrive.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/OpenSign/src/pages/Opensigndrive.js b/apps/OpenSign/src/pages/Opensigndrive.js index 377b5f286..5633706fa 100644 --- a/apps/OpenSign/src/pages/Opensigndrive.js +++ b/apps/OpenSign/src/pages/Opensigndrive.js @@ -138,7 +138,7 @@ function Opensigndrive() { }; } // eslint-disable-next-line - }, [loading, sortingOrder]); // 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) => { From 036c9b8d4a9cb9bd20ae92bd1fe7a4f3d62e4af5 Mon Sep 17 00:00:00 2001 From: RaktimaNXG Date: Thu, 28 Mar 2024 12:46:15 +0530 Subject: [PATCH 09/10] fix: open-sign drive sorting issue by name --- apps/OpenSign/src/pages/Opensigndrive.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/OpenSign/src/pages/Opensigndrive.js b/apps/OpenSign/src/pages/Opensigndrive.js index 5633706fa..192a9d766 100644 --- a/apps/OpenSign/src/pages/Opensigndrive.js +++ b/apps/OpenSign/src/pages/Opensigndrive.js @@ -245,7 +245,7 @@ function Opensigndrive() { const allPdfData = isInitial ? [...pdfData, ...driveDetails] : driveDetails; //call sortedBy function according to selected Type and order if (selectedSortType === orderName.Name) { - sortedBy(driveDetails, orderName.Name, sortOrder); + sortedBy(allPdfData, orderName.Name, sortOrder); } else if (selectedSortType === orderName.Date) { sortedBy(allPdfData, orderName.Date, sortOrder); } From 0bf07c27037e97777dc782a7d03fe08339c0ff58 Mon Sep 17 00:00:00 2001 From: Andrew <148278535+andrew-opensignlabs@users.noreply.github.com> Date: Sat, 30 Mar 2024 13:26:13 +0530 Subject: [PATCH 10/10] Update README.md --- README.md | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 7a3ad6656..82a1c3b4c 100644 --- a/README.md +++ b/README.md @@ -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. @@ -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). ---