From 1a455415f191cf0e53d41a50aefe73417b2b92e8 Mon Sep 17 00:00:00 2001 From: prafull-opensignlabs Date: Tue, 19 Nov 2024 18:10:59 +0530 Subject: [PATCH] feat: add extend document expiry date functionality --- .../public/locales/en/translation.json | 10 +- .../public/locales/es/translation.json | 10 +- .../public/locales/fr/translation.json | 10 +- apps/OpenSign/src/components/pdf/EmbedTab.js | 22 ++--- apps/OpenSign/src/json/ReportJson.js | 19 ++++ apps/OpenSign/src/pages/PdfRequestFiles.js | 39 ++++++++ .../src/primitives/GetReportDisplay.js | 99 ++++++++++++++++++- .../src/primitives/PdfDeclineModal.js | 66 ++++++++++++- .../src/script/locales/en/translation.json | 10 +- .../src/script/locales/es/translation.json | 10 +- .../src/script/locales/fr/translation.json | 10 +- 11 files changed, 269 insertions(+), 36 deletions(-) diff --git a/apps/OpenSign/public/locales/en/translation.json b/apps/OpenSign/public/locales/en/translation.json index afa45e8e8..e3c02ce5b 100644 --- a/apps/OpenSign/public/locales/en/translation.json +++ b/apps/OpenSign/public/locales/en/translation.json @@ -134,7 +134,8 @@ "option": "Option", "Embed": "Embed", "Copy TemplateId":"Copy TemplateId", - "Copy Public URL":"Copy Public URL" + "Copy Public URL":"Copy Public URL", + "extend-expiry-date": "Extend expiry date" }, "report-heading": { "Sr.No": "Sr.No", @@ -267,7 +268,8 @@ "make-template-public-alert": "Are you sure you want to make this template public?", "make-template-private-alert": "Are you sure you want to make this template private? This will remove it from your public profile.", "public-role": "Public role", - "public-url": "Public profile needed", + "public-url": "Public profile", + "embed-template": "Embed Template", "public-url-copy": "Here’s your public URL: ", "public-url-copy-mssg":"Copy it or share it with the signer, and you will be able to see all your publicly set templates.", "add-public-url-alert": "Please complete your OpenSign public profile setup. Once done, you’ll be able to make templates public. This process only needs to be completed once.", @@ -703,5 +705,7 @@ "notify-on-signatures-help": { "p1": "The document creator will receive an email notification whenever a signer signs the document.", "note": "Note: Notification email will not be sent for the last signer, as the document creator will receive a completion email instead." - } + }, + "expiry-date-updated": "The expiry date has been successfully extended to {{newexpirydate}}", + "expiry-date-error": "Please provide a new expiry date that is later than the current one" } diff --git a/apps/OpenSign/public/locales/es/translation.json b/apps/OpenSign/public/locales/es/translation.json index f7856af7a..5154c87d7 100644 --- a/apps/OpenSign/public/locales/es/translation.json +++ b/apps/OpenSign/public/locales/es/translation.json @@ -134,7 +134,8 @@ "option": "Opción", "Embed": "Incrustar", "Copy TemplateId": "Copiar ID de plantilla", - "Copy Public URL": "Copiar URL pública" + "Copy Public URL": "Copiar URL pública", + "extend-expiry-date": "Ampliar fecha de caducidad" }, "report-heading": { "Sr.No": "Nº", @@ -267,7 +268,8 @@ "make-template-public-alert": "¿En definitiva quieres convertir esta plantilla en pública?", "make-template-private-alert": "¿En definitiva quieres convertir esta plantilla en privada? Esto lo removerá de tu perfil público.", "public-role": "Rol público", - "public-url": "Se requiere perfil público", + "public-url": "Perfil publico", + "embed-template": "Insertar plantilla", "public-url-copy": "Aquí está tu URL pública: ", "public-url-copy-mssg": "Cópiala o compártela con el firmante y podrás ver todas tus plantillas públicas.", "add-public-url-alert": "Por favor, completa la configuración de tu perfil público OpenSign. Una vez terminado, podrás crear plantillas públicas. Este proceso solo necesita ser completado una vez.", @@ -703,5 +705,7 @@ "notify-on-signatures-help": { "p1": "El creador del documento recibirá una notificación por correo electrónico cada vez que un firmante firme el documento.", "note": "Nota: No se enviará un correo electrónico de notificación al último firmante, ya que el creador del documento recibirá un correo electrónico de finalización." - } + }, + "expiry-date-updated": "La fecha de vencimiento se ha extendido con éxito hasta el {{newexpirydate}}", + "expiry-date-error": "Proporcione una nueva fecha de vencimiento que sea posterior a la actual" } diff --git a/apps/OpenSign/public/locales/fr/translation.json b/apps/OpenSign/public/locales/fr/translation.json index 03a717a55..321cf94d2 100644 --- a/apps/OpenSign/public/locales/fr/translation.json +++ b/apps/OpenSign/public/locales/fr/translation.json @@ -155,7 +155,8 @@ "option": "Option", "Embed": "Intégrer", "Copy TemplateId": "Copier l'ID du modèle", - "Copy Public URL":"Copier l'URL publique" + "Copy Public URL":"Copier l'URL publique", + "extend-expiry-date": "Prolonger la date d'expiration" }, "report-help": { "Draft Documents": "Il s'agit de documents que vous avez commencés mais que vous n'avez pas finalisés pour envoi.", @@ -266,7 +267,8 @@ "make-template-public-alert": "Êtes-vous sûr de vouloir rendre ce modèle public ?", "make-template-private-alert": "Êtes-vous sûr de vouloir rendre ce modèle privé ? Cela le supprimera de votre profil public.", "public-role": "Rôle public", - "public-url": "Profil public requis", + "public-url": "Profil public", + "embed-template": "Intégrer le modèle", "public-url-copy": "Voici votre URL publique : ", "public-url-copy-mssg": "copiez-la ou partagez-le avec le signataire et vous pouvoir voir tous vos paramètres publics modèles.", "add-public-url-alert": "Veuillez terminer la configuration de votre profil public OpenSign. Une fois cela fait, vous pourrez rendre les modèles publics. Ce processus ne doit être effectué qu’une seule fois.", @@ -702,5 +704,7 @@ "notify-on-signatures-help": { "p1": "Le créateur du document recevra une notification par e-mail chaque fois qu'un signataire signera le document.", "note": "Remarque : L'e-mail de notification ne sera pas envoyé pour le dernier signataire, car le créateur du document recevra à la place un e-mail de fin." - } + }, + "expiry-date-updated": "La fecha de vencimiento se ha extendido con éxito hasta el {{newexpirydate}}", + "expiry-date-error": "Veuillez fournir une nouvelle date d'expiration postérieure à la date actuelle" } diff --git a/apps/OpenSign/src/components/pdf/EmbedTab.js b/apps/OpenSign/src/components/pdf/EmbedTab.js index c60686f76..65213cfaa 100644 --- a/apps/OpenSign/src/components/pdf/EmbedTab.js +++ b/apps/OpenSign/src/components/pdf/EmbedTab.js @@ -18,17 +18,16 @@ function EmbedTab(props) { { id: 0, title: "Installation", - codeString: ` -npm install @opensign/react` + codeString: `npm install @opensign/react` }, { id: 1, title: "Usage", codeString: ` -import React from "react"; +import React from "react"; import Opensign from "@opensign/react"; -export function App() { +export default function App() { return (
\`, }) -export class AppComponent{ +export class AppComponent { handleLoad() { console.log("success"); } handleError(error: string) { console.log(error); } - } - ` } ]; @@ -98,6 +93,9 @@ export class AppComponent{ return (
+

+ {t("embed-template")} +

{tabName.map((tabData, ind) => ( @@ -107,7 +105,7 @@ export class AppComponent{ role="tab" className={`${ activeTab === ind ? "op-tab-active" : "" - } op-tab flex items-center`} + } op-tab flex items-center pb-10 md:pb-0`} > ); }; + + const handleExpiry = async (expiryDate) => { + setIsUiLoading(true); + const doc = pdfDetails?.[0]; + const oldExpiryDate = new Date(doc?.ExpiryDate?.iso); + const newExpiryDate = new Date(expiryDate); + if (newExpiryDate > oldExpiryDate) { + const updateExpiryDate = new Date(expiryDate).toISOString(); + const expiryIsoFormat = { iso: updateExpiryDate, __type: "Date" }; + try { + const serverUrl = serverUrl_fn(); + const url = serverUrl + `/classes/contracts_Document/`; + const body = { ExpiryDate: expiryIsoFormat }; + const res = await axios.put(url + doc.objectId, body, { + headers: { + "Content-Type": "application/json", + "X-Parse-Application-Id": localStorage.getItem("parseAppId"), + "X-Parse-Session-Token": localStorage.getItem("accesstoken") + } + }); + if (res.data && res.data.updatedAt) { + setIsExpired(false); + let doc = pdfDetails?.[0]; + doc.ExpiryDate = expiryIsoFormat; + setPdfDetails([doc]); + } + } catch (err) { + console.log("err", err); + } finally { + setIsUiLoading(false); + } + } else { + setIsUiLoading(false); + alert(t("expiry-date-error")); + } + }; return ( @@ -1838,10 +1875,12 @@ function PdfRequestFiles(props) { {/* this modal is used for show expired alert */} <PdfDeclineModal show={isExpired} + doc={pdfDetails?.[0]} headMsg={t("expired-doc-title")} bodyMssg={t("expired-on-mssg", { expiredDate })} isDownloadBtn={true} handleDownloadBtn={handleDownloadBtn} + handleExpiry={handleExpiry} /> {!isEmailVerified && ( <VerifyEmail diff --git a/apps/OpenSign/src/primitives/GetReportDisplay.js b/apps/OpenSign/src/primitives/GetReportDisplay.js index 0cd0faf2d..4f3a2f79b 100644 --- a/apps/OpenSign/src/primitives/GetReportDisplay.js +++ b/apps/OpenSign/src/primitives/GetReportDisplay.js @@ -81,6 +81,7 @@ const ReportTable = (props) => { const [isEmbed, setIsEmbed] = useState(false); const [isPublicTour, setIsPublicTour] = useState(); const [signatureType, setSignatureType] = useState([]); + const [expiryDate, setExpiryDate] = useState(""); const Extand_Class = localStorage.getItem("Extand_Class"); const extClass = Extand_Class && JSON.parse(Extand_Class); const startIndex = (currentPage - 1) * props.docPerPage; @@ -433,6 +434,8 @@ const ReportTable = (props) => { } else { setIsPublicTour({ [item.objectId]: true }); } + } else if (act.action) { + setIsModal({ [`extendexpiry_${item.objectId}`]: true }); } }; // Get current list @@ -1210,6 +1213,67 @@ const ReportTable = (props) => { const closePublicTour = () => { setIsPublicTour(); }; + const handleUpdateExpiry = async (e, item) => { + e.preventDefault(); + e.stopPropagation(); + if (expiryDate) { + const oldExpiryDate = new Date(item?.ExpiryDate?.iso); + const newExpiryDate = new Date(expiryDate); + if (newExpiryDate > oldExpiryDate) { + setActLoader({ [`${item.objectId}`]: true }); + const updateExpiryDate = new Date(expiryDate).toISOString(); + const expiryIsoFormat = { iso: updateExpiryDate, __type: "Date" }; + try { + const serverUrl = serverUrl_fn(); + const cls = "contracts_Document"; + const url = serverUrl + `/classes/${cls}/`; + const body = { ExpiryDate: expiryIsoFormat }; + const res = await axios.put(url + item.objectId, body, { + headers: { + "Content-Type": "application/json", + "X-Parse-Application-Id": localStorage.getItem("parseAppId"), + "X-Parse-Session-Token": localStorage.getItem("accesstoken") + } + }); + if (res.data && res.data.updatedAt) { + setIsAlert(true); + setAlertMsg({ + type: "success", + message: t("expiry-date-updated", { + newexpirydate: new Date(expiryDate)?.toLocaleDateString() + }) + }); + if (props.ReportName === "Expired Documents") { + const upldatedList = props.List.filter( + (x) => x.objectId !== item.objectId + ); + props.setList(upldatedList); + } + } + } catch (err) { + console.log("err", err); + setIsAlert(true); + setAlertMsg({ + type: "danger", + message: t("something-went-wrong-mssg") + }); + } finally { + setActLoader({}); + setExpiryDate(); + setTimeout(() => setIsAlert(false), 2000); + setIsModal({}); + } + } else { + setIsAlert(true); + setAlertMsg({ type: "danger", message: t("expiry-date-error") }); + setTimeout(() => setIsAlert(false), 2000); + } + } else { + setIsAlert(true); + setAlertMsg({ type: "danger", message: t("expiry-date-error") }); + setTimeout(() => setIsAlert(false), 2000); + } + }; return ( <div className="relative"> {Object.keys(actLoader)?.length > 0 && ( @@ -1490,7 +1554,7 @@ const ReportTable = (props) => { <td className=" pl-[20px] py-2"> {props.ReportName === "Templates" && ( <div - className="flex flex-row " + className="flex flex-row" data-tut="IsPublic" > <label className="cursor-pointer relative inline-flex items-center mb-0"> @@ -1773,6 +1837,39 @@ const ReportTable = (props) => { ) )} </div> + {isModal["extendexpiry_" + item.objectId] && ( + <ModalUi + isOpen + title={t("btnLabel.extend-expiry-date")} + reduceWidth={"md:max-w-[450px]"} + handleClose={() => setIsModal({})} + > + <form + className="px-4 py-2 flex flex-col" + onSubmit={(e) => handleUpdateExpiry(e, item)} + > + <label className="mr-2">Expiry date</label> + <input + type="date" + className="rounded-full mb-2 bg-base-300 w-full px-4 py-2 text-black border-2 hover:border-spacing-2" + defaultValue={ + item?.ExpiryDate?.iso?.split("T")?.[0] + } + onChange={(e) => { + setExpiryDate(e.target.value); + }} + /> + <div className="flex justify-start mb-1"> + <button + type="submit" + className="op-btn op-btn-primary" + > + {t("update")} + </button> + </div> + </form> + </ModalUi> + )} {isShareWith[item.objectId] && ( <div className="op-modal op-modal-open"> <div className="max-h-90 bg-base-100 w-[95%] md:max-w-[500px] rounded-box relative"> diff --git a/apps/OpenSign/src/primitives/PdfDeclineModal.js b/apps/OpenSign/src/primitives/PdfDeclineModal.js index cb42ef6a7..b8dfa8840 100644 --- a/apps/OpenSign/src/primitives/PdfDeclineModal.js +++ b/apps/OpenSign/src/primitives/PdfDeclineModal.js @@ -5,6 +5,29 @@ import { useTranslation } from "react-i18next"; function CustomModal(props) { const { t } = useTranslation(); const [reason, setReason] = useState(""); + const [isExtendExpiry, setIsExtendExpiry] = useState(false); + const [expiryDate, setExpiryDate] = useState(""); + const localuser = localStorage.getItem( + `Parse/${localStorage.getItem("parseAppId")}/currentUser` + ); + + const currentUser = JSON.parse(localuser); + const isCreator = props?.doc + ? props?.doc?.CreatedBy?.objectId === currentUser?.objectId && + localStorage.getItem("_user_role") !== "Guest" + : false; + const handleExtendBtn = () => setIsExtendExpiry(!isExtendExpiry); + + const handleUpdateExpiry = async (e) => { + e.preventDefault(); + e.stopPropagation(); + if (expiryDate) { + props.handleExpiry && props.handleExpiry(expiryDate); + } else { + alert(t("expiry-date-error")); + } + }; + return ( props.show && ( <dialog className="op-modal op-modal-open absolute z-[448]"> @@ -15,16 +38,24 @@ function CustomModal(props) { <div className="p-[10px] px-[20px]"> <p className="text-[15px]">{props.bodyMssg && props.bodyMssg}</p> </div> - {props.isDownloadBtn && ( - <div className="flex justify-start w-full ml-[20px] mb-3 mt-1"> + <div className="flex flex-row items-center"> + {isCreator && ( <button - className="op-btn op-btn-primary " + className="op-btn op-btn-primary px-6 ml-[20px] mb-3 mt-1" + onClick={() => handleExtendBtn()} + > + Extend + </button> + )} + {props.isDownloadBtn && ( + <button + className="op-btn op-btn-primary ml-[10px] mb-3 mt-1" onClick={() => props.handleDownloadBtn()} > Download </button> - </div> - )} + )} + </div> {props.footerMessage && ( <> <div className="mx-3"> @@ -60,6 +91,31 @@ function CustomModal(props) { </div> </> )} + {isExtendExpiry && ( + <form className="mx-3 mb-3" onSubmit={handleUpdateExpiry}> + <input + type="date" + className="rounded-full bg-base-300 w-full px-4 py-2 text-black border-2 hover:border-spacing-2" + defaultValue={props?.doc?.ExpiryDate?.iso?.split("T")[0]} + onChange={(e) => setExpiryDate(e.target.value)} + /> + <div className="flex flex-row items-center mt-2"> + <button type="submit" className="op-btn op-btn-primary mr-2"> + {t("update")} + </button> + <button + type="button" + className="op-btn op-btn-secondary" + onClick={() => { + setExpiryDate(""); + setIsExtendExpiry(false); + }} + > + {t("close")} + </button> + </div> + </form> + )} </div> </dialog> ) diff --git a/apps/OpenSign/src/script/locales/en/translation.json b/apps/OpenSign/src/script/locales/en/translation.json index 49e0c88d8..b5dad6262 100644 --- a/apps/OpenSign/src/script/locales/en/translation.json +++ b/apps/OpenSign/src/script/locales/en/translation.json @@ -134,7 +134,8 @@ "option": "Option", "Embed": "Embed", "Copy TemplateId": "Copy TemplateId", - "Copy Public URL": "Copy Public URL" + "Copy Public URL": "Copy Public URL", + "extend-expiry-date": "Extend expiry date" }, "report-heading": { "Sr.No": "Sr.No", @@ -267,7 +268,8 @@ "make-template-public-alert": "Are you sure you want to make this template public?", "make-template-private-alert": "Are you sure you want to make this template private? This will remove it from your public profile.", "public-role": "Public role", - "public-url": "Public profile needed", + "public-url": "Public profile", + "embed-template": "Embed Template", "public-url-copy": "Here’s your public URL: ", "public-url-copy-mssg": "Copy it or share it with the signer, and you will be able to see all your publicly set templates.", "add-public-url-alert": "Please complete your OpenSign public profile setup. Once done, you’ll be able to make templates public. This process only needs to be completed once.", @@ -703,5 +705,7 @@ "notify-on-signatures-help": { "p1": "The document creator will receive an email notification whenever a signer signs the document.", "note": "Note: Notification email will not be sent for the last signer, as the document creator will receive a completion email instead." - } + }, + "expiry-date-updated": "The expiry date has been successfully extended to {{newexpirydate}}", + "expiry-date-error": "Please provide a new expiry date that is later than the current one" } diff --git a/apps/OpenSign/src/script/locales/es/translation.json b/apps/OpenSign/src/script/locales/es/translation.json index 7ef921ffc..cf964b53e 100644 --- a/apps/OpenSign/src/script/locales/es/translation.json +++ b/apps/OpenSign/src/script/locales/es/translation.json @@ -134,7 +134,8 @@ "option": "Opción", "Embed": "Incrustar", "Copy TemplateId": "Copiar ID de plantilla", - "Copy Public URL": "Copiar URL pública" + "Copy Public URL": "Copiar URL pública", + "Expiry-date": "Date d'expiration" }, "report-heading": { "Sr.No": "Nº", @@ -267,7 +268,8 @@ "make-template-public-alert": "¿En definitiva quieres convertir esta plantilla en pública?", "make-template-private-alert": "¿En definitiva quieres convertir esta plantilla en privada? Esto lo removerá de tu perfil público.", "public-role": "Rol público", - "public-url": "Se requiere perfil público", + "public-url": "Perfil publico", + "embed-template": "Insertar plantilla", "public-url-copy": "Aquí está tu URL pública: ", "public-url-copy-mssg": "Cópiala o compártela con el firmante y podrás ver todas tus plantillas públicas.", "add-public-url-alert": "Por favor, completa la configuración de tu perfil público OpenSign. Una vez terminado, podrás crear plantillas públicas. Este proceso solo necesita ser completado una vez.", @@ -703,5 +705,7 @@ "notify-on-signatures-help": { "p1": "El creador del documento recibirá una notificación por correo electrónico cada vez que un firmante firme el documento.", "note": "Nota: No se enviará un correo electrónico de notificación al último firmante, ya que el creador del documento recibirá un correo electrónico de finalización." - } + }, + "expiry-date-updated": "La fecha de vencimiento se ha extendido con éxito hasta el {{newexpirydate}}", + "expiry-date-error": "Proporcione una nueva fecha de vencimiento que sea posterior a la actual" } diff --git a/apps/OpenSign/src/script/locales/fr/translation.json b/apps/OpenSign/src/script/locales/fr/translation.json index 376f444d0..3611ee6f3 100644 --- a/apps/OpenSign/src/script/locales/fr/translation.json +++ b/apps/OpenSign/src/script/locales/fr/translation.json @@ -155,7 +155,8 @@ "option": "Option", "Embed": "Intégrer", "Copy TemplateId": "Copier l'ID du modèle", - "Copy Public URL": "Copier l'URL publique" + "Copy Public URL": "Copier l'URL publique", + "extend-expiry-date": "Prolonger la date d'expiration" }, "report-help": { "Draft Documents": "Il s'agit de documents que vous avez commencés mais que vous n'avez pas finalisés pour envoi.", @@ -266,7 +267,8 @@ "make-template-public-alert": "Êtes-vous sûr de vouloir rendre ce modèle public ?", "make-template-private-alert": "Êtes-vous sûr de vouloir rendre ce modèle privé ? Cela le supprimera de votre profil public.", "public-role": "Rôle public", - "public-url": "Profil public requis", + "public-url": "Profil public", + "embed-template": "Intégrer le modèle", "public-url-copy": "Voici votre URL publique : ", "public-url-copy-mssg": "copiez-la ou partagez-le avec le signataire et vous pouvoir voir tous vos paramètres publics modèles.", "add-public-url-alert": "Veuillez terminer la configuration de votre profil public OpenSign. Une fois cela fait, vous pourrez rendre les modèles publics. Ce processus ne doit être effectué qu’une seule fois.", @@ -702,5 +704,7 @@ "notify-on-signatures-help": { "p1": "Le créateur du document recevra une notification par e-mail chaque fois qu'un signataire signera le document.", "note": "Remarque : L'e-mail de notification ne sera pas envoyé pour le dernier signataire, car le créateur du document recevra à la place un e-mail de fin." - } + }, + "expiry-date-updated": "La date d'expiration a été prolongée avec succès jusqu'au {{newexpirydate}}", + "expiry-date-error": "Veuillez fournir une nouvelle date d'expiration postérieure à la date actuelle" }