Compare commits

...
Author SHA1 Message Date
nxglabs e7d3453744 Merge pull request #1064 from nxglabs/signers_completed_main 2025-07-29 13:30:45 +00:00
prafull-opensignlabsandGitHub 47cc0ef580 Merge pull request #1858 from OpenSignLabs/updates-16525889391
remove checkbox from sign agreement screen
2025-07-25 21:18:33 +05:30
prafull-opensignlabs 04f71be6a2 Merge pull request #1044 from nxglabs/raktima-patch-main-2
fix: remove agreement checkbox and remove agreement checkbox tour
2025-07-25 15:38:38 +00:00
prafull-opensignlabsandGitHub 07603f4bc2 Merge pull request #1856 from OpenSignLabs/imgbot
[ImgBot] Optimize images
2025-07-24 14:40:19 +05:30
ImgBotApp ea16180551 [ImgBot] Optimize images
*Total -- 487.98kb -> 238.96kb (51.03%)

/apps/OpenSign/public/logo512.png -- 10.72kb -> 2.72kb (74.62%)
/apps/OpenSignServer/logo.png -- 86.48kb -> 24.83kb (71.28%)
/apps/OpenSign/src/assets/images/logo.png -- 86.48kb -> 24.83kb (71.28%)
/apps/OpenSign/public/static/js/assets/images/logo.2a7bff0c1189183fafe71d7d5b94e0cd.png -- 86.48kb -> 24.83kb (71.28%)
/apps/OpenSign/public/logo192.png -- 2.13kb -> 0.65kb (69.69%)
/apps/OpenSign/src/assets/images/dp.png -- 12.83kb -> 4.25kb (66.9%)
/apps/OpenSign/src/assets/images/folder.png -- 4.39kb -> 1.93kb (56.05%)
/apps/OpenSign/public/static/js/assets/images/logo-dark.png -- 95.21kb -> 57.21kb (39.91%)
/apps/OpenSignServer/public/assets/images/parse-logo.png -- 5.16kb -> 3.81kb (26.21%)
/apps/OpenSign/src/assets/images/pdf3.png -- 11.66kb -> 9.77kb (16.21%)
/apps/OpenSign/src/assets/images/login_img.svg -- 40.75kb -> 39.10kb (4.04%)
/apps/OpenSign/src/assets/images/recreatedoc.png -- 40.69kb -> 40.08kb (1.48%)
/apps/OpenSign/src/assets/images/pad.svg -- 5.00kb -> 4.94kb (1.07%)

Signed-off-by: ImgBotApp <ImgBotHelp@gmail.com>
2025-07-24 08:28:02 +00:00
prafull-opensignlabsandGitHub 75ad566d54 Merge pull request #1841 from OpenSignLabs/updates-16144605887
v2.26.1
2025-07-08 19:01:19 +05:30
nxglabs fda9fb534b Merge pull request #963 from nxglabs/staging
v2.26.1
2025-07-08 13:27:37 +00:00
prafull-opensignlabsandGitHub cb3e31ebbf Merge pull request #1838 from OpenSignLabs/updates-16124490027
dark-theme logo
2025-07-07 23:43:31 +05:30
nxglabs 400525debb Merge pull request #960 from nxglabs/fix_customlogo
fix: custom applogo not visible in header
2025-07-07 18:07:24 +00:00
22 changed files with 355 additions and 372 deletions
+21 -7
View File
@@ -2730,19 +2730,32 @@
} }
}, },
"node_modules/@eslint/plugin-kit": { "node_modules/@eslint/plugin-kit": {
"version": "0.3.1", "version": "0.3.4",
"resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.3.1.tgz", "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.3.4.tgz",
"integrity": "sha512-0J+zgWxHN+xXONWIyPWKFMgVuJoZuGiIFu8yxk7RJjxkzpGmyja5wRFqZIVtjDVOQpV+Rw0iOAjYPE2eQyjr0w==", "integrity": "sha512-Ul5l+lHEcw3L5+k8POx6r74mxEYKG5kOb6Xpy2gCRW6zweT6TEhAf8vhxGgjhqrd/VO/Dirhsb+1hNpD1ue9hw==",
"dev": true, "dev": true,
"license": "Apache-2.0", "license": "Apache-2.0",
"dependencies": { "dependencies": {
"@eslint/core": "^0.14.0", "@eslint/core": "^0.15.1",
"levn": "^0.4.1" "levn": "^0.4.1"
}, },
"engines": { "engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0" "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
} }
}, },
"node_modules/@eslint/plugin-kit/node_modules/@eslint/core": {
"version": "0.15.1",
"resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.15.1.tgz",
"integrity": "sha512-bkOp+iumZCCbt1K1CmWf0R9pM5yKpDv+ZXtvSyQpudrI9kuFLp+bM2WOPXImuD/ceQuaa8f5pj93Y7zyECIGNA==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
"@types/json-schema": "^7.0.15"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
}
},
"node_modules/@floating-ui/core": { "node_modules/@floating-ui/core": {
"version": "1.7.0", "version": "1.7.0",
"resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.7.0.tgz", "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.7.0.tgz",
@@ -8655,14 +8668,15 @@
} }
}, },
"node_modules/form-data": { "node_modules/form-data": {
"version": "4.0.2", "version": "4.0.4",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.2.tgz", "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.4.tgz",
"integrity": "sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w==", "integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"asynckit": "^0.4.0", "asynckit": "^0.4.0",
"combined-stream": "^1.0.8", "combined-stream": "^1.0.8",
"es-set-tostringtag": "^2.1.0", "es-set-tostringtag": "^2.1.0",
"hasown": "^2.0.2",
"mime-types": "^2.1.12" "mime-types": "^2.1.12"
}, },
"engines": { "engines": {
@@ -379,6 +379,7 @@
"certificate": "Zertifikat", "certificate": "Zertifikat",
"decline": "Ablehnen", "decline": "Ablehnen",
"finish": "Fertigstellen", "finish": "Fertigstellen",
"done": "Fertig",
"mail": "E-Mail", "mail": "E-Mail",
"sign-now": "Jetzt unterzeichnen", "sign-now": "Jetzt unterzeichnen",
"successfully-signed": "Erfolgreich unterzeichnet!", "successfully-signed": "Erfolgreich unterzeichnet!",
@@ -1041,5 +1042,6 @@
"vertical": "Vertikal", "vertical": "Vertikal",
"horizontal": "Horizontal", "horizontal": "Horizontal",
"billing": "Abrechnung", "billing": "Abrechnung",
"console": "Konsole" "console": "Konsole",
"action-prohibited": "Diese Aktion ist für Ihre E-Mail-Domain nicht erlaubt. Bitte wenden Sie sich an Ihren Administrator, um Hilfe zu erhalten."
} }
@@ -379,6 +379,7 @@
"certificate": "Certificate", "certificate": "Certificate",
"decline": "Decline", "decline": "Decline",
"finish": "Finish", "finish": "Finish",
"done": "Done",
"mail": "Mail", "mail": "Mail",
"sign-now": "Sign now", "sign-now": "Sign now",
"successfully-signed": "Successfully signed!", "successfully-signed": "Successfully signed!",
@@ -1041,5 +1042,6 @@
"vertical": "Vertical", "vertical": "Vertical",
"horizontal": "Horizontal", "horizontal": "Horizontal",
"billing": "Billing", "billing": "Billing",
"console": "Console" "console": "Console",
"action-prohibited": "This action isn't allowed for your email domain. Please contact your administrator for assistance."
} }
@@ -380,6 +380,7 @@
"certificate": "Certificado", "certificate": "Certificado",
"decline": "Rechazar", "decline": "Rechazar",
"finish": "Finalizar", "finish": "Finalizar",
"done": "Hecho",
"mail": "Correo", "mail": "Correo",
"sign-now": "Firmar ahora", "sign-now": "Firmar ahora",
"successfully-signed": "¡Firmado exitosamente!", "successfully-signed": "¡Firmado exitosamente!",
@@ -1041,5 +1042,6 @@
"vertical": "Vertical", "vertical": "Vertical",
"horizontal": "Horizontal", "horizontal": "Horizontal",
"billing": "Facturación", "billing": "Facturación",
"console": "Consola" "console": "Consola",
"action-prohibited": "Esta acción no está permitida para su dominio de correo electrónico. Por favor, contacte con su administrador para obtener ayuda."
} }
@@ -379,6 +379,7 @@
"certificate": "Certificat", "certificate": "Certificat",
"decline": "refusé", "decline": "refusé",
"finish": "terminé", "finish": "terminé",
"done": "Terminé",
"mail": "Mail", "mail": "Mail",
"sign-now": "Signez maintenant", "sign-now": "Signez maintenant",
"successfully-signed": "Signé avec succès !", "successfully-signed": "Signé avec succès !",
@@ -1041,5 +1042,6 @@
"vertical": "Vertical", "vertical": "Vertical",
"horizontal": "Horizontal", "horizontal": "Horizontal",
"billing": "Facturation", "billing": "Facturation",
"console": "Console" "console": "Console",
"action-prohibited": "Cette action n'est pas autorisée pour votre domaine de messagerie. Veuillez contacter votre administrateur pour obtenir de l'aide."
} }
@@ -379,6 +379,7 @@
"certificate": "प्रमाण पत्र", "certificate": "प्रमाण पत्र",
"decline": "अस्वीकार करें", "decline": "अस्वीकार करें",
"finish": "समाप्त करें", "finish": "समाप्त करें",
"done": "हो गया",
"mail": "मेल", "mail": "मेल",
"sign-now": "अभी हस्ताक्षर करें", "sign-now": "अभी हस्ताक्षर करें",
"successfully-signed": "सफलतापूर्वक हस्ताक्षर किए गए!", "successfully-signed": "सफलतापूर्वक हस्ताक्षर किए गए!",
@@ -1041,5 +1042,6 @@
"vertical": "वर्टिकल", "vertical": "वर्टिकल",
"horizontal": "हॉरिज़ॉन्टल", "horizontal": "हॉरिज़ॉन्टल",
"billing": "बिलिंग", "billing": "बिलिंग",
"console": "कंसोल" "console": "कंसोल",
"action-prohibited": "यह क्रिया आपके ईमेल डोमेन के लिए अनुमत नहीं है। कृपया सहायता के लिए अपने व्यवस्थापक से संपर्क करें।"
} }
@@ -379,6 +379,7 @@
"certificate": "Certificato", "certificate": "Certificato",
"decline": "Rifiuta", "decline": "Rifiuta",
"finish": "Completa", "finish": "Completa",
"done": "Fatto",
"mail": "Email", "mail": "Email",
"sign-now": "Firma ora", "sign-now": "Firma ora",
"successfully-signed": "Firmato con successo!", "successfully-signed": "Firmato con successo!",
@@ -1041,5 +1042,6 @@
"vertical": "Verticale", "vertical": "Verticale",
"horizontal": "Orizzontale", "horizontal": "Orizzontale",
"billing": "Fatturazione", "billing": "Fatturazione",
"console": "Console" "console": "Console",
"action-prohibited": "Questa azione non è consentita per il tuo dominio email. Contatta il tuo amministratore per ricevere assistenza."
} }
+16 -14
View File
@@ -19,8 +19,13 @@ const Header = ({ showSidebar, setIsMenu, isConsole }) => {
const { width } = useWindowSize(); const { width } = useWindowSize();
const username = localStorage.getItem("username") || ""; const username = localStorage.getItem("username") || "";
const image = localStorage.getItem("profileImg") || dp; const image = localStorage.getItem("profileImg") || dp;
const isAdmin =
localStorage.getItem("Extand_Class") &&
JSON.parse(localStorage.getItem("Extand_Class"))?.[0]?.UserRole ===
"contracts_Admin";
const [isOpen, setIsOpen] = useState(false); const [isOpen, setIsOpen] = useState(false);
const [applogo, setAppLogo] = useState(""); const [applogo, setAppLogo] = useState("");
const [isDarkTheme, setIsDarkTheme] = useState();
const toggleDropdown = () => { const toggleDropdown = () => {
setIsOpen(!isOpen); setIsOpen(!isOpen);
@@ -88,22 +93,15 @@ const Header = ({ showSidebar, setIsMenu, isConsole }) => {
useEffect(() => { useEffect(() => {
const updateLogoForTheme = () => { const updateThemeStatus = () => {
const isDarkMode = const isDarkTheme =
document.documentElement.getAttribute("data-theme") === "opensigndark"; document.documentElement.getAttribute("data-theme") === "opensigndark";
const logo = isDarkMode setIsDarkTheme(isDarkTheme);
? "/static/js/assets/images/logo-dark.png" // Path to the dark mode logo
: appInfo.applogo; // Use current logo for light mode
if (applogo !== logo) {
setAppLogo(logo);
}
}; };
updateThemeStatus();
// Set the logo immediately based on the current theme
updateLogoForTheme();
const observer = new MutationObserver(() => { const observer = new MutationObserver(() => {
updateLogoForTheme(); updateThemeStatus();
}); });
observer.observe(document.documentElement, { observer.observe(document.documentElement, {
@@ -112,7 +110,7 @@ const Header = ({ showSidebar, setIsMenu, isConsole }) => {
}); });
return () => observer.disconnect(); return () => observer.disconnect();
}, [applogo]); }, []);
return ( return (
<div> <div>
@@ -130,7 +128,11 @@ const Header = ({ showSidebar, setIsMenu, isConsole }) => {
{applogo && ( {applogo && (
<img <img
className="object-contain h-full w-auto" className="object-contain h-full w-auto"
src={applogo} src={
isDarkTheme
? "/static/js/assets/images/logo-dark.png"
: applogo
}
alt="logo" alt="logo"
/> />
)} )}
@@ -9,7 +9,6 @@ function AgreementContent(props) {
const h2Style = "text-base-content font-medium text-lg"; const h2Style = "text-base-content font-medium text-lg";
const ulStyle = "list-disc px-4 py-3"; const ulStyle = "list-disc px-4 py-3";
const handleOnclick = () => { const handleOnclick = () => {
props.setIsAgreeTour(false);
props.setIsAgree(true); props.setIsAgree(true);
props.setIsShowAgreeTerms(false); props.setIsShowAgreeTerms(false);
props.showFirstWidget(); props.showFirstWidget();
@@ -4,7 +4,6 @@ import AgreementContent from "./AgreementContent";
function AgreementSign(props) { function AgreementSign(props) {
const { t } = useTranslation(); const { t } = useTranslation();
const [isChecked, setIsChecked] = useState(false);
const [isShowAgreeTerms, setIsShowAgreeTerms] = useState(false); const [isShowAgreeTerms, setIsShowAgreeTerms] = useState(false);
return ( return (
@@ -12,39 +11,12 @@ function AgreementSign(props) {
<div className="op-modal op-modal-open absolute z-[448]"> <div className="op-modal op-modal-open absolute z-[448]">
<div className="w-[95%] md:w-[60%] lg:w-[40%] op-modal-box overflow-y-auto hide-scrollbar text-sm p-4"> <div className="w-[95%] md:w-[60%] lg:w-[40%] op-modal-box overflow-y-auto hide-scrollbar text-sm p-4">
<div className="flex flex-row items-center"> <div className="flex flex-row items-center">
<label className="inline-flex justify-center items-center cursor-pointer mb-0">
{/* 1) This div becomes the “fake” checkbox */}
<div
data-tut="IsAgree"
className={`w-6 h-6 border-2 mr-3 rounded-full flex text-center items-center justify-center ${isChecked ? "op-border-primary" : "border-red-500"}`}
>
{isChecked ? (
<span className="op-text-primary text-sm font-bold"></span>
) : (
<span className="text-red-500 text-sm font-bold">X</span>
)}
</div>
{/* 2) Visually hide the native checkbox but keep it in the DOM */}
<input
className="sr-only"
type="checkbox"
checked={isChecked}
onChange={(e) => {
setIsChecked(e.target.checked);
if (e.target.checked) {
props.setIsAgreeTour(false);
}
props.showFirstWidget();
}}
/>
</label>
<div className="text-[11px] md:text-base text-base-content"> <div className="text-[11px] md:text-base text-base-content">
<span>{t("agree-p1")}</span> <span>{t("agree-p1")}</span>
<span <span
className="font-bold text-blue-600 cursor-pointer" className="font-bold text-blue-600 cursor-pointer"
onClick={() => { onClick={() => {
setIsShowAgreeTerms(true); setIsShowAgreeTerms(true);
props.setIsAgreeTour(false);
}} }}
> >
{t("agree-p2")} {t("agree-p2")}
@@ -52,15 +24,11 @@ function AgreementSign(props) {
<span> {t("agree-p3")}</span> <span> {t("agree-p3")}</span>
</div> </div>
</div> </div>
<div className="flex ml-[35px] mt-3"> <div className="flex mt-3">
<button <button
onClick={() => { onClick={() => {
if (isChecked) { props.setIsAgree(true);
props.setIsAgreeTour(false); props.showFirstWidget()
props.setIsAgree(true);
} else {
props.setIsAgreeTour(true);
}
}} }}
className="op-btn op-btn-primary op-btn-sm w-full md:w-auto" className="op-btn op-btn-primary op-btn-sm w-full md:w-auto"
> >
@@ -74,7 +42,6 @@ function AgreementSign(props) {
</div> </div>
{isShowAgreeTerms && ( {isShowAgreeTerms && (
<AgreementContent <AgreementContent
setIsAgreeTour={props.setIsAgreeTour}
setIsAgree={props.setIsAgree} setIsAgree={props.setIsAgree}
setIsShowAgreeTerms={setIsShowAgreeTerms} setIsShowAgreeTerms={setIsShowAgreeTerms}
showFirstWidget={props.showFirstWidget} showFirstWidget={props.showFirstWidget}
@@ -3,43 +3,39 @@ import { useTranslation } from "react-i18next";
import { useSelector } from "react-redux"; import { useSelector } from "react-redux";
function DefaultSignature(props) { function DefaultSignature(props) {
const { t } = useTranslation(); const { t } = useTranslation();
const defaultSignImg = useSelector((state) => state.widget.defaultSignImg); const defaultSignImg = useSelector((state) => state.widget.defaultSignImg);
const myInitial = useSelector((state) => state.widget.myInitial) const myInitial = useSelector((state) => state.widget.myInitial);
const tabName = ["my-signature", "my-initials"]; const tabName = ["my-signature", "my-initials"];
const [activeTab, setActiveTab] = useState(0); const [activeTab, setActiveTab] = useState(0);
const confirmToaddDefaultSign = (type) => { const confirmToaddDefaultSign = (type) => {
if (!props.isAgree) { if (props?.xyPosition.length > 0) {
props.setIsAgreeTour(true); //check signature or initial widgets exist or not for auto signing
} else { const getCurrentSignerXY = props?.xyPosition.filter(
if (props?.xyPosition.length > 0) { (data) => data.Id === props.uniqueId
//check signature or initial widgets exist or not for auto signing );
const getCurrentSignerXY = props?.xyPosition.filter( const checkIsSignInitialExist = getCurrentSignerXY?.every(
(data) => data.Id === props.uniqueId (placeholderObj) =>
); placeholderObj?.placeHolder?.some((placeholder) =>
const checkIsSignInitialExist = getCurrentSignerXY?.every( placeholder?.pos?.some((posItem) => posItem?.type === type)
(placeholderObj) => )
placeholderObj?.placeHolder?.some((placeholder) => );
placeholder?.pos?.some((posItem) => posItem?.type === type) if (checkIsSignInitialExist) {
) props?.setDefaultSignAlert({
); isShow: true,
if (checkIsSignInitialExist) { alertMessage: t("default-sign-alert", { widgetsType: type }),
props?.setDefaultSignAlert({ type: type
isShow: true, });
alertMessage: t("default-sign-alert", { widgetsType: type }),
type: type
});
} else {
props?.setDefaultSignAlert({
isShow: true,
alertMessage: t("defaultSign-alert", { widgetsType: type })
});
}
} else { } else {
props?.setDefaultSignAlert({ props?.setDefaultSignAlert({
isShow: true, isShow: true,
alertMessage: t("please-select-position!") alertMessage: t("defaultSign-alert", { widgetsType: type })
}); });
} }
} else {
props?.setDefaultSignAlert({
isShow: true,
alertMessage: t("please-select-position!")
});
} }
}; };
@@ -180,13 +180,8 @@ function Placeholder(props) {
const widgetClickHandler = () => { const widgetClickHandler = () => {
props.setCurrWidgetsDetails && props.setCurrWidgetsDetails(props.pos); props.setCurrWidgetsDetails && props.setCurrWidgetsDetails(props.pos);
//condition to check in request signing flow user click on agree or not
if (props?.data?.signerObjId === props?.signerObjId && !props.isDragging) { if (props?.data?.signerObjId === props?.signerObjId && !props.isDragging) {
if (!props.isAgree && !props.isSelfSign) { handleWidgetIdandPopup();
props.setIsAgreeTour && props.setIsAgreeTour(true);
} else {
handleWidgetIdandPopup();
}
} //condition for open contact details popup when sign templet from public signing flow } //condition for open contact details popup when sign templet from public signing flow
else if (props?.uniqueId && props.data?.Id === props?.uniqueId) { else if (props?.uniqueId && props.data?.Id === props?.uniqueId) {
handleWidgetIdandPopup(); handleWidgetIdandPopup();
@@ -108,7 +108,7 @@ function PlaceholderType(props) {
alt="signature" alt="signature"
draggable="false" draggable="false"
src={props.pos.SignUrl} src={props.pos.SignUrl}
className="w-full h-full select-none-cls " className={`${props.pos.signatureType !== "type" ? "object-contain" : ""} w-full h-full select-none-cls`}
/> />
) : ( ) : (
<div className={widgetCls}> <div className={widgetCls}>
@@ -132,7 +132,7 @@ function PlaceholderType(props) {
alt="stamp" alt="stamp"
draggable="false" draggable="false"
src={props.pos.SignUrl} src={props.pos.SignUrl}
className="w-full h-full select-none-cls" className="w-full h-full select-none-cls object-contain"
/> />
) : ( ) : (
<div className={widgetCls}> <div className={widgetCls}>
@@ -253,7 +253,7 @@ function PlaceholderType(props) {
alt="initials" alt="initials"
draggable="false" draggable="false"
src={props.pos.SignUrl} src={props.pos.SignUrl}
className="w-full h-full select-none-cls" className={`${props.pos.signatureType !== "type" ? "object-contain" : ""} w-full h-full select-none-cls`}
/> />
) : ( ) : (
<div className={widgetCls}> <div className={widgetCls}>
@@ -402,7 +402,7 @@ function PlaceholderType(props) {
alt="image" alt="image"
draggable="false" draggable="false"
src={props.pos.SignUrl} src={props.pos.SignUrl}
className="w-full h-full select-none-cls" className="w-full h-full select-none-cls object-contain"
/> />
) : ( ) : (
<div className={widgetCls}> <div className={widgetCls}>
@@ -160,8 +160,6 @@ function RenderPdf(props) {
ispublicTemplate={props.ispublicTemplate} ispublicTemplate={props.ispublicTemplate}
handleUserDetails={props.handleUserDetails} handleUserDetails={props.handleUserDetails}
isResize={props.isResize} isResize={props.isResize}
setIsAgreeTour={props.setIsAgreeTour}
isAgree={props.isAgree}
handleTabDrag={props.handleTabDrag} handleTabDrag={props.handleTabDrag}
handleStop={props.handleStop} handleStop={props.handleStop}
setUniqueId={props.setUniqueId} setUniqueId={props.setUniqueId}
@@ -18,7 +18,8 @@ import {
cellsWidget, cellsWidget,
textWidget, textWidget,
years, years,
convertTextToImg convertTextToImg,
convertJpegToPng
} from "../../constant/Utils"; } from "../../constant/Utils";
import CellsWidget from "./CellsWidget"; import CellsWidget from "./CellsWidget";
import DatePicker from "react-datepicker"; import DatePicker from "react-datepicker";
@@ -110,7 +111,6 @@ function WidgetsValueModal(props) {
const [signature, setSignature] = useState(); const [signature, setSignature] = useState();
const [isImageSelect, setIsImageSelect] = useState(false); const [isImageSelect, setIsImageSelect] = useState(false);
const [isFinish, setIsFinish] = useState(false); const [isFinish, setIsFinish] = useState(false);
const [imgWH, setImgWH] = useState({});
const [fontSelect, setFontSelect] = useState(fontOptions[0].value); const [fontSelect, setFontSelect] = useState(fontOptions[0].value);
const [isSavedSign, setIsSavedSign] = useState(false); const [isSavedSign, setIsSavedSign] = useState(false);
const [isAutoSign, setIsAutoSign] = useState(false); const [isAutoSign, setIsAutoSign] = useState(false);
@@ -257,11 +257,11 @@ function WidgetsValueModal(props) {
setOriginalImage(null); // Reset original image when a new file is selected setOriginalImage(null); // Reset original image when a new file is selected
setRemoveBgEnabled(false); // Optionally reset toggle setRemoveBgEnabled(false); // Optionally reset toggle
// Ensure compressedFileSize calls setImage, which then triggers the useEffect for BG removal. // Ensure compressedFileSize calls setImage, which then triggers the useEffect for BG removal.
compressedFileSize(file, setImgWH, setImage); compressedFileSize(file, setImage);
} }
}; };
//function is used to save image,stamp widgets data //function is used to save image,stamp widgets data
const handleSaveImage = () => { const handleSaveImage = (signatureType) => {
const widgetsType = currWidgetsDetails?.type; const widgetsType = currWidgetsDetails?.type;
//`isApplyAll` is used when user edit stamp then updated signature apply all existing drawn signatures //`isApplyAll` is used when user edit stamp then updated signature apply all existing drawn signatures
const isApplyAll = true; const isApplyAll = true;
@@ -278,10 +278,10 @@ function WidgetsValueModal(props) {
// Get updated placeholder list // Get updated placeholder list
const updatedPlaceholders = onSaveImage( const updatedPlaceholders = onSaveImage(
signatureType,
signer.placeHolder, signer.placeHolder,
index, index,
currWidgetsDetails?.key, currWidgetsDetails?.key,
imgWH,
image, image,
isAutoSign, isAutoSign,
widgetsType, widgetsType,
@@ -299,11 +299,13 @@ function WidgetsValueModal(props) {
return object.pageNumber === pageNumber; return object.pageNumber === pageNumber;
}); });
const getImage = onSaveImage( const getImage = onSaveImage(
signatureType,
props?.xyPosition, props?.xyPosition,
index, index,
currWidgetsDetails?.key, currWidgetsDetails?.key,
imgWH, image,
image false,
widgetsType
); );
setXyPosition(getImage); setXyPosition(getImage);
} }
@@ -311,36 +313,28 @@ function WidgetsValueModal(props) {
}; };
//function is used to save draw type or initial type signature //function is used to save draw type or initial type signature
const handleSaveSignature = ( const handleSaveSignature = async (
type, signType,
isDefaultSign, isDefaultSign,
width, width,
height, height,
typedSignature typedSignature
) => { ) => {
//get current click widget type // get current click widget type
const widgetsType = currWidgetsDetails?.type; const widgetsType = currWidgetsDetails?.type;
//if there are any width and height then it will typed signature // if there are any width and height then it will typed signature
const isTypeText = width && height ? true : false; const isTypeText = width && height ? true : false;
//final getting signature url via default select sign/default initial sign/self draw sign // final getting signature url via default select sign/default initial sign/self draw sign
const signatureImg = isDefaultSign const signUrl = isDefaultSign
? isDefaultSign === "initials" ? isDefaultSign === "initials"
? myInitial ? await convertJpegToPng(myInitial, "myinitials") // default initials set through my signature tab
: defaultSignImg : await convertJpegToPng(defaultSignImg, "mysign") // default signature set through my signature tab
: signature; : signature; // signature done by user thorugh draw, upload, typed
const signatureImg = signUrl;
let imgWH = { width: width ? width : "", height: height ? height : "" }; let imgWH = { width: width ? width : "", height: height ? height : "" };
setIsImageSelect(false); setIsImageSelect(false);
setImage(); setImage();
//set default signature image width and height // `isApplyAll` is used when user edit signature/initial then updated signature apply all existing drawn signatures
if (isDefaultSign) {
const img = new Image();
img.src = defaultSignImg;
if (img.complete) {
imgWH = { width: img.width, height: img.height };
}
}
//`isApplyAll` is used when user edit signature/initial then updated signature apply all existing drawn signatures
const isApplyAll = true; const isApplyAll = true;
if (uniqueId) { if (uniqueId) {
setXyPosition((prevState) => setXyPosition((prevState) =>
@@ -351,13 +345,12 @@ function WidgetsValueModal(props) {
(x) => x.pageNumber === pageNumber (x) => x.pageNumber === pageNumber
); );
const updatedPlaceholders = onSaveSign( const updatedPlaceholders = onSaveSign(
type, signType,
signer.placeHolder, signer.placeHolder,
placeholderIndex, placeholderIndex,
currWidgetsDetails?.key, currWidgetsDetails?.key,
signatureImg, signatureImg,
imgWH, imgWH,
isDefaultSign,
isTypeText, isTypeText,
typedSignature, typedSignature,
isAutoSign, isAutoSign,
@@ -377,13 +370,12 @@ function WidgetsValueModal(props) {
return object.pageNumber === pageNumber; return object.pageNumber === pageNumber;
}); });
const getUpdatePosition = onSaveSign( const getUpdatePosition = onSaveSign(
type, signType,
props?.xyPosition, props?.xyPosition,
index, index,
currWidgetsDetails?.key, currWidgetsDetails?.key,
signatureImg, signatureImg,
imgWH, imgWH,
isDefaultSign,
isTypeText, isTypeText,
typedSignature, typedSignature,
false, false,
@@ -535,7 +527,7 @@ function WidgetsValueModal(props) {
} }
}; };
// `handlesavesign` is used to save signaute, initials, stamp as a default // `handlesavesign` is used to save signature, initials, stamp as a default
const handleSaveSign = async () => { const handleSaveSign = async () => {
if (signature || image?.src) { if (signature || image?.src) {
setIsLoader(true); setIsLoader(true);
@@ -556,7 +548,7 @@ function WidgetsValueModal(props) {
objectId: User?.id objectId: User?.id
}; };
if (imageUrl) { if (imageUrl) {
// below code is used to save or update default signaute, initials, stamp // below code is used to save or update default signature, initials, stamp
try { try {
const signCls = new Parse.Object("contracts_Signature"); const signCls = new Parse.Object("contracts_Signature");
if (props?.saveSignCheckbox?.signId) { if (props?.saveSignCheckbox?.signId) {
@@ -642,13 +634,14 @@ function WidgetsValueModal(props) {
} else { } else {
setSignature(""); setSignature("");
canvasRef?.current?.clear(); canvasRef?.current?.clear();
handleSaveSignature(isTab); const tab = isTab === "uploadImage" ? "image" : isTab;
handleSaveSignature(tab);
} }
} }
setPenColor("blue"); setPenColor("blue");
} else { } else {
setSignature(""); setSignature("");
handleSaveImage(); handleSaveImage("image");
} }
setIsImageSelect(false); setIsImageSelect(false);
setIsDefaultSign(false); setIsDefaultSign(false);
@@ -1178,7 +1171,9 @@ function WidgetsValueModal(props) {
hidden hidden
/> />
<i className="fa-light fa-cloud-upload-alt uploadImgLogo text-base-content"></i> <i className="fa-light fa-cloud-upload-alt uploadImgLogo text-base-content"></i>
<div className="text-[10px] text-base-content">{t("upload")}</div> <div className="text-[10px] text-base-content">
{t("upload")}
</div>
</div> </div>
</div> </div>
) : ( ) : (
@@ -1324,7 +1319,6 @@ function WidgetsValueModal(props) {
dotSize={1} dotSize={1}
/> />
</div> </div>
<div className="flex flex-row justify-between mt-[10px]"> <div className="flex flex-row justify-between mt-[10px]">
<PenColorComponent /> <PenColorComponent />
</div> </div>
@@ -1988,7 +1982,7 @@ function WidgetsValueModal(props) {
handleClickOnNext(isFinishDoc); handleClickOnNext(isFinishDoc);
}} }}
> >
{t("finish")} {t("done")}
</button> </button>
) : ( ) : (
<button <button
+142 -62
View File
@@ -361,7 +361,7 @@ export const selectFormat = (data) => {
case "DD MMMM, YYYY": case "DD MMMM, YYYY":
return "dd MMMM, yyyy"; return "dd MMMM, yyyy";
case "DD.MM.YYYY": case "DD.MM.YYYY":
return "dd.MM.yyyy"; return "dd.MM.yyyy";
default: default:
return "MM/dd/yyyy"; return "MM/dd/yyyy";
} }
@@ -390,7 +390,7 @@ export const changeDateToMomentFormat = (format) => {
case "dd MMMM, yyyy": case "dd MMMM, yyyy":
return "DD MMMM, YYYY"; return "DD MMMM, YYYY";
case "dd.MM.yyyy": case "dd.MM.yyyy":
return"DD.MM.YYYY"; return "DD.MM.YYYY";
default: default:
return "L"; return "L";
} }
@@ -1318,15 +1318,14 @@ export function convertTextToImg(fontStyle, text, color, widgetDims) {
return dataUrl; return dataUrl;
} }
//function for save button to save signature or image url // `onSaveSign` trigger on save button to save for signature, initials widget for type: draw, typed, default
export function onSaveSign( export function onSaveSign(
type, type,
xyPosition, xyPosition,
index, index,
signKey, signKey,
signatureImg, signatureImg,
defaultImgWH, updatedImgWH,
isDefaultSign,
isTypeText, isTypeText,
typedSignature, typedSignature,
isAutoSign, isAutoSign,
@@ -1341,27 +1340,11 @@ export function onSaveSign(
widgetsType && ["signature", "initials"].includes(widgetsType); widgetsType && ["signature", "initials"].includes(widgetsType);
const updateXYData = getXYdata.map((position) => { const updateXYData = getXYdata.map((position) => {
if (position.key === signKey) { if (position.key === signKey) {
if (isDefaultSign === "initials") { if (isTypeText) {
let imgWH = { width: position.Width, height: position.Height };
getIMGWH = calculateImgAspectRatio(imgWH, position);
} else if (isDefaultSign === "default") {
getIMGWH = calculateImgAspectRatio(defaultImgWH, position);
} else if (isTypeText) {
getIMGWH = { getIMGWH = {
newWidth: defaultImgWH.width, newWidth: updatedImgWH.width,
newHeight: defaultImgWH.height newHeight: updatedImgWH.height
}; };
} else {
const defaultWidth = defaultWidthHeight(position?.type).width;
const defaultHeight = defaultWidthHeight(position?.type).height;
getIMGWH = calculateImgAspectRatio(
{
width: defaultWidth ? defaultWidth : 150,
height: defaultHeight ? defaultHeight : 60
},
position
);
} }
posWidth = getIMGWH ? getIMGWH.newWidth : 150; posWidth = getIMGWH ? getIMGWH.newWidth : 150;
posHeight = getIMGWH ? getIMGWH.newHeight : 60; posHeight = getIMGWH ? getIMGWH.newHeight : 60;
@@ -1371,8 +1354,8 @@ export function onSaveSign(
: signatureImg; : signatureImg;
return { return {
...position, ...position,
Width: posWidth, ...(type === "type" ? { Width: posWidth } : {}),
Height: posHeight, ...(type === "type" ? { Height: posHeight } : {}),
SignUrl: signImg, SignUrl: signImg,
...(isSignOrInitials && { signatureType: type || "" }), ...(isSignOrInitials && { signatureType: type || "" }),
options: { ...position.options, response: signImg }, options: { ...position.options, response: signImg },
@@ -1392,7 +1375,7 @@ export function onSaveSign(
} }
return obj; return obj;
}); });
//condition when draw/upload signature/initials then apply it all related to widgets (signature,image,typed signature or default signature) //condition when draw/upload signature/initials then apply it all related to widgets (draw, typed signature or default signature)
if (isApplyAll || isAutoSign) { if (isApplyAll || isAutoSign) {
const updatedArray = updateXYposition.map((page) => ({ const updatedArray = updateXYposition.map((page) => ({
...page, ...page,
@@ -1404,9 +1387,6 @@ export function onSaveSign(
: signatureImg; : signatureImg;
return { return {
...item, ...item,
// Only copy signature content, keep existing dimensions
// Width: posWidth,
// Height: posHeight,
SignUrl: signImg, SignUrl: signImg,
...(isSignOrInitials && { signatureType: type || "" }), ...(isSignOrInitials && { signatureType: type || "" }),
options: { ...item.options, response: signImg }, options: { ...item.options, response: signImg },
@@ -1426,6 +1406,54 @@ export function onSaveSign(
} }
} }
/**
* Scales and centers a base64encoded image into a fixedsize widget
* and returns a new base64 PNG.
*
* @param {string} base64Image A data-URL (e.g. "data:image/png;base64,…")
* @param {{ Width: number, Height: number }} widgetDims
* @returns {Promise<string>} A Promise that resolves to a data-URL of the new image
*/
export async function convertBase64ToImg(base64Image, widgetDims) {
const { Width: maxWidth, Height: maxHeight } = widgetDims;
// Detect input format from data URL
const match = base64Image.match(/^data:(image\/(png|jpeg|jpg|webp));base64,/);
const inputMime = match ? match[1] : "image/png"; // fallback to PNG if unknown
// 1. Load the image off-DOM
const img = new Image();
img.src = base64Image;
await new Promise((resolve, reject) => {
img.onload = resolve;
img.onerror = reject;
});
// 2. Compute scale to fit within widget (preserving aspect ratio)
const { naturalWidth: imgW, naturalHeight: imgH } = img;
const scale = Math.min(maxWidth / imgW, maxHeight / imgH, 1);
const drawW = imgW * scale;
const drawH = imgH * scale;
// 3. Prepare a high-DPI canvas
const pxRatio = (window.devicePixelRatio || 1) * 2;
const canvas = document.createElement("canvas");
canvas.width = Math.ceil(maxWidth * pxRatio);
canvas.height = Math.ceil(maxHeight * pxRatio);
const ctx = canvas.getContext("2d");
ctx.scale(pxRatio, pxRatio);
ctx.clearRect(0, 0, maxWidth, maxHeight);
// 4. Center the image in the widget rectangle
const x = (maxWidth - drawW) / 2;
const y = (maxHeight - drawH) / 2;
ctx.drawImage(img, x, y, drawW, drawH);
// 5. Return new base64 in same format as input
const quality =
inputMime.includes("jpeg") || inputMime.includes("jpg") ? 0.9 : undefined;
return canvas.toDataURL(inputMime, quality);
}
//function to use After setting the signature URL for the first signature widget, clicking on subsequent //function to use After setting the signature URL for the first signature widget, clicking on subsequent
//signature widgets should automatically apply and display the signature. apply for initial,signature and stamp widget //signature widgets should automatically apply and display the signature. apply for initial,signature and stamp widget
export const handleCopySignUrl = ( export const handleCopySignUrl = (
@@ -1488,35 +1516,30 @@ export const calculateImgAspectRatio = (imgWH, pos) => {
return { newHeight, newWidth }; return { newHeight, newWidth };
}; };
//function for upload stamp or image // `onSaveImage` trigger for upload image through stamp, image, signature, initials widgets
export function onSaveImage( export function onSaveImage(
signatureType,
xyPosition, xyPosition,
index, index,
signKey, signKey,
imgWH,
image, image,
isAutoSign, isAutoSign,
widgetsType, widgetsType,
isApplyAll isApplyAll
) { ) {
let getIMGWH; // let getIMGWH;
const isSignOrInitials =
widgetsType && ["signature", "initials"].includes(widgetsType);
//get current page position //get current page position
const getXYData = xyPosition[index].pos; const getXYData = xyPosition[index].pos;
const updateXYData = getXYData.map((position) => { const updateXYData = getXYData.map((position) => {
if (position.key === signKey) { if (position.key === signKey) {
getIMGWH = calculateImgAspectRatio(imgWH, position);
return { return {
...position, ...position,
Width: getIMGWH.newWidth,
Height: getIMGWH.newHeight,
SignUrl: image.src, SignUrl: image.src,
ImageType: image.imgType, ImageType: image.imgType,
options: { ...(isSignOrInitials && { signatureType: signatureType || "" }),
...position.options, options: { ...position.options, response: image.src }
response: image.src
}
}; };
} }
return position; return position;
@@ -1528,17 +1551,16 @@ export function onSaveImage(
} }
return obj; return obj;
}); });
//condition when user upload(stamp) then apply it all related to widgets // condition when user upload(stamp) then apply it all related to widgets
if (isApplyAll || isAutoSign) { if (isApplyAll || isAutoSign) {
const updatedArray = updateXYposition.map((page) => ({ const updatedArray = updateXYposition.map((page) => ({
...page, ...page,
pos: page.pos.map( pos: page.pos.map(
(item) => (item) =>
// below condition to exclude apply all for image widget
item.type === widgetsType && item.type !== "image" item.type === widgetsType && item.type !== "image"
? { ? {
...item, ...item,
// Width: getIMGWH.newWidth,
// Height: getIMGWH.newHeight,
SignUrl: image.src, SignUrl: image.src,
ImageType: image.imgType, ImageType: image.imgType,
options: { options: {
@@ -1556,7 +1578,7 @@ export function onSaveImage(
} }
//function for select image and upload image //function for select image and upload image
export const onImageSelect = (setImgWH, setImage, file) => { export const onImageSelect = (setImage, file) => {
const reader = new FileReader(); const reader = new FileReader();
reader.readAsDataURL(file); reader.readAsDataURL(file);
reader.onloadend = function (e) { reader.onloadend = function (e) {
@@ -1575,13 +1597,12 @@ export const onImageSelect = (setImgWH, setImage, file) => {
width = 184 * imgR; width = 184 * imgR;
height = 184; height = 184;
} }
setImgWH({ width: width, height: height });
}; };
image.src = reader.result; image.src = reader.result;
setImage({ src: image.src, imgType: file.type }); setImage({ src: image.src, imgType: file.type });
}; };
}; };
export const compressedFileSize = (file, setImgWH, setImage) => { export const compressedFileSize = (file, setImage) => {
// Create a new FileReader instance to read the uploaded file // Create a new FileReader instance to read the uploaded file
const reader = new FileReader(); const reader = new FileReader();
@@ -1606,7 +1627,7 @@ export const compressedFileSize = (file, setImgWH, setImage) => {
// Draw the image onto the canvas with the specified dimensions // Draw the image onto the canvas with the specified dimensions
ctx.drawImage(img, 0, 0, canvas.width, canvas.height); ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
// Get the original file type (default to "image/png" if not recognized) // Get the original file type (default to "image/png" if not recognized)
const fileType = file.type || "image/png"; const fileType = "image/png"; //file.type || "image/png"
// Compress the image and convert it into a Blob // Compress the image and convert it into a Blob
canvas.toBlob( canvas.toBlob(
(blob) => { (blob) => {
@@ -1616,7 +1637,7 @@ export const compressedFileSize = (file, setImgWH, setImage) => {
lastModified: Date.now() // Update the last modified timestamp lastModified: Date.now() // Update the last modified timestamp
}); });
// Pass the compressed file to a custom function for further processing // Pass the compressed file to a custom function for further processing
onImageSelect(setImgWH, setImage, compressedFile); onImageSelect(setImage, compressedFile);
}, },
fileType, // Output format for the compressed image fileType, // Output format for the compressed image
0.3 // Compression quality (30%) 0.3 // Compression quality (30%)
@@ -1741,10 +1762,12 @@ export const multiSignEmbed = async (widgets, pdfDoc, signyourself, scale) => {
widgetsPositionArr.map(async (widget) => { widgetsPositionArr.map(async (widget) => {
// `SignUrl` this is wrong nomenclature and maintain for older code in this options we save base64 of signature image from sign pad // `SignUrl` this is wrong nomenclature and maintain for older code in this options we save base64 of signature image from sign pad
let signbase64 = widget.SignUrl && widget.SignUrl; let signbase64 = widget.SignUrl && widget.SignUrl;
const widgetDims = { Width: widget.Width, Height: widget.Height };
if (signbase64) { if (signbase64) {
let arr = signbase64.split(","), let arr = signbase64.split(","),
mime = arr[0].match(/:(.*?);/)[1]; mime = arr[0].match(/:(.*?);/)[1];
const res = await fetch(signbase64); const signatureImg = await convertBase64ToImg(signbase64, widgetDims);
const res = await fetch(signatureImg);
const arrayBuffer = await res.arrayBuffer(); const arrayBuffer = await res.arrayBuffer();
const obj = { mimetype: mime, arrayBuffer: arrayBuffer }; const obj = { mimetype: mime, arrayBuffer: arrayBuffer };
return obj; return obj;
@@ -2272,28 +2295,25 @@ export const addDefaultSignatureImg = (xyPosition, defaultSignImg, type) => {
const img = new Image(); const img = new Image();
img.src = defaultSignImg; img.src = defaultSignImg;
if (img.complete) { if (img.complete) {
imgWH = { imgWH = { width: img.width, height: img.height };
width: img.width,
height: img.height
};
} }
let xyDefaultPos = []; let xyDefaultPos = [];
for (let i = 0; i < xyPosition.length; i++) { for (let i = 0; i < xyPosition.length; i++) {
let getIMGWH; // let getIMGWH;
const getXYdata = xyPosition[i].pos; const getXYdata = xyPosition[i].pos;
const getPageNo = xyPosition[i].pageNumber; const getPageNo = xyPosition[i].pageNumber;
const getPosData = getXYdata; const getPosData = getXYdata;
const addSign = getPosData.map((position) => { const addSign = getPosData.map((position) => {
getIMGWH = calculateImgAspectRatio(imgWH, position); // getIMGWH = calculateImgAspectRatio(imgWH, position);
if (position.type) { if (position.type) {
if (position?.type === type) { if (position?.type === type) {
return { return {
...position, ...position,
SignUrl: defaultSignImg, SignUrl: defaultSignImg,
Width: getIMGWH.newWidth, // Width: getIMGWH.newWidth,
Height: getIMGWH.newHeight, // Height: getIMGWH.newHeight,
ImageType: "default", ImageType: "default",
options: { options: {
...position.options, ...position.options,
@@ -2305,8 +2325,8 @@ export const addDefaultSignatureImg = (xyPosition, defaultSignImg, type) => {
return { return {
...position, ...position,
SignUrl: defaultSignImg, SignUrl: defaultSignImg,
Width: getIMGWH.newWidth, // Width: getIMGWH.newWidth,
Height: getIMGWH.newHeight, // Height: getIMGWH.newHeight,
ImageType: "default", ImageType: "default",
options: { options: {
...position.options, ...position.options,
@@ -2414,7 +2434,10 @@ export const getAppLogo = async () => {
}); });
if (tenant) { if (tenant) {
localStorage.setItem("appname", "OpenSign™"); localStorage.setItem("appname", "OpenSign™");
return { logo: tenant?.logo, user: tenant?.user }; return {
logo: tenant?.logo,
user: tenant?.user
};
} }
} catch (err) { } catch (err) {
console.log("err in getlogo ", err); console.log("err in getlogo ", err);
@@ -3650,3 +3673,60 @@ export function getFileAsArrayBuffer(file) {
reader.readAsArrayBuffer(file); reader.readAsArrayBuffer(file);
}); });
} }
/**
* Converts a JPEG/JPG File/Blob into a PNG File.
*
* @param {string} base64Image - A data-URL (e.g. "data:image/jpeg;base64,…")
* @param {string} filename - Desired filename (e.g. "input").
* @returns {Promise<File>} - A promise that resolves with a new PNG File.
*/
export function convertJpegToPng(base64Image, filename) {
const arr = base64Image.split(",");
const mimeMatch = arr[0].match(/:(.*?);/);
if (!mimeMatch) throw new Error("Invalid dataURL");
const mime = mimeMatch[1];
const type = mime.split("/")[1];
if (type === "png") {
return base64Image;
} else {
const bstr = atob(arr[1]);
let n = bstr.length;
const u8arr = new Uint8Array(n);
while (n--) u8arr[n] = bstr.charCodeAt(n);
const inputFile = new File([u8arr], `${filename}.${type}`, { type: mime });
return new Promise((resolve, reject) => {
// ensure its JPEG/JPG (you can remove this check if not needed)
if (!/image\/jpe?g/.test(inputFile.type)) {
return reject(new Error("Input must be a JPEG or JPG image"));
}
// Read the file as a data URL
const reader = new FileReader();
reader.onerror = () => reject(new Error("Failed to read the file"));
reader.onload = () => {
const img = new Image();
img.onerror = () => reject(new Error("Failed to load image"));
img.onload = () => {
// draw image onto a canvas
const canvas = document.createElement("canvas");
canvas.width = img.width;
canvas.height = img.height;
const ctx = canvas.getContext("2d");
ctx.drawImage(img, 0, 0);
// directly get PNG as base64 data URL
try {
const pngDataUrl = canvas.toDataURL("image/png");
resolve(pngDataUrl);
} catch (err) {
reject(new Error("Failed to convert canvas to PNG"));
}
};
img.src = reader.result;
};
reader.readAsDataURL(inputFile);
});
}
}
+5 -1
View File
@@ -125,7 +125,11 @@ function Login() {
} }
} catch (error) { } catch (error) {
console.error("Error while logging in user", error); console.error("Error while logging in user", error);
showToast("danger", "Invalid username/password or region"); if (error?.code === 1001) {
showToast("danger", t("action-prohibited"));
} else {
showToast("danger", "Invalid username/password or region");
}
} }
}; };
const handleLoginBtn = async (event) => { const handleLoginBtn = async (event) => {
+2 -30
View File
@@ -144,7 +144,6 @@ function PdfRequestFiles(
const [signatureType, setSignatureType] = useState([]); const [signatureType, setSignatureType] = useState([]);
const [pdfBase64Url, setPdfBase64Url] = useState(""); const [pdfBase64Url, setPdfBase64Url] = useState("");
const [isAgree, setIsAgree] = useState(false); const [isAgree, setIsAgree] = useState(false);
const [isAgreeTour, setIsAgreeTour] = useState(false);
const [redirectTimeLeft, setRedirectTimeLeft] = useState(5); const [redirectTimeLeft, setRedirectTimeLeft] = useState(5);
const [isredirectCanceled, setIsredirectCanceled] = useState(true); const [isredirectCanceled, setIsredirectCanceled] = useState(true);
const [isDragging, setIsDragging] = useState(false); const [isDragging, setIsDragging] = useState(false);
@@ -1378,18 +1377,7 @@ function PdfRequestFiles(
setIsUiLoading(false); setIsUiLoading(false);
alert(t("expiry-date-error")); alert(t("expiry-date-error"));
} }
}; };
const AgreementTour = [
{
selector: '[data-tut="IsAgree"]',
content: () => <p className="p-0">{t("agrrement-alert")}</p>,
position: "top",
style: { fontSize: "13px" }
}
];
const handleCloseAgreeTour = () => {
setIsAgreeTour(false);
};
// `handleRedirectCancel` is used to cancel redirecting to redirectUrl // `handleRedirectCancel` is used to cancel redirecting to redirectUrl
const handleRedirectCancel = () => { const handleRedirectCancel = () => {
setIsredirectCanceled(true); setIsredirectCanceled(true);
@@ -1599,7 +1587,7 @@ function PdfRequestFiles(
} }
} }
}; };
//function to get first widget and page number to assign currect signer and tour message //function to get first widget id and page number to assign correct signer and show tour message
const showFirstWidget = () => { const showFirstWidget = () => {
if (!requestSignTour) { if (!requestSignTour) {
const getCurrentUserPlaceholder = signerPos?.find( const getCurrentUserPlaceholder = signerPos?.find(
@@ -1644,21 +1632,9 @@ function PdfRequestFiles(
!isDecline?.isDeclined && ( !isDecline?.isDeclined && (
<AgreementSign <AgreementSign
setIsAgree={setIsAgree} setIsAgree={setIsAgree}
setIsAgreeTour={setIsAgreeTour}
showFirstWidget={showFirstWidget} showFirstWidget={showFirstWidget}
/> />
)} )}
<Tour
showNumber={false}
showNavigation={false}
showNavigationNumber={false}
onRequestClose={handleCloseAgreeTour}
steps={AgreementTour}
isOpen={isAgreeTour}
rounded={5}
closeWithMask={false}
/>
{isUiLoading && ( {isUiLoading && (
<div className="absolute h-[100vh] w-full flex flex-col justify-center items-center z-[999] bg-[#e6f2f2] bg-opacity-80"> <div className="absolute h-[100vh] w-full flex flex-col justify-center items-center z-[999] bg-[#e6f2f2] bg-opacity-80">
<Loader /> <Loader />
@@ -2011,8 +1987,6 @@ function PdfRequestFiles(
scale={scale} scale={scale}
uniqueId={uniqueId} uniqueId={uniqueId}
pdfBase64Url={pdfBase64Url} pdfBase64Url={pdfBase64Url}
setIsAgreeTour={setIsAgreeTour}
isAgree={isAgree}
handleTabDrag={handleTabDrag} handleTabDrag={handleTabDrag}
handleStop={handleStop} handleStop={handleStop}
isDragging={isDragging} isDragging={isDragging}
@@ -2095,8 +2069,6 @@ function PdfRequestFiles(
signatureType?.find((x) => x.name === "default") signatureType?.find((x) => x.name === "default")
?.enabled || false ?.enabled || false
} }
isAgree={isAgree}
setIsAgreeTour={setIsAgreeTour}
/> />
)} )}
</div> </div>
@@ -994,6 +994,7 @@ const ReportTable = (props) => {
const timezone = extClass?.[0]?.Timezone || ""; const timezone = extClass?.[0]?.Timezone || "";
const DateFormat = extClass?.[0]?.DateFormat || "MM/DD/YYYY"; const DateFormat = extClass?.[0]?.DateFormat || "MM/DD/YYYY";
const Is12Hr = extClass?.[0]?.Is12HourTime || false; const Is12Hr = extClass?.[0]?.Is12HourTime || false;
const isCompletedReport = props?.ReportName === "Completed Documents";
const signers = item?.Placeholders?.map((x, i) => { const signers = item?.Placeholders?.map((x, i) => {
const audit = item?.AuditTrail?.find( const audit = item?.AuditTrail?.find(
(audit) => audit?.UserPtr?.objectId === x.signerObjId (audit) => audit?.UserPtr?.objectId === x.signerObjId
@@ -1021,20 +1022,22 @@ const ReportTable = (props) => {
key={i} key={i}
className="text-sm font-medium flex flex-row gap-2 items-center" className="text-sm font-medium flex flex-row gap-2 items-center"
> >
<button {!isCompletedReport && (
onClick={() => setIsModal({ [`${item.objectId}_${i}`]: true })} <button
className={`${ onClick={() => setIsModal({ [`${item.objectId}_${i}`]: true })}
x.Activity === "SIGNED" className={`${
? "op-border-primary op-text-primary" x.Activity === "SIGNED"
: x.Activity === "VIEWED" ? "op-border-primary op-text-primary"
? "border-green-400 text-green-400" : x.Activity === "VIEWED"
: "border-base-content text-base-content" ? "border-green-400 text-green-400"
} focus:outline-none border-2 w-[60px] h-[30px] text-[11px] rounded-full`} : "border-base-content text-base-content"
> } focus:outline-none border-2 w-[60px] h-[30px] text-[11px] rounded-full`}
{x?.Activity?.toUpperCase() || "-"} >
</button> {x?.Activity?.toUpperCase() || "-"}
</button>
)}
<div className="py-2 font-bold text-[12px]">{x?.Email || "-"}</div> <div className="py-2 font-bold text-[12px]">{x?.Email || "-"}</div>
{isModal[`${item.objectId}_${i}`] && ( {!isCompletedReport && isModal[`${item.objectId}_${i}`] && (
<ModalUi <ModalUi
isOpen isOpen
title={t("document-logs")} title={t("document-logs")}
@@ -1657,21 +1660,22 @@ const ReportTable = (props) => {
<React.Fragment key={index}> <React.Fragment key={index}>
<th className="p-2"> <th className="p-2">
{t(`report-heading.${item}`)} {t(`report-heading.${item}`)}
{props.ReportName === "Contactbook" && item === "Name" && ( {props.ReportName === "Contactbook" &&
<button item === "Name" && (
type="button" <button
onClick={toggleSortOrder} type="button"
className="ml-1" onClick={toggleSortOrder}
> className="ml-1"
<i >
className={ <i
sortOrder === "asc" className={
? "fa-light fa-arrow-down-a-z" sortOrder === "asc"
: "fa-light fa-arrow-up-a-z" ? "fa-light fa-arrow-down-a-z"
} : "fa-light fa-arrow-up-a-z"
></i> }
</button> ></i>
)} </button>
)}
</th> </th>
</React.Fragment> </React.Fragment>
))} ))}
@@ -1807,12 +1811,16 @@ const ReportTable = (props) => {
</td> </td>
)} )}
{props.heading.includes("Signers") && {props.heading.includes("Signers") &&
["In-progress documents", "Need your sign"].includes( [
props.ReportName "In-progress documents",
) ? ( "Need your sign",
"Completed Documents"
].includes(props.ReportName) ? (
<td className="px-1 py-2"> <td className="px-1 py-2">
{!item?.IsSignyourself && item?.Placeholders && ( {!item?.IsSignyourself && item?.Placeholders ? (
<>{formatStatusRow(item)}</> <>{formatStatusRow(item)}</>
) : (
<>-</>
)} )}
</td> </td>
) : ( ) : (
@@ -43,9 +43,9 @@ async function saveUser(userDetails) {
} }
export default async function usersignup(request) { export default async function usersignup(request) {
const userDetails = request.params.userDetails; const userDetails = request.params.userDetails;
const user = await saveUser(userDetails);
try { try {
const user = await saveUser(userDetails);
const extClass = userDetails.role.split('_')[0]; const extClass = userDetails.role.split('_')[0];
const extQuery = new Parse.Query(extClass + '_Users'); const extQuery = new Parse.Query(extClass + '_Users');
+44 -103
View File
@@ -105,9 +105,10 @@
} }
}, },
"node_modules/@apollo/server": { "node_modules/@apollo/server": {
"version": "4.12.0", "version": "4.12.1",
"resolved": "https://registry.npmjs.org/@apollo/server/-/server-4.12.0.tgz", "resolved": "https://registry.npmjs.org/@apollo/server/-/server-4.12.1.tgz",
"integrity": "sha512-Z5RNTCnIia+dFsP5HW2ugQMrIOWgyNWyKP+jMVXthp/ECjYyyRYPC41ukCDwxHQY4vNZ3rgbgqroWVQUGFt2gA==", "integrity": "sha512-jceK1LK6l074in4mWu8XkwzDjvxdSzkmk8M7YpVLOGjQ6PmlaChcGRJ9BUwB46r22MxdPCXdC/6U5Vi8gzYbvQ==",
"deprecated": "Apollo Server v4 is deprecated and will transition to end-of-life on January 26, 2026. As long as you are already using a non-EOL version of Node.js, upgrading to v5 should take only a few minutes. See https://www.apollographql.com/docs/apollo-server/previous-versions for details.",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@apollo/cache-control-types": "^1.0.3", "@apollo/cache-control-types": "^1.0.3",
@@ -146,6 +147,7 @@
"version": "1.1.1", "version": "1.1.1",
"resolved": "https://registry.npmjs.org/@apollo/server-gateway-interface/-/server-gateway-interface-1.1.1.tgz", "resolved": "https://registry.npmjs.org/@apollo/server-gateway-interface/-/server-gateway-interface-1.1.1.tgz",
"integrity": "sha512-pGwCl/po6+rxRmDMFgozKQo2pbsSwE91TpsDBAOgf74CRDPXHHtM88wbwjab0wMMZh95QfR45GGyDIdhY24bkQ==", "integrity": "sha512-pGwCl/po6+rxRmDMFgozKQo2pbsSwE91TpsDBAOgf74CRDPXHHtM88wbwjab0wMMZh95QfR45GGyDIdhY24bkQ==",
"deprecated": "@apollo/server-gateway-interface v1 is part of Apollo Server v4, which is deprecated and will transition to end-of-life on January 26, 2026. As long as you are already using a non-EOL version of Node.js, upgrading to v2 should take only a few minutes. See https://www.apollographql.com/docs/apollo-server/previous-versions for details.",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@apollo/usage-reporting-protobuf": "^4.1.1", "@apollo/usage-reporting-protobuf": "^4.1.1",
@@ -6119,18 +6121,30 @@
} }
}, },
"node_modules/@eslint/plugin-kit": { "node_modules/@eslint/plugin-kit": {
"version": "0.3.1", "version": "0.3.4",
"resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.3.1.tgz", "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.3.4.tgz",
"integrity": "sha512-0J+zgWxHN+xXONWIyPWKFMgVuJoZuGiIFu8yxk7RJjxkzpGmyja5wRFqZIVtjDVOQpV+Rw0iOAjYPE2eQyjr0w==", "integrity": "sha512-Ul5l+lHEcw3L5+k8POx6r74mxEYKG5kOb6Xpy2gCRW6zweT6TEhAf8vhxGgjhqrd/VO/Dirhsb+1hNpD1ue9hw==",
"license": "Apache-2.0", "license": "Apache-2.0",
"dependencies": { "dependencies": {
"@eslint/core": "^0.14.0", "@eslint/core": "^0.15.1",
"levn": "^0.4.1" "levn": "^0.4.1"
}, },
"engines": { "engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0" "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
} }
}, },
"node_modules/@eslint/plugin-kit/node_modules/@eslint/core": {
"version": "0.15.1",
"resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.15.1.tgz",
"integrity": "sha512-bkOp+iumZCCbt1K1CmWf0R9pM5yKpDv+ZXtvSyQpudrI9kuFLp+bM2WOPXImuD/ceQuaa8f5pj93Y7zyECIGNA==",
"license": "Apache-2.0",
"dependencies": {
"@types/json-schema": "^7.0.15"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
}
},
"node_modules/@fastify/busboy": { "node_modules/@fastify/busboy": {
"version": "3.1.1", "version": "3.1.1",
"resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-3.1.1.tgz", "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-3.1.1.tgz",
@@ -10978,23 +10992,6 @@
"form-data": "^2.5.0" "form-data": "^2.5.0"
} }
}, },
"node_modules/@types/request/node_modules/form-data": {
"version": "2.5.3",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.3.tgz",
"integrity": "sha512-XHIrMD0NpDrNM/Ckf7XJiBbLl57KEhT3+i3yY+eWm+cqYZJQTZrKo8Y8AWKnuV5GT4scfuUGt9LzNoIx3dU1nQ==",
"license": "MIT",
"optional": true,
"dependencies": {
"asynckit": "^0.4.0",
"combined-stream": "^1.0.8",
"es-set-tostringtag": "^2.1.0",
"mime-types": "^2.1.35",
"safe-buffer": "^5.2.1"
},
"engines": {
"node": ">= 0.12"
}
},
"node_modules/@types/send": { "node_modules/@types/send": {
"version": "0.17.4", "version": "0.17.4",
"resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz", "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz",
@@ -13468,9 +13465,9 @@
} }
}, },
"node_modules/form-data": { "node_modules/form-data": {
"version": "4.0.3", "version": "4.0.4",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.3.tgz", "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.4.tgz",
"integrity": "sha512-qsITQPfmvMOSAdeyZ+12I1c+CKSstAFAwu+97zrnWAbIr5u8wfsExUzCesVLC8NgHuRUqNN4Zy6UPWUTRGslcA==", "integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"asynckit": "^0.4.0", "asynckit": "^0.4.0",
@@ -15737,9 +15734,9 @@
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
}, },
"node_modules/multer": { "node_modules/multer": {
"version": "2.0.1", "version": "2.0.2",
"resolved": "https://registry.npmjs.org/multer/-/multer-2.0.1.tgz", "resolved": "https://registry.npmjs.org/multer/-/multer-2.0.2.tgz",
"integrity": "sha512-Ug8bXeTIUlxurg8xLTEskKShvcKDZALo1THEX5E41pYCD2sCVub5/kIRIGqWNoqV6szyLyQKV6mD4QUrWE5GCQ==", "integrity": "sha512-u7f2xaZ/UG8oLXHvtF/oWTRvT44p9ecwBBqTwgJVq0+4BW1g8OW01TyMEGWBHbyMOYVHXslaut7qEQ1meATXgw==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"append-field": "^1.0.0", "append-field": "^1.0.0",
@@ -16476,13 +16473,13 @@
} }
}, },
"node_modules/parse-server": { "node_modules/parse-server": {
"version": "8.2.1", "version": "8.2.2",
"resolved": "https://registry.npmjs.org/parse-server/-/parse-server-8.2.1.tgz", "resolved": "https://registry.npmjs.org/parse-server/-/parse-server-8.2.2.tgz",
"integrity": "sha512-Z0k0a6UAmcbWTt21naacGDjNRNQpe3vrS+EM/cjSlXHPVAxYFnXuXK8R3kSCWKXU49tYkhep6A4KbtcFr2NsVw==", "integrity": "sha512-qFP5QpJW0NL6s3GhIonlmdCg5lJHwDCnTlxkINCsxnsoeKJVsFou0xy2x6dNquMIU0RJi3qolQaFbNGICZV3NA==",
"hasInstallScript": true, "hasInstallScript": true,
"license": "Apache-2.0", "license": "Apache-2.0",
"dependencies": { "dependencies": {
"@apollo/server": "4.12.0", "@apollo/server": "4.12.1",
"@babel/eslint-parser": "7.27.1", "@babel/eslint-parser": "7.27.1",
"@graphql-tools/merge": "9.0.24", "@graphql-tools/merge": "9.0.24",
"@graphql-tools/schema": "10.0.23", "@graphql-tools/schema": "10.0.23",
@@ -16508,7 +16505,7 @@
"lodash": "4.17.21", "lodash": "4.17.21",
"lru-cache": "10.4.0", "lru-cache": "10.4.0",
"mime": "4.0.7", "mime": "4.0.7",
"mongodb": "6.16.0", "mongodb": "6.17.0",
"mustache": "4.2.0", "mustache": "4.2.0",
"otpauth": "9.4.0", "otpauth": "9.4.0",
"parse": "6.1.1", "parse": "6.1.1",
@@ -16589,52 +16586,6 @@
"node": ">=18" "node": ">=18"
} }
}, },
"node_modules/parse-server/node_modules/mongodb": {
"version": "6.16.0",
"resolved": "https://registry.npmjs.org/mongodb/-/mongodb-6.16.0.tgz",
"integrity": "sha512-D1PNcdT0y4Grhou5Zi/qgipZOYeWrhLEpk33n3nm6LGtz61jvO88WlrWCK/bigMjpnOdAUKKQwsGIl0NtWMyYw==",
"license": "Apache-2.0",
"dependencies": {
"@mongodb-js/saslprep": "^1.1.9",
"bson": "^6.10.3",
"mongodb-connection-string-url": "^3.0.0"
},
"engines": {
"node": ">=16.20.1"
},
"peerDependencies": {
"@aws-sdk/credential-providers": "^3.188.0",
"@mongodb-js/zstd": "^1.1.0 || ^2.0.0",
"gcp-metadata": "^5.2.0",
"kerberos": "^2.0.1",
"mongodb-client-encryption": ">=6.0.0 <7",
"snappy": "^7.2.2",
"socks": "^2.7.1"
},
"peerDependenciesMeta": {
"@aws-sdk/credential-providers": {
"optional": true
},
"@mongodb-js/zstd": {
"optional": true
},
"gcp-metadata": {
"optional": true
},
"kerberos": {
"optional": true
},
"mongodb-client-encryption": {
"optional": true
},
"snappy": {
"optional": true
},
"socks": {
"optional": true
}
}
},
"node_modules/parse-server/node_modules/path-to-regexp": { "node_modules/parse-server/node_modules/path-to-regexp": {
"version": "6.3.0", "version": "6.3.0",
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.3.0.tgz", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.3.0.tgz",
@@ -17645,20 +17596,6 @@
"node": ">= 4" "node": ">= 4"
} }
}, },
"node_modules/request/node_modules/form-data": {
"version": "2.3.3",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz",
"integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==",
"license": "MIT",
"dependencies": {
"asynckit": "^0.4.0",
"combined-stream": "^1.0.6",
"mime-types": "^2.1.12"
},
"engines": {
"node": ">= 0.12"
}
},
"node_modules/request/node_modules/qs": { "node_modules/request/node_modules/qs": {
"version": "6.5.3", "version": "6.5.3",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz", "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz",
@@ -17985,16 +17922,23 @@
"integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw=="
}, },
"node_modules/sha.js": { "node_modules/sha.js": {
"version": "2.4.11", "version": "2.4.12",
"resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.12.tgz",
"integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", "integrity": "sha512-8LzC5+bvI45BjpfXU8V5fdU2mfeKiQe1D1gIMn7XUlF3OTUrpdJpPPH4EMAnF0DsHHdSZqCdSss5qCmJKuiO3w==",
"license": "(MIT AND BSD-3-Clause)", "license": "(MIT AND BSD-3-Clause)",
"dependencies": { "dependencies": {
"inherits": "^2.0.1", "inherits": "^2.0.4",
"safe-buffer": "^5.0.1" "safe-buffer": "^5.2.1",
"to-buffer": "^1.2.0"
}, },
"bin": { "bin": {
"sha.js": "bin.js" "sha.js": "bin.js"
},
"engines": {
"node": ">= 0.10"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
} }
}, },
"node_modules/shebang-command": { "node_modules/shebang-command": {
@@ -18701,7 +18645,6 @@
"version": "1.2.1", "version": "1.2.1",
"resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.2.1.tgz", "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.2.1.tgz",
"integrity": "sha512-tB82LpAIWjhLYbqjx3X4zEeHN6M8CiuOEy2JY8SEQVdYRe3CCHOFaqrBW1doLDrfpWhplcW7BL+bO3/6S3pcDQ==", "integrity": "sha512-tB82LpAIWjhLYbqjx3X4zEeHN6M8CiuOEy2JY8SEQVdYRe3CCHOFaqrBW1doLDrfpWhplcW7BL+bO3/6S3pcDQ==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"isarray": "^2.0.5", "isarray": "^2.0.5",
@@ -18716,7 +18659,6 @@
"version": "2.0.5", "version": "2.0.5",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz",
"integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==",
"dev": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/to-regex-range": { "node_modules/to-regex-range": {
@@ -18868,7 +18810,6 @@
"version": "1.0.3", "version": "1.0.3",
"resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz", "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz",
"integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==", "integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"call-bound": "^1.0.3", "call-bound": "^1.0.3",
+2 -1
View File
@@ -66,7 +66,8 @@
}, },
"overrides": { "overrides": {
"ws": "$ws", "ws": "$ws",
"parse": "$parse" "parse": "$parse",
"form-data": "$form-data"
}, },
"engines": { "engines": {
"node": "18 || 20 || 22" "node": "18 || 20 || 22"