diff --git a/apps/OpenSign/docs/DARK_MODE_USAGE.md b/apps/OpenSign/docs/DARK_MODE_USAGE.md new file mode 100644 index 0000000000..0ebf8f7095 --- /dev/null +++ b/apps/OpenSign/docs/DARK_MODE_USAGE.md @@ -0,0 +1,213 @@ +# Tailwind Dark Mode Usage Guide + +## Overview +This guide shows how to use the new Tailwind utilities for better dark mode visibility in OpenSign. + +## Button Styling + +### VS Code-style Disabled Buttons +```jsx +// Option 1: Direct VS Code styling + + +// Option 2: Themed disabled styling + + +// Option 3: Conditional styling + +``` + +## Icon Styling + +### Theme-aware Icons +```jsx +// Better visibility in dark mode + + +// Muted but still visible + + +// Disabled state + +``` + +### CSS Variable Approach +```jsx +// Using CSS variables + + + +// Inline styles with CSS variables + +``` + +### Legacy JavaScript Function (Still Supported) +```jsx +// Existing approach - still works + +``` + +## Text Styling + +### Improved Gray Text +```jsx +// These automatically improve in dark mode +More visible in dark mode +Muted but readable +Clear text +``` + +## Complete Examples + +### Toolbar with Better Visibility +```jsx +const Toolbar = () => ( +
+ + + +
+); +``` + +### Form with Disabled States +```jsx +const Form = ({ isSubmitting }) => ( +
+ + +
+); +``` + +## React-Tour and Tooltip Dark Mode Support + +### React-Tour Modals +The react-tour modals now automatically support dark mode with VS Code-inspired styling: + +```jsx +// These components automatically get dark mode styling + +``` + +### ReactTooltip Components +All ReactTooltip instances now support dark mode: + +```jsx +// Automatically styled for dark mode + +
+

Tooltip content

+
+
+``` + +### HoverCard Balloon UI +The balloon tooltips in OpenSign Drive now properly support dark mode: + +```jsx +// These automatically get dark styling in dark mode + + + Document information + + +``` + +## Dark Mode Features Added + +### 1. **React-Tour Modal Styling** +- Background: `#1F2937` (VS Code modal background) +- Text: `#E5E7EB` (soft white for readability) +- Borders: `#374151` (subtle borders) +- Buttons: VS Code-style primary/secondary buttons + +### 2. **ReactTooltip Styling** +- Background: `#1F2937` with proper contrast +- Border: `#374151` for definition +- Box shadow: Enhanced for dark backgrounds +- Text: `#E5E7EB` for optimal readability + +### 3. **HoverCard Balloon UI** +- Background: `#1F2937` (matches VS Code) +- Text: `#E5E7EB` for readability +- Arrow: Automatically matches background color +- Enhanced shadows for dark backgrounds + +### 4. **React-Datepicker Support** +- Calendar background: `#1F2937` +- Selected dates: VS Code blue (`#007ACC`) +- Hover states: Proper contrast ratios +- Navigation arrows: Themed appropriately + +## CSS Classes Reference + +| Class | Purpose | Dark Mode Color | +|-------|---------|----------------| +| `icon-improved` | Better icon visibility | `#CCCCCC` | +| `icon-muted` | Muted but visible icons | `#999999` | +| `icon-disabled` | Disabled icon state | `#858585` | +| `op-btn-vscode-disabled` | VS Code disabled button | Background: `#3C3C3C` | +| `btn-themed-disabled` | Themed disabled button | Uses CSS variables | +| `icon-themed` | Variable-based icon color | `var(--icon-color)` | +| `.reactour__helper` | `#1F2937` background | +| `.react-tooltip` | `#1F2937` background | +| `.HoverCardContent` | `#1F2937` background | +| `.react-datepicker` | `#1F2937` background | + +## Migration Guide + +### From JavaScript Function to Tailwind +```jsx +// Before + + +// After + +``` + +### From Hardcoded Colors to Theme-aware +```jsx +// Before + + +// After (automatic improvement) + +// OR explicitly + +``` + +## Migration Notes + +All existing tooltip and tour components will automatically inherit the new dark mode styling when the theme is set to `opensigndark`. No code changes required for existing implementations. diff --git a/apps/OpenSign/examples/tailwind-usage-examples.js b/apps/OpenSign/examples/tailwind-usage-examples.js new file mode 100644 index 0000000000..97ac61ae64 --- /dev/null +++ b/apps/OpenSign/examples/tailwind-usage-examples.js @@ -0,0 +1,92 @@ +/** + * Tailwind Dark Mode Usage Examples for OpenSign + * + * This file demonstrates how to use the new Tailwind utilities + * for better dark mode visibility of buttons and icons. + */ + +// Example 1: VS Code-style disabled buttons +const DisabledButtonExamples = () => { + return ( +
+ {/* Option A: Using the VS Code disabled style */} + + + {/* Option B: Using themed disabled style */} + + + {/* Option C: Conditional styling */} + +
+ ); +}; + +// Example 2: Icon visibility improvements +const IconExamples = () => { + return ( +
+ {/* Theme-aware icons with better visibility */} + + + + + {/* Using CSS variables */} + + + + {/* Gray text that automatically improves in dark mode */} + + This text is now more visible in dark mode + + Muted but still readable +
+ ); +}; + +// Example 3: Using CSS variables in inline styles +const InlineStyleExamples = () => { + return ( +
+ {/* Using CSS variables directly */} + + + {/* Using the existing JavaScript function */} + +
+ ); +}; + +// Example 4: Toolbar with improved icons +const ToolbarExample = () => { + return ( +
+ + + +
+ ); +}; + +export { + DisabledButtonExamples, + IconExamples, + InlineStyleExamples, + ToolbarExample +}; diff --git a/apps/OpenSign/examples/tailwind-usage-examples.jsx b/apps/OpenSign/examples/tailwind-usage-examples.jsx new file mode 100644 index 0000000000..406a71985e --- /dev/null +++ b/apps/OpenSign/examples/tailwind-usage-examples.jsx @@ -0,0 +1,94 @@ +/** + * Tailwind Dark Mode Usage Examples for OpenSign + * + * This file demonstrates how to use the new Tailwind utilities + * for better dark mode visibility of buttons and icons. + */ + +// Example 1: VS Code-style disabled buttons +const DisabledButtonExamples = () => { + return ( +
+ {/* Option A: Using the VS Code disabled style */} + + + {/* Option B: Using themed disabled style */} + + + {/* Option C: Conditional styling */} + +
+ ); +}; + +// Example 2: Icon visibility improvements +const IconExamples = () => { + return ( +
+ {/* Theme-aware icons with better visibility */} + + + + + {/* Using CSS variables */} + + + + {/* Gray text that automatically improves in dark mode */} + This text is now more visible in dark mode + Muted but still readable +
+ ); +}; + +// Example 3: Using CSS variables in inline styles +const InlineStyleExamples = () => { + return ( +
+ {/* Using CSS variables directly */} + + + {/* Using the existing JavaScript function */} + +
+ ); +}; + +// Example 4: Toolbar with improved icons +const ToolbarExample = () => { + return ( +
+ + + +
+ ); +}; + +export { + DisabledButtonExamples, + IconExamples, + InlineStyleExamples, + ToolbarExample +}; diff --git a/apps/OpenSign/package-lock.json b/apps/OpenSign/package-lock.json index 0970efa566..3d4d02e6a0 100644 --- a/apps/OpenSign/package-lock.json +++ b/apps/OpenSign/package-lock.json @@ -28,6 +28,7 @@ "pkijs": "^3.0.8", "print-js": "^1.6.0", "prismjs": "^1.30.0", + "quill-html-edit-button": "^3.0.0", "radix-ui": "^1.4.2", "react": "^18.3.1", "react-bootstrap": "^2.10.10", @@ -5995,9 +5996,9 @@ } }, "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", @@ -12462,6 +12463,15 @@ "node": ">= 12.0.0" } }, + "node_modules/quill-html-edit-button": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/quill-html-edit-button/-/quill-html-edit-button-3.0.0.tgz", + "integrity": "sha512-ZUV3rYjEvXz+v/7f8N0Mkp2+0D8VGDj6yCYPfagSLmyshczeMawS7vZJzaJ18dJp35IfjiPnzqyVk3KCI8qN1w==", + "license": "MIT", + "peerDependencies": { + "quill": "^2.x" + } + }, "node_modules/radix-ui": { "version": "1.4.2", "resolved": "https://registry.npmjs.org/radix-ui/-/radix-ui-1.4.2.tgz", @@ -15976,9 +15986,9 @@ } }, "node_modules/sucrase/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", "dev": true, "license": "MIT", "dependencies": { diff --git a/apps/OpenSign/package.json b/apps/OpenSign/package.json index e85d12a20c..bfd9af1e0d 100644 --- a/apps/OpenSign/package.json +++ b/apps/OpenSign/package.json @@ -23,6 +23,7 @@ "pkijs": "^3.0.8", "print-js": "^1.6.0", "prismjs": "^1.30.0", + "quill-html-edit-button": "^3.0.0", "radix-ui": "^1.4.2", "react": "^18.3.1", "react-bootstrap": "^2.10.10", diff --git a/apps/OpenSign/public/locales/de/translation.json b/apps/OpenSign/public/locales/de/translation.json index 32b2b682b0..6b3b1b3875 100644 --- a/apps/OpenSign/public/locales/de/translation.json +++ b/apps/OpenSign/public/locales/de/translation.json @@ -5,6 +5,7 @@ "create-account": "Konto erstellen", "login": "Anmelden", "language": "Sprache", + "dark-mode": "Dunkelmodus", "name": "Name", "phone": "Telefon", "phone-optional": "optional", @@ -361,6 +362,7 @@ "date": "Datum", "text": "Text", "text input": "Texteingabe", + "cells": "Zellen", "checkbox": "Checkbox", "dropdown": "Dropdown", "radio button": "Radiobutton", @@ -415,10 +417,12 @@ "options": "Optionen", "minimun-check": "Minimale Anzahl", "maximum-check": "Maximale Anzahl", + "cell-count": "Zellzahl", "default-value": "Standardwert", "select": "Auswählen", - "read-only": "Nur lesen", + "read-only": "Ist schreibgeschützt", "hide-labels": "Labels ausblenden", + "layout": "Layout", "checkbox": "Checkbox", "alert": "Warnung", "zoom-in": "Vergrößern", @@ -750,6 +754,7 @@ "delete-page": "Seite löschen", "merge-pdf": "PDFs zusammenführen", "add-pages": "Seiten hinzufügen", + "reorder-pages": "Seiten neu anordnen", "delete-alert": "Einzelne Seite kann nicht gelöscht werden.", "delete-alert-2": "Sind Sie sicher, dass Sie diese Seite löschen möchten?", "delete-note": "Hinweis: Sobald Sie diese Seite löschen, kann dies nicht rückgängig gemacht werden.", @@ -982,6 +987,7 @@ "review": "Überprüfen", "next-field": "Nächstes Feld", "required-mssg": "{{leftRequiredWidget}} von {{totalWidget}} Feldern übrig", + "verify-document": "Dokument verifizieren", "verify-document-signature": "Dokumentensignatur überprüfen", "select-pdf-document": "PDF-Dokument auswählen", "selected-file": "Ausgewählte Datei", @@ -1023,7 +1029,9 @@ "could-not-parse-signer-info": "Signaturinformationen konnten nicht analysiert werden", "not-calculated": "Nicht berechnet", "not-found-in-signature": "Nicht in Signatur gefunden", - "readonly-textinput-error": "Schreibgeschütztes Text-Widget muss einen Standardwert haben oder optional sein.", - "readonly-dropdown-error": "Schreibgeschütztes Dropdown-Widget muss einen Standardwert haben oder optional sein.", - "readonly-radiobtn-error": "Schreibgeschütztes Optionsfeld-Widget muss einen Standardwert haben oder optional sein." + "readonly-error": "Das schreibgeschützte {{widgetName}}-Widget muss einen Standardwert haben oder kann optional gemacht werden.", + "choose-one":"Wählen Sie eine aus", + "search-templates": "Vorlagen durchsuchen…", + "search-documents": "Dokumente suchen…", + "search-contacts": "Kontakte durchsuchen…" } diff --git a/apps/OpenSign/public/locales/en/translation.json b/apps/OpenSign/public/locales/en/translation.json index 39d3774054..6bc3784150 100644 --- a/apps/OpenSign/public/locales/en/translation.json +++ b/apps/OpenSign/public/locales/en/translation.json @@ -5,6 +5,7 @@ "create-account": "Create account", "login": "Login", "language": "Language", + "dark-mode": "Dark mode", "name": "Name", "phone": "Phone", "phone-optional": "optional", @@ -199,7 +200,7 @@ }, "file-type": "pdf, png, jpg, jpeg", "docx": "docx", - "file-selected": "file selected", + "file-selected": "file(s) selected", "template-title": "Template title", "document-title": "Document title", "description": "Description", @@ -361,6 +362,7 @@ "date": "date", "text": "text", "text input": "text input", + "cells": "cells", "checkbox": "checkbox", "dropdown": "dropdown", "radio button": "radio button", @@ -415,10 +417,12 @@ "options": "Options", "minimun-check": "Minimun check", "maximum-check": "Maximum check", + "cell-count": "Cell count", "default-value": "Default value", "select": "Select", - "read-only": "Is read only", + "read-only": "read only", "hide-labels": "Hide labels", + "layout": "Layout", "checkbox": "Checkbox", "alert": "Alert", "zoom-in": "Zoom in", @@ -526,7 +530,7 @@ "new-password": "New password", "confirm-password": "Confirm password", "file-alert-1": "The selected file size is too large. Please select a file less than", - "file-alert-2": "Please select file.", + "file-alert-2": "Please select file(s).", "file-alert-3": "Please wait while the document is being uploaded.", "enter-pdf-password": "Enter Pdf password", "correct-password": "Please provide correct password", @@ -750,6 +754,7 @@ "delete-page": "Delete page", "merge-pdf": "Merge pdf", "add-pages": "Add pages", + "reorder-pages": "Reorder pages", "delete-alert": "Can not delete single page", "delete-alert-2": "Are you sure you want to delete this page?", "delete-note": "Note: Once you delete this page, you cannot undo.", @@ -885,7 +890,7 @@ "you-will-receive-email-shortly": "✅ That's it! You'll receive a confirmation email shortly.", "please-provide-templateid": "Please provide templateid", "this-template-is-not-public": "This template is not public", - "invalid-templateid": "Invaldi templateid", + "invalid-templateid": "Invalid templateid", "contact-billing-at-opensign": "To add more seats, please contact OpenSign™ at <1>billing@opensignlabs.com for assistance", "title-length-alert": "Title must be at most 250 characters long.", "note-length-alert": "Note must be at most 200 characters long.", @@ -982,6 +987,7 @@ "review":"Review", "next-field":"Next Field", "required-mssg":"{{leftRequiredWidget}} of {{totalWidget}} fields left", + "verify-document": "Verify document", "verify-document-signature": "Verify Document Signature", "select-pdf-document": "Select PDF Document", "selected-file": "Selected file", @@ -1023,7 +1029,9 @@ "could-not-parse-signer-info": "Could not parse signer info", "not-calculated": "Not calculated", "not-found-in-signature": "Not found in signature", - "readonly-textinput-error": "Read-only text widget must have a default value or you can make it optional.", - "readonly-dropdown-error": "Read-only dropdown widget must have a default value or you can make it optional.", - "readonly-radiobtn-error": "Read-only radio button widget must have a default value or you can make it optional." + "readonly-error": "Read-only {{widgetName}} widget must have a default value or you can make it optional.", + "choose-one":"Choose One", + "search-templates": "Search templates…", + "search-documents": "Search documents…", + "search-contacts": "Search contacts…" } \ No newline at end of file diff --git a/apps/OpenSign/public/locales/es/translation.json b/apps/OpenSign/public/locales/es/translation.json index 551e3104d4..f4825aab35 100644 --- a/apps/OpenSign/public/locales/es/translation.json +++ b/apps/OpenSign/public/locales/es/translation.json @@ -5,6 +5,7 @@ "create-account": "Crear cuenta", "login": "Iniciar sesión", "language": "Idioma", + "dark-mode": "Modo oscuro", "name": "Nombre", "phone": "Teléfono", "phone-optional": "opcional", @@ -362,6 +363,7 @@ "date": "fecha", "text": "texto", "text input": "entrada de texto", + "cells": "células", "checkbox": "casilla", "dropdown": "desplegable", "radio button": "botón de radio", @@ -416,10 +418,12 @@ "options": "Opciones", "minimun-check": "Chequeo mínimo", "maximum-check": "Chequeo máximo", + "cell-count": "recuento de células", "default-value": "Valor por defecto", "select": "Seleccionar", "read-only": "Es de solo lectura", "hide-labels": "Esconder etiquetas", + "layout": "Diseño", "checkbox": "Casilla", "alert": "Alerta", "zoom-in": "Acercar", @@ -750,6 +754,7 @@ "delete-page": "eliminar página", "merge-pdf": "fusionar pdf", "add-pages": "Agregar páginas", + "reorder-pages": "Reordenar páginas", "delete-alert": "No se puede eliminar una sola página", "delete-alert-2": "¿Está seguro de que desea eliminar esta página?", "delete-note": "Nota: una vez que elimines esta página, no podrás deshacerla", @@ -982,6 +987,7 @@ "review": "Revisar", "next-field": "Siguiente campo", "required-mssg": "{{leftRequiredWidget}} de {{totalWidget}} campos restantes", + "verify-document": "Verificar documento", "verify-document-signature": "Verificar firma del documento", "select-pdf-document": "Seleccionar documento PDF", "selected-file": "Archivo seleccionado", @@ -1023,7 +1029,9 @@ "could-not-parse-signer-info": "No se pudo analizar la información del firmante", "not-calculated": "No calculado", "not-found-in-signature": "No encontrado en la firma", - "readonly-textinput-error": "El widget de texto de solo lectura debe tener un valor predeterminado o puede hacerse opcional.", - "readonly-dropdown-error": "El widget desplegable de solo lectura debe tener un valor predeterminado o puede hacerse opcional.", - "readonly-radiobtn-error": "El widget de botón de opción de solo lectura debe tener un valor predeterminado o puede hacerse opcional." + "readonly-error": "El widget de solo lectura {{widgetName}} debe tener un valor predeterminado o puede hacerlo opcional.", + "choose-one":"Elige uno", + "search-templates": "Buscar plantillas…", + "search-documents": "Buscar documentos…", + "search-contacts": "Buscar contactos…" } diff --git a/apps/OpenSign/public/locales/fr/translation.json b/apps/OpenSign/public/locales/fr/translation.json index b2d558179c..3880369a6b 100644 --- a/apps/OpenSign/public/locales/fr/translation.json +++ b/apps/OpenSign/public/locales/fr/translation.json @@ -5,6 +5,7 @@ "create-account": "Créer un compte", "login": "Se Connecter", "language": "Langue", + "dark-mode": "Mode sombre", "name": "Nom et Prénom", "phone": "Téléphone", "phone-optional": "(facultatif)", @@ -361,6 +362,7 @@ "date": "date", "text": "texte", "text input": "saisie de texte", + "cells": "cellules", "checkbox": "case à cocher", "dropdown": "dérouler", "radio button": "bouton radio", @@ -415,10 +417,12 @@ "options": "Possibilités", "minimun-check": "Vérification minimale", "maximum-check": "Contrôle maximum", + "cell-count": "numération cellulaire", "default-value": "Valeur par défaut", "select": "Sélectionner", "read-only": "Est en lecture seule", "hide-labels": "Masquer les étiquettes", + "layout": "Disposition", "checkbox": "Case à cocher", "alert": "Alerte", "zoom-in": "Agrandir", @@ -750,6 +754,7 @@ "delete-page": "supprimer la page", "merge-pdf": "Fusionner le pdf", "add-pages": "Ajouter des pages", + "reorder-pages": "Réorganiser les pages", "delete-alert": "Impossible de supprimer une seule page", "delete-alert-2": "Etes-vous sûr de vouloir supprimer cette page ?", "delete-note": "Remarque : une fois cette page supprimée, vous ne pouvez plus l'annuler", @@ -982,6 +987,7 @@ "review": "Revoir", "next-field": "Champ suivant", "required-mssg":"{{leftRequiredWidget}} champs sur {{totalWidget}} restants", + "verify-document": "Vérifier le document", "verify-document-signature": "Vérifier la signature du document", "select-pdf-document": "Sélectionner le document PDF", "selected-file": "Fichier sélectionné", @@ -1023,7 +1029,9 @@ "could-not-parse-signer-info": "Impossible d'analyser les informations sur le signataire", "not-calculated": "Non calculé", "not-found-in-signature": "Introuvable dans la signature", - "readonly-textinput-error": "Le widget de texte en lecture seule doit avoir une valeur par défaut ou être rendu optionnel.", - "readonly-dropdown-error": "Le widget déroulant en lecture seule doit avoir une valeur par défaut ou être rendu optionnel.", - "readonly-radiobtn-error": "Le widget bouton radio en lecture seule doit avoir une valeur par défaut ou être rendu optionnel." + "readonly-error": "Le widget en lecture seule {{widgetName}} doit avoir une valeur par défaut ou vous pouvez le rendre facultatif.", + "choose-one":"Choisissez-en un", + "search-templates": "Rechercher des modèles…", + "search-documents": "Rechercher des documents…", + "search-contacts": "Rechercher des contacts…" } diff --git a/apps/OpenSign/public/locales/hi/translation.json b/apps/OpenSign/public/locales/hi/translation.json index aefb718d3e..cd399fbf48 100644 --- a/apps/OpenSign/public/locales/hi/translation.json +++ b/apps/OpenSign/public/locales/hi/translation.json @@ -5,6 +5,7 @@ "create-account": "खाता बनाएं", "login": "लॉग इन करें", "language": "भाषा", + "dark-mode": "डार्क मोड", "name": "नाम", "phone": "फ़ोन", "phone-optional": "वैकल्पिक", @@ -361,6 +362,7 @@ "date": "दिनांक", "text": "पाठ", "text input": "पाठ इनपुट", + "cells": "सेल्स", "checkbox": "चेकबॉक्स", "dropdown": "ड्रॉपडाउन", "radio button": "रेडियो बटन", @@ -415,10 +417,12 @@ "options": "विकल्प", "minimun-check": "न्यूनतम जाँच", "maximum-check": "अधिकतम जाँच", + "cell-count": "सेल्स संख्या", "default-value": "डिफ़ॉल्ट मान", "select": "चुनें", - "read-only": "केवल पढ़ने के लिए है", + "read-only": "सिर्फ पढ़ने के लिए है", "hide-labels": "लेबल छिपाएँ", + "layout": "लेआउट", "checkbox": "चेकबॉक्स", "alert": "चेतावनी", "zoom-in": "ज़ूम इन करें", @@ -750,6 +754,7 @@ "delete-page": "पृष्ठ हटाएं", "merge-pdf": "पीडीएफ मर्ज करें", "add-pages": "पृष्ठ जोड़ें", + "reorder-pages": "पृष्ठ पुनः व्यवस्थित करें", "delete-alert": "एकल पृष्ठ नहीं हटाया जा सकता", "delete-alert-2": "क्या आप वाकई इस पृष्ठ को हटाना चाहते हैं?", "delete-note": "ध्यान दें: एक बार जब आप इस पृष्ठ को हटा देते हैं, तो आप इसे पूर्ववत नहीं कर सकते।", @@ -982,6 +987,7 @@ "review": "समीक्षा", "next-field": "अगला फ़ील्ड", "required-mssg": "{{totalWidget}} में से {{leftRequiredWidget}} फ़ील्ड शेष हैं", + "verify-document": "दस्तावेज़ सत्यापित करें", "verify-document-signature": "दस्तावेज़ हस्ताक्षर सत्यापित करें", "select-pdf-document": "पीडीएफ दस्तावेज़ चुनें", "selected-file": "चयनित फ़ाइल", @@ -1023,7 +1029,9 @@ "could-not-parse-signer-info": "हस्ताक्षरकर्ता जानकारी पार्स नहीं की जा सकी", "not-calculated": "गणना नहीं की गई", "not-found-in-signature": "हस्ताक्षर में नहीं मिला", - "readonly-textinput-error": "रीड-ओनली टेक्स्ट विजेट में एक डिफ़ॉल्ट मान होना चाहिए या आप इसे वैकल्पिक बना सकते हैं।", - "readonly-dropdown-error": "रीड-ओनली ड्रॉपडाउन विजेट में एक डिफ़ॉल्ट मान होना चाहिए या आप इसे वैकल्पिक बना सकते हैं।", - "readonly-radiobtn-error": "रीड-ओनली रेडियो बटन विजेट में एक डिफ़ॉल्ट मान होना चाहिए या आप इसे वैकल्पिक बना सकते हैं।" + "readonly-error": "रीड-ओनली {{widgetName}} विजेट में एक डिफ़ॉल्ट मान होना चाहिए या आप इसे वैकल्पिक बना सकते हैं।", + "choose-one":"एक का चयन", + "search-templates": "टेम्पलेट खोजें…", + "search-documents": "दस्तावेज़ खोजें…", + "search-contacts": "संपर्क खोजें…" } diff --git a/apps/OpenSign/public/locales/it/translation.json b/apps/OpenSign/public/locales/it/translation.json index b164e80fee..f2b52e6676 100644 --- a/apps/OpenSign/public/locales/it/translation.json +++ b/apps/OpenSign/public/locales/it/translation.json @@ -5,6 +5,7 @@ "create-account": "Crea Account", "login": "Accedi", "language": "Lingua", + "dark-mode": "Modalità scura", "name": "Nome", "phone": "Telefono", "phone-optional": "facoltativo", @@ -361,6 +362,7 @@ "date": "data", "text": "testo", "text input": "campo di testo", + "cells": "cellule", "checkbox": "casella di controllo", "dropdown": "menu a tendina", "radio button": "pulsante di opzione", @@ -415,10 +417,12 @@ "options": "Opzioni", "minimun-check": "Controllo minimo", "maximum-check": "Controllo massimo", + "cell-count": "conteggio delle cellule", "default-value": "Valore predefinita", "select": "Seleziona", - "read-only": "È solo lettura", + "read-only": "È di sola lettura", "hide-labels": "Nascondi etichette", + "layout": "Layout", "checkbox": "Casella di controllo", "alert": "Avviso", "zoom-in": "Ingrandisci", @@ -750,6 +754,7 @@ "delete-page": "Elimina pagina", "merge-pdf": "Unisci PDF", "add-pages": "Aggiungi pagine", + "reorder-pages": "Riordina pagine", "delete-alert": "Non è possibile eliminare una singola pagina", "delete-alert-2": "Sei sicuro di voler eliminare questa pagina?", "delete-note": "Nota: Una volta eliminata questa pagina, non potrai annullare l'operazione.", @@ -982,6 +987,7 @@ "review": "Rivedere", "next-field": "Campo successivo", "required-mssg":"{{leftRequiredWidget}} di {{totalWidget}} campi rimanenti", + "verify-document": "Verifica documento", "verify-document-signature": "Verifica firma documento", "select-pdf-document": "Seleziona documento PDF", "selected-file": "File selezionato", @@ -1023,7 +1029,9 @@ "could-not-parse-signer-info": "Impossibile analizzare le informazioni del firmatario", "not-calculated": "Non calcolato", "not-found-in-signature": "Non trovato nella firma", - "readonly-textinput-error": "Il widget di testo di sola lettura deve avere un valore predefinito oppure può essere reso opzionale.", - "readonly-dropdown-error": "Il widget a discesa di sola lettura deve avere un valore predefinito oppure può essere reso opzionale.", - "readonly-radiobtn-error": "Il widget pulsante di opzione di sola lettura deve avere un valore predefinito oppure può essere reso opzionale." + "readonly-error": "Il widget {{widgetName}} di sola lettura deve avere un valore predefinito oppure può essere reso facoltativo.", + "choose-one":"Scegline uno", + "search-templates": "Cerca modelli…", + "search-documents": "Cerca documenti…", + "search-contacts": "Cerca contatti…" } diff --git a/apps/OpenSign/public/static/js/assets/images/logo-dark.png b/apps/OpenSign/public/static/js/assets/images/logo-dark.png new file mode 100644 index 0000000000..33a512e4c2 Binary files /dev/null and b/apps/OpenSign/public/static/js/assets/images/logo-dark.png differ diff --git a/apps/OpenSign/src/App.jsx b/apps/OpenSign/src/App.jsx index 5a69c1da8b..342964fde2 100644 --- a/apps/OpenSign/src/App.jsx +++ b/apps/OpenSign/src/App.jsx @@ -142,7 +142,7 @@ function App() { /> {/* signyouself route with no rowlevel data using docId from url */} } /> - {/* draft document route to handle and navigate route page accordiing to document status */} + {/* draft document route to handle and navigate route page according to document status */} } /> {/* recipient placeholder set route with no rowlevel data using docId from url*/} { // eslint-disable-next-line react-hooks/exhaustive-deps }, []); - //function to check atleast one signature field exist + //function to check at least one signature field exist const signatureExist = async () => { setIsDisableBulkSend(false); const getPlaceholder = props?.Placeholders; diff --git a/apps/OpenSign/src/components/Header.jsx b/apps/OpenSign/src/components/Header.jsx index 595b9c8550..7fee264bea 100644 --- a/apps/OpenSign/src/components/Header.jsx +++ b/apps/OpenSign/src/components/Header.jsx @@ -1,6 +1,7 @@ import { useState, useEffect } from "react"; import dp from "../assets/images/dp.png"; import FullScreenButton from "./FullScreenButton"; +import ThemeToggle from "./ThemeToggle"; import { useNavigate } from "react-router"; import Parse from "parse"; import { useWindowSize } from "../hook/useWindowSize"; @@ -85,6 +86,34 @@ const Header = ({ showSidebar, setIsMenu, isConsole }) => { }; }, [isOpen]); + + useEffect(() => { + const updateLogoForTheme = () => { + const isDarkMode = + document.documentElement.getAttribute("data-theme") === "opensigndark"; + const logo = isDarkMode + ? "/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); + } + }; + + // Set the logo immediately based on the current theme + updateLogoForTheme(); + + const observer = new MutationObserver(() => { + updateLogoForTheme(); + }); + + observer.observe(document.documentElement, { + attributes: true, + attributeFilter: ["data-theme"] + }); + + return () => observer.disconnect(); + }, [applogo]); + return (
@@ -147,7 +176,7 @@ const Header = ({ showSidebar, setIsMenu, isConsole }) => {
    @@ -194,6 +223,16 @@ const Header = ({ showSidebar, setIsMenu, isConsole }) => { {t("verify-document")} +
  • + + + {t("dark-mode")} + + BETA + + + +
  • )}
  • diff --git a/apps/OpenSign/src/components/ThemeToggle.jsx b/apps/OpenSign/src/components/ThemeToggle.jsx new file mode 100644 index 0000000000..4cb7207bcc --- /dev/null +++ b/apps/OpenSign/src/components/ThemeToggle.jsx @@ -0,0 +1,41 @@ +import { useEffect, useState } from "react"; + +const ThemeToggle = () => { + const [isDark, setIsDark] = useState(false); + + useEffect(() => { + const storedTheme = localStorage.getItem("theme"); + if (storedTheme === "dark") { + setIsDark(true); + document.documentElement.setAttribute("data-theme", "opensigndark"); + } else { + document.documentElement.setAttribute("data-theme", "opensigncss"); + } + }, []); + + const handleChange = () => { + const newTheme = !isDark; + setIsDark(newTheme); + if (newTheme) { + document.documentElement.setAttribute("data-theme", "opensigndark"); + localStorage.setItem("theme", "dark"); + } else { + document.documentElement.setAttribute("data-theme", "opensigncss"); + localStorage.setItem("theme", "light"); + } + }; + + return ( + <> + + + ); +}; + +export default ThemeToggle; diff --git a/apps/OpenSign/src/components/dashboard/DashboardButton.jsx b/apps/OpenSign/src/components/dashboard/DashboardButton.jsx index e1c7e3f8c4..b19cbe8f6e 100644 --- a/apps/OpenSign/src/components/dashboard/DashboardButton.jsx +++ b/apps/OpenSign/src/components/dashboard/DashboardButton.jsx @@ -29,7 +29,7 @@ const DashboardButton = (props) => { : "cursor-default" } w-full shadow-md px-3 py-2 op-card bg-base-100`} > -
    +
    { >
    -
    +
    {t(`sidebar.${props.Label}`)} {props.Label === "Sign yourself" && (
    diff --git a/apps/OpenSign/src/components/dashboard/DashboardReport.jsx b/apps/OpenSign/src/components/dashboard/DashboardReport.jsx index b6706ebb51..25f6f0263d 100644 --- a/apps/OpenSign/src/components/dashboard/DashboardReport.jsx +++ b/apps/OpenSign/src/components/dashboard/DashboardReport.jsx @@ -1,4 +1,4 @@ -import React, { useEffect, useState } from "react"; +import React, { useEffect, useState, useRef } from "react"; import Parse from "parse"; import ReportTable from "../../primitives/GetReportDisplay"; import reportJson from "../../json/ReportJson"; @@ -17,10 +17,16 @@ function DashboardReport(props) { const [isMoreDocs, setIsMoreDocs] = useState(true); const abortController = new AbortController(); const docPerPage = 5; + const [searchTerm, setSearchTerm] = useState(""); + const [mobileSearchOpen, setMobileSearchOpen] = useState(false); + const [isSearchResult, setIsSearchResult] = useState(false); + const debounceTimer = useRef(null); useEffect(() => { setReportName(""); - getReportData(props.Record.reportId); + setSearchTerm(""); + setMobileSearchOpen(false); + getReportData(props.Record.reportId, 0, 20, ""); // Function returned from useEffect is called on unmount return () => { @@ -36,12 +42,69 @@ function DashboardReport(props) { // below useEffect call when isNextRecord state is true and fetch next record useEffect(() => { if (isNextRecord) { - getReportData(props.Record.reportId, List.length, 20); + getReportData(props.Record.reportId, List.length, 20, searchTerm); } // eslint-disable-next-line }, [isNextRecord]); - const getReportData = async (id, skipUserRecord = 0, limit = 20) => { + const handleSearchChange = async (e) => { + const term = e.target.value.toLowerCase(); + setSearchTerm(term); + if (debounceTimer.current) { + clearTimeout(debounceTimer.current); + } + debounceTimer.current = setTimeout(async () => { + try { + const headers = { + "Content-Type": "application/json", + "X-Parse-Application-Id": localStorage.getItem("parseAppId"), + sessiontoken: localStorage.getItem("accesstoken") + }; + const url = `${localStorage.getItem("baseUrl")}functions/getReport`; + const res = await axios.post( + url, + { + reportId: props.Record.reportId, + searchTerm: term, + skip: 0, + limit: docPerPage + }, + { headers } + ); + const data = res.data?.result || []; + if (!data.error) { + setList(data); + setIsMoreDocs(data.length >= docPerPage); + setIsNextRecord(false); + setIsSearchResult(true); + } + } catch (err) { + console.error("Search error:", err); + } + }, 300); + setIsSearchResult(false); + }; + + const handleSearchPaste = (e) => { + setTimeout(() => { + handleSearchChange({ target: { value: e.target.value } }); + }, 0); + }; + + useEffect(() => { + return () => { + if (debounceTimer.current) { + clearTimeout(debounceTimer.current); + } + }; + }, []); + + const getReportData = async ( + id, + skipUserRecord = 0, + limit = 20, + term = searchTerm + ) => { setIsLoader(true); const json = reportJson(id); if (json) { @@ -59,6 +122,9 @@ function DashboardReport(props) { const skipRecord = id === "5Go51Q7T8r" ? 0 : skipUserRecord; const limitRecord = id === "5Go51Q7T8r" ? 200 : limit; const params = { reportId: id, skip: skipRecord, limit: limitRecord }; + if (term) { + params.searchTerm = term; + } const url = `${localStorage.getItem("baseUrl")}functions/getReport`; const res = await axios.post(url, params, { headers: headers, @@ -141,11 +207,17 @@ function DashboardReport(props) { setIsNextRecord={setIsNextRecord} isMoreDocs={isMoreDocs} docPerPage={docPerPage} + mobileSearchOpen={mobileSearchOpen} + setMobileSearchOpen={setMobileSearchOpen} + searchTerm={searchTerm} + handleSearchChange={handleSearchChange} + handleSearchPaste={handleSearchPaste} + isSearchResult={isSearchResult} /> ) : (
    -

    {t("report-not-found")}

    +

    {t("report-not-found")}

    )} diff --git a/apps/OpenSign/src/components/pdf/AddRoleModal.jsx b/apps/OpenSign/src/components/pdf/AddRoleModal.jsx index 6696306dd7..f052a74a39 100644 --- a/apps/OpenSign/src/components/pdf/AddRoleModal.jsx +++ b/apps/OpenSign/src/components/pdf/AddRoleModal.jsx @@ -10,7 +10,7 @@ const AddRoleModal = (props) => { isOpen={props.isModalRole} handleClose={props.handleCloseRoleModal} > -
    +
    -
    +
    {t("agree-p1")}
    -
    +
    {t("agreement-note")}
    diff --git a/apps/OpenSign/src/components/pdf/BorderResize.jsx b/apps/OpenSign/src/components/pdf/BorderResize.jsx index ca40eba721..0315100141 100644 --- a/apps/OpenSign/src/components/pdf/BorderResize.jsx +++ b/apps/OpenSign/src/components/pdf/BorderResize.jsx @@ -12,12 +12,9 @@ function BorderResize(props) { return (
    ); diff --git a/apps/OpenSign/src/components/pdf/CellsSettingModal.jsx b/apps/OpenSign/src/components/pdf/CellsSettingModal.jsx new file mode 100644 index 0000000000..50a3e59b56 --- /dev/null +++ b/apps/OpenSign/src/components/pdf/CellsSettingModal.jsx @@ -0,0 +1,104 @@ +import React, { useState, useEffect } from "react"; +import ModalUi from "../../primitives/ModalUi"; +import { fontsizeArr, fontColorArr } from "../../constant/Utils"; +import { useTranslation } from "react-i18next"; + +export default function CellsSettingModal({ + isOpen, + handleClose, + defaultData, + handleSave +}) { + const { t } = useTranslation(); + const [name, setName] = useState(""); + const [cellCount, setCellCount] = useState(5); + const [fontSize, setFontSize] = useState(12); + const [fontColor, setFontColor] = useState("black"); + + useEffect(() => { + if (defaultData) { + setName(defaultData.options?.name || "Cells"); + setCellCount(defaultData.options?.cellCount || 5); + setFontSize(defaultData.options?.fontSize || 12); + setFontColor(defaultData.options?.fontColor || "black"); + } + }, [defaultData]); + + const onSubmit = (e) => { + e.preventDefault(); + handleSave && + handleSave({ + name, + cellCount: parseInt(cellCount, 10), + fontSize, + fontColor + }); + }; + + return ( + + +
    + + setName(e.target.value)} + /> +
    +
    + + setCellCount(e.target.value)} + /> +
    +
    +
    + {t("font-size")}: + +
    +
    + {t("color")}: + + +
    +
    +
    + + +
    + ); +} diff --git a/apps/OpenSign/src/components/pdf/CellsWidget.jsx b/apps/OpenSign/src/components/pdf/CellsWidget.jsx new file mode 100644 index 0000000000..8a94dd687d --- /dev/null +++ b/apps/OpenSign/src/components/pdf/CellsWidget.jsx @@ -0,0 +1,143 @@ +import { useState, useEffect, useRef } from "react"; + +const Cell = ({ + isEnabled, + count, + h, + value, + editable, + onChange, + onKeyDown, + onBlur, + inputRef, + index, + fontSize, + fontColor, + hint +}) => ( +
    + onChange && onChange(e, index) : undefined} + onKeyDown={editable ? (e) => onKeyDown && onKeyDown(e, index) : undefined} + // trigger validation when leaving a cell + onBlur={editable ? (e) => onBlur && onBlur(e, index) : undefined} + className={`${isEnabled ? "placeholder-gray-300" : "placeholder-gray-500"} w-full text-center focus:outline-none bg-transparent`} + placeholder={hint} + style={{ fontFamily: "Arial, sans-serif", fontSize, color: fontColor }} + /> +
    +); + +export default function CellsWidget({ + isEnabled, + count = 8, + height = 40, + value = "", + editable = false, + onChange, + onKeyDown, + onBlur, + onCellCountChange, + inputRefs, + resizable = false, + fontSize = "12px", + fontColor = "black", + hint = "" +}) { + const [cellCount, setCellCount] = useState(count); + + // keep internal state in sync with prop updates + useEffect(() => setCellCount(count), [count]); + + const startX = useRef(0); + const startCount = useRef(cellCount); + + const capture = (downEv, onMove, onUp = () => {}) => { + const id = downEv.pointerId; + const move = (ev) => id === ev.pointerId && onMove(ev); + const up = (ev) => { + if (id !== ev.pointerId) return; + onUp(ev); + downEv.target.releasePointerCapture(id); + window.removeEventListener("pointermove", move); + window.removeEventListener("pointerup", up); + }; + window.addEventListener("pointermove", move); + window.addEventListener("pointerup", up); + downEv.target.setPointerCapture(id); + }; + + const onTopHandlePointerDown = (ev) => { + // Prevent triggering the widget drag logic + ev.stopPropagation(); + ev.preventDefault(); + startX.current = ev.clientX; + startCount.current = cellCount; + capture(ev, (moveEv) => { + const dx = moveEv.clientX - startX.current; + const delta = Math.floor(-dx / 5); + let newCount = Math.max(1, startCount.current + delta); + if (newCount !== cellCount) { + setCellCount(newCount); + onCellCountChange?.(newCount); + } + }); + }; + + const cells = Array.from({ length: cellCount }).map((_, i) => value[i] || ""); + const hints = Array.from({ length: cellCount }).map((_, i) => hint[i] || ""); + + return ( +
    + {resizable && ( +
    + +
    + )} + {cells.map((val, i) => ( + (inputRefs.current[i] = el) : undefined} + index={i} + fontSize={fontSize} + fontColor={fontColor} + hint={hints[i]} + /> + ))} +
    + ); +} diff --git a/apps/OpenSign/src/components/pdf/DropdownWidgetOption.jsx b/apps/OpenSign/src/components/pdf/DropdownWidgetOption.jsx index 7a7800f303..75837a3828 100644 --- a/apps/OpenSign/src/components/pdf/DropdownWidgetOption.jsx +++ b/apps/OpenSign/src/components/pdf/DropdownWidgetOption.jsx @@ -7,8 +7,8 @@ import { fontColorArr, fontsizeArr } from "../../constant/Utils"; function DropdownWidgetOption(props) { const { t } = useTranslation(); const [dropdownOptionList, setDropdownOptionList] = useState([ - "option-1", - "option-2" + "Option-1", + "Option-2" ]); const [minCount, setMinCount] = useState(0); const [maxCount, setMaxCount] = useState(0); @@ -17,11 +17,13 @@ function DropdownWidgetOption(props) { const [isHideLabel, setIsHideLabel] = useState(false); const [status, setStatus] = useState("required"); const [defaultValue, setDefaultValue] = useState(""); - const statusArr = ["required", "optional"]; const [defaultCheckbox, setDefaultCheckbox] = useState([]); + const [layout, setLayout] = useState("vertical"); + const statusArr = ["required", "optional"]; + const layoutArr = ["vertical", "horizontal"]; const resetState = () => { - setDropdownOptionList(["option-1", "option-2"]); + setDropdownOptionList(["Option-1", "Option-2"]); setDropdownName(props.currWidgetsDetails?.options?.name || props.type); setIsReadOnly(false); setIsHideLabel(false); @@ -29,6 +31,7 @@ function DropdownWidgetOption(props) { setMaxCount(0); setDefaultCheckbox([]); setDefaultValue(""); + setLayout("vertical"); }; useEffect(() => { if ( @@ -48,6 +51,7 @@ function DropdownWidgetOption(props) { setStatus(props.currWidgetsDetails?.options?.status || "required"); setDefaultValue(props.currWidgetsDetails?.options?.defaultValue || ""); setDefaultCheckbox(props.currWidgetsDetails?.options?.defaultValue || []); + setLayout(props.currWidgetsDetails?.options?.layout || "vertical"); } else { setStatus("required"); resetState(); @@ -107,14 +111,22 @@ function DropdownWidgetOption(props) { props?.type === "dropdown" || props?.type === radioButtonWidget; const readOnlyWithoutValue = isReadOnly && !defaultValue && status !== "optional"; + const isCheckbox = props?.type === "checkbox"; + const WidgetLayout = ["checkbox", radioButtonWidget].includes(props.type) + ? layout + : null; // If it’s a dropdown and it’s read-only without a value (nor marked optional), stop here. if (isDropdownOrRadio && readOnlyWithoutValue) { - alert( - props?.type === "dropdown" - ? t("readonly-dropdown-error") - : t("readonly-radiobtn-error") - ); + alert(t("readonly-error", { widgetName: props?.type })); + return; + } else if ( + isCheckbox && + isReadOnly && + minCount > 0 && + defaultCheckbox?.length === 0 + ) { + alert(t("readonly-error", { widgetName: props?.type })); return; } @@ -129,7 +141,8 @@ function DropdownWidgetOption(props) { null, status, defaultData, - isHideLabel + isHideLabel, + WidgetLayout ); resetState(); }; @@ -153,17 +166,18 @@ function DropdownWidgetOption(props) { }} >
    -
    + + ); +} diff --git a/apps/OpenSign/src/components/pdf/PdfHeader.jsx b/apps/OpenSign/src/components/pdf/PdfHeader.jsx index db801803cf..32569674f7 100644 --- a/apps/OpenSign/src/components/pdf/PdfHeader.jsx +++ b/apps/OpenSign/src/components/pdf/PdfHeader.jsx @@ -2,16 +2,21 @@ import React, { useRef, useState } from "react"; import PrevNext from "./PrevNext"; import { base64ToArrayBuffer, + decryptPdf, deletePdfPage, + flattenPdf, + getFileAsArrayBuffer, handleDownloadCertificate, handleDownloadPdf, handleRemoveWidgets, - handleToPrint + handleToPrint, + reorderPdfPages } from "../../constant/Utils"; import "../../styles/signature.css"; import { DropdownMenu } from "radix-ui"; import ModalUi from "../../primitives/ModalUi"; import Loader from "../../primitives/Loader"; +import PageReorderModal from "./PageReorderModal"; import { useTranslation } from "react-i18next"; import { PDFDocument } from "pdf-lib"; import { maxFileSize } from "../../constant/const"; @@ -24,6 +29,7 @@ function Header(props) { const isMobile = window.innerWidth < 767; const [isDownloading, setIsDownloading] = useState(""); const [isDeletePage, setIsDeletePage] = useState(false); + const [isReorderModal, setIsReorderModal] = useState(false); const mergePdfInputRef = useRef(null); const enabledBackBtn = props?.disabledBackBtn === true ? false : true; //function for show decline alert @@ -80,7 +86,42 @@ function Header(props) { return; } try { - const uploadedPdfBytes = await file.arrayBuffer(); + let uploadedPdfBytes = await file.arrayBuffer(); + try { + uploadedPdfBytes = await flattenPdf(uploadedPdfBytes); + } catch (err) { + if (err?.message?.includes("is encrypted")) { + try { + const pdfFile = await decryptPdf(file, ""); + const pdfArrayBuffer = await getFileAsArrayBuffer(pdfFile); + uploadedPdfBytes = await flattenPdf(pdfArrayBuffer); + } catch (err) { + if (err?.response?.status === 401) { + const password = prompt( + `PDF "${file.name}" is password-protected. Enter password:` + ); + if (password) { + try { + const pdfFile = await decryptPdf(file, password); + const pdfArrayBuffer = await getFileAsArrayBuffer(pdfFile); + uploadedPdfBytes = await flattenPdf(pdfArrayBuffer); + // Upload the file to Parse Server + } catch (err) { + console.error("Incorrect password or decryption failed", err); + alert("Incorrect password or decryption failed."); + } + } else { + alert("Please provided Password."); + } + } else { + console.log("Err ", err); + alert("error while uploading pdf."); + } + } + } else { + alert("error while uploading pdf."); + } + } const uploadedPdfDoc = await PDFDocument.load(uploadedPdfBytes, { ignoreEncryption: true }); @@ -106,6 +147,21 @@ function Header(props) { console.error("Error merging PDF:", error); } }; + + const handleReorderSave = async (order) => { + try { + const pdfupdatedData = await reorderPdfPages(props.pdfArrayBuffer, order); + if (pdfupdatedData) { + props.setPdfArrayBuffer(pdfupdatedData.arrayBuffer); + props.setPdfBase64Url(pdfupdatedData.base64); + props.setAllPages(pdfupdatedData.totalPages); + props.setPageNumber(1); + } + } catch (e) { + console.log("error in reorder pdf pages", e); + } + setIsReorderModal(false); + }; return (
    {isMobile && props?.isShowHeader ? ( @@ -334,6 +390,17 @@ function Header(props) {
    + setIsReorderModal(true)} + > +
    + + + {t("reorder-pages")} + +
    +
    + setIsReorderModal(false)} + totalPages={props.allPages} + onSave={handleReorderSave} + />
    ); } diff --git a/apps/OpenSign/src/components/pdf/PdfZoom.jsx b/apps/OpenSign/src/components/pdf/PdfZoom.jsx index dc74ffd0a4..caff5f9e99 100644 --- a/apps/OpenSign/src/components/pdf/PdfZoom.jsx +++ b/apps/OpenSign/src/components/pdf/PdfZoom.jsx @@ -1,18 +1,24 @@ -import React, { useRef, useState } from "react"; +import { useRef, useState } from "react"; import { useTranslation } from "react-i18next"; import { base64ToArrayBuffer, + decryptPdf, deletePdfPage, - handleRemoveWidgets + flattenPdf, + getFileAsArrayBuffer, + handleRemoveWidgets, + reorderPdfPages } from "../../constant/Utils"; import ModalUi from "../../primitives/ModalUi"; import { PDFDocument } from "pdf-lib"; import { maxFileSize } from "../../constant/const"; +import PageReorderModal from "./PageReorderModal"; function PdfZoom(props) { const { t } = useTranslation(); const mergePdfInputRef = useRef(null); const [isDeletePage, setIsDeletePage] = useState(false); + const [isReorderModal, setIsReorderModal] = useState(false); const handleDetelePage = async () => { props.setIsUploadPdf && props.setIsUploadPdf(true); try { @@ -67,7 +73,42 @@ function PdfZoom(props) { return; } try { - const uploadedPdfBytes = await file.arrayBuffer(); + let uploadedPdfBytes = await file.arrayBuffer(); + try { + uploadedPdfBytes = await flattenPdf(uploadedPdfBytes); + } catch (err) { + if (err?.message?.includes("is encrypted")) { + try { + const pdfFile = await decryptPdf(file, ""); + const pdfArrayBuffer = await getFileAsArrayBuffer(pdfFile); + uploadedPdfBytes = await flattenPdf(pdfArrayBuffer); + } catch (err) { + if (err?.response?.status === 401) { + const password = prompt( + `PDF "${file.name}" is password-protected. Enter password:` + ); + if (password) { + try { + const pdfFile = await decryptPdf(file, password); + const pdfArrayBuffer = await getFileAsArrayBuffer(pdfFile); + uploadedPdfBytes = await flattenPdf(pdfArrayBuffer); + // Upload the file to Parse Server + } catch (err) { + console.error("Incorrect password or decryption failed", err); + alert("Incorrect password or decryption failed."); + } + } else { + alert("Please provided Password."); + } + } else { + console.log("Err ", err); + alert("error while uploading pdf."); + } + } + } else { + alert("error while uploading pdf."); + } + } const uploadedPdfDoc = await PDFDocument.load(uploadedPdfBytes, { ignoreEncryption: true }); @@ -94,6 +135,21 @@ function PdfZoom(props) { } }; + const handleReorderSave = async (order) => { + try { + const pdfupdatedData = await reorderPdfPages(props.pdfArrayBuffer, order); + if (pdfupdatedData) { + props.setPdfArrayBuffer(pdfupdatedData.arrayBuffer); + props.setPdfBase64Url(pdfupdatedData.base64); + props.setAllPages(pdfupdatedData.totalPages); + props.setPageNumber(1); + } + } catch (e) { + console.log("error in reorder pdf pages", e); + } + setIsReorderModal(false); + }; + return ( <> @@ -120,6 +176,13 @@ function PdfZoom(props) { > + setIsReorderModal(true)} + title={t("reorder-pages")} + > + + )}
    + setIsReorderModal(false)} + totalPages={props.allPages} + onSave={handleReorderSave} + /> ); } diff --git a/apps/OpenSign/src/components/pdf/Placeholder.jsx b/apps/OpenSign/src/components/pdf/Placeholder.jsx index 7b34cc9d08..27be575927 100644 --- a/apps/OpenSign/src/components/pdf/Placeholder.jsx +++ b/apps/OpenSign/src/components/pdf/Placeholder.jsx @@ -1,4 +1,4 @@ -import { useState, useEffect, useRef } from "react"; +import { useState, useEffect } from "react"; import BorderResize from "./BorderResize"; import { Rnd } from "react-rnd"; import { @@ -13,6 +13,7 @@ import { onChangeInput, radioButtonWidget, textInputWidget, + cellsWidget, textWidget } from "../../constant/Utils"; import PlaceholderType from "./PlaceholderType"; @@ -80,11 +81,12 @@ function Placeholder(props) { props.pos?.options?.defaultValue || props.pos?.options?.response; const [isDateModal, setIsDateModal] = useState(false); const [containerScale, setContainerScale] = useState(); - const holdTimeout = useRef(null); - const startTime = useRef(null); // Track when the user starts holdings const [selectDate, setSelectDate] = useState({}); const [dateFormat, setDateFormat] = useState([]); const [clickonWidget, setClickonWidget] = useState({}); + const [isDateReadOnly, setIsDateReadOnly] = useState( + props?.pos?.options?.isReadOnly || false + ); const startDate = props?.pos?.options?.response ? getDefaultDate( props?.pos?.options?.response, @@ -303,6 +305,13 @@ function Placeholder(props) { } else if (props.pos.type === "checkbox") { props?.setIsCheckbox(true); } + // cells widget settings in sign yourself flow + else if ( + props.pos.type === cellsWidget && + (props.isSignYourself || props.isSelfSign) + ) { + props.handleCellSettingModal && props.handleCellSettingModal(); + } //condition to handle setting icon for signyour-self flow for all type text widgets else if ( [ @@ -406,11 +415,54 @@ function Placeholder(props) { false, data?.format, props.fontSize || props.pos?.options?.fontSize || 12, - props.fontColor || props.pos?.options?.fontColor || "black" + props.fontColor || props.pos?.options?.fontColor || "black", + isDateReadOnly || false ); setSelectDate({ date: date, format: data?.format }); }; + + const setCellCount = (key, newCount) => { + props.setXyPosition((prev) => { + const isSignerList = prev.some((d) => d.signerPtr); + if (isSignerList) { + const signerId = props.data?.Id || props.uniqueId; + const filterSignerPos = prev.filter((d) => d.Id === signerId); + if (filterSignerPos.length > 0) { + const getPlaceHolder = filterSignerPos[0].placeHolder; + const updatedPlaceHolder = getPlaceHolder.map((ph) => { + if (ph.pageNumber !== props.pageNumber) return ph; + const newPos = ph.pos.map((p) => + p.key === key + ? { ...p, options: { ...p.options, cellCount: newCount } } + : p + ); + return { ...ph, pos: newPos }; + }); + return prev.map((obj) => + obj.Id === signerId + ? { ...obj, placeHolder: updatedPlaceHolder } + : obj + ); + } + } else { + const updatePos = prev[props.index].pos.map((p) => + p.key === key + ? { ...p, options: { ...p.options, cellCount: newCount } } + : p + ); + return prev.map((obj, ind) => + ind === props.index ? { ...obj, pos: updatePos } : obj + ); + } + return prev; + }); + }; const PlaceholderIcon = () => { + const isSettingForCells = + props?.isAlllowModify && !props?.assignedWidgetId.includes(props.pos.key) + ? [] + : [cellsWidget]; + // 1- If props.isShowBorder is true, display border's icon for all widgets. OR // 2- Use the combination of props?.isAlllowModify and !props?.assignedWidgetId.includes(props.pos.key) to determine when to show border's icon: // 1- When isAlllowModify is true, show border's icon. @@ -434,10 +486,15 @@ function Placeholder(props) { "name", "company", "job title", - "email" + "email", + ...isSettingForCells ].includes(props.pos.type) && (props.isSignYourself || props.isSelfSign) ? ( { + e.stopPropagation(); + handleOnClickSettingIcon(); + }} onClick={(e) => { e.stopPropagation(); handleOnClickSettingIcon(); @@ -447,7 +504,14 @@ function Placeholder(props) { handleOnClickSettingIcon(); }} className="fa-light fa-gear icon" - style={{ color: "#188ae2", right: "29px", top: "-19px" }} + style={{ + color: "#188ae2", + right: "29px", + top: "-19px", + cursor: "pointer", + zIndex: 99, + pointerEvents: "auto" + }} > ) : ( /* condition to add setting icon for placeholder & template flow for all widgets except signature and date */ @@ -457,6 +521,10 @@ function Placeholder(props) { !props.isSignYourself && !props.isSelfSign)) && ( { + e.stopPropagation(); + handleOnClickSettingIcon(); + }} onClick={(e) => { e.stopPropagation(); handleOnClickSettingIcon(); @@ -469,7 +537,10 @@ function Placeholder(props) { style={{ color: "#188ae2", right: props?.pos?.type === textWidget ? "32px" : "51px", - top: "-19px" + top: "-19px", + cursor: "pointer", + zIndex: 99, + pointerEvents: "auto" }} > ) @@ -507,6 +578,7 @@ function Placeholder(props) { {/* setting icon only for date widgets */} {props.pos.type === "date" && selectDate && ( e.stopPropagation()} onClick={(e) => { props.setCurrWidgetsDetails(props.pos); setIsDateModal(!isDateModal); @@ -539,7 +611,9 @@ function Placeholder(props) { top: "-18px", right: props.isPlaceholder ? "50px" : "30px", color: "#188ae2", - fontSize: "14px" + fontSize: "14px", + cursor: "pointer", + pointerEvents: "auto" }} className="fa-light fa-gear icon" > @@ -666,7 +740,7 @@ function Placeholder(props) { return "not-allowed"; } } else { - return "all-scroll"; + return "move"; } }; @@ -686,21 +760,6 @@ function Placeholder(props) { return "rgba(203, 233, 237, 0.69)"; } }; - const handleTouchEnd = () => { - if (!props.isNeedSign || props.isAlllowModify) { - const holdDuration = Date.now() - startTime.current; // Calculate hold time - clearTimeout(holdTimeout.current); // Cancel timeout if touch ended early - - if (holdDuration < 1000) { - try { - navigator.vibrate([]); // Cancel any ongoing vibration - } catch (e) { - console.log("error in navigator.vibrate", e); - } - } - } - if (!props.isNeedSign || props.isAlllowModify) handleOnClickPlaceholder(); - }; const fontSize = calculateFont(props.pos.options?.fontSize); const fontColor = props.pos.options?.fontColor || "black"; @@ -751,20 +810,16 @@ function Placeholder(props) { id={props.pos.key} data-tut={props.pos.key === props.unSignedWidgetId ? "IsSigned" : ""} key={props.pos.key} + cancel=".cell-size-handle, .icon" lockAspectRatio={ - !props.isFreeResize && - ![ - textWidget, - "email", - "name", - "company", - "job title", - textInputWidget - ].includes(props.pos.type) && - (props.pos.Width - ? props.pos.Width / props.pos.Height - : defaultWidthHeight(props.pos.type).width / - defaultWidthHeight(props.pos.type).height) + props?.isAlllowModify && + !props?.assignedWidgetId.includes(props.pos.key) + ? false + : !props.isFreeResize && + (props.pos.Width + ? props.pos.Width / props.pos.Height + : defaultWidthHeight(props.pos.type).width / + defaultWidthHeight(props.pos.type).height) } enableResizing={{ top: false, @@ -820,8 +875,10 @@ function Placeholder(props) { : props.posHeight(props.pos, props.isSignYourself) }} minHeight={ - props.pos.type !== "checkbox" && - calculateFont(props.pos.options?.fontSize, true) + props.pos.type === cellsWidget + ? calculateFont(props.pos.options?.fontSize, true) + : props.pos.type !== "checkbox" && + calculateFont(props.pos.options?.fontSize, true) } maxHeight="auto" onResizeStart={() => { @@ -889,23 +946,24 @@ function Placeholder(props) { props.pos.key === props?.currWidgetsDetails?.key && )} - {/* 1- Show a ouline if props.pos.key === props?.currWidgetsDetails?.key, indicating the current user's selected widget. - 2- If props.isShowBorder is true, display ouline for all widgets. - 3- Use the combination of props?.isAlllowModify and !props?.assignedWidgetId.includes(props.pos.key) to determine when to show ouline: - 3.1- When isAlllowModify is true, show ouline. - 3.2- Do not display ouline for widgets already assigned (props.assignedWidgetId.includes(props.pos.key) is true). + {/* 1- Show a border if props.pos.key === props?.currWidgetsDetails?.key, indicating the current user's selected widget. + 2- If props.isShowBorder is true, display border for all widgets. + 3- Use the combination of props?.isAlllowModify and !props?.assignedWidgetId.includes(props.pos.key) to determine when to show border: + 3.1- When isAlllowModify is true, show border. + 3.2- Do not display border for widgets already assigned (props.assignedWidgetId.includes(props.pos.key) is true). */} + {props.pos.key === props?.currWidgetsDetails?.key && + (props.isShowBorder || + (props?.isAlllowModify && + !props?.assignedWidgetId.includes(props.pos.key))) && ( +
    + )}
    )} -
    -
    - {t("format")} : -
    +
    +
    +
    + {t("format")} : props.setFontSize(parseInt(e.target.value))} - > - {fontsizeArr.map((size, ind) => { - return ( +
    +
    + {t("font-size")} : + -
    - {t("color")}: + ))} + +
    +
    + {t("color")} :
    - + {props?.isPlaceholder && ( +
    + setIsDateReadOnly(!isDateReadOnly)} + /> + +
    + )}
    ); case "checkbox": + const checkBoxLayout = props.pos.options?.layout || "vertical"; + const isMultipleCheckbox = + props.pos.options?.values?.length > 0 ? true : false; + const checkBoxWrapperClass = `flex items-start ${ + checkBoxLayout === "horizontal" + ? `flex-row flex-wrap ${isMultipleCheckbox ? "gap-x-2" : ""}` + : `flex-col ${isMultipleCheckbox ? "gap-y-[5px]" : ""}` + }`; // Using gap-y-1 for consistency, adjust if needed + return ( -
    - {props.pos.options?.values?.map((data, ind) => { - return ( -
    - -
    - ); - })} +
    + {props.pos.options?.values?.map((data, ind) => ( +
    + +
    + ))}
    ); case textInputWidget: @@ -192,24 +197,15 @@ function PlaceholderType(props) { placeholder={hint || t("widgets-name.text")} rows={1} value={widgetValue} - className={`${ - props.pos.options?.isReadOnly || - props.data?.signerObjId !== props.signerObjId - ? "select-none" - : textWidgetCls - }`} + className={`${textWidgetCls} ${isReadOnly ? "select-none" : ""}`} style={{ fontSize: fontSize, color: fontColor, - background: props.data?.blockColor, + background: isReadOnly ? props.data?.blockColor : "white", pointerEvents: "none" }} readOnly - disabled={ - props.isNeedSign && - (props.pos.options?.isReadOnly || - props.data?.signerObjId !== props.signerObjId) - } + disabled={props.isNeedSign && isReadOnly} cols="50" /> ) : ( @@ -217,13 +213,39 @@ function PlaceholderType(props) { {hint || widgetTypeTranslation}
    ); + case cellsWidget: { + const count = props.pos.options?.cellCount || 5; + const cells = (widgetValue || "").split(""); + const height = "100%"; + const fontSize = props.calculateFont(props.pos.options?.fontSize); + const fontColor = props.pos.options?.fontColor || "black"; + const handleCellResize = (newCount) => { + if (props.setCellCount) props.setCellCount(props.pos.key, newCount); + }; + const isEditable = + props.isPlaceholder || props.isSignYourself || props.isSelfSign; + return ( + + ); + } case "dropdown": return (
    - {widgetData || hint || widgetTypeTranslation} + {widgetData || t("choose-one")}
    ); @@ -259,13 +281,15 @@ function PlaceholderType(props) { placeholder={hint || widgetTypeTranslation} rows={1} value={widgetValue} - className={textWidgetCls} + className={`${textWidgetCls} ${isReadOnly ? "select-none" : ""}`} style={{ fontSize: fontSize, color: fontColor, + background: isReadOnly ? props.data?.blockColor : "white", pointerEvents: "none" }} cols="50" + disabled={props.isNeedSign && isReadOnly} /> ) : (
    @@ -280,13 +304,15 @@ function PlaceholderType(props) { placeholder={hint || widgetTypeTranslation} rows={1} value={widgetValue} - className={textWidgetCls} + className={`${textWidgetCls} ${isReadOnly ? "select-none" : ""}`} style={{ fontSize: fontSize, color: fontColor, + background: isReadOnly ? props.data?.blockColor : "white", pointerEvents: "none" }} cols="50" + disabled={props.isNeedSign && isReadOnly} /> ) : (
    @@ -301,13 +327,15 @@ function PlaceholderType(props) { placeholder={hint || widgetTypeTranslation} rows={1} value={widgetValue} - className={textWidgetCls} + className={`${textWidgetCls} ${isReadOnly ? "select-none" : ""}`} style={{ fontSize: fontSize, color: fontColor, + background: isReadOnly ? props.data?.blockColor : "white", pointerEvents: "none" }} cols="50" + disabled={props.isNeedSign && isReadOnly} /> ) : (
    @@ -405,15 +433,15 @@ function PlaceholderType(props) { placeholder={hint || widgetTypeTranslation} rows={1} value={widgetValue} - className={textWidgetCls} + className={`${textWidgetCls} ${isReadOnly ? "select-none" : ""}`} style={{ fontSize: fontSize, color: fontColor, - fontFamily: "Arial, sans-serif", + background: isReadOnly ? props.data?.blockColor : "white", pointerEvents: "none" }} - disabled cols="1" + disabled={props.isNeedSign && isReadOnly} /> ) : (
    @@ -421,46 +449,39 @@ function PlaceholderType(props) {
    ); case radioButtonWidget: + const radioLayout = props.pos.options?.layout || "vertical"; + const isOnlyOneBtn = props.pos.options?.values?.length > 0 ? true : false; + const radioWrapperClass = `flex items-start ${ + radioLayout === "horizontal" + ? `flex-row flex-wrap ${isOnlyOneBtn ? "gap-x-2" : ""}` + : `flex-col ${isOnlyOneBtn ? "gap-y-[5px]" : ""}` + }`; // Using gap-y-1 for consistency, adjust if needed return ( -
    - {props.pos.options?.values.map((data, ind) => { - return ( -
    - -
    - ); - })} +
    + {props.pos.options?.values.map((data, ind) => ( +
    + +
    + ))}
    ); case textWidget: @@ -474,7 +495,8 @@ function PlaceholderType(props) { style={{ fontFamily: "Arial, sans-serif", fontSize: fontSize, - color: fontColor + color: fontColor, + background: "white" }} cols="50" /> diff --git a/apps/OpenSign/src/components/pdf/RecipientList.jsx b/apps/OpenSign/src/components/pdf/RecipientList.jsx index 26b41c1e61..eae63acdf4 100644 --- a/apps/OpenSign/src/components/pdf/RecipientList.jsx +++ b/apps/OpenSign/src/components/pdf/RecipientList.jsx @@ -31,7 +31,7 @@ const RecipientList = (props) => { e.preventDefault(); }; - //handle draggable element drop and also used in mobile view on up and down key to chnage sequence of recipient's list + //handle draggable element drop and also used in mobile view on up and down key to change sequence of recipient's list const handleChangeSequence = (e, ind, isUp, isDown, obj) => { e.preventDefault(); let draggedItemId; diff --git a/apps/OpenSign/src/components/pdf/RenderAllPdfPage.jsx b/apps/OpenSign/src/components/pdf/RenderAllPdfPage.jsx index 58372a396d..be42c23948 100644 --- a/apps/OpenSign/src/components/pdf/RenderAllPdfPage.jsx +++ b/apps/OpenSign/src/components/pdf/RenderAllPdfPage.jsx @@ -3,7 +3,12 @@ import { useTranslation } from "react-i18next"; import { Document, Page } from "react-pdf"; import { useSelector } from "react-redux"; import { PDFDocument } from "pdf-lib"; -import { base64ToArrayBuffer } from "../../constant/Utils"; +import { + base64ToArrayBuffer, + decryptPdf, + flattenPdf, + getFileAsArrayBuffer +} from "../../constant/Utils"; import { maxFileSize } from "../../constant/const"; function RenderAllPdfPage(props) { @@ -87,7 +92,42 @@ function RenderAllPdfPage(props) { return; } try { - const uploadedPdfBytes = await file.arrayBuffer(); + let uploadedPdfBytes = await file.arrayBuffer(); + try { + uploadedPdfBytes = await flattenPdf(uploadedPdfBytes); + } catch (err) { + if (err?.message?.includes("is encrypted")) { + try { + const pdfFile = await decryptPdf(file, ""); + const pdfArrayBuffer = await getFileAsArrayBuffer(pdfFile); + uploadedPdfBytes = await flattenPdf(pdfArrayBuffer); + } catch (err) { + if (err?.response?.status === 401) { + const password = prompt( + `PDF "${file.name}" is password-protected. Enter password:` + ); + if (password) { + try { + const pdfFile = await decryptPdf(file, password); + const pdfArrayBuffer = await getFileAsArrayBuffer(pdfFile); + uploadedPdfBytes = await flattenPdf(pdfArrayBuffer); + // Upload the file to Parse Server + } catch (err) { + console.error("Incorrect password or decryption failed", err); + alert("Incorrect password or decryption failed."); + } + } else { + alert("Please provided Password."); + } + } else { + console.log("Err ", err); + alert("error while uploading pdf."); + } + } + } else { + alert("error while uploading pdf."); + } + } const uploadedPdfDoc = await PDFDocument.load(uploadedPdfBytes, { ignoreEncryption: true }); diff --git a/apps/OpenSign/src/components/pdf/RenderPdf.jsx b/apps/OpenSign/src/components/pdf/RenderPdf.jsx index 8d69ab6bf9..46f78ca08c 100644 --- a/apps/OpenSign/src/components/pdf/RenderPdf.jsx +++ b/apps/OpenSign/src/components/pdf/RenderPdf.jsx @@ -79,7 +79,7 @@ function RenderPdf(props) { } }; - //function for render placeholder block over pdf document + // function for render placeholder block over pdf document (all signing flow) const checkSignedSigners = (data) => { let checkSign = []; //condition to handle quick send flow and using normal request sign flow @@ -91,73 +91,72 @@ function RenderPdf(props) { : []; return ( checkSign.length === 0 && - data?.placeHolder?.map((placeData, key) => { - return ( - - {placeData.pageNumber === props.pageNumber && - placeData.pos.map((pos, ind) => { - return ( - pos && ( - - - - ) - ); - })} - - ); - }) + data?.placeHolder?.map((placeData, key) => ( + + {placeData.pageNumber === props.pageNumber && + placeData.pos.map( + (pos, ind) => + pos && ( + + + + ) + )} + + )) ); }; @@ -172,148 +171,141 @@ function RenderPdf(props) { } }; const pdfDataBase64 = `data:application/pdf;base64,${props.pdfBase64Url}`; - //calculate render height of pdf in mobile view + // calculate render height of pdf in mobile view const handlePageLoadSuccess = (page) => { - const containerWidth = props.divRef.current.offsetWidth; // Get container width - const viewport = page.getViewport({ scale: 1 }); - const scale = containerWidth / viewport.width; // Scale to fit container width - const scaleHeight = viewport.height * scale; - setScaledHeight(scaleHeight); + if (isMobile) { + const containerWidth = props.divRef.current.offsetWidth; // Get container width + const viewport = page.getViewport({ scale: 1 }); + const scale = containerWidth / viewport.width; // Scale to fit container width + const scaleHeight = viewport.height * scale; + setScaledHeight(scaleHeight); + } }; return ( <> {props.successEmail && ( {t("success-email-alert")} )} - {isMobile ? ( - +
    -
    - {props.containerWH?.width && - props.pdfOriginalWH.length > 0 && - (props.pdfRequest || props.isSelfSign - ? props.signerPos?.map((data, key) => { - return ( + {props.pdfLoad !== false && + props.containerWH?.width && + props.pdfOriginalWH.length > 0 && ( + <> + {props.pdfRequest || props.isSelfSign + ? // request sign, guest sign, + props.signerPos?.map((data, key) => ( {checkSignedSigners(data)} - ); - }) - : props.placeholder // placeholder mobile - ? props.signerPos?.map((data, ind) => { - return ( + )) + : props.placeholder // placeholdersign document, draft document, create template, draft template + ? props.signerPos?.map((data, ind) => ( {data?.placeHolder && - data?.placeHolder.map((placeData, index) => { - return ( - - {placeData.pageNumber === props.pageNumber && - placeData.pos.map((pos) => { - return ( - - - - ); - })} - - ); - })} + data?.placeHolder.map((placeData, index) => ( + + {placeData.pageNumber === props.pageNumber && + placeData.pos.map((pos) => ( + + + + ))} + + ))} - ); - }) - : !props.pdfDetails?.[0]?.IsCompleted && - props.xyPosition?.map((data, ind) => { - return ( + )) + : !props.pdfDetails?.[0]?.IsCompleted && // signyourself flow + props.xyPosition?.map((data, ind) => ( {data.pageNumber === props.pageNumber && - data.pos.map((pos, id) => { - return ( + data.pos.map( + (pos, id) => pos && ( ) - ); - })} + )} - ); - }))} - {/* Mobile */} - {t("failed-to-load-refresh-page")}

    } - onLoadError={() => props.setPdfLoad(false)} - loading={t("loading-doc")} - onLoadSuccess={props.pageDetails} - onClick={() => - props.setCurrWidgetsDetails && props.setCurrWidgetsDetails({}) - } - file={pdfDataBase64} - > - { - console.log("annotation error", error); - }} - className="select-none touch-callout-none" - /> -
    -
    - - ) : ( - -
    + )} + {t("failed-to-load-refresh-page")}

    } + onLoadError={(e) => { + console.log("PDF load error", e); + props.setPdfLoad(false); }} - ref={props.drop} - id="container" + loading={t("loading-doc")} + onLoadSuccess={(pdf) => { + props.setPdfLoad(true); + props.pageDetails(pdf); + }} + onClick={() => + props.setCurrWidgetsDetails && props.setCurrWidgetsDetails({}) + } + file={pdfDataBase64} > - {props.pdfLoad && - props.containerWH?.width && - props.pdfOriginalWH.length > 0 && - (props.pdfRequest || props.isSelfSign //pdf request sign flow - ? props.signerPos?.map((data, key) => { - return ( - - {checkSignedSigners(data)} - - ); - }) - : props.placeholder //placeholder and template flow - ? props.signerPos.map((data, ind) => { - return ( - - {data?.placeHolder && - data?.placeHolder.map((placeData, index) => { - return ( - - {placeData.pageNumber === props.pageNumber && - placeData.pos.map((pos) => { - return ( - - - - ); - })} - - ); - })} - - ); - }) - : !props.pdfDetails?.[0]?.IsCompleted && - props.xyPosition?.map((data, ind) => { - // signyourself flow - return ( - - {data.pageNumber === props.pageNumber && - data.pos.map((pos) => { - return ( - - - props.handleStop( - event, - dragElement, - pos.type - ) - } - handleSignYourselfImageResize={ - handleSignYourselfImageResize - } - index={props.index} - xyPosition={props.xyPosition} - setXyPosition={props.setXyPosition} - isShowBorder={true} - isSignYourself={true} - posWidth={posWidth} - posHeight={posHeight} - pdfDetails={props.pdfDetails[0]} - isDragging={props.isDragging} - setIsCheckbox={props.setIsCheckbox} - setCurrWidgetsDetails={ - props.setCurrWidgetsDetails - } - handleTextSettingModal={ - props.handleTextSettingModal - } - scale={props.scale} - containerWH={props.containerWH} - pdfOriginalWH={props.pdfOriginalWH} - pageNumber={props.pageNumber} - fontSize={props.fontSize} - setFontSize={props.setFontSize} - fontColor={props.fontColor} - setFontColor={props.setFontColor} - isResize={props.isResize} - setIsResize={props.setIsResize} - isFreeResize={false} - isOpenSignPad={true} - calculateFontsize={calculateFontsize} - currWidgetsDetails={ - props?.currWidgetsDetails - } - /> - - ); - })} - - ); - }))} - {/* large device */} - {/* this component for render pdf document is in middle of the component */} - {t("failed-to-load-refresh-page")}

    } - onLoadError={() => props.setPdfLoad(false)} - loading={t("loading-doc")} - onLoadSuccess={props.pageDetails} - onClick={() => - props.setCurrWidgetsDetails && props.setCurrWidgetsDetails({}) - } - file={pdfDataBase64} - > - { - console.log("annotation error", error); - }} - /> -
    -
    -
    - )} + { + console.log("annotation error", error); + }} + /> + +
    +
    ); } diff --git a/apps/OpenSign/src/components/pdf/SelectLanguage.jsx b/apps/OpenSign/src/components/pdf/SelectLanguage.jsx index 06aad4be31..eecf75747b 100644 --- a/apps/OpenSign/src/components/pdf/SelectLanguage.jsx +++ b/apps/OpenSign/src/components/pdf/SelectLanguage.jsx @@ -24,14 +24,14 @@ function SelectLanguage(props) {
    handleChange(e)} + required + /> +
    + )} + {[textInputWidget, cellsWidget].includes(props.defaultdata?.type) && ( <>
    - {[textInputWidget].includes(props.defaultdata?.type) && ( + {[textInputWidget, cellsWidget].includes( + props.defaultdata?.type + ) && (
    { })) } /> -
    @@ -317,6 +371,7 @@ const WidgetNameModal = (props) => { {[ textInputWidget, textWidget, + cellsWidget, "name", "company", "job title", diff --git a/apps/OpenSign/src/components/pdf/WidgetsValueModal.jsx b/apps/OpenSign/src/components/pdf/WidgetsValueModal.jsx index 44d78d2d72..89240dbe7d 100644 --- a/apps/OpenSign/src/components/pdf/WidgetsValueModal.jsx +++ b/apps/OpenSign/src/components/pdf/WidgetsValueModal.jsx @@ -15,9 +15,11 @@ import { radioButtonWidget, selectCheckbox, textInputWidget, + cellsWidget, textWidget, years } from "../../constant/Utils"; +import CellsWidget from "./CellsWidget"; import DatePicker from "react-datepicker"; import "react-datepicker/dist/react-datepicker.css"; import SignatureCanvas from "react-signature-canvas"; @@ -44,9 +46,9 @@ import RegexParser from "regex-parser"; //function to get default format const getDefaultFormat = (dateFormat) => dateFormat || "MM/dd/yyyy"; -//function to convert formated date to new Date() format +//function to convert formatted date to new Date() format const getDefaultDate = (dateStr, format) => { - //get valid date format for moment to convert formated date to new Date() format + //get valid date format for moment to convert formatted date to new Date() format const formats = changeDateToMomentFormat(format); const parsedDate = moment(dateStr, formats); let date; @@ -85,7 +87,9 @@ function WidgetsValueModal(props) { isSave, setUniqueId, tempSignerId, - signatureTypes + signatureTypes, + setCellCount, + allowCellResize = true } = props; const [penColor, setPenColor] = useState("blue"); const [isOptional, setIsOptional] = useState(true); @@ -93,7 +97,6 @@ function WidgetsValueModal(props) { const [isTab, setIsTab] = useState(""); const [textWidth, setTextWidth] = useState(0); const [textHeight, setTextHeight] = useState(0); - const [signatureType, setSignatureType] = useState(""); const [isSignTypes, setIsSignTypes] = useState(true); const [typedSignature, setTypedSignature] = useState(""); const [selectDate, setSelectDate] = useState({}); @@ -119,13 +122,42 @@ function WidgetsValueModal(props) { const currentUserName = jsonSender && jsonSender?.name; const widgetTypeTranslation = t(`widgets-name.${currWidgetsDetails?.type}`); const [widgetValue, setWidgetValue] = useState( - currWidgetsDetails?.options?.response || - currWidgetsDetails?.options?.defaultValue + currWidgetsDetails.type !== "checkbox" && + (currWidgetsDetails?.options?.response || + currWidgetsDetails?.options?.defaultValue) ); - const [selectedCheckbox, setSelectedCheckbox] = useState( - currWidgetsDetails?.options?.response || + const [cellsValue, setCellsValue] = useState(() => { + const count = currWidgetsDetails?.options?.cellCount || 5; + const val = + currWidgetsDetails?.options?.response || currWidgetsDetails?.options?.defaultValue || - [] + ""; + return Array.from({ length: count }, (_, i) => val[i] || ""); + }); + const cellRefs = useRef([]); + // keep track of the first empty cell to automatically focus it after updates + useEffect(() => { + const index = cellsValue.findIndex((v) => !v); + if (index !== -1) { + setTimeout(() => { + cellRefs.current[index]?.focus(); + }, 0); + } + }, [cellsValue]); + + useEffect(() => { + const count = currWidgetsDetails?.options?.cellCount || 5; + const val = + currWidgetsDetails?.options?.response || + currWidgetsDetails?.options?.defaultValue || + ""; + setCellsValue(Array.from({ length: count }, (_, i) => val[i] || "")); + }, [currWidgetsDetails?.key, currWidgetsDetails?.options?.cellCount]); + const [selectedCheckbox, setSelectedCheckbox] = useState( + currWidgetsDetails.type === "checkbox" && + (currWidgetsDetails?.options?.response || + currWidgetsDetails?.options?.defaultValue || + []) ); const [startDate, setStartDate] = useState( currWidgetsDetails?.options?.response @@ -137,7 +169,7 @@ function WidgetsValueModal(props) { ); const allColor = ["blue", "red", "black"]; const textInputcls = - "op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs"; + "op-input op-input-bordered op-input-sm focus:outline-none text-base-content hover:border-base-content w-full text-xs"; const isTabCls = "bg-[#002864] text-white rounded-[15px] px-[10px] py-[4px]"; useEffect(() => { if ( @@ -156,34 +188,6 @@ function WidgetsValueModal(props) { setHint(currWidgetsDetails?.type); } } - //set already draw or save signature url/text url of signature text type and draw type for initial type and signature type widgets - 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 (currWidgetsDetails?.type === "initials") { - if (isWidgetType === "initials" && signatureType === "draw" && url) { - canvasRef.current.fromDataURL(url); - } - } else if ( - isWidgetType === "signature" && - signatureType === "draw" && - url - ) { - canvasRef.current.fromDataURL(url); - } - - const trimmedName = currentUserName && currentUserName?.trim(); - const firstCharacter = trimmedName?.charAt(0); - const userName = - currWidgetsDetails?.type === "initials" - ? firstCharacter - : currentUserName; - const signatureValue = currWidgetsDetails?.typeSignature; - setTypedSignature(signatureValue || userName || ""); - setFontSelect("Fasthand"); - } // eslint-disable-next-line react-hooks/exhaustive-deps }, [currWidgetsDetails]); // Added currWidgetsDetails to dependency array for reset logic @@ -193,7 +197,7 @@ function WidgetsValueModal(props) { setRemoveBgEnabled(false); }, [currWidgetsDetails?.key]); - //function to save date and format after seleted new date in response field and after finish document it should be emebed new selected date instead of current date + //function to save date and format after selected new date in response field and after finish document it should embed the new selected date instead of current date useEffect(() => { if (currWidgetsDetails?.type === "date") { const isDateChange = true; @@ -403,7 +407,6 @@ function WidgetsValueModal(props) { const tab = signatureTypes?.[getIndex].name; if (tab === "draw") { setIsTab("draw"); - setSignatureType("draw"); } else if (tab === "upload") { setIsImageSelect(true); setIsTab("uploadImage"); @@ -449,7 +452,32 @@ function WidgetsValueModal(props) { setTypedSignature(""); } } else { - setWidgetValue(""); + if (currWidgetsDetails?.type === cellsWidget) { + const count = + currWidgetsDetails?.options?.cellCount || cellsValue.length || 1; + const cleared = Array.from({ length: count }, () => ""); + setCellsValue(cleared); + const combined = cleared.join(""); + setWidgetValue(combined); + onChangeInput( + combined, + currWidgetsDetails?.key, + xyPosition, + props.index, + setXyPosition, + uniqueId + ); + } else { + setWidgetValue(""); + onChangeInput( + "", + currWidgetsDetails?.key, + xyPosition, + props.index, + setXyPosition, + uniqueId + ); + } } }; //function for set signature url @@ -583,7 +611,7 @@ function WidgetsValueModal(props) { if (isTab === "mysignature") { setSignature(""); if (currWidgetsDetails?.type === "initials") { - handleSaveSignature(signatureType, "initials"); + handleSaveSignature(isTab, "initials"); } else { handleSaveSignature(null, "default"); } @@ -604,13 +632,13 @@ function WidgetsValueModal(props) { } else { setSignature(""); canvasRef?.current?.clear(); - handleSaveSignature(signatureType); + handleSaveSignature(isTab); } } setPenColor("blue"); } else { setSignature(""); - handleSaveImage(signatureType); + handleSaveImage(); } setIsImageSelect(false); setIsDefaultSign(false); @@ -649,24 +677,21 @@ function WidgetsValueModal(props) { }, [fontSelect]); useEffect(() => { - if ( - ["signature", "initials"].includes(currWidgetsDetails?.type) && - widgetValue - ) { - if (isTab === "draw" && currWidgetsDetails?.signatureType === "draw") { - setSignature(widgetValue); - } else if (isTab === "uploadImage" && currWidgetsDetails?.ImageType) { - setImage({ imgType: currWidgetsDetails?.ImageType, src: widgetValue }); + if (currWidgetsDetails?.options?.response) { + const url = currWidgetsDetails?.options?.response; + if (["signature", "initials"].includes(currWidgetsDetails?.type)) { + if (isTab === "draw" && currWidgetsDetails?.signatureType === "draw") { + setSignature(url); + // Load the default signature after the component mounts + if (canvasRef.current) { + canvasRef.current.fromDataURL(url); + } + } else if (isTab === "uploadImage" && currWidgetsDetails?.ImageType) { + setImage({ imgType: currWidgetsDetails?.ImageType, src: url }); + } + } else if (["image", "stamp"].includes(currWidgetsDetails?.type)) { + setImage({ imgType: currWidgetsDetails?.ImageType, src: url }); } - } else if ( - ["image", "stamp"].includes(currWidgetsDetails?.type) && - widgetValue - ) { - setImage({ imgType: currWidgetsDetails?.ImageType, src: widgetValue }); - } - // Load the default signature after the component mounts - if (canvasRef.current) { - canvasRef.current.fromDataURL(signature); } if (isTab === "type") { const trimmedName = typedSignature @@ -746,7 +771,7 @@ function WidgetsValueModal(props) { const PenColorComponent = (props) => { return (
    - Options + Options {allColor.map((data, key) => { return ( { + // hide any prior validation error while typing setIsShowValidation(false); setWidgetValue(e.target.value); onChangeInput( @@ -953,6 +979,55 @@ function WidgetsValueModal(props) { uniqueId ); }; + const updateCells = (updated) => { + setCellsValue(updated); + const combined = updated.join(""); + setWidgetValue(combined); + props.setCurrWidgetsDetails?.((prev) => + prev && prev.key === currWidgetsDetails?.key + ? { ...prev, options: { ...prev.options, response: combined } } + : prev + ); + onChangeInput( + combined, + currWidgetsDetails?.key, + xyPosition, + props.index, + setXyPosition, + uniqueId + ); + }; + + const handleCellsInput = (e, idx) => { + setIsShowValidation(false); + const val = e.target.value.slice(0, 1); + const updated = [...cellsValue]; + updated[idx] = val; + updateCells(updated); + }; + const handleCellsKeyDown = (e, idx) => { + if (e.key === "Backspace" && !cellsValue[idx] && idx > 0) { + e.preventDefault(); + cellRefs.current[idx - 1]?.focus(); + } + }; + + const handleCellResize = (newCount) => { + let updated = [...cellsValue]; + if (newCount > updated.length) { + updated = [...updated, ...Array(newCount - updated.length).fill("")]; + } else if (newCount < updated.length) { + updated = updated.slice(0, newCount); + } + cellRefs.current = cellRefs.current.slice(0, newCount); + updateCells(updated); + setCellCount?.(currWidgetsDetails?.key, newCount); + }; + + // when focus leaves the cells widget, validate the input + const handleCellsBlur = (e, idx) => { + handleInputBlur(); + }; //function is used to show widgets on modal according to selected widget type checkbox/date/radio/drodown/textbox/signature/image const getWidgetType = (type) => { switch (type) { @@ -971,7 +1046,7 @@ function WidgetsValueModal(props) { <> {currWidgetsDetails?.type !== "stamp" && currWidgetsDetails?.type !== "image" && ( -
    +
    <> {currWidgetsDetails?.type !== "initials" && @@ -983,7 +1058,6 @@ function WidgetsValueModal(props) { setIsDefaultSign(true); setIsImageSelect(true); setIsTab("mysignature"); - setSignatureType(""); setImage(); }} className={`${ @@ -1003,7 +1077,6 @@ function WidgetsValueModal(props) { setIsDefaultSign(true); setIsImageSelect(true); setIsTab("mysignature"); - setSignatureType(""); setImage(); }} className={`${ @@ -1040,7 +1113,6 @@ function WidgetsValueModal(props) { setIsDefaultSign(false); setIsImageSelect(true); setIsTab("uploadImage"); - setSignatureType(""); }} className={`${ isTab === "uploadImage" && `${isTabCls}` @@ -1057,7 +1129,6 @@ function WidgetsValueModal(props) { setIsDefaultSign(false); setIsImageSelect(false); setIsTab("type"); - setSignatureType(""); setImage(); }} className={`${ @@ -1272,7 +1343,7 @@ function WidgetsValueModal(props) {
    -
    +
    {/* Standalone autoSignAll for "Type" tab if conditions met */} {setIsAutoSign && uniqueId && (
    @@ -1308,7 +1379,7 @@ function WidgetsValueModal(props) {
    -
    +
    {/* Standalone autoSignAll for "Draw" tab if conditions met */} {setIsAutoSign && uniqueId && (
    @@ -1326,69 +1397,66 @@ function WidgetsValueModal(props) {
    ) : ( -
    -
    -
    - {t("signature")} -
    -
    - × -
    -
    -
    -

    {t("at-least-one-signature-type")}

    -
    +
    +

    {t("at-least-one-signature-type")}

    )}
    ); case "checkbox": + const checkBoxLayout = + currWidgetsDetails?.options?.layout || "vertical"; + const isMultipleCheckbox = + currWidgetsDetails?.options?.values?.length > 0 ? true : false; + const checkBoxWrapperClass = `flex items-start ${ + checkBoxLayout === "horizontal" + ? `flex-row flex-wrap ${isMultipleCheckbox ? "gap-x-2" : ""}` + : `flex-col ${isMultipleCheckbox ? "gap-y-[5px]" : ""}` + }`; // Using gap-y-1 for consistency, adjust if needed + return ( -
    - {currWidgetsDetails?.options?.values?.map((data, ind) => { - return ( -
    -
    ); case textInputWidget: @@ -1401,6 +1469,23 @@ function WidgetsValueModal(props) { className={textInputcls} /> ); + case cellsWidget: + return ( + + ); case "dropdown": return ( ); case "name": @@ -1468,7 +1546,7 @@ function WidgetsValueModal(props) { case "date": return (
    ( @@ -1529,30 +1607,38 @@ function WidgetsValueModal(props) { ); case radioButtonWidget: + const radioLayout = currWidgetsDetails.options?.layout || "vertical"; + const isOnlyOneBtn = + currWidgetsDetails.options?.values?.length > 0 ? true : false; + const radioWrapperClass = `flex items-start ${ + radioLayout === "horizontal" + ? `flex-row flex-wrap ${isOnlyOneBtn ? "gap-x-2" : ""}` + : `flex-col ${isOnlyOneBtn ? "gap-y-[5px]" : ""}` + }`; // Using gap-y-1 for consistency, adjust if needed return ( -
    - {currWidgetsDetails?.options?.values.map((data, ind) => { - return ( -
    - -
    - ); - })} +
    + {currWidgetsDetails?.options?.values.map((data, ind) => ( +
    + +
    + ))}
    ); case textWidget: @@ -1590,15 +1676,9 @@ function WidgetsValueModal(props) { const minCount = currWidgetsDetails?.options?.validation?.minRequiredCount; const parseMin = minCount && parseInt(minCount); - //get maximum required count if exist - const maxCount = - currWidgetsDetails?.options?.validation?.maxRequiredCount; - const parseMax = maxCount && parseInt(maxCount); - if (parseMin > 0 && parseMax > 0) { + if (parseMin > 0) { isRequired = true; } - } else if (isRadio) { - isRequired = true; } else { isRequired = currWidgetsDetails.options?.status === "required"; } @@ -1670,7 +1750,7 @@ function WidgetsValueModal(props) { } } }; - //funtion is used when user enter value any textbox then check validation + //function is used when user enter value in any textbox then check validation const handleInputBlur = () => { const validateType = currWidgetsDetails?.options?.validation?.type; let regexValidation; @@ -1683,6 +1763,10 @@ function WidgetsValueModal(props) { regexValidation = /^[0-9\s]*$/; validateExpression(regexValidation); break; + case "ssn": + regexValidation = /^(?!000|666|9\d{2})\d{3}-(?!00)\d{2}-(?!0000)\d{4}$/; + validateExpression(regexValidation); + break; default: // Grab the current pattern (if it exists) const pattern = currWidgetsDetails?.options?.validation?.pattern; @@ -1694,7 +1778,7 @@ function WidgetsValueModal(props) { break; } }; - //funtion too uuse on click on next/finish button then update modal ui according to cuurent widgets + //function too use on click on next/finish button then update modal UI according to current widgets const handleClickOnNext = (isFinishDoc) => { if ( ["signature", "stamp", "image", "initials"].includes( @@ -1793,22 +1877,76 @@ function WidgetsValueModal(props) { } }; const handleclose = () => { + // If validation is shown, clear the response and close the modal + if (isShowValidation) { + handleClear(); + setIsShowValidation(false); + } dispatch(setIsShowModal({})); dispatch(setLastIndex("")); if (currWidgetsDetails?.type === textWidget && uniqueId) { setUniqueId(tempSignerId); } }; + //function is used to execute the finish button functionality const handleFinish = () => { props?.finishDocument(); dispatch(setIsShowModal({})); }; + useEffect(() => { + if (!isSave) { + handleFinishButton(); + } + }, [isSave]); + //'handleFinishButton' function is used to show finish button click on any widget if all required widgets have response + const handleFinishButton = () => { + const widgetsPosition = xyPosition?.find((data) => data.Id === uniqueId); + //using 'flatMap' create all nested array in one level + const editableWidgets = widgetsPosition?.placeHolder?.flatMap((page) => + page.pos + .filter((widget) => !widget.options?.isReadOnly) + .map((widget) => widget) + ); + const getcurrentwidget = editableWidgets?.find( + (data) => data?.key === currWidgetsDetails?.key + ); + if (getcurrentwidget?.options?.response) { + props?.setCurrWidgetsDetails(getcurrentwidget); + } + let isResponse = true; + //condition to check all required widgets have response or not then show finish buutton + for (const data of editableWidgets) { + if (data?.type === "checkbox") { + const minCount = data.options?.validation?.minRequiredCount; + const parseMin = minCount && parseInt(minCount); + const hasNoResponse = + (!Array.isArray(data?.options?.response) || + data.options.response.length === 0) && + (!Array.isArray(data?.options?.defaultValue) || + data.options.defaultValue.length === 0); + if (parseMin > 0 && hasNoResponse) { + isResponse = false; + break; + } + } else if ( + !data.options.response && + !data?.options?.defaultValue && + data.options?.status === "required" + ) { + isResponse = false; + break; + } + } + if (isResponse) { + setIsLastWidget(true); + } + }; return ( <> !isShowValidation && handleclose()} + handleClose={() => handleclose()} position="bottom" >
    @@ -1840,7 +1978,7 @@ function WidgetsValueModal(props) { <>
    - + {currWidgetsDetails?.options?.name || widgetTypeTranslation} {!isOptional && ( @@ -1866,7 +2004,7 @@ function WidgetsValueModal(props) { ) ? ( @@ -681,7 +688,7 @@ function Opensigndrive() {
    @@ -793,7 +800,7 @@ function Opensigndrive() { >
    @@ -809,7 +816,7 @@ function Opensigndrive() {
    diff --git a/apps/OpenSign/src/pages/PdfRequestFiles.jsx b/apps/OpenSign/src/pages/PdfRequestFiles.jsx index f6b09d32e0..7bd022c023 100644 --- a/apps/OpenSign/src/pages/PdfRequestFiles.jsx +++ b/apps/OpenSign/src/pages/PdfRequestFiles.jsx @@ -23,7 +23,6 @@ import { pdfNewWidthFun, signPdfFun, addDefaultSignatureImg, - radioButtonWidget, replaceMailVaribles, convertPdfArrayBuffer, contractUsers, @@ -47,7 +46,8 @@ import { mailTemplate, updateDateWidgetsRes, widgetDataValue, - getOriginalWH + getOriginalWH, + handleCheckResponse, } from "../constant/Utils"; import Header from "../components/pdf/PdfHeader"; import RenderPdf from "../components/pdf/RenderPdf"; @@ -277,6 +277,15 @@ function PdfRequestFiles( let currUserId; //getting document details const documentData = await contractDocument(docId); + // Filter out 'prefill' roles from the Placeholder array + const filteredPlaceholder = documentData[0].Placeholders.filter( + (data) => data.Role !== "prefill" + ); + // Reassign the updated Placeholder back to the documentData array + documentData[0] = { + ...documentData[0], + Placeholders: filteredPlaceholder + }; if (documentData && documentData.length > 0) { const userSignatureType = documentData[0]?.ExtUserPtr?.SignatureType || signatureTypes; @@ -624,6 +633,7 @@ function PdfRequestFiles( } catch (err) { console.log("err in get email verification ", err); setHandleError(t("something-went-wrong-mssg")); + setIsUiLoading(false); } } //check if isEmailVerified then go on next step @@ -633,153 +643,13 @@ function PdfRequestFiles( (data) => data.signerObjId === signerObjectId ); if (checkUser && checkUser.length > 0) { - let checkboxExist, - requiredRadio, - showAlert = false, - widgetKey, - radioExist, - requiredCheckbox, - TourPageNumber; // `pageNumber` is used to check on which page user did not fill widget's data then change current pageNumber and show tour message on that page - - for (let i = 0; i < checkUser[0].placeHolder.length; i++) { - for (let j = 0; j < checkUser[0].placeHolder[i].pos.length; j++) { - //get current page - const updatePage = checkUser[0].placeHolder[i]?.pageNumber; - //checking checbox type widget - checkboxExist = - checkUser[0].placeHolder[i].pos[j].type === "checkbox"; - //checking radio button type widget - radioExist = - checkUser[0].placeHolder[i].pos[j].type === radioButtonWidget; - //condition to check checkbox widget exist or not - if (checkboxExist) { - //get all required type checkbox - requiredCheckbox = checkUser[0].placeHolder[i].pos.filter( - (position) => - !position.options?.isReadOnly && - position.type === "checkbox" - ); - //if required type checkbox data exit then check user checked all checkbox or some checkbox remain to check - //also validate to minimum and maximum required checkbox - if (requiredCheckbox && requiredCheckbox.length > 0) { - for (let i = 0; i < requiredCheckbox.length; i++) { - //get minimum required count if exit - const minCount = - requiredCheckbox[i].options?.validation?.minRequiredCount; - const parseMin = minCount && parseInt(minCount); - //get maximum required count if exit - const maxCount = - requiredCheckbox[i].options?.validation?.maxRequiredCount; - const parseMax = maxCount && parseInt(maxCount); - //in `response` variable is used to get how many checkbox checked by user - const response = - requiredCheckbox[i].options?.response?.length; - //in `defaultValue` variable is used to get how many checkbox checked by default - const defaultValue = - requiredCheckbox[i].options?.defaultValue?.length; - //condition to check parseMin and parseMax greater than 0 then consider it as a required check box - if ( - parseMin > 0 && - parseMax > 0 && - !response && - !defaultValue && - !showAlert - ) { - showAlert = true; - widgetKey = requiredCheckbox[i].key; - TourPageNumber = updatePage; - setminRequiredCount(parseMin); - } - //else condition to validate minimum required checkbox - else if ( - parseMin > 0 && - (parseMin > response || !response) - ) { - if (!showAlert) { - showAlert = true; - widgetKey = requiredCheckbox[i].key; - TourPageNumber = updatePage; - setminRequiredCount(parseMin); - } - } - } - } - } - //condition to check radio widget exist or not - else if (radioExist) { - //get all required type radio button - requiredRadio = checkUser[0].placeHolder[i].pos.filter( - (position) => - !position.options?.isReadOnly && - position.type === radioButtonWidget - ); - //if required type radio data exit then check user checked all radio button or some radio remain to check - if (requiredRadio && requiredRadio?.length > 0) { - let checkSigned; - for (let i = 0; i < requiredRadio?.length; i++) { - checkSigned = requiredRadio[i]?.options?.response; - if (!checkSigned) { - let checkDefaultSigned = - requiredRadio[i]?.options?.defaultValue; - if (!checkDefaultSigned && !showAlert) { - showAlert = true; - widgetKey = requiredRadio[i].key; - TourPageNumber = updatePage; - setminRequiredCount(null); - } - } - } - } - } - //else condition to check all type widget data fill or not except checkbox and radio button - else { - //get all required type widgets except checkbox and radio - const requiredWidgets = checkUser[0].placeHolder[i].pos.filter( - (position) => - position.options?.status === "required" && - position.type !== radioButtonWidget && - position.type !== "checkbox" - ); - if (requiredWidgets && requiredWidgets?.length > 0) { - let checkSigned; - for (let i = 0; i < requiredWidgets?.length; i++) { - checkSigned = requiredWidgets[i]?.options?.response; - if (!checkSigned) { - const checkSignUrl = requiredWidgets[i]?.pos?.SignUrl; - if (!checkSignUrl) { - let checkDefaultSigned = - requiredWidgets[i]?.options?.defaultValue; - if (!checkDefaultSigned && !showAlert) { - showAlert = true; - widgetKey = requiredWidgets[i].key; - TourPageNumber = updatePage; - setminRequiredCount(null); - } - } - } - } - } - } - } - //when showAlert is true then break the loop and show alert to fill required data in widgets - if (showAlert) { - break; - } - } - if (checkboxExist && requiredCheckbox && showAlert) { - setUnSignedWidgetId(widgetKey); - setPageNumber(TourPageNumber); - setWidgetsTour(true); - } else if (radioExist && showAlert) { - setUnSignedWidgetId(widgetKey); - setPageNumber(TourPageNumber); - setWidgetsTour(true); - } else if (showAlert) { - setUnSignedWidgetId(widgetKey); - setPageNumber(TourPageNumber); + const status = handleCheckResponse(checkUser,setminRequiredCount) + if (status?.showAlert) { + setUnSignedWidgetId(status?.widgetKey); + setPageNumber(status?.tourPageNumber); setWidgetsTour(true); + setIsUiLoading(false); } else { - setIsUiLoading(true); // `widgets` is Used to return widgets details with page number of current user const widgets = checkUser?.[0]?.placeHolder; let pdfArrBuffer; @@ -829,7 +699,6 @@ function PdfRequestFiles( isSignYourSelfFlow, scale ); - // console.log("pdfte", pdfBytes); //get ExistUserPtr object id of user class to get tenantDetails if (!pdfBytes?.error) { const objectId = pdfDetails?.[0]?.ExtUserPtr?.UserId?.objectId; @@ -855,16 +724,19 @@ function PdfRequestFiles( isSuccessRoute, contactId ); - const index = pdfDetails?.[0]?.Signers.findIndex( - (x) => x.objectId === signerObjectId - ); + const index = + updatedDoc.updatedPdfDetails?.[0]?.Signers.findIndex( + (x) => x.objectId === contactId + ); const newIndex = index + 1; const usermail = { - Email: pdfDetails?.[0]?.Placeholders[newIndex]?.email || "" + Email: + updatedDoc.updatedPdfDetails?.[0]?.Placeholders[newIndex] + ?.email || "" }; const user = usermail?.Email ? usermail - : pdfDetails?.[0]?.Signers[newIndex]; + : updatedDoc.updatedPdfDetails?.[0]?.Signers[newIndex]; if ( sendmail !== "false" && sendInOrder @@ -1023,6 +895,7 @@ function PdfRequestFiles( isShow: true, alertMessage: t("something-went-wrong-mssg") }); + setIsUiLoading(false); } } catch (err) { console.log("err in embedsign", err); @@ -1034,8 +907,8 @@ function PdfRequestFiles( } } } - const handleSignPdf = async () => { + setIsUiLoading(true); await embedWidgetsData(); }; @@ -1059,15 +932,15 @@ function PdfRequestFiles( let filterSignerPos = []; if (signerObjId) { //get current signerObjId placeholder details - filterSignerPos = updateSignPos.filter( + filterSignerPos = updateSignPos?.filter( (data) => data.Id === signerObjId ); } if (filterSignerPos.length > 0) { - const getPlaceHolder = filterSignerPos[0].placeHolder; + const getPlaceHolder = filterSignerPos[0]?.placeHolder; //get position of current pagenumber - const getPageNumer = getPlaceHolder.filter( + const getPageNumer = getPlaceHolder?.filter( (data) => data.pageNumber === pageNumber ); if (getPageNumer.length > 0) { @@ -1111,9 +984,9 @@ function PdfRequestFiles( setIsTextSetting(value); }; const handleSaveFontSize = () => { - const filterSignerPos = signerPos.filter((data) => data.Id === uniqueId); + const filterSignerPos = signerPos?.filter((data) => data.Id === uniqueId); if (filterSignerPos) { - const placehoder = filterSignerPos[0].placeHolder; + const placehoder = filterSignerPos[0]?.placeHolder; const getPageNumer = placehoder.filter( (data) => data.pageNumber === pageNumber ); @@ -1229,7 +1102,7 @@ function PdfRequestFiles( const addDefaultSignature = () => { const type = defaultSignAlert?.type; //get current signers placeholder position data - const currentSignerPosition = signerPos.filter( + const currentSignerPosition = signerPos?.filter( (data) => data.signerObjId === signerObjectId ); const defaultSign = type === "signature" ? defaultSignImg : myInitial; @@ -1254,7 +1127,8 @@ function PdfRequestFiles( setRequestSignTour(true); if (isDontShow) { const isEnableOTP = pdfDetails?.[0]?.IsEnableOTP || false; - if (!isEnableOTP) { + const sessionToken = localStorage.getItem("accesstoken"); + if (!isEnableOTP && !sessionToken) { try { await axios.post( `${localStorage.getItem("baseUrl")}functions/updatecontacttour`, @@ -1619,11 +1493,11 @@ function PdfRequestFiles( } if (uniqueId) { let filterSignerPos, currentPagePosition; - filterSignerPos = signerPos.find((data) => data.Id === uniqueId); + filterSignerPos = signerPos?.find((data) => data.Id === uniqueId); const getPlaceHolder = filterSignerPos?.placeHolder; if (getPlaceHolder) { //checking exist placeholder on same page - currentPagePosition = getPlaceHolder.find( + currentPagePosition = getPlaceHolder?.find( (data) => data.pageNumber === pageNumber ); } @@ -1651,12 +1525,6 @@ function PdfRequestFiles( ); setSignerPos(updatesignerPos); } - - // if (dragTypeValue === "dropdown") { - // setShowDropdown(true); - // } else if (dragTypeValue === "checkbox") { - // setIsCheckbox(true); - // } else if ( [textWidget, "name", "company", "job title", "email"].includes( dragTypeValue @@ -1672,7 +1540,7 @@ function PdfRequestFiles( //function for delete signature block const handleDeleteSign = (key, Id) => { const updateData = []; - const filterSignerPos = signerPos.filter((data) => data.Id === Id); + const filterSignerPos = signerPos?.filter((data) => data.Id === Id); if (filterSignerPos.length > 0) { const getPlaceHolder = filterSignerPos[0].placeHolder; const getPageNumer = getPlaceHolder.filter( @@ -1700,7 +1568,7 @@ function PdfRequestFiles( }); setSignerPos(newUpdateSigner); } else { - const getRemainPage = filterSignerPos[0].placeHolder.filter( + const getRemainPage = filterSignerPos[0]?.placeHolder?.filter( (data) => data.pageNumber !== pageNumber ); //condition to check placeholder length is greater than 1 do not need to remove whole placeholder @@ -1713,11 +1581,11 @@ function PdfRequestFiles( return obj; }); let signerupdate = []; - signerupdate = signerPos.filter((data) => data.Id !== Id); + signerupdate = signerPos?.filter((data) => data.Id !== Id); signerupdate.push(newUpdatePos[0]); setSignerPos(signerupdate); } else { - const updatedData = signerPos.map((item) => { + const updatedData = signerPos?.map((item) => { if (item.Id === Id) { // Create a copy of the item object and delete the placeHolder field const updatedItem = { ...item }; @@ -1735,7 +1603,7 @@ function PdfRequestFiles( //function to get first widget and page number to assign currect signer and tour message const showFirstWidget = () => { if (!requestSignTour) { - const getCurrentUserPlaceholder = signerPos.find( + const getCurrentUserPlaceholder = signerPos?.find( (x) => x.Id === uniqueId ); const placeholder = getCurrentUserPlaceholder.placeHolder; @@ -1756,7 +1624,6 @@ function PdfRequestFiles( setShowSignPagenumber(sortedPagenumber); } }; - return ( )} <DownloadPdfZip diff --git a/apps/OpenSign/src/pages/PlaceHolderSign.jsx b/apps/OpenSign/src/pages/PlaceHolderSign.jsx index e215d3d816..51e3f8412f 100644 --- a/apps/OpenSign/src/pages/PlaceHolderSign.jsx +++ b/apps/OpenSign/src/pages/PlaceHolderSign.jsx @@ -27,6 +27,7 @@ import { multiSignEmbed, addWidgetOptions, textInputWidget, + cellsWidget, textWidget, radioButtonWidget, color, @@ -1417,7 +1418,8 @@ function PlaceHolderSign() { deleteOption, status, defaultValue, - isHideLabel + isHideLabel, + layout ) => { const filterSignerPos = signerPos.filter((data) => data.Id === uniqueId); if (filterSignerPos.length > 0) { @@ -1453,6 +1455,7 @@ function PlaceHolderSign() { name: dropdownName, values: dropdownOptions, status: status, + layout: layout, isReadOnly: isReadOnly || false, isHideLabel: isHideLabel || false, defaultValue: defaultValue, @@ -1492,6 +1495,7 @@ function PlaceHolderSign() { maxRequiredCount: maxCount }, defaultValue: defaultValue, + layout: layout, isReadOnly: isReadOnly || false, isHideLabel: isHideLabel || false, fontSize: @@ -1590,6 +1594,30 @@ function PlaceHolderSign() { isReadOnly: defaultdata?.isReadOnly || false } }; + } else if (position.type === cellsWidget) { + return { + ...position, + options: { + ...position.options, + name: defaultdata?.name || "Cells", + status: defaultdata?.status || "required", + hint: defaultdata?.hint || "", + cellCount: parseInt(defaultdata?.cellCount || 5), + defaultValue: (defaultdata?.defaultValue || "").slice( + 0, + parseInt(defaultdata?.cellCount || 5) + ), + validation: + {}, + fontSize: + fontSize || currWidgetsDetails?.options?.fontSize || 12, + fontColor: + fontColor || + currWidgetsDetails?.options?.fontColor || + "black", + isReadOnly: defaultdata?.isReadOnly || false + } + }; } else if (["signature"].includes(position.type)) { return { ...position, @@ -2150,7 +2178,7 @@ function PlaceHolderSign() { navigate("/report/1MwEuxLEkF"); }} > - <div className="h-[100%] p-[20px]"> + <div className="h-[100%] p-[20px] text-base-content"> {mailStatus === "success" ? ( <div className="text-center mb-[10px]"> <LottieWithLoader /> @@ -2602,7 +2630,7 @@ function PlaceHolderSign() { title={t("document-alert")} showClose={false} > - <div className="h-[100%] p-[20px]"> + <div className="h-[100%] p-[20px] text-base-content"> <p>{isAlreadyPlace.message}</p> <div className="h-[1px] w-full my-[15px] bg-[#9f9f9f]"></div> <button diff --git a/apps/OpenSign/src/pages/Preferences.jsx b/apps/OpenSign/src/pages/Preferences.jsx index 85179c40c6..0e6d170e30 100644 --- a/apps/OpenSign/src/pages/Preferences.jsx +++ b/apps/OpenSign/src/pages/Preferences.jsx @@ -301,7 +301,7 @@ const Preferences = () => { JSON.parse(localStorage.getItem("Extand_Class"))?.[0]; if (extUser && extUser?.objectId) { extUser.TenantId.RequestBody = updateRes?.RequestBody; - extUser.TenantId.RequestBody = updateRes?.RequestSubject; + extUser.TenantId.RequestSubject = updateRes?.RequestSubject; const _extUser = JSON.parse(JSON.stringify(extUser)); localStorage.setItem("Extand_Class", JSON.stringify([_extUser])); } diff --git a/apps/OpenSign/src/pages/Report.jsx b/apps/OpenSign/src/pages/Report.jsx index 6b96481f8c..868e2a9bb0 100644 --- a/apps/OpenSign/src/pages/Report.jsx +++ b/apps/OpenSign/src/pages/Report.jsx @@ -1,4 +1,4 @@ -import React, { useEffect, useState } from "react"; +import React, { useEffect, useState, useRef } from "react"; import ReportTable from "../primitives/GetReportDisplay"; import Parse from "parse"; import axios from "axios"; @@ -27,12 +27,18 @@ const Report = () => { const [isImport, setIsImport] = useState(false); const abortController = new AbortController(); const docPerPage = 10; + const [searchTerm, setSearchTerm] = useState(""); + const [mobileSearchOpen, setMobileSearchOpen] = useState(false); + const [isSearchResult, setIsSearchResult] = useState(false); + const debounceTimer = useRef(null); // below useEffect is call when id param change useEffect(() => { setReportName(""); setList([]); - getReportData(); + setSearchTerm(""); + setMobileSearchOpen(false); + getReportData(0, docPerPage, ""); // Function returned from useEffect is called on unmount return () => { @@ -48,7 +54,7 @@ const Report = () => { // below useEffect call when isNextRecord state is true and fetch next record useEffect(() => { if (isNextRecord) { - getReportData(List.length, 20); + getReportData(List.length, 20, searchTerm); } // eslint-disable-next-line }, [isNextRecord]); @@ -56,7 +62,58 @@ const Report = () => { const handleDontShow = (isChecked) => { setIsDontShow(isChecked); }; - const getReportData = async (skipUserRecord = 0, limit = 20) => { + + const handleSearchChange = async (e) => { + const term = e.target.value.toLowerCase(); + setSearchTerm(term); + if (debounceTimer.current) { + clearTimeout(debounceTimer.current); + } + debounceTimer.current = setTimeout(async () => { + try { + const headers = { + "Content-Type": "application/json", + "X-Parse-Application-Id": localStorage.getItem("parseAppId"), + sessiontoken: localStorage.getItem("accesstoken") + }; + const url = `${localStorage.getItem("baseUrl")}functions/getReport`; + const res = await axios.post( + url, + { reportId: id, searchTerm: term, skip: 0, limit: docPerPage }, + { headers } + ); + const data = res.data?.result || []; + if (!data.error) { + setList(data); + setIsMoreDocs(data.length >= docPerPage); + setIsNextRecord(false); + setIsSearchResult(true); + } + } catch (err) { + console.error("Search error:", err); + } + }, 300); + setIsSearchResult(false); + }; + + const handleSearchPaste = (e) => { + setTimeout(() => { + handleSearchChange({ target: { value: e.target.value } }); + }, 0); + }; + + useEffect(() => { + return () => { + if (debounceTimer.current) { + clearTimeout(debounceTimer.current); + } + }; + }, []); + const getReportData = async ( + skipUserRecord = 0, + limit = 20, + term = searchTerm + ) => { // setIsLoader(true); const json = reportJson(id); if (json) { @@ -77,6 +134,9 @@ const Report = () => { const skipRecord = id === "4Hhwbp482K" ? 0 : skipUserRecord; const limitRecord = id === "4Hhwbp482K" ? 200 : limit; const params = { reportId: id, skip: skipRecord, limit: limitRecord }; + if (term) { + params.searchTerm = term; + } const url = `${localStorage.getItem("baseUrl")}functions/getReport`; const res = await axios.post(url, params, { headers: headers, @@ -197,6 +257,12 @@ const Report = () => { report_help={reporthelp} tourData={tourData} isDontShow={isDontShow} + mobileSearchOpen={mobileSearchOpen} + setMobileSearchOpen={setMobileSearchOpen} + searchTerm={searchTerm} + handleSearchChange={handleSearchChange} + handleSearchPaste={handleSearchPaste} + isSearchResult={isSearchResult} isImport={isImport} /> ) : ( diff --git a/apps/OpenSign/src/pages/SignyourselfPdf.jsx b/apps/OpenSign/src/pages/SignyourselfPdf.jsx index 3b7a3bae39..93f5a79f1f 100644 --- a/apps/OpenSign/src/pages/SignyourselfPdf.jsx +++ b/apps/OpenSign/src/pages/SignyourselfPdf.jsx @@ -22,6 +22,7 @@ import { randomId, getDate, textWidget, + cellsWidget, convertPdfArrayBuffer, textInputWidget, fetchImageBase64, @@ -68,6 +69,8 @@ import { resetWidgetState } from "../redux/reducers/widgetSlice.js"; import WidgetsValueModal from "../components/pdf/WidgetsValueModal"; +import WidgetNameModal from "../components/pdf/WidgetNameModal"; +import CellsSettingModal from "../components/pdf/CellsSettingModal"; //For signYourself inProgress section signer can add sign and complete doc sign. function SignYourSelf() { const { t } = useTranslation(); @@ -118,6 +121,10 @@ function SignYourSelf() { const [isTextSetting, setIsTextSetting] = useState(false); const [currWidgetsDetails, setCurrWidgetsDetails] = useState({}); const [isCheckbox, setIsCheckbox] = useState(false); + const [isNameModal, setIsNameModal] = useState(false); + const [isCellsSetting, setIsCellsSetting] = useState(false); + const openNameModal = () => setIsNameModal(true); + const openCellsSettingModal = () => setIsCellsSetting(true); const [pdfLoad, setPdfLoad] = useState(false); const [isAlert, setIsAlert] = useState({ isShow: false, alertMessage: "" }); const [isDontShow, setIsDontShow] = useState(false); @@ -356,9 +363,13 @@ function SignYourSelf() { ); const dragTypeValue = item?.text ? item.text : monitor.type; const widgetValue = getWidgetValue(dragTypeValue); - const widgetTypeExist = ["name", "company", "job title", "email"].includes( - dragTypeValue - ); + const widgetTypeExist = [ + "name", + "company", + "job title", + "email", + cellsWidget + ].includes(dragTypeValue); const containerScale = getContainerScale( pdfOriginalWH, pageNumber, @@ -439,6 +450,7 @@ function SignYourSelf() { [ textInputWidget, textWidget, + cellsWidget, "name", "company", "job title", @@ -931,7 +943,8 @@ function SignYourSelf() { deleteOption, status, defaultValue, - isHideLabel + isHideLabel, + layout ) => { const getPageNumer = xyPosition.filter( (data) => data.pageNumber === pageNumber @@ -939,6 +952,8 @@ function SignYourSelf() { if (getPageNumer.length > 0) { const getXYdata = getPageNumer[0].pos; const getPosData = getXYdata; + const widgetLayout = + currWidgetsDetails?.type === "checkbox" ? { layout: layout } : {}; const addSignPos = getPosData.map((position) => { if (position.key === currWidgetsDetails?.key) { if (addOption) { @@ -962,6 +977,7 @@ function SignYourSelf() { ...position.options, name: dropdownName, values: dropdownOptions, + ...widgetLayout, isReadOnly: isReadOnly, isHideLabel: isHideLabel || false, fontSize: @@ -1028,6 +1044,92 @@ function SignYourSelf() { handleTextSettingModal(false); } }; + + const setCellCount = (key, newCount) => { + setXyPosition((prev) => { + const getPageNumer = prev.filter((data) => data.pageNumber === pageNumber); + if (getPageNumer.length > 0) { + const updatePos = getPageNumer[0].pos.map((p) => + p.key === key ? { ...p, options: { ...p.options, cellCount: newCount } } : p + ); + return prev.map((obj, ind) => (ind === index ? { ...obj, pos: updatePos } : obj)); + } + return prev; + }); + }; + + const handleWidgetdefaultdata = (defaultdata) => { + const newFontSize = + defaultdata?.fontSize !== undefined ? defaultdata.fontSize : fontSize; + const newFontColor = + defaultdata?.fontColor !== undefined ? defaultdata.fontColor : fontColor; + + const getPageNumer = xyPosition.filter( + (data) => data.pageNumber === pageNumber + ); + if (getPageNumer.length > 0) { + const updatePos = getPageNumer[0].pos.map((position) => { + if (position.key === currWidgetsDetails?.key) { + if (position.type === cellsWidget) { + const count = parseInt( + defaultdata?.cellCount ?? position.options?.cellCount ?? 5, + 10 + ); + return { + ...position, + options: { + ...position.options, + name: defaultdata?.name || position.options?.name || "Cells", + cellCount: count, + defaultValue: (defaultdata?.defaultValue || "").slice(0, count), + fontSize: newFontSize || position.options?.fontSize || 12, + fontColor: newFontColor || position.options?.fontColor || "black" + } + }; + } else { + return { + ...position, + options: { + ...position.options, + name: defaultdata?.name || position.options?.name, + fontSize: newFontSize || position.options?.fontSize || 12, + fontColor: + newFontColor || position.options?.fontColor || "black" + } + }; + } + } + return position; + }); + const updateXYposition = xyPosition.map((obj, ind) => + ind === index ? { ...obj, pos: updatePos } : obj + ); + setXyPosition(updateXYposition); + } + setFontSize(); + setFontColor(); + setCurrWidgetsDetails({}); + setIsNameModal(false); + }; + + const handleNameModal = () => { + setIsNameModal(false); + setCurrWidgetsDetails({}); + setIsCheckbox(false); + }; + + const handleCellsSettingSave = (data) => { + // ensure font and color are updated before applying widget changes + if (data?.fontSize !== undefined) setFontSize(data.fontSize); + if (data?.fontColor !== undefined) setFontColor(data.fontColor); + handleWidgetdefaultdata(data); + setIsCellsSetting(false); + }; + + const handleCellsSettingClose = () => { + setIsCellsSetting(false); + setCurrWidgetsDetails({}); + }; const clickOnZoomIn = () => { onClickZoomIn(scale, zoomPercent, setScale, setZoomPercent); }; @@ -1183,9 +1285,8 @@ function SignYourSelf() { title={t("document-signed")} handleClose={() => setShowAlreadySignDoc({ status: false })} > - <div className="p-[20px] h-full"> + <div className="p-[20px] h-full text-base-content"> <p>{showAlreadySignDoc.mssg}</p> - <div className="h-[1px] w-full my-[15px] bg-[#9f9f9f]"></div> <button className="op-btn op-btn-ghost shadow-md" @@ -1283,12 +1384,15 @@ function SignYourSelf() { setIsPageCopy={setIsPageCopy} setIsCheckbox={setIsCheckbox} setCurrWidgetsDetails={setCurrWidgetsDetails} + handleNameModal={openNameModal} + handleCellSettingModal={openCellsSettingModal} handleTextSettingModal={handleTextSettingModal} setScale={setScale} scale={scale} pdfBase64Url={pdfBase64Url} fontSize={fontSize} setFontSize={setFontSize} + setCellCount={setCellCount} fontColor={fontColor} setFontColor={setFontColor} isResize={isResize} @@ -1330,6 +1434,7 @@ function SignYourSelf() { xyPosition={xyPosition} //placeholder details pageNumber={pageNumber} //current page number setXyPosition={setXyPosition} //placeholder details state + setCellCount={setCellCount} setPageNumber={setPageNumber} setCurrWidgetsDetails={setCurrWidgetsDetails} currWidgetsDetails={currWidgetsDetails} @@ -1338,6 +1443,23 @@ function SignYourSelf() { signatureTypes={signatureTypes} /> )} + <WidgetNameModal + widgetName={currWidgetsDetails?.options?.name} + defaultdata={currWidgetsDetails} + isOpen={isNameModal} + handleClose={handleNameModal} + handleData={handleWidgetdefaultdata} + fontSize={fontSize} + setFontSize={setFontSize} + fontColor={fontColor} + setFontColor={setFontColor} + /> + <CellsSettingModal + isOpen={isCellsSetting} + defaultData={currWidgetsDetails} + handleClose={handleCellsSettingClose} + handleSave={handleCellsSettingSave} + /> <RotateAlert showRotateAlert={showRotateAlert.status} setShowRotateAlert={setShowRotateAlert} diff --git a/apps/OpenSign/src/pages/TemplatePlaceholder.jsx b/apps/OpenSign/src/pages/TemplatePlaceholder.jsx index 85b4e249f9..4cb2d3bd68 100644 --- a/apps/OpenSign/src/pages/TemplatePlaceholder.jsx +++ b/apps/OpenSign/src/pages/TemplatePlaceholder.jsx @@ -1,4 +1,4 @@ -import React, { useEffect, useState, useRef } from "react"; +import { useEffect, useState, useRef } from "react"; import RenderAllPdfPage from "../components/pdf/RenderAllPdfPage"; import { useParams, useNavigate } from "react-router"; import axios from "axios"; @@ -22,6 +22,7 @@ import { defaultWidthHeight, addWidgetOptions, textInputWidget, + cellsWidget, radioButtonWidget, getContainerScale, convertBase64ToFile, @@ -1274,7 +1275,8 @@ const TemplatePlaceholder = () => { deleteOption, status, defaultValue, - isHideLabel + isHideLabel, + layout ) => { const filterSignerPos = signerPos.filter((data) => data.Id === uniqueId); if (filterSignerPos.length > 0) { @@ -1313,6 +1315,7 @@ const TemplatePlaceholder = () => { name: dropdownName, values: dropdownOptions, status: status, + layout: layout, defaultValue: defaultValue, isReadOnly: isReadOnly || false, isHideLabel: isHideLabel || false, @@ -1351,6 +1354,7 @@ const TemplatePlaceholder = () => { minRequiredCount: minCount, maxRequiredCount: maxCount }, + layout: layout, isReadOnly: isReadOnly || false, defaultValue: defaultValue, isHideLabel: isHideLabel || false, @@ -1451,6 +1455,36 @@ const TemplatePlaceholder = () => { "black" } }; + } else if (position.type === cellsWidget) { + return { + ...position, + options: { + ...position.options, + name: defaultdata?.name || "Cells", + status: defaultdata?.status || "required", + hint: defaultdata?.hint || "", + cellCount: parseInt(defaultdata?.cellCount || 5), + defaultValue: (defaultdata?.defaultValue || "").slice( + 0, + parseInt(defaultdata?.cellCount || 5) + ), + validation: + isSubscribe && inputype + ? { + type: inputype, + pattern: + inputype === "regex" ? defaultdata.textvalidate : "" + } + : {}, + isReadOnly: defaultdata?.isReadOnly || false, + fontSize: + fontSize || currWidgetsDetails?.options?.fontSize || 12, + fontColor: + fontColor || + currWidgetsDetails?.options?.fontColor || + "black" + } + }; } else if (["signature"].includes(position.type)) { return { ...position, @@ -1510,6 +1544,22 @@ const TemplatePlaceholder = () => { setIsRadio(false); setIsCheckbox(false); }; + const setCellCount = (key, newCount) => { + const updated = signerPos.map((signer) => { + if (signer.Id !== uniqueId) return signer; + const placeHolder = signer.placeHolder.map((ph) => { + if (ph.pageNumber !== pageNumber) return ph; + const pos = ph.pos.map((p) => + p.key === key + ? { ...p, options: { ...p.options, cellCount: newCount } } + : p + ); + return { ...ph, pos }; + }); + return { ...signer, placeHolder }; + }); + setSignerPos(updated); + }; const clickOnZoomIn = () => { onClickZoomIn(scale, zoomPercent, setScale, setZoomPercent); @@ -1671,7 +1721,7 @@ const TemplatePlaceholder = () => { navigate("/report/6TeaPr321t"); }} > - <div className="h-full p-[20px] mb-2"> + <div className="h-full p-[20px] mb-2 text-base-content"> <p>{t("template-created-alert")}</p> <div className="h-[1px] w-full my-[15px] bg-[#9f9f9f]"></div> <div className="flex gap-1 flex-col md:flex-row"> @@ -1828,6 +1878,7 @@ const TemplatePlaceholder = () => { pdfBase64Url={pdfBase64Url} fontSize={fontSize} setFontSize={setFontSize} + setCellCount={setCellCount} fontColor={fontColor} setFontColor={setFontColor} isResize={isResize} diff --git a/apps/OpenSign/src/pages/UserList.jsx b/apps/OpenSign/src/pages/UserList.jsx index bdf38ee2f8..52d2d20e69 100644 --- a/apps/OpenSign/src/pages/UserList.jsx +++ b/apps/OpenSign/src/pages/UserList.jsx @@ -284,7 +284,7 @@ const UserList = () => { handleClose={handleClose} > <div className="m-[20px]"> - <div className="text-lg font-normal text-black"> + <div className="text-lg font-normal text-base-content"> {t("are-you-sure")}{" "} {item?.IsDisabled ? t("activate") diff --git a/apps/OpenSign/src/pages/UserProfile.jsx b/apps/OpenSign/src/pages/UserProfile.jsx index 8c6f02c2ca..17f286a3f1 100644 --- a/apps/OpenSign/src/pages/UserProfile.jsx +++ b/apps/OpenSign/src/pages/UserProfile.jsx @@ -286,7 +286,7 @@ function UserProfile() { style={{ width: `${percentage}%` }} ></div> </div> - <span className="text-black text-sm">{percentage}%</span> + <span className="text-base-contentk text-sm">{percentage}%</span> </div> )} <div className="text-base font-semibold pt-4"> diff --git a/apps/OpenSign/src/primitives/DownloadPdfZip.jsx b/apps/OpenSign/src/primitives/DownloadPdfZip.jsx index 2c454316e2..f6e59d21e7 100644 --- a/apps/OpenSign/src/primitives/DownloadPdfZip.jsx +++ b/apps/OpenSign/src/primitives/DownloadPdfZip.jsx @@ -91,7 +91,7 @@ function DownloadPdfZip(props) { title={t("download-files")} handleClose={() => props.setIsDownloadModal(false)} > - <div className="p-[20px] h-full"> + <div className="p-[20px] h-full text-base-content"> {downloadType.map((data, ind) => { return ( <label diff --git a/apps/OpenSign/src/primitives/GetReportDisplay.jsx b/apps/OpenSign/src/primitives/GetReportDisplay.jsx index 8c7b15ee96..302f1a02ae 100644 --- a/apps/OpenSign/src/primitives/GetReportDisplay.jsx +++ b/apps/OpenSign/src/primitives/GetReportDisplay.jsx @@ -7,6 +7,7 @@ import ModalUi from "./ModalUi"; import AddSigner from "../components/AddSigner"; import { emailRegex, + iconColor, } from "../constant/const"; import Alert from "./Alert"; import Tooltip from "./Tooltip"; @@ -38,9 +39,12 @@ import { useTranslation } from "react-i18next"; import DownloadPdfZip from "./DownloadPdfZip"; import * as XLSX from "xlsx"; import EditContactForm from "../components/EditContactForm"; +import { useElSize } from "../hook/useElSize"; const ReportTable = (props) => { const copyUrlRef = useRef(null); + const titleRef = useRef(null); + const titleElement = useElSize(titleRef); const appName = "OpenSign™"; const drivename = appName === "OpenSign™" ? "OpenSign™" : ""; @@ -92,6 +96,12 @@ const ReportTable = (props) => { const startIndex = (currentPage - 1) * props.docPerPage; const { isMoreDocs, setIsNextRecord } = props; + useEffect(() => { + if (props.isSearchResult) { + setCurrentPage(1); + } + }, [props.isSearchResult]); + const getPaginationRange = () => { const totalPageNumbers = 7; // Adjust this value to show more/less page numbers const pages = []; @@ -907,7 +917,6 @@ const ReportTable = (props) => { setActLoader({}); } }; - const handleUpdateExpiry = async (e, item) => { e.preventDefault(); e.stopPropagation(); @@ -999,7 +1008,7 @@ const ReportTable = (props) => { ? "op-border-primary op-text-primary" : x.Activity === "VIEWED" ? "border-green-400 text-green-400" - : "border-black text-black" + : "border-base-content text-base-content" } focus:outline-none border-2 w-[60px] h-[30px] text-[11px] rounded-full`} > {x?.Activity?.toUpperCase() || "-"} @@ -1314,7 +1323,6 @@ const ReportTable = (props) => { try { const params = { docId: doc?.objectId }; const templateRes = await Parse.Cloud.run("saveastemplate", params); - // console.log("templateRes ", templateRes); setTemplateId(templateRes?.id); setIsSuccess({ [doc.objectId]: true }); } catch (err) { @@ -1394,6 +1402,12 @@ const ReportTable = (props) => { setActLoader({}); } }; + + const restrictBtn = (item, act) => { + return item.IsSignyourself && act.action === "recreatedocument" + ? true + : false; + }; return ( <div className="relative"> {Object.keys(actLoader)?.length > 0 && ( @@ -1416,7 +1430,10 @@ const ReportTable = (props) => { /> </> )} - <div className="flex flex-row items-center justify-between my-2 mx-3 text-[20px] md:text-[23px]"> + <div + ref={titleRef} + className="flex flex-row items-center justify-between my-2 mx-3 text-[20px] md:text-[23px]" + > <div className="font-light"> {t(`report-name.${props.ReportName}`)}{" "} {props.report_help && ( @@ -1428,26 +1445,68 @@ const ReportTable = (props) => { </span> )} </div> - <div className="flex flex-row justify-center items-center gap-3"> + <div className="flex flex-row justify-center items-center gap-3 mb-2"> + {/* Search input for report bigger in width */} + {titleElement?.width > 500 && ( + <div className="flex"> + <input + type="search" + value={props.searchTerm} + onChange={props.handleSearchChange} + placeholder={ + props.ReportName === "Contactbook" + ? t("search-contacts") + : isTemplateReport + ? t("search-templates") + : t("search-documents") + } + onPaste={props.handleSearchPaste} + className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-64 text-xs" + /> + </div> + )} + {/* contact import */} {props.isImport && ( - <div className="cursor-pointer" onClick={() => handleImportBtn()}> - <i className="fa-light fa-upload op-text-secondary text-[23px] md:text-[30px]"></i> + <div + className="cursor-pointer flex" + onClick={() => handleImportBtn()} + > + <i className="fa-light fa-upload op-text-secondary text-[23px] md:text-[25px]"></i> </div> )} + {/* add contact form */} {props.form && ( <div - className="cursor-pointer" + className="cursor-pointer flex" onClick={() => handleContactFormModal()} > - <i className="fa-light fa-square-plus text-accent text-[30px] md:text-[35px]"></i> + <i className="fa-light fa-square-plus text-accent text-[30px] md:text-[32px]"></i> </div> )} + {/* create template form */} {isTemplateReport && ( - <i + <div data-tut="reactourFirst" + className="cursor-pointer flex" onClick={() => navigate("/form/template")} - className="cursor-pointer fa-light fa-square-plus text-accent text-[30px] md:text-[35px]" - ></i> + > + <i className="cursor-pointer fa-light fa-square-plus text-accent text-[30px] md:text-[32px]"></i> + </div> + )} + {/* search icon/magnifer icon */} + {titleElement?.width < 500 && ( + <button + className="flex justify-center items-center focus:outline-none rounded-md text-[18px]" + aria-label="Search" + onClick={() => + props.setMobileSearchOpen(!props.mobileSearchOpen) + } + > + <i + style={{ color: `${iconColor}` }} + className="fa-solid fa-magnifying-glass" + ></i> + </button> )} <ModalUi isOpen={isModal?.export} @@ -1536,6 +1595,19 @@ const ReportTable = (props) => { </ModalUi> </div> </div> + {/* Search input for report smalle in width */} + {titleElement?.width < 500 && props.mobileSearchOpen && ( + <div className="top-full left-0 w-full bg-white px-3 pt-1 pb-3"> + <input + type="search" + value={props.searchTerm} + onChange={props.handleSearchChange} + placeholder={t("search-documents")} + onPaste={props.handleSearchPaste} + className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs" + /> + </div> + )} <div className={`overflow-auto w-full border-b ${ props.List?.length > 0 @@ -1602,7 +1674,7 @@ const ReportTable = (props) => { handleClose={handleClose} > <div className="m-[20px]"> - <div className="text-lg font-normal text-black"> + <div className="text-lg font-normal text-base-content"> {t("contact-delete-alert")} </div> <hr className="bg-[#ccc] mt-4 " /> @@ -1837,33 +1909,39 @@ const ReportTable = (props) => { {isOption[item.objectId] && act.action === "option" && ( <ul className="absolute -right-1 top-auto z-[70] w-max op-dropdown-content op-menu shadow-black/20 shadow bg-base-100 text-base-content rounded-box"> - {act.subaction?.map((subact) => ( - <li - key={subact.btnId} - onClick={() => - handleActionBtn( - subact, - item - ) - } - title={t( - `btnLabel.${subact.hoverLabel}` - )} - > - <span> - <i - className={`${subact.btnIcon} mr-1.5`} - ></i> - {subact.btnLabel && ( - <span className="text-[13px] capitalize font-medium"> - {t( - `btnLabel.${subact.btnLabel}` + {act.subaction?.map( + (subact) => + !restrictBtn( + item, + subact + ) && ( + <li + key={subact.btnId} + onClick={() => + handleActionBtn( + subact, + item + ) + } + title={t( + `btnLabel.${subact.hoverLabel}` + )} + > + <span> + <i + className={`${subact.btnIcon} mr-1.5`} + ></i> + {subact.btnLabel && ( + <span className="text-[13px] capitalize font-medium"> + {t( + `btnLabel.${subact.btnLabel}` + )} + </span> )} </span> - )} - </span> - </li> - ))} + </li> + ) + )} </ul> )} </div> @@ -1972,7 +2050,7 @@ const ReportTable = (props) => { </div> ) : ( <div className="m-[20px]"> - <div className="text-lg font-normal text-black"> + <div className="text-lg font-normal text-base-content"> {t("save-as-template-?")} </div> <hr className="bg-[#ccc] mt-3" /> @@ -2010,7 +2088,7 @@ const ReportTable = (props) => { </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" + className="rounded-full mb-2 bg-base-300 w-full px-4 py-2 text-base-content border-2 hover:border-spacing-2" defaultValue={ item?.ExpiryDate?.iso?.split("T")?.[0] } @@ -2120,7 +2198,7 @@ const ReportTable = (props) => { handleClose={handleClose} > <div className="m-[20px]"> - <div className="text-lg font-normal text-black"> + <div className="text-lg font-normal text-base-content"> {t("delete-document-alert")} </div> <hr className="bg-[#ccc] mt-4" /> @@ -2177,7 +2255,7 @@ const ReportTable = (props) => { {shareUrls.map((share, i) => ( <div key={i} - className="text-sm font-normal text-black flex my-2 justify-between items-center" + className="text-sm font-normal text-base-content flex my-2 justify-between items-center" > <span className="w-[150px] mr-[5px] md:mr-0 md:w-[300px] whitespace-nowrap overflow-hidden text-ellipsis text-sm font-semibold"> {share.email} @@ -2219,14 +2297,14 @@ const ReportTable = (props) => { handleClose={handleClose} > <div className="m-[20px]"> - <div className="text-sm md:text-lg font-normal text-black"> + <div className="text-sm md:text-lg font-normal text-base-content"> {t("revoke-document-alert")} </div> <div className="mt-2"> <textarea rows={3} placeholder="Reason (optional)" - className="px-4 op-textarea op-textarea-bordered focus:outline-none hover:border-base-content w-full text-xs" + className="px-4 op-textarea op-textarea-bordered text-base-content focus:outline-none hover:border-base-content w-full text-xs" value={reason} onChange={(e) => setReason(e.target.value)} ></textarea> @@ -2337,7 +2415,7 @@ const ReportTable = (props) => { )} {Object?.keys(isNextStep) <= 0 && ( <div className="flex justify-between items-center gap-2 my-2 px-3"> - <div className="text-black"> + <div className="text-base-content"> {user?.signerPtr?.Name || "-"}{" "} {`<${ user?.email diff --git a/apps/OpenSign/src/primitives/PdfDeclineModal.jsx b/apps/OpenSign/src/primitives/PdfDeclineModal.jsx index 3bef8d5431..1200581dda 100644 --- a/apps/OpenSign/src/primitives/PdfDeclineModal.jsx +++ b/apps/OpenSign/src/primitives/PdfDeclineModal.jsx @@ -43,7 +43,7 @@ function CustomModal(props) { </h3> {!isExtendExpiry && ( <div className="p-[10px] px-[20px]"> - <p className="text-[15px]">{props.bodyMssg && props.bodyMssg}</p> + <p className="text-[15px] text-base-content">{props.bodyMssg && props.bodyMssg}</p> </div> )} {!isExtendExpiry && ( @@ -68,7 +68,7 @@ function CustomModal(props) { )} {props.footerMessage && ( <> - <div className="mx-3"> + <div className="mx-3 text-base-content"> <textarea rows={3} placeholder="Reason (optional)" @@ -108,7 +108,7 @@ function CustomModal(props) { </label> <input type="date" - className="rounded-full bg-base-300 w-full px-4 py-2 text-black border-2 hover:border-spacing-2" + className="rounded-full bg-base-300 w-full px-4 py-2 text-base-content border-2 hover:border-spacing-2" defaultValue={props?.doc?.ExpiryDate?.iso?.split("T")?.[0]} onChange={(e) => setExpiryDate(e.target.value)} /> diff --git a/apps/OpenSign/src/styles/AddUser.css b/apps/OpenSign/src/styles/AddUser.css index 0ce531387c..f723dc0a25 100644 --- a/apps/OpenSign/src/styles/AddUser.css +++ b/apps/OpenSign/src/styles/AddUser.css @@ -10,6 +10,10 @@ background-position: right 0.7rem top 50%; background-size: 1rem auto; } +[data-theme="opensigndark"] .validationlist{ + background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABkAAAAZCAYAAADE6YVjAAAAAXNSR0IArs4c6QAAAQ1JREFUSEvtlDtKBTEARc/Fys8OXumndhl2ggt4jTuwsVJQK92DtY1Yuw3bp2jlDvxUcn2BDIQ4k2Sa1ziBNMmdHO4JGbGCoRUwmCCjLP8DXbYPgD3gVtLnkB/bm8AxsJD02Jfr1WX7EJjHD16BC0kf+QG2N4BzYDfu3Um6z3N/ILb3gbMs+AJcpo1igwDYybIh95Su9UFmwPVyrg+BCoBv4FTSexESNm1vRw1bGegNuAFOEkVdJABCi0VVVxewHS49aAve0/EDrGVrX8u1qz5AyBXfSaFRyhhs0IWqj7ECKjZohhTuqAlQ1ZU6yRo1A0ZBYqPw6I6AB0nPrX/J6p20HlTKTZBRFiddo3T9ArZOWBrGcf52AAAAAElFTkSuQmCC"); +} + @media (max-width: 375px) { .validationlist { @@ -17,7 +21,7 @@ } } -@media (min-width:375px) and (max-width: 767px) { +@media (min-width: 375px) and (max-width: 767px) { .validationlist { background-position: right 1rem top 50%; } diff --git a/apps/OpenSign/src/styles/dark-theme-improvements.css b/apps/OpenSign/src/styles/dark-theme-improvements.css new file mode 100644 index 0000000000..11f530c57f --- /dev/null +++ b/apps/OpenSign/src/styles/dark-theme-improvements.css @@ -0,0 +1,143 @@ +/* VS Code Dark Theme Improvements for OpenSign */ + +/* Better disabled button styling for dark mode */ +[data-theme="opensigndark"] { + /* Primary button disabled state */ + .op-btn-primary:disabled { + background-color: #3C3C3C !important; + color: #CCCCCC !important; + border-color: #565656 !important; + opacity: 1 !important; + cursor: not-allowed !important; + } + + .op-btn-primary:disabled:hover { + background-color: #3C3C3C !important; + color: #CCCCCC !important; + border-color: #565656 !important; + transform: none !important; + box-shadow: none !important; + } + + /* Secondary button disabled state */ + .op-btn-secondary:disabled { + background-color: #2A2A2A !important; + color: #999999 !important; + border-color: #444444 !important; + opacity: 1 !important; + cursor: not-allowed !important; + } + + /* Ghost button disabled state */ + .op-btn-ghost:disabled { + background-color: transparent !important; + color: #666666 !important; + border-color: #444444 !important; + opacity: 1 !important; + cursor: not-allowed !important; + } + + /* Better icon visibility for various states */ + .icon-disabled, + .fa-light.text-gray-400, + .fa-light.text-gray-500 { + color: #858585 !important; + } + + .icon-visible, + .nav-icon, + .folder-icon { + color: #CCCCCC !important; + } + + /* Muted/inactive icons with better visibility */ + .muted-icon, + .inactive-icon { + color: #999999 !important; + } + + /* Hover states for better interactivity */ + .hover\\:bg-gray-200:hover { + background-color: #2A2A2A !important; + } + + .hover\\:text-gray-600:hover { + color: #E5E7EB !important; + } + + /* Form elements in disabled state */ + .op-input:disabled, + .op-select:disabled, + .op-textarea:disabled { + background-color: #2A2A2A !important; + color: #999999 !important; + border-color: #444444 !important; + cursor: not-allowed !important; + } + + /* Dropdown menu items */ + .dropdown-item { + color: #E5E7EB !important; + } + + .dropdown-item:hover { + background-color: #2A2A2A !important; + color: #FFFFFF !important; + } + + /* Better text contrast for various elements */ + .text-gray-600 { + color: #CCCCCC !important; + } + + .text-gray-500 { + color: #999999 !important; + } + + .text-gray-400 { + color: #858585 !important; + } + + /* Status indicators with better visibility */ + .status-badge { + box-shadow: 0 2px 4px rgba(255, 255, 255, 0.1) !important; + } + + /* Tooltip improvements */ + .op-tooltip { + background-color: #1F2937 !important; + color: #E5E7EB !important; + border-color: #4B5563 !important; + } + + /* Card and panel borders */ + .op-card, + .border-gray-300 { + border-color: #2C2C2C !important; + } + + /* Loading states */ + .opacity-50 { + opacity: 0.7 !important; + } + + /* Focus states for better accessibility */ + .op-btn:focus-visible, + .op-input:focus-visible, + .op-select:focus-visible { + outline: 2px solid #007ACC !important; + outline-offset: 2px !important; + } +} + +/* Ensure these styles don't affect light mode */ +[data-theme="opensigncss"] { + /* Keep original colors for light mode */ + .icon-disabled { + color: #9CA3AF; + } + + .icon-visible { + color: #6B7280; + } +} diff --git a/apps/OpenSign/src/styles/managesign.css b/apps/OpenSign/src/styles/managesign.css index a15c18073d..d8e749b2b9 100644 --- a/apps/OpenSign/src/styles/managesign.css +++ b/apps/OpenSign/src/styles/managesign.css @@ -1,3 +1,26 @@ +/* Dark mode support for custom warning in Managesign */ +[data-theme="opensigndark"] .customwarning { + background-color: #374151 !important; + color: #E5E7EB !important; + border-color: #4B5563 !important; +} + +[data-theme="opensigndark"] .customwarning::before { + border-color: transparent transparent #4B5563 transparent !important; +} + +/* Dark mode support for signature management warning */ +[data-theme="opensigndark"] .signWarning { + background-color: #374151 !important; + color: #E5E7EB !important; +} + +/* Ensure the Managesign page background is consistent */ +[data-theme="opensigndark"] .managesign-container { + background-color: #121212 !important; + color: #F3F4F6 !important; +} + .customwarning { position: absolute; padding: 8px; diff --git a/apps/OpenSign/src/styles/opensigndrive.css b/apps/OpenSign/src/styles/opensigndrive.css index bd1fd4ea84..8d167b030e 100644 --- a/apps/OpenSign/src/styles/opensigndrive.css +++ b/apps/OpenSign/src/styles/opensigndrive.css @@ -204,6 +204,15 @@ a { align-items: center; } +/* Dark mode support for HoverCard */ +[data-theme="opensigndark"] .HoverCardContent { + background-color: #1F2937; + color: #E5E7EB; + box-shadow: + hsl(0 0% 0% / 50%) 0px 10px 38px -10px, + hsl(0 0% 0% / 30%) 0px 10px 20px -15px; +} + .HoverCardContent[data-side="top"] { animation-name: slideDownAndFade; } @@ -224,6 +233,11 @@ a { fill: white; } +/* Dark mode support for HoverCard arrow */ +[data-theme="opensigndark"] .HoverCardArrow { + fill: #1F2937; +} + @keyframes slideUpAndFade { 0% { opacity: 0; diff --git a/apps/OpenSign/src/styles/signature.css b/apps/OpenSign/src/styles/signature.css index 61c8311b9b..2365a2a9de 100644 --- a/apps/OpenSign/src/styles/signature.css +++ b/apps/OpenSign/src/styles/signature.css @@ -6,7 +6,7 @@ .react-datepicker__input-container { position: initial !important; } -.select-none-cls{ +.select-none-cls { -webkit-user-select: none; /* Disable text selection in WebKit browsers */ -moz-user-select: none; @@ -33,10 +33,17 @@ width: 440px; height: 167px; } -.tabWidth{ +.tabWidth { + border: 1px solid #f3f4f6; + background-color: #f3f4f6; width: 440px; } +[data-theme="opensigndark"] .tabWidth { + border: 1px solid #1f2937 !important; + background-color: #1f2937 !important; +} + .intialSignatureCanvas { width: 150px; height: 150px; @@ -52,7 +59,6 @@ background-color: #111111; /* blue-500 */ } - .intialSignature { border: 2px solid #888; background-color: rgb(255, 255, 255); @@ -60,6 +66,40 @@ height: 183px; } +/* Dark mode support for initials box in /managesign */ +[data-theme="opensigndark"] .intialSignature { + background-color: #1f2937 !important; + border-color: #4b5563 !important; +} + +[data-theme="opensigndark"] .intialSignatureCanvas { + background-color: #1f2937 !important; + border-color: #4b5563 !important; +} + +/* Also support signature canvas for consistency */ +[data-theme="opensigndark"] .signatureCanvas { + background-color: #1f2937 !important; + border-color: #4b5563 !important; +} + +/* Dark mode support for initials box in /managesign */ +[data-theme="opensigndark"] .intialSignature { + background-color: #1f2937 !important; + border-color: #4b5563 !important; +} + +[data-theme="opensigndark"] .intialSignatureCanvas { + background-color: #1f2937 !important; + border-color: #4b5563 !important; +} + +/* Also support signature canvas for consistency */ +[data-theme="opensigndark"] .signatureCanvas { + background-color: #1f2937 !important; + border-color: #4b5563 !important; +} + .penContainerDefault { width: 460px; } @@ -401,7 +441,7 @@ option { width: 300px; height: 120px; } - .tabWidth{ + .tabWidth { width: 300px; } @@ -427,7 +467,7 @@ option { width: 280px; height: 112px; } - .tabWidth{ + .tabWidth { width: 280px; } @@ -451,7 +491,7 @@ option { width: 230px; height: 92px; } - .tabWidth{ + .tabWidth { width: 230px; } diff --git a/apps/OpenSign/tailwind.config.js b/apps/OpenSign/tailwind.config.js index f7c10fe1d9..5dddda0da5 100644 --- a/apps/OpenSign/tailwind.config.js +++ b/apps/OpenSign/tailwind.config.js @@ -6,11 +6,67 @@ module.exports = { }, plugins: [ require("daisyui"), - function ({ addUtilities }) { + function ({ addUtilities, theme }) { addUtilities({ // Prevent iOS long-press popup ".touch-callout-none": { "-webkit-touch-callout": "none" + }, + // VS Code-style disabled button for all themes + ".op-btn-vscode-disabled": { + "background-color": "#3C3C3C !important", + color: "#CCCCCC !important", + "border-color": "#565656 !important", + cursor: "not-allowed !important", + opacity: "1 !important", + "&:hover": { + "background-color": "#3C3C3C !important", + color: "#CCCCCC !important", + "border-color": "#565656 !important", + transform: "none !important" + } + }, + // Dark mode icon improvements using DaisyUI theme detection + '[data-theme="opensigndark"] .icon-improved': { + color: "#CCCCCC !important" + }, + '[data-theme="opensigndark"] .icon-muted': { + color: "#999999 !important" + }, + '[data-theme="opensigndark"] .icon-disabled': { + color: "#858585 !important" + }, + // Gray text improvements for dark mode + '[data-theme="opensigndark"] .text-gray-500': { + color: "#CCCCCC !important" + }, + '[data-theme="opensigndark"] .text-gray-400': { + color: "#999999 !important" + }, + '[data-theme="opensigndark"] .text-gray-600': { + color: "#CCCCCC !important" + }, + // CSS variable utilities that work with arbitrary values + ".icon-themed": { + color: "var(--icon-color)" + }, + ".icon-themed-muted": { + color: "var(--icon-color-muted)" + }, + ".icon-themed-disabled": { + color: "var(--icon-color-disabled)" + }, + ".btn-themed-disabled": { + "background-color": "var(--btn-disabled-bg)", + color: "var(--btn-disabled-color)", + "border-color": "var(--btn-disabled-border)", + cursor: "not-allowed", + "&:hover": { + "background-color": "var(--btn-disabled-bg)", + color: "var(--btn-disabled-color)", + "border-color": "var(--btn-disabled-border)", + transform: "none" + } } }); } @@ -18,7 +74,48 @@ module.exports = { daisyui: { // themes: true, themes: [ - "dark", + { + opensigndark: { + primary: "#007ACC", // VS Code blue - CTA & highlight color + "primary-content": "#FFFFFF", + + secondary: "#1F2937", // Sidebar background (darker slate) + "secondary-content": "#E5E7EB", + + accent: "#4A9EFF", // Lighter VS Code blue for hover, minor CTA + "accent-content": "#FFFFFF", + + neutral: "#3C3C3C", // VS Code inactive/disabled element background + "neutral-content": "#CCCCCC", // VS Code inactive text color + + "base-100": "#121212", // App background + "base-200": "#181818", // Slight elevation (cards) + "base-300": "#1E1E1E", // Further elevated items (panels) + "base-content": "#F3F4F6", // Main text color (soft white) + + info: "#2563EB", // For info panels like "Out for signature" + success: "#22C55E", // Optional: for completed docs or alerts + warning: "#FBBF24", + error: "#EF4444", + + "--rounded-btn": "1.9rem", + "--tab-border": "2px", + "--tab-radius": "0.7rem", + + // Custom CSS variables for icon and button states + "--icon-color": "#CCCCCC", + "--icon-color-muted": "#999999", + "--icon-color-disabled": "#858585", + "--btn-disabled-bg": "#3C3C3C", + "--btn-disabled-color": "#CCCCCC", + "--btn-disabled-border": "#565656", + + // Optional polish + "--navbar-padding": "0.8rem", + "--border-color": "#2C2C2C", // Card/table separation + "--tooltip-color": "#1F2937" + } + }, { opensigncss: { primary: "#002864", diff --git a/apps/OpenSignServer/Dockerhubfile b/apps/OpenSignServer/Dockerhubfile index 45a2aea7ad..459562228e 100644 --- a/apps/OpenSignServer/Dockerhubfile +++ b/apps/OpenSignServer/Dockerhubfile @@ -2,6 +2,11 @@ FROM node:22.14.0 +# Install LibreOffice for DOCX to PDF conversions +RUN apt-get update \ + && apt-get install -y libreoffice \ + && rm -rf /var/lib/apt/lists/* + # Set the working directory inside the container WORKDIR /usr/src/app diff --git a/apps/OpenSignServer/cloud/customRoute/customApp.js b/apps/OpenSignServer/cloud/customRoute/customApp.js index 98ae7cb11e..2fdb0a21e9 100644 --- a/apps/OpenSignServer/cloud/customRoute/customApp.js +++ b/apps/OpenSignServer/cloud/customRoute/customApp.js @@ -2,6 +2,8 @@ import express from 'express'; import cors from 'cors'; import dotenv from 'dotenv'; import uploadFile from './uploadFile.js'; +import docxtopdf, { upload as docxUpload } from './docxtopdf.js'; +import decryptpdf, { upload as decryptUpload } from './decryptpdf.js'; export const app = express(); @@ -11,4 +13,5 @@ app.use(express.json({ limit: '50mb' })); app.use(express.urlencoded({ limit: '50mb', extended: true })); app.post('/file_upload', uploadFile); - +app.post('/docxtopdf', docxUpload.single('file'), docxtopdf); +app.post('/decryptpdf', decryptUpload.single('file'), decryptpdf); diff --git a/apps/OpenSignServer/cloud/customRoute/decryptpdf.js b/apps/OpenSignServer/cloud/customRoute/decryptpdf.js new file mode 100644 index 0000000000..f8aa99c374 --- /dev/null +++ b/apps/OpenSignServer/cloud/customRoute/decryptpdf.js @@ -0,0 +1,43 @@ +import fs from 'node:fs'; +import multer from 'multer'; +import Coherentpdf from 'coherentpdf'; + +const storage = multer.diskStorage({ + destination(req, file, cb) { + cb(null, 'exports'); + }, + filename(req, file, cb) { + cb(null, file.originalname); + }, +}); + +export const upload = multer({ storage }); + +export default async function decryptpdf(req, res) { + const inputPath = req.file.path; + const password = req.body.password || ''; + try { + const file = fs.readFileSync(inputPath); + const pdf = await Coherentpdf.fromMemory(file, password); + await Coherentpdf.decryptPdf(pdf, password); + // Get decrypted buffer directly from memory (no file I/O) + const buffer = await Coherentpdf.toMemory(pdf, false, false); + res.set({ + 'Content-Type': 'application/pdf', + 'Content-Disposition': 'inline; filename="decrypted.pdf"', + 'Content-Length': buffer.length, + }); + res.send(buffer); + fs.unlink(inputPath, () => {}); + } catch (err) { + fs.unlink(inputPath, () => {}); + console.log('Error in decrypt file: ', err); + let code = err?.code ? err.code : 400; + let message = err?.[2]?.c ? err[2].c : 'Something went wrong.'; + if (err?.[2]?.c?.includes('Bad password') || err?.[2]?.c?.includes('decrypt_pdf_inner')) { + code = 401; + message = 'Incorrect password.'; + } + return res.status(code).json({ error: message }); + } +} diff --git a/apps/OpenSignServer/cloud/customRoute/docxtopdf.js b/apps/OpenSignServer/cloud/customRoute/docxtopdf.js new file mode 100644 index 0000000000..76f8f3567f --- /dev/null +++ b/apps/OpenSignServer/cloud/customRoute/docxtopdf.js @@ -0,0 +1,166 @@ +import fs from 'node:fs'; +import axios from 'axios'; +import multer from 'multer'; +import libre from 'libreoffice-convert'; +import util from 'node:util'; +import { cloudServerUrl, getSecureUrl } from '../../Utils.js'; + +libre.convertAsync = util.promisify(libre.convert); + +const storage = multer.diskStorage({ + destination(req, file, cb) { + cb(null, 'exports'); + }, + filename(req, file, cb) { + cb(null, file.originalname); + }, +}); + +export const upload = multer({ storage }); + +function generatePdfName(length) { + const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; + let result = ''; + for (let i = 0; i < length; i++) { + result += chars.charAt(Math.floor(Math.random() * chars.length)); + } + return result; +} + +export default async function docxtopdf(req, res) { + const serverUrl = cloudServerUrl; + const appId = process.env.APP_ID; + const masterKey = process.env.MASTER_KEY; + const inputPath = req.file.path; + const name = generatePdfName(16); + const fileName = `${name}.pdf`; + const outputPath = './exports/output.pdf'; + + try { + const userRes = await axios.get(serverUrl + '/users/me', { + headers: { + 'X-Parse-Application-Id': appId, + 'X-Parse-Session-Token': req.headers['sessiontoken'], + }, + }); + const userId = JSON.stringify({ + UserId: { + __type: 'Pointer', + className: '_User', + objectId: userRes.data.objectId, + }, + }); + const resUser = await axios.get( + serverUrl + `/classes/contracts_Users?where=${userId}&limit=1&include=TenantId`, + { + headers: { + 'X-Parse-Application-Id': appId, + 'X-Parse-Master-Key': masterKey, + }, + } + ); + + if (resUser?.data?.results?.length > 0) { + const tenantId = resUser.data.results[0].TenantId?.objectId; + const ext = '.pdf'; + const outPath = `./exports/output${ext}`; + const docxBuf = fs.readFileSync(inputPath); + const pdfBuffer = await libre.convertAsync(docxBuf, ext, undefined); + fs.writeFileSync(outPath, pdfBuffer); + const file = fs.readFileSync(outPath); + const size = fs.statSync(outPath).size; + const PartnersTenant = JSON.stringify({ + PartnersTenant: { + __type: 'Pointer', + className: 'partners_Tenant', + objectId: tenantId, + }, + }); + const resTenantCredit = await axios.get( + serverUrl + `/classes/partners_TenantCredits?where=${PartnersTenant}&limit=1`, + { + headers: { + 'X-Parse-Application-Id': appId, + 'X-Parse-Master-Key': masterKey, + }, + } + ); + if (resTenantCredit.data?.results?.length > 0) { + const tenantCreditsId = resTenantCredit.data.results[0].objectId; + const activeFileAdapter = resUser.data.results[0].TenantId?.ActiveFileAdapter; + let fileUrl; + if (activeFileAdapter) { + const params = { + fileBase64: file.toString('base64'), + fileName, + id: activeFileAdapter, + }; + const url = serverUrl + '/functions/savetofileadapter'; + const headers = { + 'Content-Type': 'application/json', + 'X-Parse-Application-Id': appId, + 'X-Parse-Session-Token': req.headers['sessiontoken'], + }; + try { + const savetos3 = await axios.post(url, params, { headers }); + fileUrl = savetos3?.data?.result?.url; + } catch (err) { + console.log('err in save to customfile', err); + } + } else { + const parsefile = await axios.post(serverUrl + `/files/${fileName}`, file, { + headers: { + 'X-Parse-Application-Id': appId, + 'X-Parse-Master-Key': masterKey, + 'Content-Type': 'application/pdf', + }, + }); + const fileRes = getSecureUrl(parsefile.data.url); + fileUrl = fileRes.url; + } + const usedStorage = resTenantCredit.data.results[0].usedStorage + ? resTenantCredit.data.results[0].usedStorage + size + : size; + await axios.put( + serverUrl + `/classes/partners_TenantCredits/${tenantCreditsId}`, + { usedStorage }, + { + headers: { + 'X-Parse-Application-Id': appId, + 'X-Parse-Master-Key': masterKey, + }, + } + ); + await axios.post( + serverUrl + '/classes/partners_DataFiles', + { + FileSize: size, + FileUrl: fileUrl, + TenantPtr: { + __type: 'Pointer', + className: 'partners_Tenant', + objectId: tenantId, + }, + }, + { + headers: { + 'X-Parse-Application-Id': appId, + 'X-Parse-Master-Key': masterKey, + }, + } + ); + [inputPath, outPath].forEach(p => fs.existsSync(p) && fs.unlinkSync(p)); + return res.status(200).json({ message: 'success.', url: fileUrl }); + } + } + } catch (err) { + [inputPath, outputPath].forEach(p => fs.existsSync(p) && fs.unlinkSync(p)); + const msg = + err?.response?.data?.error || err?.response?.data || err?.message || 'Something went wrong.'; + console.log(`Error converting file: ${msg}`); + + const message = + 'We are currently experiencing some issues with processing DOCX files. Please upload the PDF version or contact us on support@opensignlabs.com'; + return res.status(400).json({ error: message }); + } +} diff --git a/apps/OpenSignServer/cloud/parsefunction/createBatchDocs.js b/apps/OpenSignServer/cloud/parsefunction/createBatchDocs.js index 2d4ce58996..0ac40523f4 100644 --- a/apps/OpenSignServer/cloud/parsefunction/createBatchDocs.js +++ b/apps/OpenSignServer/cloud/parsefunction/createBatchDocs.js @@ -15,8 +15,6 @@ async function deductcount(docsCount, extUserId) { async function sendMail(document, publicUrl) { //sessionToken const baseUrl = new URL(publicUrl); - - // console.log("pdfDetails", pdfDetails); const timeToCompleteDays = document?.TimeToCompleteDays || 15; const ExpireDate = new Date(document.createdAt); ExpireDate.setDate(ExpireDate.getDate() + timeToCompleteDays); @@ -168,9 +166,9 @@ async function batchQuery(userId, Documents, Ip, parseConfig, type, publicUrl) { })), ACL: Acl, SentToOthers: true, - RemindOnceInEvery: x.RemindOnceInEvery || 5, + RemindOnceInEvery: x.RemindOnceInEvery ? parseInt(x.RemindOnceInEvery) : 5, AutomaticReminders: x.AutomaticReminders || false, - TimeToCompleteDays: x.TimeToCompleteDays || 15, + TimeToCompleteDays: x.TimeToCompleteDays ? parseInt(x.TimeToCompleteDays) : 15, OriginIp: Ip, DocSentAt: { __type: 'Date', iso: isoDate }, IsEnableOTP: x?.IsEnableOTP || false, @@ -231,6 +229,7 @@ export default async function createBatchDocs(request) { const sessionToken = request.headers?.sessiontoken; const type = request.headers?.type || 'quicksend'; const Documents = JSON.parse(strDocuments); + const Ip = request?.headers?.['x-real-ip'] || ''; // Access the host from the headers const publicUrl = request.headers.public_url; diff --git a/apps/OpenSignServer/cloud/parsefunction/generateCertificatebydocId.js b/apps/OpenSignServer/cloud/parsefunction/generateCertificatebydocId.js index 84a2f32df6..5c322ae460 100644 --- a/apps/OpenSignServer/cloud/parsefunction/generateCertificatebydocId.js +++ b/apps/OpenSignServer/cloud/parsefunction/generateCertificatebydocId.js @@ -65,7 +65,7 @@ export default async function generateCertificatebydocId(req) { const certificate = await GenerateCertificate(doc); const certificatePdf = await PDFDocument.load(certificate); const p12 = new P12Signer(P12Buffer, { passphrase: process.env.PASS_PHRASE || null }); - // `pdflibAddPlaceholder` is used to add code of only digitial sign in certificate + // `pdflibAddPlaceholder` is used to add code of only digital sign in certificate pdflibAddPlaceholder({ pdfDoc: certificatePdf, reason: `Digitally signed by ${eSignName}.`, diff --git a/apps/OpenSignServer/cloud/parsefunction/getReport.js b/apps/OpenSignServer/cloud/parsefunction/getReport.js index a55496c6e0..85eb6f6622 100644 --- a/apps/OpenSignServer/cloud/parsefunction/getReport.js +++ b/apps/OpenSignServer/cloud/parsefunction/getReport.js @@ -2,19 +2,26 @@ import { cloudServerUrl } from '../../Utils.js'; import reportJson from './reportsJson.js'; import axios from 'axios'; +// Escape regex special characters. Copied from filterDocs.js +function escapeRegExp(str) { + return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); +} + export default async function getReport(request) { const reportId = request.params.reportId; const limit = request.params.limit; const skip = request.params.skip; + const searchTerm = request.params.searchTerm || ''; const serverUrl = cloudServerUrl; //process.env.SERVER_URL; const appId = process.env.APP_ID; const masterKey = process.env.MASTER_KEY; + const sessionToken = request.headers['sessiontoken'] || request.headers['x-parse-session-token']; try { const userRes = await axios.get(serverUrl + '/users/me', { headers: { 'X-Parse-Application-Id': appId, - 'X-Parse-Session-Token': request.headers['sessiontoken'], + 'X-Parse-Session-Token': sessionToken, }, }); const userId = userRes.data && userRes.data.objectId; @@ -25,7 +32,7 @@ export default async function getReport(request) { const { params, keys } = json; const orderBy = '-updatedAt'; const strKeys = keys.join(); - let strParams = JSON.stringify(params); + let paramsObj = { ...params }; if (reportId == '6TeaPr321t') { const extUserQuery = new Parse.Query('contracts_Users'); extUserQuery.equalTo('Email', userRes.data.email); @@ -36,8 +43,8 @@ export default async function getReport(request) { if (_extUser?.TeamIds && _extUser.TeamIds?.length > 0) { let teamArr = []; _extUser?.TeamIds?.forEach(x => (teamArr = [...teamArr, ...x.Ancestors])); - strParams = JSON.stringify({ - ...params, + paramsObj = { + ...paramsObj, $or: [ { SharedWith: { $in: teamArr } }, { @@ -55,15 +62,23 @@ export default async function getReport(request) { }, }, ], - }); + }; } else { - strParams = JSON.stringify({ - ...params, + paramsObj = { + ...paramsObj, CreatedBy: { __type: 'Pointer', className: '_User', objectId: userId }, - }); + }; } } } + if (searchTerm) { + const escaped = escapeRegExp(searchTerm); + paramsObj = { + ...paramsObj, + Name: { $regex: `.*${escaped}.*`, $options: 'i' }, + }; + } + const strParams = JSON.stringify(paramsObj); const headers = { 'Content-Type': 'application/json', 'X-Parse-Application-Id': appId, diff --git a/apps/OpenSignServer/cloud/parsefunction/recreateDocument.js b/apps/OpenSignServer/cloud/parsefunction/recreateDocument.js index 16dbbf7c31..8ddcaf26e6 100644 --- a/apps/OpenSignServer/cloud/parsefunction/recreateDocument.js +++ b/apps/OpenSignServer/cloud/parsefunction/recreateDocument.js @@ -14,11 +14,14 @@ export default async function recreateDocument(request) { if (!doc) { throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'Document not found'); } + if (doc?.get('IsSignyourself')) { + throw new Parse.Error(Parse.Error.INVALID_SESSION_TOKEN, 'Signyourself Document not allowed'); + } const _docRes = doc?.toJSON(); const { objectId, SignedUrl, AuditTrail, ACL, DeclineBy, DeclineReason, ...docRes } = _docRes; const createDoc = new Parse.Object('contracts_Document'); Object.entries(docRes).forEach(([key, value]) => { - if (key === 'IsDeclined') { + if (key === 'IsDeclined' || key === 'IsCompleted') { createDoc.set(key, false); } else { createDoc.set(key, value); diff --git a/apps/OpenSignServer/cloud/parsefunction/reportsJson.js b/apps/OpenSignServer/cloud/parsefunction/reportsJson.js index 387387ac86..2a2e796510 100644 --- a/apps/OpenSignServer/cloud/parsefunction/reportsJson.js +++ b/apps/OpenSignServer/cloud/parsefunction/reportsJson.js @@ -55,7 +55,7 @@ export default function reportJson(id, userId) { 'ExpiryDate', ], }; - // In progess report + // In progress report case '1MwEuxLEkF': return { reportName: 'In-progress documents', @@ -123,6 +123,8 @@ export default function reportJson(id, userId) { 'TimeToCompleteDays', 'IsSignyourself', 'IsCompleted', + 'ExpiryDate', + 'IsSignyourself', ], }; // declined documents report diff --git a/apps/OpenSignServer/cloud/parsefunction/saveAsTemplate.js b/apps/OpenSignServer/cloud/parsefunction/saveAsTemplate.js index 85433c476a..53708732dd 100644 --- a/apps/OpenSignServer/cloud/parsefunction/saveAsTemplate.js +++ b/apps/OpenSignServer/cloud/parsefunction/saveAsTemplate.js @@ -51,6 +51,17 @@ export default async function saveAsTemplate(request) { if (_docRes?.Placeholders?.length > 0) { if (_docRes?.IsSignyourself) { + //add required option for all widget when save as template using signyour-self draft document + const updatedPlaceholder = _docRes?.Placeholders.map(pageItem => ({ + ...pageItem, + pos: pageItem.pos.map(p => ({ + ...p, + options: { + ...p.options, + status: 'required', + }, + })), + })); const placeHolders = { signerObjId: '', signerPtr: {}, @@ -58,7 +69,7 @@ export default async function saveAsTemplate(request) { blockColor: '#93a3db', Role: 'Role 1', email: '', - placeHolder: _docRes?.Placeholders, + placeHolder: updatedPlaceholder, }; templateCls.set('Placeholders', [placeHolders]); } else { diff --git a/apps/OpenSignServer/cloud/parsefunction/sendMailGmailProvider.js b/apps/OpenSignServer/cloud/parsefunction/sendMailGmailProvider.js index b02905d9c2..fb5c85f64f 100644 --- a/apps/OpenSignServer/cloud/parsefunction/sendMailGmailProvider.js +++ b/apps/OpenSignServer/cloud/parsefunction/sendMailGmailProvider.js @@ -53,10 +53,16 @@ const makeEmail = async ( const isSecure = new URL(url)?.protocol === 'https:' && new URL(url)?.hostname !== 'localhost'; if (isSecure) { - https.get(url, async function (response) { - response.pipe(Pdf); - response.on('end', () => resolve('success')); - }); + https + .get(url, async function (response) { + response.pipe(Pdf); + Pdf.on('finish', () => resolve('success')); + Pdf.on('error', () => resolve('error')); + }) + .on('error', e => { + console.error(`error: ${e.message}`); + resolve('error'); + }); } else { const httpsAgent = new https.Agent({ rejectUnauthorized: false }); // Disable SSL validation axios diff --git a/apps/OpenSignServer/package-lock.json b/apps/OpenSignServer/package-lock.json index 775af1d104..0656eda38b 100644 --- a/apps/OpenSignServer/package-lock.json +++ b/apps/OpenSignServer/package-lock.json @@ -9,23 +9,25 @@ "version": "2.21.1", "license": "MIT", "dependencies": { - "@aws-sdk/client-s3": "^3.824.0", - "@aws-sdk/s3-request-presigner": "^3.824.0", + "@aws-sdk/client-s3": "^3.828.0", + "@aws-sdk/s3-request-presigner": "^3.828.0", "@parse/fs-files-adapter": "^3.0.0", - "@parse/s3-files-adapter": "^4.1.1", + "@parse/s3-files-adapter": "^4.2.0", "@pdf-lib/fontkit": "^1.1.1", "@signpdf/placeholder-pdf-lib": "^3.2.6", "@signpdf/signer-p12": "^3.2.4", "@signpdf/signpdf": "^3.2.5", "aws-sdk": "^2.1692.0", - "axios": "^1.9.0", + "axios": "^1.10.0", + "coherentpdf": "^2.5.5", "cors": "^2.8.5", "date-fns-tz": "^3.2.0", "dotenv": "^16.5.0", "express": "^5.1.0", - "form-data": "^4.0.2", + "form-data": "^4.0.3", "generate-api-key": "^1.0.2", - "googleapis": "^149.0.0", + "googleapis": "^150.0.1", + "libreoffice-convert": "^1.6.1", "mailgun.js": "^12.0.2", "mongodb": "^6.17.0", "multer": "^2.0.1", @@ -37,7 +39,7 @@ "parse-server": "^8.2.1", "parse-server-api-mail-adapter": "^4.1.0", "pdf-lib": "^1.17.1", - "posthog-node": "^4.18.0", + "posthog-node": "^5.1.0", "qrcode": "^1.5.4", "rate-limiter-flexible": "^7.1.1", "speakeasy": "^2.0.0", @@ -45,9 +47,9 @@ }, "devDependencies": { "@babel/eslint-parser": "^7.27.5", - "eslint": "^9.28.0", - "jasmine": "^5.7.1", - "mongodb-runner": "^5.8.3", + "eslint": "^9.29.0", + "jasmine": "^5.8.0", + "mongodb-runner": "^5.9.0", "nodemon": "^3.1.10", "nyc": "^17.1.0", "prettier": "^3.5.3" @@ -809,35 +811,35 @@ } }, "node_modules/@aws-sdk/client-s3": { - "version": "3.824.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-s3/-/client-s3-3.824.0.tgz", - "integrity": "sha512-7neTQIdSVP/F4RTWG5T87LDpB955iQD6lxg9nJ00fdkIPczDcRtAEXow44NjF4fEdpQ1A9jokUtBSVE+GMXZ/A==", + "version": "3.828.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-s3/-/client-s3-3.828.0.tgz", + "integrity": "sha512-TvFyrEfJkf9NN3cq5mXCgFv/sPaA8Rm5tEPgV5emuLedeGsORlWmVpdSKqfZ4lSoED1tMfNM6LY4uA9D8/RS5g==", "license": "Apache-2.0", "dependencies": { "@aws-crypto/sha1-browser": "5.2.0", "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "3.823.0", - "@aws-sdk/credential-provider-node": "3.823.0", + "@aws-sdk/core": "3.826.0", + "@aws-sdk/credential-provider-node": "3.828.0", "@aws-sdk/middleware-bucket-endpoint": "3.821.0", "@aws-sdk/middleware-expect-continue": "3.821.0", - "@aws-sdk/middleware-flexible-checksums": "3.823.0", + "@aws-sdk/middleware-flexible-checksums": "3.826.0", "@aws-sdk/middleware-host-header": "3.821.0", "@aws-sdk/middleware-location-constraint": "3.821.0", "@aws-sdk/middleware-logger": "3.821.0", "@aws-sdk/middleware-recursion-detection": "3.821.0", - "@aws-sdk/middleware-sdk-s3": "3.823.0", + "@aws-sdk/middleware-sdk-s3": "3.826.0", "@aws-sdk/middleware-ssec": "3.821.0", - "@aws-sdk/middleware-user-agent": "3.823.0", + "@aws-sdk/middleware-user-agent": "3.828.0", "@aws-sdk/region-config-resolver": "3.821.0", - "@aws-sdk/signature-v4-multi-region": "3.824.0", + "@aws-sdk/signature-v4-multi-region": "3.826.0", "@aws-sdk/types": "3.821.0", - "@aws-sdk/util-endpoints": "3.821.0", + "@aws-sdk/util-endpoints": "3.828.0", "@aws-sdk/util-user-agent-browser": "3.821.0", - "@aws-sdk/util-user-agent-node": "3.823.0", + "@aws-sdk/util-user-agent-node": "3.828.0", "@aws-sdk/xml-builder": "3.821.0", "@smithy/config-resolver": "^4.1.4", - "@smithy/core": "^3.5.1", + "@smithy/core": "^3.5.3", "@smithy/eventstream-serde-browser": "^4.0.4", "@smithy/eventstream-serde-config-resolver": "^4.1.2", "@smithy/eventstream-serde-node": "^4.0.4", @@ -848,21 +850,21 @@ "@smithy/invalid-dependency": "^4.0.4", "@smithy/md5-js": "^4.0.4", "@smithy/middleware-content-length": "^4.0.4", - "@smithy/middleware-endpoint": "^4.1.9", - "@smithy/middleware-retry": "^4.1.10", + "@smithy/middleware-endpoint": "^4.1.11", + "@smithy/middleware-retry": "^4.1.12", "@smithy/middleware-serde": "^4.0.8", "@smithy/middleware-stack": "^4.0.4", "@smithy/node-config-provider": "^4.1.3", "@smithy/node-http-handler": "^4.0.6", "@smithy/protocol-http": "^5.1.2", - "@smithy/smithy-client": "^4.4.1", + "@smithy/smithy-client": "^4.4.3", "@smithy/types": "^4.3.1", "@smithy/url-parser": "^4.0.4", "@smithy/util-base64": "^4.0.0", "@smithy/util-body-length-browser": "^4.0.0", "@smithy/util-body-length-node": "^4.0.0", - "@smithy/util-defaults-mode-browser": "^4.0.17", - "@smithy/util-defaults-mode-node": "^4.0.17", + "@smithy/util-defaults-mode-browser": "^4.0.19", + "@smithy/util-defaults-mode-node": "^4.0.19", "@smithy/util-endpoints": "^3.0.6", "@smithy/util-middleware": "^4.0.4", "@smithy/util-retry": "^4.0.5", @@ -1232,44 +1234,44 @@ } }, "node_modules/@aws-sdk/client-sso": { - "version": "3.823.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.823.0.tgz", - "integrity": "sha512-dBWdsbyGw8rPfdCsZySNtTOGQK4EZ8lxB/CneSQWRBPHgQ+Ys88NXxImO8xfWO7Itt1eh8O7UDTZ9+smcvw2pw==", + "version": "3.828.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.828.0.tgz", + "integrity": "sha512-qxw8JcPTaFaBwTBUr4YmLajaMh3En65SuBWAKEtjctbITRRekzR7tvr/TkwoyVOh+XoAtkwOn+BQeQbX+/wgHw==", "license": "Apache-2.0", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "3.823.0", + "@aws-sdk/core": "3.826.0", "@aws-sdk/middleware-host-header": "3.821.0", "@aws-sdk/middleware-logger": "3.821.0", "@aws-sdk/middleware-recursion-detection": "3.821.0", - "@aws-sdk/middleware-user-agent": "3.823.0", + "@aws-sdk/middleware-user-agent": "3.828.0", "@aws-sdk/region-config-resolver": "3.821.0", "@aws-sdk/types": "3.821.0", - "@aws-sdk/util-endpoints": "3.821.0", + "@aws-sdk/util-endpoints": "3.828.0", "@aws-sdk/util-user-agent-browser": "3.821.0", - "@aws-sdk/util-user-agent-node": "3.823.0", + "@aws-sdk/util-user-agent-node": "3.828.0", "@smithy/config-resolver": "^4.1.4", - "@smithy/core": "^3.5.1", + "@smithy/core": "^3.5.3", "@smithy/fetch-http-handler": "^5.0.4", "@smithy/hash-node": "^4.0.4", "@smithy/invalid-dependency": "^4.0.4", "@smithy/middleware-content-length": "^4.0.4", - "@smithy/middleware-endpoint": "^4.1.9", - "@smithy/middleware-retry": "^4.1.10", + "@smithy/middleware-endpoint": "^4.1.11", + "@smithy/middleware-retry": "^4.1.12", "@smithy/middleware-serde": "^4.0.8", "@smithy/middleware-stack": "^4.0.4", "@smithy/node-config-provider": "^4.1.3", "@smithy/node-http-handler": "^4.0.6", "@smithy/protocol-http": "^5.1.2", - "@smithy/smithy-client": "^4.4.1", + "@smithy/smithy-client": "^4.4.3", "@smithy/types": "^4.3.1", "@smithy/url-parser": "^4.0.4", "@smithy/util-base64": "^4.0.0", "@smithy/util-body-length-browser": "^4.0.0", "@smithy/util-body-length-node": "^4.0.0", - "@smithy/util-defaults-mode-browser": "^4.0.17", - "@smithy/util-defaults-mode-node": "^4.0.17", + "@smithy/util-defaults-mode-browser": "^4.0.19", + "@smithy/util-defaults-mode-node": "^4.0.19", "@smithy/util-endpoints": "^3.0.6", "@smithy/util-middleware": "^4.0.4", "@smithy/util-retry": "^4.0.5", @@ -1637,19 +1639,19 @@ } }, "node_modules/@aws-sdk/core": { - "version": "3.823.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.823.0.tgz", - "integrity": "sha512-1Cf4w8J7wYexz0KU3zpaikHvldGXQEjFldHOhm0SBGRy7qfYNXecfJAamccF7RdgLxKGgkv5Pl9zX/Z/DcW9zg==", + "version": "3.826.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.826.0.tgz", + "integrity": "sha512-BGbQYzWj3ps+dblq33FY5tz/SsgJCcXX0zjQlSC07tYvU1jHTUvsefphyig+fY38xZ4wdKjbTop+KUmXUYrOXw==", "license": "Apache-2.0", "dependencies": { "@aws-sdk/types": "3.821.0", "@aws-sdk/xml-builder": "3.821.0", - "@smithy/core": "^3.5.1", + "@smithy/core": "^3.5.3", "@smithy/node-config-provider": "^4.1.3", "@smithy/property-provider": "^4.0.4", "@smithy/protocol-http": "^5.1.2", "@smithy/signature-v4": "^5.1.2", - "@smithy/smithy-client": "^4.4.1", + "@smithy/smithy-client": "^4.4.3", "@smithy/types": "^4.3.1", "@smithy/util-base64": "^4.0.0", "@smithy/util-body-length-browser": "^4.0.0", @@ -2019,12 +2021,12 @@ } }, "node_modules/@aws-sdk/credential-provider-env": { - "version": "3.823.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.823.0.tgz", - "integrity": "sha512-AIrLLwumObge+U1klN4j5ToIozI+gE9NosENRyHe0GIIZgTLOG/8jxrMFVYFeNHs7RUtjDTxxewislhFyGxJ/w==", + "version": "3.826.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.826.0.tgz", + "integrity": "sha512-DK3pQY8+iKK3MGDdC3uOZQ2psU01obaKlTYhEwNu4VWzgwQL4Vi3sWj4xSWGEK41vqZxiRLq6fOq7ysRI+qEZA==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "3.823.0", + "@aws-sdk/core": "3.826.0", "@aws-sdk/types": "3.821.0", "@smithy/property-provider": "^4.0.4", "@smithy/types": "^4.3.1", @@ -2060,18 +2062,18 @@ } }, "node_modules/@aws-sdk/credential-provider-http": { - "version": "3.823.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.823.0.tgz", - "integrity": "sha512-u4DXvB/J/o2bcvP1JP6n3ch7V3/NngmiJFPsM0hKUyRlLuWM37HEDEdjPRs3/uL/soTxrEhWKTA9//YVkvzI0w==", + "version": "3.826.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.826.0.tgz", + "integrity": "sha512-N+IVZBh+yx/9GbMZTKO/gErBi/FYZQtcFRItoLbY+6WU+0cSWyZYfkoeOxHmQV3iX9k65oljERIWUmL9x6OSQg==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "3.823.0", + "@aws-sdk/core": "3.826.0", "@aws-sdk/types": "3.821.0", "@smithy/fetch-http-handler": "^5.0.4", "@smithy/node-http-handler": "^4.0.6", "@smithy/property-provider": "^4.0.4", "@smithy/protocol-http": "^5.1.2", - "@smithy/smithy-client": "^4.4.1", + "@smithy/smithy-client": "^4.4.3", "@smithy/types": "^4.3.1", "@smithy/util-stream": "^4.2.2", "tslib": "^2.6.2" @@ -2437,18 +2439,18 @@ } }, "node_modules/@aws-sdk/credential-provider-ini": { - "version": "3.823.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.823.0.tgz", - "integrity": "sha512-C0o63qviK5yFvjH9zKWAnCUBkssJoQ1A1XAHe0IAQkurzoNBSmu9oVemqwnKKHA4H6QrmusaEERfL00yohIkJA==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/core": "3.823.0", - "@aws-sdk/credential-provider-env": "3.823.0", - "@aws-sdk/credential-provider-http": "3.823.0", - "@aws-sdk/credential-provider-process": "3.823.0", - "@aws-sdk/credential-provider-sso": "3.823.0", - "@aws-sdk/credential-provider-web-identity": "3.823.0", - "@aws-sdk/nested-clients": "3.823.0", + "version": "3.828.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.828.0.tgz", + "integrity": "sha512-T3DJMo2/j7gCPpFg2+xEHWgua05t8WP89ye7PaZxA2Fc6CgScHkZsJZTri1QQIU2h+eOZ75EZWkeFLIPgN0kRQ==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "3.826.0", + "@aws-sdk/credential-provider-env": "3.826.0", + "@aws-sdk/credential-provider-http": "3.826.0", + "@aws-sdk/credential-provider-process": "3.826.0", + "@aws-sdk/credential-provider-sso": "3.828.0", + "@aws-sdk/credential-provider-web-identity": "3.828.0", + "@aws-sdk/nested-clients": "3.828.0", "@aws-sdk/types": "3.821.0", "@smithy/credential-provider-imds": "^4.0.6", "@smithy/property-provider": "^4.0.4", @@ -2499,17 +2501,17 @@ } }, "node_modules/@aws-sdk/credential-provider-node": { - "version": "3.823.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.823.0.tgz", - "integrity": "sha512-nfSxXVuZ+2GJDpVFlflNfh55Yb4BtDsXLGNssXF5YU6UgSPsi8j2YkaE92Jv2s7dlUK07l0vRpLyPuXMaGeiRQ==", + "version": "3.828.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.828.0.tgz", + "integrity": "sha512-9z3iPwVYOQYNzVZj8qycZaS/BOSKRXWA+QVNQlfEnQ4sA4sOcKR4kmV2h+rJcuBsSFfmOF62ZDxyIBGvvM4t/w==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/credential-provider-env": "3.823.0", - "@aws-sdk/credential-provider-http": "3.823.0", - "@aws-sdk/credential-provider-ini": "3.823.0", - "@aws-sdk/credential-provider-process": "3.823.0", - "@aws-sdk/credential-provider-sso": "3.823.0", - "@aws-sdk/credential-provider-web-identity": "3.823.0", + "@aws-sdk/credential-provider-env": "3.826.0", + "@aws-sdk/credential-provider-http": "3.826.0", + "@aws-sdk/credential-provider-ini": "3.828.0", + "@aws-sdk/credential-provider-process": "3.826.0", + "@aws-sdk/credential-provider-sso": "3.828.0", + "@aws-sdk/credential-provider-web-identity": "3.828.0", "@aws-sdk/types": "3.821.0", "@smithy/credential-provider-imds": "^4.0.6", "@smithy/property-provider": "^4.0.4", @@ -2560,12 +2562,12 @@ } }, "node_modules/@aws-sdk/credential-provider-process": { - "version": "3.823.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.823.0.tgz", - "integrity": "sha512-U/A10/7zu2FbMFFVpIw95y0TZf+oYyrhZTBn9eL8zgWcrYRqxrxdqtPj/zMrfIfyIvQUhuJSENN4dx4tfpCMWQ==", + "version": "3.826.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.826.0.tgz", + "integrity": "sha512-kURrc4amu3NLtw1yZw7EoLNEVhmOMRUTs+chaNcmS+ERm3yK0nKjaJzmKahmwlTQTSl3wJ8jjK7x962VPo+zWw==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "3.823.0", + "@aws-sdk/core": "3.826.0", "@aws-sdk/types": "3.821.0", "@smithy/property-provider": "^4.0.4", "@smithy/shared-ini-file-loader": "^4.0.4", @@ -2615,14 +2617,14 @@ } }, "node_modules/@aws-sdk/credential-provider-sso": { - "version": "3.823.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.823.0.tgz", - "integrity": "sha512-ff8IM80Wqz1V7VVMaMUqO2iR417jggfGWLPl8j2l7uCgwpEyop1ZZl5CFVYEwSupRBtwp+VlW1gTCk7ke56MUw==", + "version": "3.828.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.828.0.tgz", + "integrity": "sha512-9CEAXzUDSzOjOCb3XfM15TZhTaM+l07kumZyx2z8NC6T2U4qbCJqn4h8mFlRvYrs6cBj2SN40sD3r5Wp0Cq2Kw==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/client-sso": "3.823.0", - "@aws-sdk/core": "3.823.0", - "@aws-sdk/token-providers": "3.823.0", + "@aws-sdk/client-sso": "3.828.0", + "@aws-sdk/core": "3.826.0", + "@aws-sdk/token-providers": "3.828.0", "@aws-sdk/types": "3.821.0", "@smithy/property-provider": "^4.0.4", "@smithy/shared-ini-file-loader": "^4.0.4", @@ -2672,13 +2674,13 @@ } }, "node_modules/@aws-sdk/credential-provider-web-identity": { - "version": "3.823.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.823.0.tgz", - "integrity": "sha512-lzoZdJMQq9w7i4lXVka30cVBe/dZoUDZST8Xz/soEd73gg7RTKgG+0szL4xFWgdBDgcJDWLfZfJzlbyIVyAyOA==", + "version": "3.828.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.828.0.tgz", + "integrity": "sha512-MguDhGHlQBeK9CQ/P4NOY0whAJ4HJU4x+f1dphg3I1sGlccFqfB8Moor2vXNKu0Th2kvAwkn9pr7gGb/+NGR9g==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "3.823.0", - "@aws-sdk/nested-clients": "3.823.0", + "@aws-sdk/core": "3.826.0", + "@aws-sdk/nested-clients": "3.828.0", "@aws-sdk/types": "3.821.0", "@smithy/property-provider": "^4.0.4", "@smithy/types": "^4.3.1", @@ -2875,15 +2877,15 @@ } }, "node_modules/@aws-sdk/middleware-flexible-checksums": { - "version": "3.823.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-flexible-checksums/-/middleware-flexible-checksums-3.823.0.tgz", - "integrity": "sha512-Elt6G1ryEEdkrppqbyJON0o2x4x9xKknimJtMLdfG1b4YfO9X+UB31pk4R2SHvMYfrJ+p8DE2jRAhvV4g/dwIQ==", + "version": "3.826.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-flexible-checksums/-/middleware-flexible-checksums-3.826.0.tgz", + "integrity": "sha512-Fz9w8CFYPfSlHEB6feSsi06hdS+s+FB8k5pO4L7IV0tUa78mlhxF/VNlAJaVWYyOkZXl4HPH2K48aapACSQOXw==", "license": "Apache-2.0", "dependencies": { "@aws-crypto/crc32": "5.2.0", "@aws-crypto/crc32c": "5.2.0", "@aws-crypto/util": "5.2.0", - "@aws-sdk/core": "3.823.0", + "@aws-sdk/core": "3.826.0", "@aws-sdk/types": "3.821.0", "@smithy/is-array-buffer": "^4.0.0", "@smithy/node-config-provider": "^4.1.3", @@ -3264,19 +3266,19 @@ } }, "node_modules/@aws-sdk/middleware-sdk-s3": { - "version": "3.823.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-s3/-/middleware-sdk-s3-3.823.0.tgz", - "integrity": "sha512-UV755wt2HDru8PbxLn2S0Fvwgdn9mYamexn31Q6wyUGQ6rkpjKNEzL+oNDGQQmDQAOcQO+nLubKFsCwtBM02fQ==", + "version": "3.826.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-s3/-/middleware-sdk-s3-3.826.0.tgz", + "integrity": "sha512-8F0qWaYKfvD/de1AKccXuigM+gb/IZSncCqxdnFWqd+TFzo9qI9Hh+TpUhWOMYSgxsMsYQ8ipmLzlD/lDhjrmA==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "3.823.0", + "@aws-sdk/core": "3.826.0", "@aws-sdk/types": "3.821.0", "@aws-sdk/util-arn-parser": "3.804.0", - "@smithy/core": "^3.5.1", + "@smithy/core": "^3.5.3", "@smithy/node-config-provider": "^4.1.3", "@smithy/protocol-http": "^5.1.2", "@smithy/signature-v4": "^5.1.2", - "@smithy/smithy-client": "^4.4.1", + "@smithy/smithy-client": "^4.4.3", "@smithy/types": "^4.3.1", "@smithy/util-config-provider": "^4.0.0", "@smithy/util-middleware": "^4.0.4", @@ -3671,15 +3673,15 @@ } }, "node_modules/@aws-sdk/middleware-user-agent": { - "version": "3.823.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.823.0.tgz", - "integrity": "sha512-TKRQK09ld1LrIPExC9rIDpqnMsWcv+eq8ABKFHVo8mDLTSuWx/IiQ4eCh9T5zDuEZcLY4nNYCSzXKqw6XKcMCA==", + "version": "3.828.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.828.0.tgz", + "integrity": "sha512-nixvI/SETXRdmrVab4D9LvXT3lrXkwAWGWk2GVvQvzlqN1/M/RfClj+o37Sn4FqRkGH9o9g7Fqb1YqZ4mqDAtA==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "3.823.0", + "@aws-sdk/core": "3.826.0", "@aws-sdk/types": "3.821.0", - "@aws-sdk/util-endpoints": "3.821.0", - "@smithy/core": "^3.5.1", + "@aws-sdk/util-endpoints": "3.828.0", + "@smithy/core": "^3.5.3", "@smithy/protocol-http": "^5.1.2", "@smithy/types": "^4.3.1", "tslib": "^2.6.2" @@ -3927,44 +3929,44 @@ } }, "node_modules/@aws-sdk/nested-clients": { - "version": "3.823.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/nested-clients/-/nested-clients-3.823.0.tgz", - "integrity": "sha512-/BcyOBubrJnd2gxlbbmNJR1w0Z3OVN/UE8Yz20e+ou+Mijjv7EbtVwmWvio1e3ZjphwdA8tVfPYZKwXmrvHKmQ==", + "version": "3.828.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/nested-clients/-/nested-clients-3.828.0.tgz", + "integrity": "sha512-xmeOILiR9LvfC8MctgeRXXN8nQTwbOvO4wHvgE8tDRsjnBpyyO0j50R4+viHXdMUGtgGkHEXRv8fFNBq54RgnA==", "license": "Apache-2.0", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "3.823.0", + "@aws-sdk/core": "3.826.0", "@aws-sdk/middleware-host-header": "3.821.0", "@aws-sdk/middleware-logger": "3.821.0", "@aws-sdk/middleware-recursion-detection": "3.821.0", - "@aws-sdk/middleware-user-agent": "3.823.0", + "@aws-sdk/middleware-user-agent": "3.828.0", "@aws-sdk/region-config-resolver": "3.821.0", "@aws-sdk/types": "3.821.0", - "@aws-sdk/util-endpoints": "3.821.0", + "@aws-sdk/util-endpoints": "3.828.0", "@aws-sdk/util-user-agent-browser": "3.821.0", - "@aws-sdk/util-user-agent-node": "3.823.0", + "@aws-sdk/util-user-agent-node": "3.828.0", "@smithy/config-resolver": "^4.1.4", - "@smithy/core": "^3.5.1", + "@smithy/core": "^3.5.3", "@smithy/fetch-http-handler": "^5.0.4", "@smithy/hash-node": "^4.0.4", "@smithy/invalid-dependency": "^4.0.4", "@smithy/middleware-content-length": "^4.0.4", - "@smithy/middleware-endpoint": "^4.1.9", - "@smithy/middleware-retry": "^4.1.10", + "@smithy/middleware-endpoint": "^4.1.11", + "@smithy/middleware-retry": "^4.1.12", "@smithy/middleware-serde": "^4.0.8", "@smithy/middleware-stack": "^4.0.4", "@smithy/node-config-provider": "^4.1.3", "@smithy/node-http-handler": "^4.0.6", "@smithy/protocol-http": "^5.1.2", - "@smithy/smithy-client": "^4.4.1", + "@smithy/smithy-client": "^4.4.3", "@smithy/types": "^4.3.1", "@smithy/url-parser": "^4.0.4", "@smithy/util-base64": "^4.0.0", "@smithy/util-body-length-browser": "^4.0.0", "@smithy/util-body-length-node": "^4.0.0", - "@smithy/util-defaults-mode-browser": "^4.0.17", - "@smithy/util-defaults-mode-node": "^4.0.17", + "@smithy/util-defaults-mode-browser": "^4.0.19", + "@smithy/util-defaults-mode-node": "^4.0.19", "@smithy/util-endpoints": "^3.0.6", "@smithy/util-middleware": "^4.0.4", "@smithy/util-retry": "^4.0.5", @@ -4415,17 +4417,17 @@ } }, "node_modules/@aws-sdk/s3-request-presigner": { - "version": "3.824.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/s3-request-presigner/-/s3-request-presigner-3.824.0.tgz", - "integrity": "sha512-r8NueKxJaoWbZTnfENmIeoDFjdYbgA9sxALrT1mDKU6+sHeAMNZLJfgEtSFKm7CjVmmdk2ZbYblrP3DY9Ftqsg==", + "version": "3.828.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/s3-request-presigner/-/s3-request-presigner-3.828.0.tgz", + "integrity": "sha512-6817h11Xi6LqnmTnHIwZf4PQB0rIMaRFwkq8/mfR9oOn+hsahxBVDbpgu+q4xzP5q+W3m5Y/din0cJPVrnP6yQ==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/signature-v4-multi-region": "3.824.0", + "@aws-sdk/signature-v4-multi-region": "3.826.0", "@aws-sdk/types": "3.821.0", "@aws-sdk/util-format-url": "3.821.0", - "@smithy/middleware-endpoint": "^4.1.9", + "@smithy/middleware-endpoint": "^4.1.11", "@smithy/protocol-http": "^5.1.2", - "@smithy/smithy-client": "^4.4.1", + "@smithy/smithy-client": "^4.4.3", "@smithy/types": "^4.3.1", "tslib": "^2.6.2" }, @@ -4790,12 +4792,12 @@ } }, "node_modules/@aws-sdk/signature-v4-multi-region": { - "version": "3.824.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/signature-v4-multi-region/-/signature-v4-multi-region-3.824.0.tgz", - "integrity": "sha512-HBjuWeN6Z1pvJjUvGXdMNLwEypKKB4km6zXj9jsbOOwP8NTL6J5rY+JmlX/mfBTmvzmI0kMu2bxlQ4ME2CIRbA==", + "version": "3.826.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/signature-v4-multi-region/-/signature-v4-multi-region-3.826.0.tgz", + "integrity": "sha512-3fEi/zy6tpMzomYosksGtu7jZqGFcdBXoL7YRsG7OEeQzBbOW9B+fVaQZ4jnsViSjzA/yKydLahMrfPnt+iaxg==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/middleware-sdk-s3": "3.823.0", + "@aws-sdk/middleware-sdk-s3": "3.826.0", "@aws-sdk/types": "3.821.0", "@smithy/protocol-http": "^5.1.2", "@smithy/signature-v4": "^5.1.2", @@ -4832,13 +4834,13 @@ } }, "node_modules/@aws-sdk/token-providers": { - "version": "3.823.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.823.0.tgz", - "integrity": "sha512-vz6onCb/+g4y+owxGGPMEMdN789dTfBOgz/c9pFv0f01840w9Rrt46l+gjQlnXnx+0KG6wNeBIVhFdbCfV3HyQ==", + "version": "3.828.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.828.0.tgz", + "integrity": "sha512-JdOjI/TxkfQpY/bWbdGMdCiePESXTbtl6MfnJxz35zZ3tfHvBnxAWCoYJirdmjzY/j/dFo5oEyS6mQuXAG9w2w==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "3.823.0", - "@aws-sdk/nested-clients": "3.823.0", + "@aws-sdk/core": "3.826.0", + "@aws-sdk/nested-clients": "3.828.0", "@aws-sdk/types": "3.821.0", "@smithy/property-provider": "^4.0.4", "@smithy/shared-ini-file-loader": "^4.0.4", @@ -4925,9 +4927,9 @@ } }, "node_modules/@aws-sdk/util-endpoints": { - "version": "3.821.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.821.0.tgz", - "integrity": "sha512-Uknt/zUZnLE76zaAAPEayOeF5/4IZ2puTFXvcSCWHsi9m3tqbb9UozlnlVqvCZLCRWfQryZQoG2W4XSS3qgk5A==", + "version": "3.828.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.828.0.tgz", + "integrity": "sha512-RvKch111SblqdkPzg3oCIdlGxlQs+k+P7Etory9FmxPHyPDvsP1j1c74PmgYqtzzMWmoXTjd+c9naUHh9xG8xg==", "license": "Apache-2.0", "dependencies": { "@aws-sdk/types": "3.821.0", @@ -5040,12 +5042,12 @@ } }, "node_modules/@aws-sdk/util-user-agent-node": { - "version": "3.823.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.823.0.tgz", - "integrity": "sha512-WvNeRz7HV3JLBVGTXW4Qr5QvvWY0vtggH5jW/NqHFH+ZEliVQaUIJ/HNLMpMoCSiu/DlpQAyAjRZXAptJ0oqbw==", + "version": "3.828.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.828.0.tgz", + "integrity": "sha512-LdN6fTBzTlQmc8O8f1wiZN0qF3yBWVGis7NwpWK7FUEzP9bEZRxYfIkV9oV9zpt6iNRze1SedK3JQVB/udxBoA==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/middleware-user-agent": "3.823.0", + "@aws-sdk/middleware-user-agent": "3.828.0", "@aws-sdk/types": "3.821.0", "@smithy/node-config-provider": "^4.1.3", "@smithy/types": "^4.3.1", @@ -5484,9 +5486,9 @@ } }, "node_modules/@eslint/config-array": { - "version": "0.20.0", - "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.20.0.tgz", - "integrity": "sha512-fxlS1kkIjx8+vy2SjuCB94q3htSNrufYTXubwiBFeaQHbH6Ipi43gFJq2zCMt6PHhImH3Xmr0NksKDvchWlpQQ==", + "version": "0.20.1", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.20.1.tgz", + "integrity": "sha512-OL0RJzC/CBzli0DrrR31qzj6d6i6Mm3HByuhflhl4LOBiWxN+3i6/t/ZQQNii4tjksXi8r2CRW1wMpWA2ULUEw==", "license": "Apache-2.0", "dependencies": { "@eslint/object-schema": "^2.1.6", @@ -5554,9 +5556,9 @@ } }, "node_modules/@eslint/js": { - "version": "9.28.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.28.0.tgz", - "integrity": "sha512-fnqSjGWd/CoIp4EXIxWVK/sHA6DOHN4+8Ix2cX5ycOY7LG0UY8nHCU5pIp2eaE1Mc7Qd8kHspYNzYXT2ojPLzg==", + "version": "9.29.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.29.0.tgz", + "integrity": "sha512-3PIF4cBw/y+1u2EazflInpV+lYsSG0aByVIQzAgb1m1MhHFSbqTyNqtBKHgWf/9Ykud+DhILS9EGkmekVhbKoQ==", "license": "MIT", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -6246,23 +6248,23 @@ "deprecated": "This package has been decomissioned. See https://github.com/ldapjs/node-ldapjs/blob/8ffd0bc9c149088a10ec4c1ec6a18450f76ad05d/README.md" }, "node_modules/@mongodb-js/mongodb-downloader": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/@mongodb-js/mongodb-downloader/-/mongodb-downloader-0.3.9.tgz", - "integrity": "sha512-6lEIESINiIAeQUw95+hkfxG6129r6KiPU2TNOcxb30PsGgFHPJFg7QY8UoSQXjDE9YaENlr6oQm3c1XDixWeEg==", + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@mongodb-js/mongodb-downloader/-/mongodb-downloader-0.4.0.tgz", + "integrity": "sha512-+xBDhZQn+tGY8bWZo9gE+Nd6Mw2r6TQWaLbgGw/H50M5ky092IS4vbTjwvJhR2m/efoxj31LZpZI0PYK7Pzu6w==", "dev": true, "license": "Apache-2.0", "dependencies": { "debug": "^4.4.0", "decompress": "^4.2.1", - "mongodb-download-url": "^1.5.7", + "mongodb-download-url": "^1.6.0", "node-fetch": "^2.7.0", "tar": "^6.1.15" } }, "node_modules/@mongodb-js/saslprep": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.2.2.tgz", - "integrity": "sha512-EB0O3SCSNRUFk66iRCpI+cXzIjdswfCs7F6nOC3RAGJ7xr5YhaicvsRwJ9eyzYvYRlCSDUO/c7g4yNulxKC1WA==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.3.0.tgz", + "integrity": "sha512-zlayKCsIjYb7/IdfqxorK5+xUMyi4vOKcFy10wKJYc63NSdKI8mNME+uJqfatkPmOSMMUiojrL58IePKBm3gvQ==", "license": "MIT", "dependencies": { "sparse-bitfield": "^3.0.3" @@ -6643,12 +6645,12 @@ } }, "node_modules/@parse/s3-files-adapter": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/@parse/s3-files-adapter/-/s3-files-adapter-4.1.1.tgz", - "integrity": "sha512-fEC8Fa1VcAuLnPyGLDBV+QCQK71uin7PcU5KbFU31K1t367Sitg0bpxyoN9WLyQ6K5gbx0bOcnijeTeHpQ2fnw==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@parse/s3-files-adapter/-/s3-files-adapter-4.2.0.tgz", + "integrity": "sha512-owHi9CBZ43FkKFdVifDgtOrDF2vcipVrIhCExTuVWCLd69CooxXo7IlaUMPzG1Yi9/ivF4M69WarqFQo0ZQbiA==", "license": "ISC", "dependencies": { - "@aws-sdk/client-s3": "3.806.0", + "@aws-sdk/client-s3": "3.824.0", "@aws-sdk/s3-request-presigner": "3.787.0" }, "engines": { @@ -6656,66 +6658,66 @@ } }, "node_modules/@parse/s3-files-adapter/node_modules/@aws-sdk/client-s3": { - "version": "3.806.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-s3/-/client-s3-3.806.0.tgz", - "integrity": "sha512-kQaBBBxEBU/IJ2wKG+LL2BK+uvBwpdvOA9jy1WhW+U2/DIMwMrjVs7M/ZvTlmVOJwhZaONcJbgQqsN4Yirjj4g==", + "version": "3.824.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-s3/-/client-s3-3.824.0.tgz", + "integrity": "sha512-7neTQIdSVP/F4RTWG5T87LDpB955iQD6lxg9nJ00fdkIPczDcRtAEXow44NjF4fEdpQ1A9jokUtBSVE+GMXZ/A==", "license": "Apache-2.0", "dependencies": { "@aws-crypto/sha1-browser": "5.2.0", "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "3.806.0", - "@aws-sdk/credential-provider-node": "3.806.0", - "@aws-sdk/middleware-bucket-endpoint": "3.806.0", - "@aws-sdk/middleware-expect-continue": "3.804.0", - "@aws-sdk/middleware-flexible-checksums": "3.806.0", - "@aws-sdk/middleware-host-header": "3.804.0", - "@aws-sdk/middleware-location-constraint": "3.804.0", - "@aws-sdk/middleware-logger": "3.804.0", - "@aws-sdk/middleware-recursion-detection": "3.804.0", - "@aws-sdk/middleware-sdk-s3": "3.806.0", - "@aws-sdk/middleware-ssec": "3.804.0", - "@aws-sdk/middleware-user-agent": "3.806.0", - "@aws-sdk/region-config-resolver": "3.806.0", - "@aws-sdk/signature-v4-multi-region": "3.806.0", - "@aws-sdk/types": "3.804.0", - "@aws-sdk/util-endpoints": "3.806.0", - "@aws-sdk/util-user-agent-browser": "3.804.0", - "@aws-sdk/util-user-agent-node": "3.806.0", - "@aws-sdk/xml-builder": "3.804.0", - "@smithy/config-resolver": "^4.1.1", - "@smithy/core": "^3.3.1", - "@smithy/eventstream-serde-browser": "^4.0.2", - "@smithy/eventstream-serde-config-resolver": "^4.1.0", - "@smithy/eventstream-serde-node": "^4.0.2", - "@smithy/fetch-http-handler": "^5.0.2", - "@smithy/hash-blob-browser": "^4.0.2", - "@smithy/hash-node": "^4.0.2", - "@smithy/hash-stream-node": "^4.0.2", - "@smithy/invalid-dependency": "^4.0.2", - "@smithy/md5-js": "^4.0.2", - "@smithy/middleware-content-length": "^4.0.2", - "@smithy/middleware-endpoint": "^4.1.3", - "@smithy/middleware-retry": "^4.1.4", - "@smithy/middleware-serde": "^4.0.3", - "@smithy/middleware-stack": "^4.0.2", - "@smithy/node-config-provider": "^4.1.0", - "@smithy/node-http-handler": "^4.0.4", - "@smithy/protocol-http": "^5.1.0", - "@smithy/smithy-client": "^4.2.3", - "@smithy/types": "^4.2.0", - "@smithy/url-parser": "^4.0.2", + "@aws-sdk/core": "3.823.0", + "@aws-sdk/credential-provider-node": "3.823.0", + "@aws-sdk/middleware-bucket-endpoint": "3.821.0", + "@aws-sdk/middleware-expect-continue": "3.821.0", + "@aws-sdk/middleware-flexible-checksums": "3.823.0", + "@aws-sdk/middleware-host-header": "3.821.0", + "@aws-sdk/middleware-location-constraint": "3.821.0", + "@aws-sdk/middleware-logger": "3.821.0", + "@aws-sdk/middleware-recursion-detection": "3.821.0", + "@aws-sdk/middleware-sdk-s3": "3.823.0", + "@aws-sdk/middleware-ssec": "3.821.0", + "@aws-sdk/middleware-user-agent": "3.823.0", + "@aws-sdk/region-config-resolver": "3.821.0", + "@aws-sdk/signature-v4-multi-region": "3.824.0", + "@aws-sdk/types": "3.821.0", + "@aws-sdk/util-endpoints": "3.821.0", + "@aws-sdk/util-user-agent-browser": "3.821.0", + "@aws-sdk/util-user-agent-node": "3.823.0", + "@aws-sdk/xml-builder": "3.821.0", + "@smithy/config-resolver": "^4.1.4", + "@smithy/core": "^3.5.1", + "@smithy/eventstream-serde-browser": "^4.0.4", + "@smithy/eventstream-serde-config-resolver": "^4.1.2", + "@smithy/eventstream-serde-node": "^4.0.4", + "@smithy/fetch-http-handler": "^5.0.4", + "@smithy/hash-blob-browser": "^4.0.4", + "@smithy/hash-node": "^4.0.4", + "@smithy/hash-stream-node": "^4.0.4", + "@smithy/invalid-dependency": "^4.0.4", + "@smithy/md5-js": "^4.0.4", + "@smithy/middleware-content-length": "^4.0.4", + "@smithy/middleware-endpoint": "^4.1.9", + "@smithy/middleware-retry": "^4.1.10", + "@smithy/middleware-serde": "^4.0.8", + "@smithy/middleware-stack": "^4.0.4", + "@smithy/node-config-provider": "^4.1.3", + "@smithy/node-http-handler": "^4.0.6", + "@smithy/protocol-http": "^5.1.2", + "@smithy/smithy-client": "^4.4.1", + "@smithy/types": "^4.3.1", + "@smithy/url-parser": "^4.0.4", "@smithy/util-base64": "^4.0.0", "@smithy/util-body-length-browser": "^4.0.0", "@smithy/util-body-length-node": "^4.0.0", - "@smithy/util-defaults-mode-browser": "^4.0.11", - "@smithy/util-defaults-mode-node": "^4.0.11", - "@smithy/util-endpoints": "^3.0.3", - "@smithy/util-middleware": "^4.0.2", - "@smithy/util-retry": "^4.0.3", - "@smithy/util-stream": "^4.2.0", + "@smithy/util-defaults-mode-browser": "^4.0.17", + "@smithy/util-defaults-mode-node": "^4.0.17", + "@smithy/util-endpoints": "^3.0.6", + "@smithy/util-middleware": "^4.0.4", + "@smithy/util-retry": "^4.0.5", + "@smithy/util-stream": "^4.2.2", "@smithy/util-utf8": "^4.0.0", - "@smithy/util-waiter": "^4.0.3", + "@smithy/util-waiter": "^4.0.5", "tslib": "^2.6.2" }, "engines": { @@ -6723,47 +6725,47 @@ } }, "node_modules/@parse/s3-files-adapter/node_modules/@aws-sdk/client-sso": { - "version": "3.806.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.806.0.tgz", - "integrity": "sha512-X0p/9/u9e6b22rlQqKucdtjdqmjSNB4c/8zDEoD5MvgYAAbMF9HNE0ST2xaA/WsJ7uE0jFfhPY2/00pslL1DqQ==", + "version": "3.823.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.823.0.tgz", + "integrity": "sha512-dBWdsbyGw8rPfdCsZySNtTOGQK4EZ8lxB/CneSQWRBPHgQ+Ys88NXxImO8xfWO7Itt1eh8O7UDTZ9+smcvw2pw==", "license": "Apache-2.0", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "3.806.0", - "@aws-sdk/middleware-host-header": "3.804.0", - "@aws-sdk/middleware-logger": "3.804.0", - "@aws-sdk/middleware-recursion-detection": "3.804.0", - "@aws-sdk/middleware-user-agent": "3.806.0", - "@aws-sdk/region-config-resolver": "3.806.0", - "@aws-sdk/types": "3.804.0", - "@aws-sdk/util-endpoints": "3.806.0", - "@aws-sdk/util-user-agent-browser": "3.804.0", - "@aws-sdk/util-user-agent-node": "3.806.0", - "@smithy/config-resolver": "^4.1.1", - "@smithy/core": "^3.3.1", - "@smithy/fetch-http-handler": "^5.0.2", - "@smithy/hash-node": "^4.0.2", - "@smithy/invalid-dependency": "^4.0.2", - "@smithy/middleware-content-length": "^4.0.2", - "@smithy/middleware-endpoint": "^4.1.3", - "@smithy/middleware-retry": "^4.1.4", - "@smithy/middleware-serde": "^4.0.3", - "@smithy/middleware-stack": "^4.0.2", - "@smithy/node-config-provider": "^4.1.0", - "@smithy/node-http-handler": "^4.0.4", - "@smithy/protocol-http": "^5.1.0", - "@smithy/smithy-client": "^4.2.3", - "@smithy/types": "^4.2.0", - "@smithy/url-parser": "^4.0.2", + "@aws-sdk/core": "3.823.0", + "@aws-sdk/middleware-host-header": "3.821.0", + "@aws-sdk/middleware-logger": "3.821.0", + "@aws-sdk/middleware-recursion-detection": "3.821.0", + "@aws-sdk/middleware-user-agent": "3.823.0", + "@aws-sdk/region-config-resolver": "3.821.0", + "@aws-sdk/types": "3.821.0", + "@aws-sdk/util-endpoints": "3.821.0", + "@aws-sdk/util-user-agent-browser": "3.821.0", + "@aws-sdk/util-user-agent-node": "3.823.0", + "@smithy/config-resolver": "^4.1.4", + "@smithy/core": "^3.5.1", + "@smithy/fetch-http-handler": "^5.0.4", + "@smithy/hash-node": "^4.0.4", + "@smithy/invalid-dependency": "^4.0.4", + "@smithy/middleware-content-length": "^4.0.4", + "@smithy/middleware-endpoint": "^4.1.9", + "@smithy/middleware-retry": "^4.1.10", + "@smithy/middleware-serde": "^4.0.8", + "@smithy/middleware-stack": "^4.0.4", + "@smithy/node-config-provider": "^4.1.3", + "@smithy/node-http-handler": "^4.0.6", + "@smithy/protocol-http": "^5.1.2", + "@smithy/smithy-client": "^4.4.1", + "@smithy/types": "^4.3.1", + "@smithy/url-parser": "^4.0.4", "@smithy/util-base64": "^4.0.0", "@smithy/util-body-length-browser": "^4.0.0", "@smithy/util-body-length-node": "^4.0.0", - "@smithy/util-defaults-mode-browser": "^4.0.11", - "@smithy/util-defaults-mode-node": "^4.0.11", - "@smithy/util-endpoints": "^3.0.3", - "@smithy/util-middleware": "^4.0.2", - "@smithy/util-retry": "^4.0.3", + "@smithy/util-defaults-mode-browser": "^4.0.17", + "@smithy/util-defaults-mode-node": "^4.0.17", + "@smithy/util-endpoints": "^3.0.6", + "@smithy/util-middleware": "^4.0.4", + "@smithy/util-retry": "^4.0.5", "@smithy/util-utf8": "^4.0.0", "tslib": "^2.6.2" }, @@ -6772,191 +6774,162 @@ } }, "node_modules/@parse/s3-files-adapter/node_modules/@aws-sdk/core": { - "version": "3.806.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.806.0.tgz", - "integrity": "sha512-HJRINPncdjPK0iL3f6cBpqCMaxVwq2oDbRCzOx04tsLZ0tNgRACBfT3d/zNVRvMt6fnOVKXoN1LAtQaw50pjEA==", + "version": "3.823.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.823.0.tgz", + "integrity": "sha512-1Cf4w8J7wYexz0KU3zpaikHvldGXQEjFldHOhm0SBGRy7qfYNXecfJAamccF7RdgLxKGgkv5Pl9zX/Z/DcW9zg==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/types": "3.804.0", - "@smithy/core": "^3.3.1", - "@smithy/node-config-provider": "^4.1.0", - "@smithy/property-provider": "^4.0.2", - "@smithy/protocol-http": "^5.1.0", - "@smithy/signature-v4": "^5.1.0", - "@smithy/smithy-client": "^4.2.3", - "@smithy/types": "^4.2.0", - "@smithy/util-middleware": "^4.0.2", - "fast-xml-parser": "4.4.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@parse/s3-files-adapter/node_modules/@aws-sdk/credential-provider-env": { - "version": "3.806.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.806.0.tgz", - "integrity": "sha512-nbPwmZn0kt6Q1XI2FaJWP6AhF9tro4cO5HlmZQx8NU+B0H1y9WMo659Q5zLLY46BXgoQVIJEsPSZpcZk27O4aw==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/core": "3.806.0", - "@aws-sdk/types": "3.804.0", - "@smithy/property-provider": "^4.0.2", - "@smithy/types": "^4.2.0", + "@aws-sdk/types": "3.821.0", + "@aws-sdk/xml-builder": "3.821.0", + "@smithy/core": "^3.5.1", + "@smithy/node-config-provider": "^4.1.3", + "@smithy/property-provider": "^4.0.4", + "@smithy/protocol-http": "^5.1.2", + "@smithy/signature-v4": "^5.1.2", + "@smithy/smithy-client": "^4.4.1", + "@smithy/types": "^4.3.1", + "@smithy/util-base64": "^4.0.0", + "@smithy/util-body-length-browser": "^4.0.0", + "@smithy/util-middleware": "^4.0.4", + "@smithy/util-utf8": "^4.0.0", + "fast-xml-parser": "4.4.1", "tslib": "^2.6.2" }, "engines": { "node": ">=18.0.0" } }, - "node_modules/@parse/s3-files-adapter/node_modules/@aws-sdk/credential-provider-http": { - "version": "3.806.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.806.0.tgz", - "integrity": "sha512-e/gB2iJQQ4ZpecOVpEFhEvjGwuTqNCzhVaVsFYVc49FPfR1seuN7qBGYe1MO7mouGDQFInzJgcNup0DnYUrLiw==", + "node_modules/@parse/s3-files-adapter/node_modules/@aws-sdk/credential-provider-env": { + "version": "3.823.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.823.0.tgz", + "integrity": "sha512-AIrLLwumObge+U1klN4j5ToIozI+gE9NosENRyHe0GIIZgTLOG/8jxrMFVYFeNHs7RUtjDTxxewislhFyGxJ/w==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "3.806.0", - "@aws-sdk/types": "3.804.0", - "@smithy/fetch-http-handler": "^5.0.2", - "@smithy/node-http-handler": "^4.0.4", - "@smithy/property-provider": "^4.0.2", - "@smithy/protocol-http": "^5.1.0", - "@smithy/smithy-client": "^4.2.3", - "@smithy/types": "^4.2.0", - "@smithy/util-stream": "^4.2.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@parse/s3-files-adapter/node_modules/@aws-sdk/credential-provider-ini": { - "version": "3.806.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.806.0.tgz", - "integrity": "sha512-FogfbuYSEZgFxbNy0QcsBZHHe5mSv5HV3+JyB5n0kCyjOISCVCZD7gwxKdXjt8O1hXq5k5SOdQvydGULlB6rew==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/core": "3.806.0", - "@aws-sdk/credential-provider-env": "3.806.0", - "@aws-sdk/credential-provider-http": "3.806.0", - "@aws-sdk/credential-provider-process": "3.806.0", - "@aws-sdk/credential-provider-sso": "3.806.0", - "@aws-sdk/credential-provider-web-identity": "3.806.0", - "@aws-sdk/nested-clients": "3.806.0", - "@aws-sdk/types": "3.804.0", - "@smithy/credential-provider-imds": "^4.0.2", - "@smithy/property-provider": "^4.0.2", - "@smithy/shared-ini-file-loader": "^4.0.2", - "@smithy/types": "^4.2.0", + "@aws-sdk/core": "3.823.0", + "@aws-sdk/types": "3.821.0", + "@smithy/property-provider": "^4.0.4", + "@smithy/types": "^4.3.1", "tslib": "^2.6.2" }, "engines": { "node": ">=18.0.0" } }, - "node_modules/@parse/s3-files-adapter/node_modules/@aws-sdk/credential-provider-node": { - "version": "3.806.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.806.0.tgz", - "integrity": "sha512-fZX8xP2Kf0k70kDTog/87fh/M+CV0E2yujSw1cUBJhDSwDX3RlUahiJk7TpB/KGw6hEFESMd6+7kq3UzYuw3rg==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/credential-provider-env": "3.806.0", - "@aws-sdk/credential-provider-http": "3.806.0", - "@aws-sdk/credential-provider-ini": "3.806.0", - "@aws-sdk/credential-provider-process": "3.806.0", - "@aws-sdk/credential-provider-sso": "3.806.0", - "@aws-sdk/credential-provider-web-identity": "3.806.0", - "@aws-sdk/types": "3.804.0", - "@smithy/credential-provider-imds": "^4.0.2", - "@smithy/property-provider": "^4.0.2", - "@smithy/shared-ini-file-loader": "^4.0.2", - "@smithy/types": "^4.2.0", + "node_modules/@parse/s3-files-adapter/node_modules/@aws-sdk/credential-provider-http": { + "version": "3.823.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.823.0.tgz", + "integrity": "sha512-u4DXvB/J/o2bcvP1JP6n3ch7V3/NngmiJFPsM0hKUyRlLuWM37HEDEdjPRs3/uL/soTxrEhWKTA9//YVkvzI0w==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "3.823.0", + "@aws-sdk/types": "3.821.0", + "@smithy/fetch-http-handler": "^5.0.4", + "@smithy/node-http-handler": "^4.0.6", + "@smithy/property-provider": "^4.0.4", + "@smithy/protocol-http": "^5.1.2", + "@smithy/smithy-client": "^4.4.1", + "@smithy/types": "^4.3.1", + "@smithy/util-stream": "^4.2.2", "tslib": "^2.6.2" }, "engines": { "node": ">=18.0.0" } }, - "node_modules/@parse/s3-files-adapter/node_modules/@aws-sdk/credential-provider-process": { - "version": "3.806.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.806.0.tgz", - "integrity": "sha512-8Y8GYEw/1e5IZRDQL02H6nsTDcRWid/afRMeWg+93oLQmbHcTtdm48tjis+7Xwqy+XazhMDmkbUht11QPTDJcQ==", + "node_modules/@parse/s3-files-adapter/node_modules/@aws-sdk/credential-provider-ini": { + "version": "3.823.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.823.0.tgz", + "integrity": "sha512-C0o63qviK5yFvjH9zKWAnCUBkssJoQ1A1XAHe0IAQkurzoNBSmu9oVemqwnKKHA4H6QrmusaEERfL00yohIkJA==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "3.806.0", - "@aws-sdk/types": "3.804.0", - "@smithy/property-provider": "^4.0.2", - "@smithy/shared-ini-file-loader": "^4.0.2", - "@smithy/types": "^4.2.0", + "@aws-sdk/core": "3.823.0", + "@aws-sdk/credential-provider-env": "3.823.0", + "@aws-sdk/credential-provider-http": "3.823.0", + "@aws-sdk/credential-provider-process": "3.823.0", + "@aws-sdk/credential-provider-sso": "3.823.0", + "@aws-sdk/credential-provider-web-identity": "3.823.0", + "@aws-sdk/nested-clients": "3.823.0", + "@aws-sdk/types": "3.821.0", + "@smithy/credential-provider-imds": "^4.0.6", + "@smithy/property-provider": "^4.0.4", + "@smithy/shared-ini-file-loader": "^4.0.4", + "@smithy/types": "^4.3.1", "tslib": "^2.6.2" }, "engines": { "node": ">=18.0.0" } }, - "node_modules/@parse/s3-files-adapter/node_modules/@aws-sdk/credential-provider-sso": { - "version": "3.806.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.806.0.tgz", - "integrity": "sha512-hT9OBwCxWMPBydNhXm2gdNNzx5AJNheS9RglwDDvXWzQ9qDuRztjuMBilMSUMb0HF9K4IqQjYzGqczMuktz4qQ==", + "node_modules/@parse/s3-files-adapter/node_modules/@aws-sdk/credential-provider-node": { + "version": "3.823.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.823.0.tgz", + "integrity": "sha512-nfSxXVuZ+2GJDpVFlflNfh55Yb4BtDsXLGNssXF5YU6UgSPsi8j2YkaE92Jv2s7dlUK07l0vRpLyPuXMaGeiRQ==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/client-sso": "3.806.0", - "@aws-sdk/core": "3.806.0", - "@aws-sdk/token-providers": "3.806.0", - "@aws-sdk/types": "3.804.0", - "@smithy/property-provider": "^4.0.2", - "@smithy/shared-ini-file-loader": "^4.0.2", - "@smithy/types": "^4.2.0", + "@aws-sdk/credential-provider-env": "3.823.0", + "@aws-sdk/credential-provider-http": "3.823.0", + "@aws-sdk/credential-provider-ini": "3.823.0", + "@aws-sdk/credential-provider-process": "3.823.0", + "@aws-sdk/credential-provider-sso": "3.823.0", + "@aws-sdk/credential-provider-web-identity": "3.823.0", + "@aws-sdk/types": "3.821.0", + "@smithy/credential-provider-imds": "^4.0.6", + "@smithy/property-provider": "^4.0.4", + "@smithy/shared-ini-file-loader": "^4.0.4", + "@smithy/types": "^4.3.1", "tslib": "^2.6.2" }, "engines": { "node": ">=18.0.0" } }, - "node_modules/@parse/s3-files-adapter/node_modules/@aws-sdk/credential-provider-web-identity": { - "version": "3.806.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.806.0.tgz", - "integrity": "sha512-XxaSY9Zd3D4ClUGENYMvi52ac5FuJPPAsvRtEfyrSdEpf6QufbMpnexWBZMYRF31h/VutgqtJwosGgNytpxMEg==", + "node_modules/@parse/s3-files-adapter/node_modules/@aws-sdk/credential-provider-process": { + "version": "3.823.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.823.0.tgz", + "integrity": "sha512-U/A10/7zu2FbMFFVpIw95y0TZf+oYyrhZTBn9eL8zgWcrYRqxrxdqtPj/zMrfIfyIvQUhuJSENN4dx4tfpCMWQ==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "3.806.0", - "@aws-sdk/nested-clients": "3.806.0", - "@aws-sdk/types": "3.804.0", - "@smithy/property-provider": "^4.0.2", - "@smithy/types": "^4.2.0", + "@aws-sdk/core": "3.823.0", + "@aws-sdk/types": "3.821.0", + "@smithy/property-provider": "^4.0.4", + "@smithy/shared-ini-file-loader": "^4.0.4", + "@smithy/types": "^4.3.1", "tslib": "^2.6.2" }, "engines": { "node": ">=18.0.0" } }, - "node_modules/@parse/s3-files-adapter/node_modules/@aws-sdk/middleware-bucket-endpoint": { - "version": "3.806.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-bucket-endpoint/-/middleware-bucket-endpoint-3.806.0.tgz", - "integrity": "sha512-ACjuyKJw9OZl8z8HzPEaqn1o7ElVW94mowyoZvyUIDouwAPGqPGJbJ5V35qx1oDTFSAJX+N3O3AO6RyFc8nUhw==", + "node_modules/@parse/s3-files-adapter/node_modules/@aws-sdk/credential-provider-sso": { + "version": "3.823.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.823.0.tgz", + "integrity": "sha512-ff8IM80Wqz1V7VVMaMUqO2iR417jggfGWLPl8j2l7uCgwpEyop1ZZl5CFVYEwSupRBtwp+VlW1gTCk7ke56MUw==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/types": "3.804.0", - "@aws-sdk/util-arn-parser": "3.804.0", - "@smithy/node-config-provider": "^4.1.0", - "@smithy/protocol-http": "^5.1.0", - "@smithy/types": "^4.2.0", - "@smithy/util-config-provider": "^4.0.0", + "@aws-sdk/client-sso": "3.823.0", + "@aws-sdk/core": "3.823.0", + "@aws-sdk/token-providers": "3.823.0", + "@aws-sdk/types": "3.821.0", + "@smithy/property-provider": "^4.0.4", + "@smithy/shared-ini-file-loader": "^4.0.4", + "@smithy/types": "^4.3.1", "tslib": "^2.6.2" }, "engines": { "node": ">=18.0.0" } }, - "node_modules/@parse/s3-files-adapter/node_modules/@aws-sdk/middleware-expect-continue": { - "version": "3.804.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-expect-continue/-/middleware-expect-continue-3.804.0.tgz", - "integrity": "sha512-YW1hySBolALMII6C8y7Z0CRG2UX1dGJjLEBNFeefhO/xP7ZuE1dvnmfJGaEuBMnvc3wkRS63VZ3aqX6sevM1CA==", + "node_modules/@parse/s3-files-adapter/node_modules/@aws-sdk/credential-provider-web-identity": { + "version": "3.823.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.823.0.tgz", + "integrity": "sha512-lzoZdJMQq9w7i4lXVka30cVBe/dZoUDZST8Xz/soEd73gg7RTKgG+0szL4xFWgdBDgcJDWLfZfJzlbyIVyAyOA==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/types": "3.804.0", - "@smithy/protocol-http": "^5.1.0", - "@smithy/types": "^4.2.0", + "@aws-sdk/core": "3.823.0", + "@aws-sdk/nested-clients": "3.823.0", + "@aws-sdk/types": "3.821.0", + "@smithy/property-provider": "^4.0.4", + "@smithy/types": "^4.3.1", "tslib": "^2.6.2" }, "engines": { @@ -6964,22 +6937,22 @@ } }, "node_modules/@parse/s3-files-adapter/node_modules/@aws-sdk/middleware-flexible-checksums": { - "version": "3.806.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-flexible-checksums/-/middleware-flexible-checksums-3.806.0.tgz", - "integrity": "sha512-YEmuU2Nr/+blhi70gS38fnCe2IoL6OVVZXMp4MbzqZRUqeBbnxZhHQrd5YOiboJz7iq+g98xwFebHY167iejcg==", + "version": "3.823.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-flexible-checksums/-/middleware-flexible-checksums-3.823.0.tgz", + "integrity": "sha512-Elt6G1ryEEdkrppqbyJON0o2x4x9xKknimJtMLdfG1b4YfO9X+UB31pk4R2SHvMYfrJ+p8DE2jRAhvV4g/dwIQ==", "license": "Apache-2.0", "dependencies": { "@aws-crypto/crc32": "5.2.0", "@aws-crypto/crc32c": "5.2.0", "@aws-crypto/util": "5.2.0", - "@aws-sdk/core": "3.806.0", - "@aws-sdk/types": "3.804.0", + "@aws-sdk/core": "3.823.0", + "@aws-sdk/types": "3.821.0", "@smithy/is-array-buffer": "^4.0.0", - "@smithy/node-config-provider": "^4.1.0", - "@smithy/protocol-http": "^5.1.0", - "@smithy/types": "^4.2.0", - "@smithy/util-middleware": "^4.0.2", - "@smithy/util-stream": "^4.2.0", + "@smithy/node-config-provider": "^4.1.3", + "@smithy/protocol-http": "^5.1.2", + "@smithy/types": "^4.3.1", + "@smithy/util-middleware": "^4.0.4", + "@smithy/util-stream": "^4.2.2", "@smithy/util-utf8": "^4.0.0", "tslib": "^2.6.2" }, @@ -6987,82 +6960,24 @@ "node": ">=18.0.0" } }, - "node_modules/@parse/s3-files-adapter/node_modules/@aws-sdk/middleware-host-header": { - "version": "3.804.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.804.0.tgz", - "integrity": "sha512-bum1hLVBrn2lJCi423Z2fMUYtsbkGI2s4N+2RI2WSjvbaVyMSv/WcejIrjkqiiMR+2Y7m5exgoKeg4/TODLDPQ==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/types": "3.804.0", - "@smithy/protocol-http": "^5.1.0", - "@smithy/types": "^4.2.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@parse/s3-files-adapter/node_modules/@aws-sdk/middleware-location-constraint": { - "version": "3.804.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-location-constraint/-/middleware-location-constraint-3.804.0.tgz", - "integrity": "sha512-AMtKnllIWKgoo7hiJfphLYotEwTERfjVMO2+cKAncz9w1g+bnYhHxiVhJJoR94y047c06X4PU5MsTxvdQ73Znw==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/types": "3.804.0", - "@smithy/types": "^4.2.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@parse/s3-files-adapter/node_modules/@aws-sdk/middleware-logger": { - "version": "3.804.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.804.0.tgz", - "integrity": "sha512-w/qLwL3iq0KOPQNat0Kb7sKndl9BtceigINwBU7SpkYWX9L/Lem6f8NPEKrC9Tl4wDBht3Yztub4oRTy/horJA==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/types": "3.804.0", - "@smithy/types": "^4.2.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@parse/s3-files-adapter/node_modules/@aws-sdk/middleware-recursion-detection": { - "version": "3.804.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.804.0.tgz", - "integrity": "sha512-zqHOrvLRdsUdN/ehYfZ9Tf8svhbiLLz5VaWUz22YndFv6m9qaAcijkpAOlKexsv3nLBMJdSdJ6GUTAeIy3BZzw==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/types": "3.804.0", - "@smithy/protocol-http": "^5.1.0", - "@smithy/types": "^4.2.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, "node_modules/@parse/s3-files-adapter/node_modules/@aws-sdk/middleware-sdk-s3": { - "version": "3.806.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-s3/-/middleware-sdk-s3-3.806.0.tgz", - "integrity": "sha512-K1ssdovHH/kPN9EUS1LznwzoL+r89Cx8qAkp0K8MqdCQuBjZ0KRnjvo9nx69Vg5d/rg01VYTxomFUPXfcPtVXw==", + "version": "3.823.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-s3/-/middleware-sdk-s3-3.823.0.tgz", + "integrity": "sha512-UV755wt2HDru8PbxLn2S0Fvwgdn9mYamexn31Q6wyUGQ6rkpjKNEzL+oNDGQQmDQAOcQO+nLubKFsCwtBM02fQ==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "3.806.0", - "@aws-sdk/types": "3.804.0", + "@aws-sdk/core": "3.823.0", + "@aws-sdk/types": "3.821.0", "@aws-sdk/util-arn-parser": "3.804.0", - "@smithy/core": "^3.3.1", - "@smithy/node-config-provider": "^4.1.0", - "@smithy/protocol-http": "^5.1.0", - "@smithy/signature-v4": "^5.1.0", - "@smithy/smithy-client": "^4.2.3", - "@smithy/types": "^4.2.0", + "@smithy/core": "^3.5.1", + "@smithy/node-config-provider": "^4.1.3", + "@smithy/protocol-http": "^5.1.2", + "@smithy/signature-v4": "^5.1.2", + "@smithy/smithy-client": "^4.4.1", + "@smithy/types": "^4.3.1", "@smithy/util-config-provider": "^4.0.0", - "@smithy/util-middleware": "^4.0.2", - "@smithy/util-stream": "^4.2.0", + "@smithy/util-middleware": "^4.0.4", + "@smithy/util-stream": "^4.2.2", "@smithy/util-utf8": "^4.0.0", "tslib": "^2.6.2" }, @@ -7070,32 +6985,18 @@ "node": ">=18.0.0" } }, - "node_modules/@parse/s3-files-adapter/node_modules/@aws-sdk/middleware-ssec": { - "version": "3.804.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-ssec/-/middleware-ssec-3.804.0.tgz", - "integrity": "sha512-Tk8jK0gOIUBvEPTz/wwSlP1V70zVQ3QYqsLPAjQRMO6zfOK9ax31dln3MgKvFDJxBydS2tS3wsn53v+brxDxTA==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/types": "3.804.0", - "@smithy/types": "^4.2.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, "node_modules/@parse/s3-files-adapter/node_modules/@aws-sdk/middleware-user-agent": { - "version": "3.806.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.806.0.tgz", - "integrity": "sha512-XoIromVffgXnc+/mjlR2EVzQVIei3bPVtafIZNsHuEmUvIWJXiWsa2eJpt3BUqa0HF9YPknK7ommNEhqRb8ucg==", + "version": "3.823.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.823.0.tgz", + "integrity": "sha512-TKRQK09ld1LrIPExC9rIDpqnMsWcv+eq8ABKFHVo8mDLTSuWx/IiQ4eCh9T5zDuEZcLY4nNYCSzXKqw6XKcMCA==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "3.806.0", - "@aws-sdk/types": "3.804.0", - "@aws-sdk/util-endpoints": "3.806.0", - "@smithy/core": "^3.3.1", - "@smithy/protocol-http": "^5.1.0", - "@smithy/types": "^4.2.0", + "@aws-sdk/core": "3.823.0", + "@aws-sdk/types": "3.821.0", + "@aws-sdk/util-endpoints": "3.821.0", + "@smithy/core": "^3.5.1", + "@smithy/protocol-http": "^5.1.2", + "@smithy/types": "^4.3.1", "tslib": "^2.6.2" }, "engines": { @@ -7103,47 +7004,47 @@ } }, "node_modules/@parse/s3-files-adapter/node_modules/@aws-sdk/nested-clients": { - "version": "3.806.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/nested-clients/-/nested-clients-3.806.0.tgz", - "integrity": "sha512-ua2gzpfQ9MF8Rny+tOAivowOWWvqEusez2rdcQK8jdBjA1ANd/0xzToSZjZh0ziN8Kl8jOhNnHbQJ0v6dT6+hg==", + "version": "3.823.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/nested-clients/-/nested-clients-3.823.0.tgz", + "integrity": "sha512-/BcyOBubrJnd2gxlbbmNJR1w0Z3OVN/UE8Yz20e+ou+Mijjv7EbtVwmWvio1e3ZjphwdA8tVfPYZKwXmrvHKmQ==", "license": "Apache-2.0", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "3.806.0", - "@aws-sdk/middleware-host-header": "3.804.0", - "@aws-sdk/middleware-logger": "3.804.0", - "@aws-sdk/middleware-recursion-detection": "3.804.0", - "@aws-sdk/middleware-user-agent": "3.806.0", - "@aws-sdk/region-config-resolver": "3.806.0", - "@aws-sdk/types": "3.804.0", - "@aws-sdk/util-endpoints": "3.806.0", - "@aws-sdk/util-user-agent-browser": "3.804.0", - "@aws-sdk/util-user-agent-node": "3.806.0", - "@smithy/config-resolver": "^4.1.1", - "@smithy/core": "^3.3.1", - "@smithy/fetch-http-handler": "^5.0.2", - "@smithy/hash-node": "^4.0.2", - "@smithy/invalid-dependency": "^4.0.2", - "@smithy/middleware-content-length": "^4.0.2", - "@smithy/middleware-endpoint": "^4.1.3", - "@smithy/middleware-retry": "^4.1.4", - "@smithy/middleware-serde": "^4.0.3", - "@smithy/middleware-stack": "^4.0.2", - "@smithy/node-config-provider": "^4.1.0", - "@smithy/node-http-handler": "^4.0.4", - "@smithy/protocol-http": "^5.1.0", - "@smithy/smithy-client": "^4.2.3", - "@smithy/types": "^4.2.0", - "@smithy/url-parser": "^4.0.2", + "@aws-sdk/core": "3.823.0", + "@aws-sdk/middleware-host-header": "3.821.0", + "@aws-sdk/middleware-logger": "3.821.0", + "@aws-sdk/middleware-recursion-detection": "3.821.0", + "@aws-sdk/middleware-user-agent": "3.823.0", + "@aws-sdk/region-config-resolver": "3.821.0", + "@aws-sdk/types": "3.821.0", + "@aws-sdk/util-endpoints": "3.821.0", + "@aws-sdk/util-user-agent-browser": "3.821.0", + "@aws-sdk/util-user-agent-node": "3.823.0", + "@smithy/config-resolver": "^4.1.4", + "@smithy/core": "^3.5.1", + "@smithy/fetch-http-handler": "^5.0.4", + "@smithy/hash-node": "^4.0.4", + "@smithy/invalid-dependency": "^4.0.4", + "@smithy/middleware-content-length": "^4.0.4", + "@smithy/middleware-endpoint": "^4.1.9", + "@smithy/middleware-retry": "^4.1.10", + "@smithy/middleware-serde": "^4.0.8", + "@smithy/middleware-stack": "^4.0.4", + "@smithy/node-config-provider": "^4.1.3", + "@smithy/node-http-handler": "^4.0.6", + "@smithy/protocol-http": "^5.1.2", + "@smithy/smithy-client": "^4.4.1", + "@smithy/types": "^4.3.1", + "@smithy/url-parser": "^4.0.4", "@smithy/util-base64": "^4.0.0", "@smithy/util-body-length-browser": "^4.0.0", "@smithy/util-body-length-node": "^4.0.0", - "@smithy/util-defaults-mode-browser": "^4.0.11", - "@smithy/util-defaults-mode-node": "^4.0.11", - "@smithy/util-endpoints": "^3.0.3", - "@smithy/util-middleware": "^4.0.2", - "@smithy/util-retry": "^4.0.3", + "@smithy/util-defaults-mode-browser": "^4.0.17", + "@smithy/util-defaults-mode-node": "^4.0.17", + "@smithy/util-endpoints": "^3.0.6", + "@smithy/util-middleware": "^4.0.4", + "@smithy/util-retry": "^4.0.5", "@smithy/util-utf8": "^4.0.0", "tslib": "^2.6.2" }, @@ -7151,23 +7052,6 @@ "node": ">=18.0.0" } }, - "node_modules/@parse/s3-files-adapter/node_modules/@aws-sdk/region-config-resolver": { - "version": "3.806.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/region-config-resolver/-/region-config-resolver-3.806.0.tgz", - "integrity": "sha512-cuv5pX55JOlzKC/iLsB5nZ9eUyVgncim3VhhWHZA/KYPh7rLMjOEfZ+xyaE9uLJXGmzOJboFH7+YdTRdIcOgrg==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/types": "3.804.0", - "@smithy/node-config-provider": "^4.1.0", - "@smithy/types": "^4.2.0", - "@smithy/util-config-provider": "^4.0.0", - "@smithy/util-middleware": "^4.0.2", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, "node_modules/@parse/s3-files-adapter/node_modules/@aws-sdk/s3-request-presigner": { "version": "3.787.0", "resolved": "https://registry.npmjs.org/@aws-sdk/s3-request-presigner/-/s3-request-presigner-3.787.0.tgz", @@ -7277,16 +7161,16 @@ } }, "node_modules/@parse/s3-files-adapter/node_modules/@aws-sdk/signature-v4-multi-region": { - "version": "3.806.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/signature-v4-multi-region/-/signature-v4-multi-region-3.806.0.tgz", - "integrity": "sha512-IrbEnpKvG8d9rUWAvsF28g8qBlQ02FaOxn4cGXtTs0b0BGMK1M+cGQrYjJ7Ak08kIXDxBqsdIlZGsKYr+Ds9+w==", + "version": "3.824.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/signature-v4-multi-region/-/signature-v4-multi-region-3.824.0.tgz", + "integrity": "sha512-HBjuWeN6Z1pvJjUvGXdMNLwEypKKB4km6zXj9jsbOOwP8NTL6J5rY+JmlX/mfBTmvzmI0kMu2bxlQ4ME2CIRbA==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/middleware-sdk-s3": "3.806.0", - "@aws-sdk/types": "3.804.0", - "@smithy/protocol-http": "^5.1.0", - "@smithy/signature-v4": "^5.1.0", - "@smithy/types": "^4.2.0", + "@aws-sdk/middleware-sdk-s3": "3.823.0", + "@aws-sdk/types": "3.821.0", + "@smithy/protocol-http": "^5.1.2", + "@smithy/signature-v4": "^5.1.2", + "@smithy/types": "^4.3.1", "tslib": "^2.6.2" }, "engines": { @@ -7294,29 +7178,17 @@ } }, "node_modules/@parse/s3-files-adapter/node_modules/@aws-sdk/token-providers": { - "version": "3.806.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.806.0.tgz", - "integrity": "sha512-I6SxcsvV7yinJZmPgGullFHS0tsTKa7K3jEc5dmyCz8X+kZPfsWNffZmtmnCvWXPqMXWBvK6hVaxwomx79yeHA==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/nested-clients": "3.806.0", - "@aws-sdk/types": "3.804.0", - "@smithy/property-provider": "^4.0.2", - "@smithy/shared-ini-file-loader": "^4.0.2", - "@smithy/types": "^4.2.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@parse/s3-files-adapter/node_modules/@aws-sdk/types": { - "version": "3.804.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.804.0.tgz", - "integrity": "sha512-A9qnsy9zQ8G89vrPPlNG9d1d8QcKRGqJKqwyGgS0dclJpwy6d1EWgQLIolKPl6vcFpLoe6avLOLxr+h8ur5wpg==", + "version": "3.823.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.823.0.tgz", + "integrity": "sha512-vz6onCb/+g4y+owxGGPMEMdN789dTfBOgz/c9pFv0f01840w9Rrt46l+gjQlnXnx+0KG6wNeBIVhFdbCfV3HyQ==", "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^4.2.0", + "@aws-sdk/core": "3.823.0", + "@aws-sdk/nested-clients": "3.823.0", + "@aws-sdk/types": "3.821.0", + "@smithy/property-provider": "^4.0.4", + "@smithy/shared-ini-file-loader": "^4.0.4", + "@smithy/types": "^4.3.1", "tslib": "^2.6.2" }, "engines": { @@ -7324,14 +7196,14 @@ } }, "node_modules/@parse/s3-files-adapter/node_modules/@aws-sdk/util-endpoints": { - "version": "3.806.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.806.0.tgz", - "integrity": "sha512-3YRRgZ+qFuWDdm5uAbxKsr65UAil4KkrFKua9f4m7Be3v24ETiFOOqhanFUIk9/WOtvzF7oFEiDjYKDGlwV2xg==", + "version": "3.821.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.821.0.tgz", + "integrity": "sha512-Uknt/zUZnLE76zaAAPEayOeF5/4IZ2puTFXvcSCWHsi9m3tqbb9UozlnlVqvCZLCRWfQryZQoG2W4XSS3qgk5A==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/types": "3.804.0", - "@smithy/types": "^4.2.0", - "@smithy/util-endpoints": "^3.0.3", + "@aws-sdk/types": "3.821.0", + "@smithy/types": "^4.3.1", + "@smithy/util-endpoints": "^3.0.6", "tslib": "^2.6.2" }, "engines": { @@ -7366,28 +7238,16 @@ "node": ">=18.0.0" } }, - "node_modules/@parse/s3-files-adapter/node_modules/@aws-sdk/util-user-agent-browser": { - "version": "3.804.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.804.0.tgz", - "integrity": "sha512-KfW6T6nQHHM/vZBBdGn6fMyG/MgX5lq82TDdX4HRQRRuHKLgBWGpKXqqvBwqIaCdXwWHgDrg2VQups6GqOWW2A==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/types": "3.804.0", - "@smithy/types": "^4.2.0", - "bowser": "^2.11.0", - "tslib": "^2.6.2" - } - }, "node_modules/@parse/s3-files-adapter/node_modules/@aws-sdk/util-user-agent-node": { - "version": "3.806.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.806.0.tgz", - "integrity": "sha512-Az2e4/gmPZ4BpB7QRj7U76I+fctXhNcxlcgsaHnMhvt+R30nvzM2EhsyBUvsWl8+r9bnLeYt9BpvEZeq2ANDzA==", + "version": "3.823.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.823.0.tgz", + "integrity": "sha512-WvNeRz7HV3JLBVGTXW4Qr5QvvWY0vtggH5jW/NqHFH+ZEliVQaUIJ/HNLMpMoCSiu/DlpQAyAjRZXAptJ0oqbw==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/middleware-user-agent": "3.806.0", - "@aws-sdk/types": "3.804.0", - "@smithy/node-config-provider": "^4.1.0", - "@smithy/types": "^4.2.0", + "@aws-sdk/middleware-user-agent": "3.823.0", + "@aws-sdk/types": "3.821.0", + "@smithy/node-config-provider": "^4.1.3", + "@smithy/types": "^4.3.1", "tslib": "^2.6.2" }, "engines": { @@ -7402,19 +7262,6 @@ } } }, - "node_modules/@parse/s3-files-adapter/node_modules/@aws-sdk/xml-builder": { - "version": "3.804.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/xml-builder/-/xml-builder-3.804.0.tgz", - "integrity": "sha512-JbGWp36IG9dgxtvC6+YXwt5WDZYfuamWFtVfK6fQpnmL96dx+GUPOXPKRWdw67WLKf2comHY28iX2d3z35I53Q==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/types": "^4.2.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, "node_modules/@parse/s3-files-adapter/node_modules/@smithy/abort-controller": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-4.0.4.tgz", @@ -10724,9 +10571,9 @@ } }, "node_modules/acorn": { - "version": "8.14.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.1.tgz", - "integrity": "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==", + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", + "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "license": "MIT", "bin": { "acorn": "bin/acorn" @@ -11015,9 +10862,9 @@ "license": "MIT" }, "node_modules/axios": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.9.0.tgz", - "integrity": "sha512-re4CqKTJaURpzbLHtIi6XpDv20/CnpXOtjRY5/CU32L8gU8ek9UIivcfvSWvmKEngmVbrUtPpdDwWDWL7DNHvg==", + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.10.0.tgz", + "integrity": "sha512-/1xYAC4MP/HEG+3duIhFr4ZQXR4sQXOIe+o6sdqzeykGLx6Upp/1p8MHqhINOvGeP7xyNHe7tsiJByc4SSVUxw==", "license": "MIT", "dependencies": { "follow-redirects": "^1.15.6", @@ -11222,9 +11069,10 @@ "integrity": "sha512-AlcaJBi/pqqJBIQ8U9Mcpc9i8Aqxn88Skv5d+xBX006BY5u8N3mGLHa5Lgppa7L/HfwgwLgZ6NYs+Ag6uUmJRA==" }, "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -11590,6 +11438,12 @@ "node": ">=0.10.0" } }, + "node_modules/coherentpdf": { + "version": "2.5.5", + "resolved": "https://registry.npmjs.org/coherentpdf/-/coherentpdf-2.5.5.tgz", + "integrity": "sha512-AAD3RG7lq2n34AtH352sbNDhJ82yfp2vFUp63/+Vu7snAqW0vyvY33XuhZdj6ubZUlFe1DNSSEaYcyc7+jTJ5Q==", + "license": "AGPL-3.0-or-later" + }, "node_modules/color": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/color/-/color-3.2.1.tgz", @@ -11762,7 +11616,8 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/cors": { "version": "2.8.5", @@ -11820,6 +11675,15 @@ "node": ">=0.10" } }, + "node_modules/data-uri-to-buffer": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", + "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==", + "license": "MIT", + "engines": { + "node": ">= 12" + } + }, "node_modules/date-fns": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-4.1.0.tgz", @@ -12275,18 +12139,18 @@ "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" }, "node_modules/eslint": { - "version": "9.28.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.28.0.tgz", - "integrity": "sha512-ocgh41VhRlf9+fVpe7QKzwLj9c92fDiqOj8Y3Sd4/ZmVA4Btx4PlUYPq4pp9JDyupkf1upbEXecxL2mwNV7jPQ==", + "version": "9.29.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.29.0.tgz", + "integrity": "sha512-GsGizj2Y1rCWDu6XoEekL3RLilp0voSePurjZIkxL3wlm5o5EC9VpgaP7lrCvjnkuLvzFBQWB3vWB3K5KQTveQ==", "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.12.1", - "@eslint/config-array": "^0.20.0", + "@eslint/config-array": "^0.20.1", "@eslint/config-helpers": "^0.2.1", "@eslint/core": "^0.14.0", "@eslint/eslintrc": "^3.3.1", - "@eslint/js": "9.28.0", + "@eslint/js": "9.29.0", "@eslint/plugin-kit": "^0.3.1", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", @@ -12298,9 +12162,9 @@ "cross-spawn": "^7.0.6", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^8.3.0", - "eslint-visitor-keys": "^4.2.0", - "espree": "^10.3.0", + "eslint-scope": "^8.4.0", + "eslint-visitor-keys": "^4.2.1", + "espree": "^10.4.0", "esquery": "^1.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", @@ -12381,9 +12245,9 @@ } }, "node_modules/eslint/node_modules/eslint-scope": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.3.0.tgz", - "integrity": "sha512-pUNxi75F8MJ/GdeKtVLSbYg4ZI34J6C0C7sbL4YOp2exGwen7ZsuBqKzUhXd0qMQ362yET3z+uPwKeg/0C2XCQ==", + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz", + "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==", "license": "BSD-2-Clause", "dependencies": { "esrecurse": "^4.3.0", @@ -12397,9 +12261,10 @@ } }, "node_modules/eslint/node_modules/eslint-visitor-keys": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", - "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "license": "Apache-2.0", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, @@ -12436,14 +12301,14 @@ } }, "node_modules/espree": { - "version": "10.3.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-10.3.0.tgz", - "integrity": "sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==", + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz", + "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==", "license": "BSD-2-Clause", "dependencies": { - "acorn": "^8.14.0", + "acorn": "^8.15.0", "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^4.2.0" + "eslint-visitor-keys": "^4.2.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -12453,9 +12318,9 @@ } }, "node_modules/espree/node_modules/eslint-visitor-keys": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", - "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", "license": "Apache-2.0", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -12808,6 +12673,29 @@ "resolved": "https://registry.npmjs.org/fecha/-/fecha-4.2.3.tgz", "integrity": "sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw==" }, + "node_modules/fetch-blob": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz", + "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "paypal", + "url": "https://paypal.me/jimmywarting" + } + ], + "license": "MIT", + "dependencies": { + "node-domexception": "^1.0.0", + "web-streams-polyfill": "^3.0.3" + }, + "engines": { + "node": "^12.20 || >= 14.13" + } + }, "node_modules/file-entry-cache": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", @@ -13025,20 +12913,33 @@ } }, "node_modules/form-data": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.2.tgz", - "integrity": "sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.3.tgz", + "integrity": "sha512-qsITQPfmvMOSAdeyZ+12I1c+CKSstAFAwu+97zrnWAbIr5u8wfsExUzCesVLC8NgHuRUqNN4Zy6UPWUTRGslcA==", "license": "MIT", "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", "mime-types": "^2.1.12" }, "engines": { "node": ">= 6" } }, + "node_modules/formdata-polyfill": { + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", + "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", + "license": "MIT", + "dependencies": { + "fetch-blob": "^3.1.2" + }, + "engines": { + "node": ">=12.20.0" + } + }, "node_modules/forwarded": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", @@ -13419,10 +13320,11 @@ } }, "node_modules/glob/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", "dev": true, + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0" } @@ -13502,33 +13404,196 @@ "node": ">=14" } }, + "node_modules/google-logging-utils": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/google-logging-utils/-/google-logging-utils-1.1.1.tgz", + "integrity": "sha512-rcX58I7nqpu4mbKztFeOAObbomBbHU2oIb/d3tJfF3dizGSApqtSwYJigGCooHdnMyQBIw8BrWyK96w3YXgr6A==", + "license": "Apache-2.0", + "engines": { + "node": ">=14" + } + }, "node_modules/googleapis": { - "version": "149.0.0", - "resolved": "https://registry.npmjs.org/googleapis/-/googleapis-149.0.0.tgz", - "integrity": "sha512-LTMc/njwYy7KTeaUHDcQt7KxftHyghdzm2XzbL46PRLd1AXB09utT9Po2ZJn2X0EApz0pE2T5x5A9zM8iue6zw==", + "version": "150.0.1", + "resolved": "https://registry.npmjs.org/googleapis/-/googleapis-150.0.1.tgz", + "integrity": "sha512-9Wa9vm3WtDpss0VFBHsbZWcoRccpOSWdpz7YIfb1LBXopZJEg/Zc8ymmaSgvDkP4FhN+pqPS9nZjO7REAJWSUg==", "license": "Apache-2.0", "dependencies": { - "google-auth-library": "^9.0.0", - "googleapis-common": "^7.0.0" + "google-auth-library": "^10.0.0-rc.1", + "googleapis-common": "^8.0.2-rc.0" }, "engines": { - "node": ">=14.0.0" + "node": ">=18" } }, "node_modules/googleapis-common": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/googleapis-common/-/googleapis-common-7.2.0.tgz", - "integrity": "sha512-/fhDZEJZvOV3X5jmD+fKxMqma5q2Q9nZNSF3kn1F18tpxmA86BcTxAGBQdM0N89Z3bEaIs+HVznSmFJEAmMTjA==", + "version": "8.0.2-rc.0", + "resolved": "https://registry.npmjs.org/googleapis-common/-/googleapis-common-8.0.2-rc.0.tgz", + "integrity": "sha512-JTcxRvmFa9Ec1uyfMEimEMeeKq1sHNZX3vn2qmoUMtnvixXXvcqTcbDZvEZXkEWpGlPlOf4joyep6/qs0BrLyg==", + "license": "Apache-2.0", "dependencies": { "extend": "^3.0.2", - "gaxios": "^6.0.3", - "google-auth-library": "^9.7.0", + "gaxios": "^7.0.0-rc.4", + "google-auth-library": "^10.0.0-rc.1", "qs": "^6.7.0", - "url-template": "^2.0.8", - "uuid": "^9.0.0" + "url-template": "^2.0.8" }, "engines": { - "node": ">=14.0.0" + "node": ">=18.0.0" + } + }, + "node_modules/googleapis-common/node_modules/gaxios": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-7.1.0.tgz", + "integrity": "sha512-y1Q0MX1Ba6eg67Zz92kW0MHHhdtWksYckQy1KJsI6P4UlDQ8cvdvpLEPslD/k7vFkdPppMESFGTvk7XpSiKj8g==", + "license": "Apache-2.0", + "dependencies": { + "extend": "^3.0.2", + "https-proxy-agent": "^7.0.1", + "node-fetch": "^3.3.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/googleapis-common/node_modules/gcp-metadata": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-7.0.0.tgz", + "integrity": "sha512-3PfRTzvT3Msu0Hy8Gf9ypxJvaClG2IB9pyH0r8QOmRBW5mUcrHgYpF4GYP+XulDbfhxEhBYtJtJJQb5S2wM+LA==", + "license": "Apache-2.0", + "dependencies": { + "gaxios": "^7.0.0", + "google-logging-utils": "^1.0.0", + "json-bigint": "^1.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/googleapis-common/node_modules/google-auth-library": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-10.1.0.tgz", + "integrity": "sha512-GspVjZj1RbyRWpQ9FbAXMKjFGzZwDKnUHi66JJ+tcjcu5/xYAP1pdlWotCuIkMwjfVsxxDvsGZXGLzRt72D0sQ==", + "license": "Apache-2.0", + "dependencies": { + "base64-js": "^1.3.0", + "ecdsa-sig-formatter": "^1.0.11", + "gaxios": "^7.0.0", + "gcp-metadata": "^7.0.0", + "google-logging-utils": "^1.0.0", + "gtoken": "^8.0.0", + "jws": "^4.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/googleapis-common/node_modules/gtoken": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/gtoken/-/gtoken-8.0.0.tgz", + "integrity": "sha512-+CqsMbHPiSTdtSO14O51eMNlrp9N79gmeqmXeouJOhfucAedHw9noVe/n5uJk3tbKE6a+6ZCQg3RPhVhHByAIw==", + "license": "MIT", + "dependencies": { + "gaxios": "^7.0.0", + "jws": "^4.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/googleapis-common/node_modules/node-fetch": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", + "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", + "license": "MIT", + "dependencies": { + "data-uri-to-buffer": "^4.0.0", + "fetch-blob": "^3.1.4", + "formdata-polyfill": "^4.0.10" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/node-fetch" + } + }, + "node_modules/googleapis/node_modules/gaxios": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-7.1.0.tgz", + "integrity": "sha512-y1Q0MX1Ba6eg67Zz92kW0MHHhdtWksYckQy1KJsI6P4UlDQ8cvdvpLEPslD/k7vFkdPppMESFGTvk7XpSiKj8g==", + "license": "Apache-2.0", + "dependencies": { + "extend": "^3.0.2", + "https-proxy-agent": "^7.0.1", + "node-fetch": "^3.3.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/googleapis/node_modules/gcp-metadata": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-7.0.0.tgz", + "integrity": "sha512-3PfRTzvT3Msu0Hy8Gf9ypxJvaClG2IB9pyH0r8QOmRBW5mUcrHgYpF4GYP+XulDbfhxEhBYtJtJJQb5S2wM+LA==", + "license": "Apache-2.0", + "dependencies": { + "gaxios": "^7.0.0", + "google-logging-utils": "^1.0.0", + "json-bigint": "^1.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/googleapis/node_modules/google-auth-library": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-10.1.0.tgz", + "integrity": "sha512-GspVjZj1RbyRWpQ9FbAXMKjFGzZwDKnUHi66JJ+tcjcu5/xYAP1pdlWotCuIkMwjfVsxxDvsGZXGLzRt72D0sQ==", + "license": "Apache-2.0", + "dependencies": { + "base64-js": "^1.3.0", + "ecdsa-sig-formatter": "^1.0.11", + "gaxios": "^7.0.0", + "gcp-metadata": "^7.0.0", + "google-logging-utils": "^1.0.0", + "gtoken": "^8.0.0", + "jws": "^4.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/googleapis/node_modules/gtoken": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/gtoken/-/gtoken-8.0.0.tgz", + "integrity": "sha512-+CqsMbHPiSTdtSO14O51eMNlrp9N79gmeqmXeouJOhfucAedHw9noVe/n5uJk3tbKE6a+6ZCQg3RPhVhHByAIw==", + "license": "MIT", + "dependencies": { + "gaxios": "^7.0.0", + "jws": "^4.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/googleapis/node_modules/node-fetch": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", + "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", + "license": "MIT", + "dependencies": { + "data-uri-to-buffer": "^4.0.0", + "fetch-blob": "^3.1.4", + "formdata-polyfill": "^4.0.10" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/node-fetch" } }, "node_modules/gopd": { @@ -14314,23 +14379,23 @@ } }, "node_modules/jasmine": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/jasmine/-/jasmine-5.7.1.tgz", - "integrity": "sha512-E/4fkRNy/9ALz6z3Z3/tYXFAohoznVy7In9FWutG2fqBSkILJHFzbgZtHJUw5UrL3jgUQ4sdGYOVZ5KpSXYjGw==", + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/jasmine/-/jasmine-5.8.0.tgz", + "integrity": "sha512-1V6HGa0+TMoMY20+/vp++RqLlL1noupV8awzV6CiPuICC0g7iKZ9z87zV2KyelRyoig0G1lHn7ueElXVMGVagg==", "dev": true, "license": "MIT", "dependencies": { "glob": "^10.2.2", - "jasmine-core": "~5.7.0" + "jasmine-core": "~5.8.0" }, "bin": { "jasmine": "bin/jasmine.js" } }, "node_modules/jasmine-core": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-5.7.0.tgz", - "integrity": "sha512-EnUzZBHxS1Ofq+FPWs16rs2YC9o6Hb3buKJQDlkhJBDx+Bm5wNF+J1gUS06dWuW2ozaQ3oNIA1SESX9M5LopOQ==", + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-5.8.0.tgz", + "integrity": "sha512-Q9dqmpUAfptwyueW3+HqBOkSuYd9I/clZSSfN97wXE/Nr2ROFNCwIBEC1F6kb3QXS9Fcz0LjFYSDQT+BiwjuhA==", "dev": true, "license": "MIT" }, @@ -14605,6 +14670,19 @@ "node": ">= 0.8.0" } }, + "node_modules/libreoffice-convert": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/libreoffice-convert/-/libreoffice-convert-1.6.1.tgz", + "integrity": "sha512-j4YtAp8/5EZIGPH1zyzuPHYXBTUXDWvDyDxJY1w67Fw7F2qryvMlYnl6W0cUZN9yWs6aZCG0Ix2/RePOlvh1bA==", + "license": "MIT", + "dependencies": { + "async": "^3.2.3", + "tmp": "^0.2.1" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/limiter": { "version": "1.1.5", "resolved": "https://registry.npmjs.org/limiter/-/limiter-1.1.5.tgz", @@ -15050,9 +15128,9 @@ } }, "node_modules/mongodb-download-url": { - "version": "1.5.7", - "resolved": "https://registry.npmjs.org/mongodb-download-url/-/mongodb-download-url-1.5.7.tgz", - "integrity": "sha512-GpQJAfYmfYwqVXUyfIUQXe5kFoiCK5kORBJnPixAmQGmabZix6fBTpX7vSy3J46VgiAe+VEOjSikK/TcGKTw+A==", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mongodb-download-url/-/mongodb-download-url-1.6.0.tgz", + "integrity": "sha512-IQcQfKi3zdejKIAPaCpsW2F1FpMBsdifzY5K0YdddmJSFDJAGY7xUbCVm0pdL36+1ck6+c2ytTSqzProLhvGoA==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -15066,9 +15144,9 @@ } }, "node_modules/mongodb-download-url/node_modules/semver": { - "version": "7.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", - "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", "dev": true, "license": "ISC", "bin": { @@ -15079,14 +15157,14 @@ } }, "node_modules/mongodb-runner": { - "version": "5.8.3", - "resolved": "https://registry.npmjs.org/mongodb-runner/-/mongodb-runner-5.8.3.tgz", - "integrity": "sha512-LLmbE9A/aGqABaaTmxFJ+TiHjmhZx1kZRLV14nFLvBz2zV3F/rLBo9kJ/Pz00h0IYk3zi7abL82I+WKZVzkoSQ==", + "version": "5.9.0", + "resolved": "https://registry.npmjs.org/mongodb-runner/-/mongodb-runner-5.9.0.tgz", + "integrity": "sha512-31oyYEmLvkuqDV9J9kuwwOE2SHV1LaPyqr+fZsgYT56ceynqq4ABUOXmmdZBXm3zdLM1QGUft5UJokkkhXGPCQ==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@mongodb-js/mongodb-downloader": "^0.3.9", - "@mongodb-js/saslprep": "^1.2.2", + "@mongodb-js/mongodb-downloader": "^0.4.0", + "@mongodb-js/saslprep": "^1.3.0", "debug": "^4.4.0", "mongodb": "^6.9.0", "mongodb-connection-string-url": "^3.0.0", @@ -15164,6 +15242,26 @@ "integrity": "sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ==", "license": "MIT" }, + "node_modules/node-domexception": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", + "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", + "deprecated": "Use your platform's native DOMException instead", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "github", + "url": "https://paypal.me/jimmywarting" + } + ], + "license": "MIT", + "engines": { + "node": ">=10.5.0" + } + }, "node_modules/node-fetch": { "version": "2.7.0", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", @@ -16471,15 +16569,12 @@ } }, "node_modules/posthog-node": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/posthog-node/-/posthog-node-4.18.0.tgz", - "integrity": "sha512-XROs1h+DNatgKh/AlIlCtDxWzwrKdYDb2mOs58n4yN8BkGN9ewqeQwG5ApS4/IzwCb7HPttUkOVulkYatd2PIw==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/posthog-node/-/posthog-node-5.1.0.tgz", + "integrity": "sha512-U+b2GJEhK1O0BuIdsoYJu3M+3OUZIbQAhAmIYHTMTCaA7dFx30Pv1nXqA4gPjEPoXhXc6akJbMTRREY5ncJ/Gw==", "license": "MIT", - "dependencies": { - "axios": "^1.8.2" - }, "engines": { - "node": ">=15.0.0" + "node": ">=20" } }, "node_modules/precond": { @@ -16518,7 +16613,8 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/process-on-spawn": { "version": "1.0.0", @@ -16900,6 +16996,7 @@ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", "dev": true, + "license": "MIT", "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", @@ -16914,7 +17011,8 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/readdirp": { "version": "3.6.0", @@ -18033,10 +18131,33 @@ "dev": true, "license": "MIT" }, + "node_modules/tmp": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.3.tgz", + "integrity": "sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w==", + "license": "MIT", + "engines": { + "node": ">=14.14" + } + }, "node_modules/to-buffer": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.1.1.tgz", - "integrity": "sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.2.0.tgz", + "integrity": "sha512-uM2Zapt+GfaxYhCxKtUn7ktNOjAHL8nthQIQVhvNCjGLe8t+ULQ5i5hyFpMzuRxHkg2nrKNFTQpYDLhzxC3Jew==", + "dev": true, + "license": "MIT", + "dependencies": { + "isarray": "^2.0.5", + "safe-buffer": "^5.2.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/to-buffer/node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", "dev": true, "license": "MIT" }, @@ -18310,7 +18431,8 @@ "node_modules/url-template": { "version": "2.0.8", "resolved": "https://registry.npmjs.org/url-template/-/url-template-2.0.8.tgz", - "integrity": "sha512-XdVKMF4SJ0nP/O7XIPB0JwAEuT9lDIYnNsK8yGVe43y0AWoKeJNdv3ZNWh7ksJ6KqQFjOO6ox/VEitLnaVNufw==" + "integrity": "sha512-XdVKMF4SJ0nP/O7XIPB0JwAEuT9lDIYnNsK8yGVe43y0AWoKeJNdv3ZNWh7ksJ6KqQFjOO6ox/VEitLnaVNufw==", + "license": "BSD" }, "node_modules/url/node_modules/punycode": { "version": "1.3.2", @@ -18438,6 +18560,15 @@ "node": ">= 16" } }, + "node_modules/web-streams-polyfill": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz", + "integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==", + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, "node_modules/webidl-conversions": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", diff --git a/apps/OpenSignServer/package.json b/apps/OpenSignServer/package.json index 4085a29e62..12c0d809b8 100644 --- a/apps/OpenSignServer/package.json +++ b/apps/OpenSignServer/package.json @@ -18,23 +18,25 @@ "watch": "nodemon index.js" }, "dependencies": { - "@aws-sdk/client-s3": "^3.824.0", - "@aws-sdk/s3-request-presigner": "^3.824.0", + "@aws-sdk/client-s3": "^3.828.0", + "@aws-sdk/s3-request-presigner": "^3.828.0", "@parse/fs-files-adapter": "^3.0.0", - "@parse/s3-files-adapter": "^4.1.1", + "@parse/s3-files-adapter": "^4.2.0", "@pdf-lib/fontkit": "^1.1.1", "@signpdf/placeholder-pdf-lib": "^3.2.6", "@signpdf/signer-p12": "^3.2.4", "@signpdf/signpdf": "^3.2.5", "aws-sdk": "^2.1692.0", - "axios": "^1.9.0", + "axios": "^1.10.0", + "coherentpdf": "^2.5.5", "cors": "^2.8.5", "date-fns-tz": "^3.2.0", "dotenv": "^16.5.0", "express": "^5.1.0", - "form-data": "^4.0.2", + "form-data": "^4.0.3", "generate-api-key": "^1.0.2", - "googleapis": "^149.0.0", + "googleapis": "^150.0.1", + "libreoffice-convert": "^1.6.1", "mailgun.js": "^12.0.2", "mongodb": "^6.17.0", "multer": "^2.0.1", @@ -46,7 +48,7 @@ "parse-server": "^8.2.1", "parse-server-api-mail-adapter": "^4.1.0", "pdf-lib": "^1.17.1", - "posthog-node": "^4.18.0", + "posthog-node": "^5.1.0", "qrcode": "^1.5.4", "rate-limiter-flexible": "^7.1.1", "speakeasy": "^2.0.0", @@ -55,9 +57,9 @@ "type": "module", "devDependencies": { "@babel/eslint-parser": "^7.27.5", - "eslint": "^9.28.0", - "jasmine": "^5.7.1", - "mongodb-runner": "^5.8.3", + "eslint": "^9.29.0", + "jasmine": "^5.8.0", + "mongodb-runner": "^5.9.0", "nodemon": "^3.1.10", "nyc": "^17.1.0", "prettier": "^3.5.3"