mirror of
https://github.com/OpenSignLabs/OpenSign.git
synced 2026-09-05 01:07:39 +02:00
Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7e87aa4c38 |
@@ -361,6 +361,7 @@
|
|||||||
"date": "Datum",
|
"date": "Datum",
|
||||||
"text": "Text",
|
"text": "Text",
|
||||||
"text input": "Texteingabe",
|
"text input": "Texteingabe",
|
||||||
|
"cells": "Zellen",
|
||||||
"checkbox": "Checkbox",
|
"checkbox": "Checkbox",
|
||||||
"dropdown": "Dropdown",
|
"dropdown": "Dropdown",
|
||||||
"radio button": "Radiobutton",
|
"radio button": "Radiobutton",
|
||||||
@@ -415,10 +416,12 @@
|
|||||||
"options": "Optionen",
|
"options": "Optionen",
|
||||||
"minimun-check": "Minimale Anzahl",
|
"minimun-check": "Minimale Anzahl",
|
||||||
"maximum-check": "Maximale Anzahl",
|
"maximum-check": "Maximale Anzahl",
|
||||||
|
"cell-count": "Zellzahl",
|
||||||
"default-value": "Standardwert",
|
"default-value": "Standardwert",
|
||||||
"select": "Auswählen",
|
"select": "Auswählen",
|
||||||
"read-only": "Nur lesen",
|
"read-only": "Ist schreibgeschützt",
|
||||||
"hide-labels": "Labels ausblenden",
|
"hide-labels": "Labels ausblenden",
|
||||||
|
"layout": "Layout",
|
||||||
"checkbox": "Checkbox",
|
"checkbox": "Checkbox",
|
||||||
"alert": "Warnung",
|
"alert": "Warnung",
|
||||||
"zoom-in": "Vergrößern",
|
"zoom-in": "Vergrößern",
|
||||||
@@ -1025,5 +1028,6 @@
|
|||||||
"not-found-in-signature": "Nicht in Signatur gefunden",
|
"not-found-in-signature": "Nicht in Signatur gefunden",
|
||||||
"readonly-textinput-error": "Schreibgeschütztes Text-Widget muss einen Standardwert haben oder optional sein.",
|
"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-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-radiobtn-error": "Schreibgeschütztes Optionsfeld-Widget muss einen Standardwert haben oder optional sein.",
|
||||||
|
"choose-one":"Wählen Sie eine aus"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -361,6 +361,7 @@
|
|||||||
"date": "date",
|
"date": "date",
|
||||||
"text": "text",
|
"text": "text",
|
||||||
"text input": "text input",
|
"text input": "text input",
|
||||||
|
"cells": "cells",
|
||||||
"checkbox": "checkbox",
|
"checkbox": "checkbox",
|
||||||
"dropdown": "dropdown",
|
"dropdown": "dropdown",
|
||||||
"radio button": "radio button",
|
"radio button": "radio button",
|
||||||
@@ -415,10 +416,12 @@
|
|||||||
"options": "Options",
|
"options": "Options",
|
||||||
"minimun-check": "Minimun check",
|
"minimun-check": "Minimun check",
|
||||||
"maximum-check": "Maximum check",
|
"maximum-check": "Maximum check",
|
||||||
|
"cell-count": "Cell count",
|
||||||
"default-value": "Default value",
|
"default-value": "Default value",
|
||||||
"select": "Select",
|
"select": "Select",
|
||||||
"read-only": "Is read only",
|
"read-only": "read only",
|
||||||
"hide-labels": "Hide labels",
|
"hide-labels": "Hide labels",
|
||||||
|
"layout": "Layout",
|
||||||
"checkbox": "Checkbox",
|
"checkbox": "Checkbox",
|
||||||
"alert": "Alert",
|
"alert": "Alert",
|
||||||
"zoom-in": "Zoom in",
|
"zoom-in": "Zoom in",
|
||||||
@@ -1025,5 +1028,6 @@
|
|||||||
"not-found-in-signature": "Not found in signature",
|
"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-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-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-radiobtn-error": "Read-only radio button widget must have a default value or you can make it optional.",
|
||||||
|
"choose-one":"Choose One"
|
||||||
}
|
}
|
||||||
@@ -362,6 +362,7 @@
|
|||||||
"date": "fecha",
|
"date": "fecha",
|
||||||
"text": "texto",
|
"text": "texto",
|
||||||
"text input": "entrada de texto",
|
"text input": "entrada de texto",
|
||||||
|
"cells": "células",
|
||||||
"checkbox": "casilla",
|
"checkbox": "casilla",
|
||||||
"dropdown": "desplegable",
|
"dropdown": "desplegable",
|
||||||
"radio button": "botón de radio",
|
"radio button": "botón de radio",
|
||||||
@@ -416,10 +417,12 @@
|
|||||||
"options": "Opciones",
|
"options": "Opciones",
|
||||||
"minimun-check": "Chequeo mínimo",
|
"minimun-check": "Chequeo mínimo",
|
||||||
"maximum-check": "Chequeo máximo",
|
"maximum-check": "Chequeo máximo",
|
||||||
|
"cell-count": "recuento de células",
|
||||||
"default-value": "Valor por defecto",
|
"default-value": "Valor por defecto",
|
||||||
"select": "Seleccionar",
|
"select": "Seleccionar",
|
||||||
"read-only": "Es de solo lectura",
|
"read-only": "Es de solo lectura",
|
||||||
"hide-labels": "Esconder etiquetas",
|
"hide-labels": "Esconder etiquetas",
|
||||||
|
"layout": "Diseño",
|
||||||
"checkbox": "Casilla",
|
"checkbox": "Casilla",
|
||||||
"alert": "Alerta",
|
"alert": "Alerta",
|
||||||
"zoom-in": "Acercar",
|
"zoom-in": "Acercar",
|
||||||
@@ -1025,5 +1028,6 @@
|
|||||||
"not-found-in-signature": "No encontrado en la firma",
|
"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-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-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-radiobtn-error": "El widget de botón de opción de solo lectura debe tener un valor predeterminado o puede hacerse opcional.",
|
||||||
|
"choose-one":"Elige uno"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -361,6 +361,7 @@
|
|||||||
"date": "date",
|
"date": "date",
|
||||||
"text": "texte",
|
"text": "texte",
|
||||||
"text input": "saisie de texte",
|
"text input": "saisie de texte",
|
||||||
|
"cells": "cellules",
|
||||||
"checkbox": "case à cocher",
|
"checkbox": "case à cocher",
|
||||||
"dropdown": "dérouler",
|
"dropdown": "dérouler",
|
||||||
"radio button": "bouton radio",
|
"radio button": "bouton radio",
|
||||||
@@ -415,10 +416,12 @@
|
|||||||
"options": "Possibilités",
|
"options": "Possibilités",
|
||||||
"minimun-check": "Vérification minimale",
|
"minimun-check": "Vérification minimale",
|
||||||
"maximum-check": "Contrôle maximum",
|
"maximum-check": "Contrôle maximum",
|
||||||
|
"cell-count": "numération cellulaire",
|
||||||
"default-value": "Valeur par défaut",
|
"default-value": "Valeur par défaut",
|
||||||
"select": "Sélectionner",
|
"select": "Sélectionner",
|
||||||
"read-only": "Est en lecture seule",
|
"read-only": "Est en lecture seule",
|
||||||
"hide-labels": "Masquer les étiquettes",
|
"hide-labels": "Masquer les étiquettes",
|
||||||
|
"layout": "Disposition",
|
||||||
"checkbox": "Case à cocher",
|
"checkbox": "Case à cocher",
|
||||||
"alert": "Alerte",
|
"alert": "Alerte",
|
||||||
"zoom-in": "Agrandir",
|
"zoom-in": "Agrandir",
|
||||||
@@ -1025,5 +1028,6 @@
|
|||||||
"not-found-in-signature": "Introuvable dans la signature",
|
"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-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-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-radiobtn-error": "Le widget bouton radio en lecture seule doit avoir une valeur par défaut ou être rendu optionnel.",
|
||||||
|
"choose-one":"Choisissez-en un"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -361,6 +361,7 @@
|
|||||||
"date": "दिनांक",
|
"date": "दिनांक",
|
||||||
"text": "पाठ",
|
"text": "पाठ",
|
||||||
"text input": "पाठ इनपुट",
|
"text input": "पाठ इनपुट",
|
||||||
|
"cells": "सेल्स",
|
||||||
"checkbox": "चेकबॉक्स",
|
"checkbox": "चेकबॉक्स",
|
||||||
"dropdown": "ड्रॉपडाउन",
|
"dropdown": "ड्रॉपडाउन",
|
||||||
"radio button": "रेडियो बटन",
|
"radio button": "रेडियो बटन",
|
||||||
@@ -415,10 +416,12 @@
|
|||||||
"options": "विकल्प",
|
"options": "विकल्प",
|
||||||
"minimun-check": "न्यूनतम जाँच",
|
"minimun-check": "न्यूनतम जाँच",
|
||||||
"maximum-check": "अधिकतम जाँच",
|
"maximum-check": "अधिकतम जाँच",
|
||||||
|
"cell-count": "सेल्स संख्या",
|
||||||
"default-value": "डिफ़ॉल्ट मान",
|
"default-value": "डिफ़ॉल्ट मान",
|
||||||
"select": "चुनें",
|
"select": "चुनें",
|
||||||
"read-only": "केवल पढ़ने के लिए है",
|
"read-only": "सिर्फ पढ़ने के लिए है",
|
||||||
"hide-labels": "लेबल छिपाएँ",
|
"hide-labels": "लेबल छिपाएँ",
|
||||||
|
"layout": "लेआउट",
|
||||||
"checkbox": "चेकबॉक्स",
|
"checkbox": "चेकबॉक्स",
|
||||||
"alert": "चेतावनी",
|
"alert": "चेतावनी",
|
||||||
"zoom-in": "ज़ूम इन करें",
|
"zoom-in": "ज़ूम इन करें",
|
||||||
@@ -1025,5 +1028,6 @@
|
|||||||
"not-found-in-signature": "हस्ताक्षर में नहीं मिला",
|
"not-found-in-signature": "हस्ताक्षर में नहीं मिला",
|
||||||
"readonly-textinput-error": "रीड-ओनली टेक्स्ट विजेट में एक डिफ़ॉल्ट मान होना चाहिए या आप इसे वैकल्पिक बना सकते हैं।",
|
"readonly-textinput-error": "रीड-ओनली टेक्स्ट विजेट में एक डिफ़ॉल्ट मान होना चाहिए या आप इसे वैकल्पिक बना सकते हैं।",
|
||||||
"readonly-dropdown-error": "रीड-ओनली ड्रॉपडाउन विजेट में एक डिफ़ॉल्ट मान होना चाहिए या आप इसे वैकल्पिक बना सकते हैं।",
|
"readonly-dropdown-error": "रीड-ओनली ड्रॉपडाउन विजेट में एक डिफ़ॉल्ट मान होना चाहिए या आप इसे वैकल्पिक बना सकते हैं।",
|
||||||
"readonly-radiobtn-error": "रीड-ओनली रेडियो बटन विजेट में एक डिफ़ॉल्ट मान होना चाहिए या आप इसे वैकल्पिक बना सकते हैं।"
|
"readonly-radiobtn-error": "रीड-ओनली रेडियो बटन विजेट में एक डिफ़ॉल्ट मान होना चाहिए या आप इसे वैकल्पिक बना सकते हैं।",
|
||||||
|
"choose-one":"एक का चयन"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -361,6 +361,7 @@
|
|||||||
"date": "data",
|
"date": "data",
|
||||||
"text": "testo",
|
"text": "testo",
|
||||||
"text input": "campo di testo",
|
"text input": "campo di testo",
|
||||||
|
"cells": "cellule",
|
||||||
"checkbox": "casella di controllo",
|
"checkbox": "casella di controllo",
|
||||||
"dropdown": "menu a tendina",
|
"dropdown": "menu a tendina",
|
||||||
"radio button": "pulsante di opzione",
|
"radio button": "pulsante di opzione",
|
||||||
@@ -415,10 +416,12 @@
|
|||||||
"options": "Opzioni",
|
"options": "Opzioni",
|
||||||
"minimun-check": "Controllo minimo",
|
"minimun-check": "Controllo minimo",
|
||||||
"maximum-check": "Controllo massimo",
|
"maximum-check": "Controllo massimo",
|
||||||
|
"cell-count": "conteggio delle cellule",
|
||||||
"default-value": "Valore predefinita",
|
"default-value": "Valore predefinita",
|
||||||
"select": "Seleziona",
|
"select": "Seleziona",
|
||||||
"read-only": "È solo lettura",
|
"read-only": "È di sola lettura",
|
||||||
"hide-labels": "Nascondi etichette",
|
"hide-labels": "Nascondi etichette",
|
||||||
|
"layout": "Layout",
|
||||||
"checkbox": "Casella di controllo",
|
"checkbox": "Casella di controllo",
|
||||||
"alert": "Avviso",
|
"alert": "Avviso",
|
||||||
"zoom-in": "Ingrandisci",
|
"zoom-in": "Ingrandisci",
|
||||||
@@ -1025,5 +1028,6 @@
|
|||||||
"not-found-in-signature": "Non trovato nella firma",
|
"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-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-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-radiobtn-error": "Il widget pulsante di opzione di sola lettura deve avere un valore predefinito oppure può essere reso opzionale.",
|
||||||
|
"choose-one":"Scegline uno"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,123 @@
|
|||||||
|
import { useState, useEffect, useRef } from "react";
|
||||||
|
|
||||||
|
const Cell = ({
|
||||||
|
count,
|
||||||
|
h,
|
||||||
|
value,
|
||||||
|
editable,
|
||||||
|
onChange,
|
||||||
|
onKeyDown,
|
||||||
|
inputRef,
|
||||||
|
index
|
||||||
|
}) => (
|
||||||
|
<div
|
||||||
|
className="flex items-center justify-center border border-gray-800 bg-white"
|
||||||
|
style={{ flex: `0 0 ${100 / count}%`, height: h }}
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
maxLength={1}
|
||||||
|
value={value}
|
||||||
|
readOnly={!editable}
|
||||||
|
ref={inputRef}
|
||||||
|
onChange={editable ? (e) => onChange && onChange(e, index) : undefined}
|
||||||
|
onKeyDown={editable ? (e) => onKeyDown && onKeyDown(e, index) : undefined}
|
||||||
|
className="w-full text-center uppercase focus:outline-none bg-transparent text-[12px]"
|
||||||
|
style={{ fontFamily: "Arial, sans-serif" }}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
|
||||||
|
export default function CellsWidget({
|
||||||
|
count = 8,
|
||||||
|
height = 40,
|
||||||
|
value = "",
|
||||||
|
editable = false,
|
||||||
|
onChange,
|
||||||
|
onKeyDown,
|
||||||
|
onCellCountChange,
|
||||||
|
inputRefs,
|
||||||
|
resizable = false
|
||||||
|
}) {
|
||||||
|
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] || "");
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className="relative flex w-full h-full overflow-visible"
|
||||||
|
style={{ height }}
|
||||||
|
>
|
||||||
|
{resizable && (
|
||||||
|
<div
|
||||||
|
className="cell-size-handle absolute left-1/2 -translate-x-1/2 -top-3 cursor-ew-resize touch-none"
|
||||||
|
onPointerDown={onTopHandlePointerDown}
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
className="w-4 h-4 text-blue-600"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
viewBox="0 0 20 20"
|
||||||
|
fill="currentColor"
|
||||||
|
aria-hidden="true"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
fillRule="evenodd"
|
||||||
|
d="m9.69 18.933.003.001C9.89 19.02 10 19 10 19s.11.02.308-.066l.002-.001.006-.003.018-.008a5.741 5.741 0 0 0 .281-.14c.186-.096.446-.24.757-.433.62-.384 1.445-.966 2.274-1.765C15.302 14.988 17 12.493 17 9A7 7 0 1 0 3 9c0 3.492 1.698 5.988 3.355 7.584a13.731 13.731 0 0 0 2.273 1.765 11.842 11.842 0 0 0 .976.544l.062.029.018.008.006.003ZM10 11.25a2.25 2.25 0 1 0 0-4.5 2.25 2.25 0 0 0 0 4.5Z"
|
||||||
|
clipRule="evenodd"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{cells.map((val, i) => (
|
||||||
|
<Cell
|
||||||
|
key={i}
|
||||||
|
count={cellCount}
|
||||||
|
h={height}
|
||||||
|
value={val}
|
||||||
|
editable={editable}
|
||||||
|
onChange={onChange}
|
||||||
|
onKeyDown={onKeyDown}
|
||||||
|
inputRef={inputRefs ? (el) => (inputRefs.current[i] = el) : undefined}
|
||||||
|
index={i}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -7,8 +7,8 @@ import { fontColorArr, fontsizeArr } from "../../constant/Utils";
|
|||||||
function DropdownWidgetOption(props) {
|
function DropdownWidgetOption(props) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const [dropdownOptionList, setDropdownOptionList] = useState([
|
const [dropdownOptionList, setDropdownOptionList] = useState([
|
||||||
"option-1",
|
"Option-1",
|
||||||
"option-2"
|
"Option-2"
|
||||||
]);
|
]);
|
||||||
const [minCount, setMinCount] = useState(0);
|
const [minCount, setMinCount] = useState(0);
|
||||||
const [maxCount, setMaxCount] = useState(0);
|
const [maxCount, setMaxCount] = useState(0);
|
||||||
@@ -17,11 +17,13 @@ function DropdownWidgetOption(props) {
|
|||||||
const [isHideLabel, setIsHideLabel] = useState(false);
|
const [isHideLabel, setIsHideLabel] = useState(false);
|
||||||
const [status, setStatus] = useState("required");
|
const [status, setStatus] = useState("required");
|
||||||
const [defaultValue, setDefaultValue] = useState("");
|
const [defaultValue, setDefaultValue] = useState("");
|
||||||
const statusArr = ["required", "optional"];
|
|
||||||
const [defaultCheckbox, setDefaultCheckbox] = useState([]);
|
const [defaultCheckbox, setDefaultCheckbox] = useState([]);
|
||||||
|
const [layout, setLayout] = useState("vertical");
|
||||||
|
const statusArr = ["required", "optional"];
|
||||||
|
const layoutArr = ["vertical", "horizontal"];
|
||||||
|
|
||||||
const resetState = () => {
|
const resetState = () => {
|
||||||
setDropdownOptionList(["option-1", "option-2"]);
|
setDropdownOptionList(["Option-1", "Option-2"]);
|
||||||
setDropdownName(props.currWidgetsDetails?.options?.name || props.type);
|
setDropdownName(props.currWidgetsDetails?.options?.name || props.type);
|
||||||
setIsReadOnly(false);
|
setIsReadOnly(false);
|
||||||
setIsHideLabel(false);
|
setIsHideLabel(false);
|
||||||
@@ -29,6 +31,7 @@ function DropdownWidgetOption(props) {
|
|||||||
setMaxCount(0);
|
setMaxCount(0);
|
||||||
setDefaultCheckbox([]);
|
setDefaultCheckbox([]);
|
||||||
setDefaultValue("");
|
setDefaultValue("");
|
||||||
|
setLayout("vertical");
|
||||||
};
|
};
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (
|
if (
|
||||||
@@ -48,6 +51,7 @@ function DropdownWidgetOption(props) {
|
|||||||
setStatus(props.currWidgetsDetails?.options?.status || "required");
|
setStatus(props.currWidgetsDetails?.options?.status || "required");
|
||||||
setDefaultValue(props.currWidgetsDetails?.options?.defaultValue || "");
|
setDefaultValue(props.currWidgetsDetails?.options?.defaultValue || "");
|
||||||
setDefaultCheckbox(props.currWidgetsDetails?.options?.defaultValue || []);
|
setDefaultCheckbox(props.currWidgetsDetails?.options?.defaultValue || []);
|
||||||
|
setLayout(props.currWidgetsDetails?.options?.layout || "vertical");
|
||||||
} else {
|
} else {
|
||||||
setStatus("required");
|
setStatus("required");
|
||||||
resetState();
|
resetState();
|
||||||
@@ -107,6 +111,9 @@ function DropdownWidgetOption(props) {
|
|||||||
props?.type === "dropdown" || props?.type === radioButtonWidget;
|
props?.type === "dropdown" || props?.type === radioButtonWidget;
|
||||||
const readOnlyWithoutValue =
|
const readOnlyWithoutValue =
|
||||||
isReadOnly && !defaultValue && status !== "optional";
|
isReadOnly && !defaultValue && status !== "optional";
|
||||||
|
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 it’s a dropdown and it’s read-only without a value (nor marked optional), stop here.
|
||||||
if (isDropdownOrRadio && readOnlyWithoutValue) {
|
if (isDropdownOrRadio && readOnlyWithoutValue) {
|
||||||
@@ -129,7 +136,8 @@ function DropdownWidgetOption(props) {
|
|||||||
null,
|
null,
|
||||||
status,
|
status,
|
||||||
defaultData,
|
defaultData,
|
||||||
isHideLabel
|
isHideLabel,
|
||||||
|
WidgetLayout
|
||||||
);
|
);
|
||||||
resetState();
|
resetState();
|
||||||
};
|
};
|
||||||
@@ -153,17 +161,18 @@ function DropdownWidgetOption(props) {
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div>
|
<div>
|
||||||
<label className="text-[13px] font-semibold">
|
<label htmlFor="title" className="text-[13px] font-semibold">
|
||||||
{t("name")}
|
{t("name")}
|
||||||
<span className="text-[red] text-[13px]"> *</span>
|
<span className="text-[red] text-[13px]"> *</span>
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
|
id="title"
|
||||||
onInvalid={(e) => e.target.setCustomValidity(t("input-required"))}
|
onInvalid={(e) => e.target.setCustomValidity(t("input-required"))}
|
||||||
onInput={(e) => e.target.setCustomValidity("")}
|
onInput={(e) => e.target.setCustomValidity("")}
|
||||||
required
|
|
||||||
value={dropdownName}
|
value={dropdownName}
|
||||||
onChange={(e) => setDropdownName(e.target.value)}
|
onChange={(e) => setDropdownName(e.target.value)}
|
||||||
className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs"
|
className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs"
|
||||||
|
required
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<label className="text-[13px] font-semibold mt-[5px]">
|
<label className="text-[13px] font-semibold mt-[5px]">
|
||||||
@@ -245,27 +254,23 @@ function DropdownWidgetOption(props) {
|
|||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
{props.type !== "checkbox" && (
|
{props.type !== "checkbox" && (
|
||||||
<>
|
<div className="flex flex-row gap-[10px] mt-[0.5rem]">
|
||||||
<div className="flex flex-row gap-[10px] mt-[0.5rem]">
|
{statusArr.map((data, ind) => (
|
||||||
{statusArr.map((data, ind) => {
|
<div
|
||||||
return (
|
key={ind}
|
||||||
<div
|
className="flex flex-row gap-[5px] items-center"
|
||||||
key={ind}
|
>
|
||||||
className="flex flex-row gap-[5px] items-center"
|
<input
|
||||||
>
|
className="op-radio op-radio-xs my-1"
|
||||||
<input
|
type="radio"
|
||||||
className="op-radio op-radio-xs my-1"
|
name="status"
|
||||||
type="radio"
|
onChange={() => setStatus(data.toLowerCase())}
|
||||||
name="status"
|
checked={status.toLowerCase() === data.toLowerCase()}
|
||||||
onChange={() => setStatus(data.toLowerCase())}
|
/>
|
||||||
checked={status.toLowerCase() === data.toLowerCase()}
|
<div className="text-[13px] font-500 capitalize">{data}</div>
|
||||||
/>
|
</div>
|
||||||
<div className="text-[13px] font-500">{data}</div>
|
))}
|
||||||
</div>
|
</div>
|
||||||
);
|
|
||||||
})}
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
)}
|
)}
|
||||||
<div className="flex items-center mt-3 mb-3">
|
<div className="flex items-center mt-3 mb-3">
|
||||||
<span>{t("font-size")} :</span>
|
<span>{t("font-size")} :</span>
|
||||||
@@ -286,8 +291,8 @@ function DropdownWidgetOption(props) {
|
|||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
</select>
|
</select>
|
||||||
<div className="flex flex-row gap-1 items-center ml-4 ">
|
<div className="flex flex-row gap-1 items-center ml-4">
|
||||||
<span>{t("color")} : </span>
|
<span className="capitalize">{t("color")} : </span>
|
||||||
<select
|
<select
|
||||||
value={
|
value={
|
||||||
props.fontColor ||
|
props.fontColor ||
|
||||||
@@ -329,7 +334,7 @@ function DropdownWidgetOption(props) {
|
|||||||
className="op-checkbox op-checkbox-sm"
|
className="op-checkbox op-checkbox-sm"
|
||||||
onChange={(e) => setIsReadOnly(e.target.checked)}
|
onChange={(e) => setIsReadOnly(e.target.checked)}
|
||||||
/>
|
/>
|
||||||
<label className="ml-1 mb-0" htmlFor="isreadonly">
|
<label className="ml-2 mb-0 capitalize" htmlFor="isreadonly">
|
||||||
{t("read-only")}
|
{t("read-only")}
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
@@ -344,15 +349,42 @@ function DropdownWidgetOption(props) {
|
|||||||
onChange={(e) => setIsHideLabel(e.target.checked)}
|
onChange={(e) => setIsHideLabel(e.target.checked)}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<label className="ml-1 mb-0" htmlFor="ishidelabel">
|
<label className="ml-2 mb-0 capitalize" htmlFor="ishidelabel">
|
||||||
{t("hide-labels")}
|
{t("hide-labels")}
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
{["checkbox", radioButtonWidget].includes(props.type) && (
|
||||||
|
<>
|
||||||
|
<div className="text-[13px] font-semibold mt-[5px] capitalize">
|
||||||
|
{t("layout")}
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
className={`${props.type === "checkbox" ? "mb-[10px]" : ""} flex flex-row gap-[10px] mt-[0.5rem]`}
|
||||||
|
>
|
||||||
|
{layoutArr.map((data, ind) => (
|
||||||
|
<div
|
||||||
|
key={ind}
|
||||||
|
className="flex flex-row gap-[5px] items-center"
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
className="op-radio op-radio-xs my-1"
|
||||||
|
type="radio"
|
||||||
|
name="layout"
|
||||||
|
checked={layout.toLowerCase() === data.toLowerCase()}
|
||||||
|
onChange={() => setLayout(data.toLowerCase())}
|
||||||
|
/>
|
||||||
|
<label className="text-[13px] font-500 mb-0 capitalize">
|
||||||
|
{data}
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
className={`${
|
className={`${
|
||||||
props.type === "checkbox" && props.isShowAdvanceFeature
|
props.type === "checkbox" && props.isShowAdvanceFeature
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import {
|
|||||||
onChangeInput,
|
onChangeInput,
|
||||||
radioButtonWidget,
|
radioButtonWidget,
|
||||||
textInputWidget,
|
textInputWidget,
|
||||||
|
cellsWidget,
|
||||||
textWidget
|
textWidget
|
||||||
} from "../../constant/Utils";
|
} from "../../constant/Utils";
|
||||||
import PlaceholderType from "./PlaceholderType";
|
import PlaceholderType from "./PlaceholderType";
|
||||||
@@ -85,6 +86,9 @@ function Placeholder(props) {
|
|||||||
const [selectDate, setSelectDate] = useState({});
|
const [selectDate, setSelectDate] = useState({});
|
||||||
const [dateFormat, setDateFormat] = useState([]);
|
const [dateFormat, setDateFormat] = useState([]);
|
||||||
const [clickonWidget, setClickonWidget] = useState({});
|
const [clickonWidget, setClickonWidget] = useState({});
|
||||||
|
const [isDateReadOnly, setIsDateReadOnly] = useState(
|
||||||
|
props?.pos?.options?.isReadOnly || false
|
||||||
|
);
|
||||||
const startDate = props?.pos?.options?.response
|
const startDate = props?.pos?.options?.response
|
||||||
? getDefaultDate(
|
? getDefaultDate(
|
||||||
props?.pos?.options?.response,
|
props?.pos?.options?.response,
|
||||||
@@ -406,10 +410,47 @@ function Placeholder(props) {
|
|||||||
false,
|
false,
|
||||||
data?.format,
|
data?.format,
|
||||||
props.fontSize || props.pos?.options?.fontSize || 12,
|
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 });
|
setSelectDate({ date: date, format: data?.format });
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const setCellCount = (key, newCount) => {
|
||||||
|
const isSignerList = props.xyPosition.some((d) => d.signerPtr);
|
||||||
|
if (isSignerList) {
|
||||||
|
const signerId = props.data?.Id || props.uniqueId;
|
||||||
|
const filterSignerPos = props.xyPosition.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 };
|
||||||
|
});
|
||||||
|
const newSignerPos = props.xyPosition.map((obj) =>
|
||||||
|
obj.Id === signerId
|
||||||
|
? { ...obj, placeHolder: updatedPlaceHolder }
|
||||||
|
: obj
|
||||||
|
);
|
||||||
|
props.setXyPosition(newSignerPos);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const updatePos = props.xyPosition[props.index].pos.map((p) =>
|
||||||
|
p.key === key
|
||||||
|
? { ...p, options: { ...p.options, cellCount: newCount } }
|
||||||
|
: p
|
||||||
|
);
|
||||||
|
const updatePlaceholder = props.xyPosition.map((obj, ind) =>
|
||||||
|
ind === props.index ? { ...obj, pos: updatePos } : obj
|
||||||
|
);
|
||||||
|
props.setXyPosition(updatePlaceholder);
|
||||||
|
}
|
||||||
|
};
|
||||||
const PlaceholderIcon = () => {
|
const PlaceholderIcon = () => {
|
||||||
// 1- If props.isShowBorder is true, display border's icon for all widgets. OR
|
// 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:
|
// 2- Use the combination of props?.isAlllowModify and !props?.assignedWidgetId.includes(props.pos.key) to determine when to show border's icon:
|
||||||
@@ -751,16 +792,9 @@ function Placeholder(props) {
|
|||||||
id={props.pos.key}
|
id={props.pos.key}
|
||||||
data-tut={props.pos.key === props.unSignedWidgetId ? "IsSigned" : ""}
|
data-tut={props.pos.key === props.unSignedWidgetId ? "IsSigned" : ""}
|
||||||
key={props.pos.key}
|
key={props.pos.key}
|
||||||
|
cancel=".cell-size-handle"
|
||||||
lockAspectRatio={
|
lockAspectRatio={
|
||||||
!props.isFreeResize &&
|
!props.isFreeResize &&
|
||||||
![
|
|
||||||
textWidget,
|
|
||||||
"email",
|
|
||||||
"name",
|
|
||||||
"company",
|
|
||||||
"job title",
|
|
||||||
textInputWidget
|
|
||||||
].includes(props.pos.type) &&
|
|
||||||
(props.pos.Width
|
(props.pos.Width
|
||||||
? props.pos.Width / props.pos.Height
|
? props.pos.Width / props.pos.Height
|
||||||
: defaultWidthHeight(props.pos.type).width /
|
: defaultWidthHeight(props.pos.type).width /
|
||||||
@@ -820,8 +854,10 @@ function Placeholder(props) {
|
|||||||
: props.posHeight(props.pos, props.isSignYourself)
|
: props.posHeight(props.pos, props.isSignYourself)
|
||||||
}}
|
}}
|
||||||
minHeight={
|
minHeight={
|
||||||
props.pos.type !== "checkbox" &&
|
props.pos.type === cellsWidget
|
||||||
calculateFont(props.pos.options?.fontSize, true)
|
? calculateFont(props.pos.options?.fontSize, true)
|
||||||
|
: props.pos.type !== "checkbox" &&
|
||||||
|
calculateFont(props.pos.options?.fontSize, true)
|
||||||
}
|
}
|
||||||
maxHeight="auto"
|
maxHeight="auto"
|
||||||
onResizeStart={() => {
|
onResizeStart={() => {
|
||||||
@@ -938,6 +974,7 @@ function Placeholder(props) {
|
|||||||
handleSaveDate={handleSaveDate}
|
handleSaveDate={handleSaveDate}
|
||||||
xPos={props.xPos}
|
xPos={props.xPos}
|
||||||
calculateFont={calculateFont}
|
calculateFont={calculateFont}
|
||||||
|
setCellCount={setCellCount}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</Rnd>
|
</Rnd>
|
||||||
@@ -945,11 +982,11 @@ function Placeholder(props) {
|
|||||||
|
|
||||||
<ModalUi isOpen={isDateModal} title={t("widget-info")} showClose={false}>
|
<ModalUi isOpen={isDateModal} title={t("widget-info")} showClose={false}>
|
||||||
<div className="h-[100%] p-[20px]">
|
<div className="h-[100%] p-[20px]">
|
||||||
<div className="flex flex-row items-center">
|
<div className="flex flex-col md:flex-row md:items-center gap-y-3">
|
||||||
<span>{t("format")} : </span>
|
<div className="flex flex-row items-center gap-x-1">
|
||||||
<div className="flex">
|
<span className="capitalize">{t("format")} :</span>
|
||||||
<select
|
<select
|
||||||
className="ml-[7px] op-select op-select-bordered op-select-sm focus:outline-none hover:border-base-content text-xs"
|
className="op-select op-select-bordered op-select-sm focus:outline-none hover:border-base-content text-xs"
|
||||||
defaultValue={""}
|
defaultValue={""}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
const selectedIndex = e.target.value;
|
const selectedIndex = e.target.value;
|
||||||
@@ -973,23 +1010,23 @@ function Placeholder(props) {
|
|||||||
{selectDate.format}
|
{selectDate.format}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-center mt-4 md:mt-2">
|
<div className="flex flex-col md:flex-row gap-y-2 md:gap-y-0 gap-x-2 mt-3">
|
||||||
<span>{t("font-size")} :</span>
|
<div className="flex flex-row items-center">
|
||||||
<select
|
<span className="capitalize">{t("font-size")} :</span>
|
||||||
className="ml-[3px] md:ml:[7px] op-select op-select-bordered op-select-sm focus:outline-none hover:border-base-content text-xs"
|
<select
|
||||||
value={props.fontSize || clickonWidget.options?.fontSize || 12}
|
className="ml-[3px] md:ml:[7px] op-select op-select-bordered op-select-sm focus:outline-none hover:border-base-content text-xs"
|
||||||
onChange={(e) => props.setFontSize(parseInt(e.target.value))}
|
value={props.fontSize || clickonWidget.options?.fontSize || 12}
|
||||||
>
|
onChange={(e) => props.setFontSize(parseInt(e.target.value))}
|
||||||
{fontsizeArr.map((size, ind) => {
|
>
|
||||||
return (
|
{fontsizeArr.map((size, ind) => (
|
||||||
<option className="text-[13px]" value={size} key={ind}>
|
<option className="text-[13px]" value={size} key={ind}>
|
||||||
{size}
|
{size}
|
||||||
</option>
|
</option>
|
||||||
);
|
))}
|
||||||
})}
|
</select>
|
||||||
</select>
|
</div>
|
||||||
<div className="flex flex-row gap-1 items-center ml-2 md:ml-4 ">
|
<div className="flex flex-row gap-1 items-center">
|
||||||
<span>{t("color")}: </span>
|
<span className="capitalize">{t("color")} :</span>
|
||||||
<select
|
<select
|
||||||
value={
|
value={
|
||||||
props.fontColor || clickonWidget.options?.fontColor || "black"
|
props.fontColor || clickonWidget.options?.fontColor || "black"
|
||||||
@@ -997,13 +1034,11 @@ function Placeholder(props) {
|
|||||||
onChange={(e) => props.setFontColor(e.target.value)}
|
onChange={(e) => props.setFontColor(e.target.value)}
|
||||||
className="ml-[4px] md:ml[7px] op-select op-select-bordered op-select-sm focus:outline-none hover:border-base-content text-xs"
|
className="ml-[4px] md:ml[7px] op-select op-select-bordered op-select-sm focus:outline-none hover:border-base-content text-xs"
|
||||||
>
|
>
|
||||||
{fontColorArr.map((color, ind) => {
|
{fontColorArr.map((color, ind) => (
|
||||||
return (
|
<option value={color} key={ind}>
|
||||||
<option value={color} key={ind}>
|
{t(`color-type.${color}`)}
|
||||||
{t(`color-type.${color}`)}
|
</option>
|
||||||
</option>
|
))}
|
||||||
);
|
|
||||||
})}
|
|
||||||
</select>
|
</select>
|
||||||
<span
|
<span
|
||||||
style={{
|
style={{
|
||||||
@@ -1014,7 +1049,26 @@ function Placeholder(props) {
|
|||||||
></span>
|
></span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
{props?.isPlaceholder && (
|
||||||
|
<div className="flex items-center mt-3">
|
||||||
|
<input
|
||||||
|
id="isReadOnly"
|
||||||
|
name="isReadOnly"
|
||||||
|
type="checkbox"
|
||||||
|
checked={
|
||||||
|
isDateReadOnly || props.pos.options?.isReadOnly || false
|
||||||
|
}
|
||||||
|
className="op-checkbox op-checkbox-xs"
|
||||||
|
onChange={() => setIsDateReadOnly(!isDateReadOnly)}
|
||||||
|
/>
|
||||||
|
<label
|
||||||
|
className="ml-1.5 mb-0 capitalize text-[13px]"
|
||||||
|
htmlFor="isreadonly"
|
||||||
|
>
|
||||||
|
{t("read-only")}
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
<div className="h-[1px] w-full my-[15px] bg-[#9f9f9f]"></div>
|
<div className="h-[1px] w-full my-[15px] bg-[#9f9f9f]"></div>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import {
|
|||||||
getYear,
|
getYear,
|
||||||
radioButtonWidget,
|
radioButtonWidget,
|
||||||
textInputWidget,
|
textInputWidget,
|
||||||
|
cellsWidget,
|
||||||
textWidget,
|
textWidget,
|
||||||
months,
|
months,
|
||||||
years,
|
years,
|
||||||
@@ -14,8 +15,9 @@ import DatePicker from "react-datepicker";
|
|||||||
import "react-datepicker/dist/react-datepicker.css";
|
import "react-datepicker/dist/react-datepicker.css";
|
||||||
import "../../styles/signature.css";
|
import "../../styles/signature.css";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
|
import CellsWidget from "./CellsWidget";
|
||||||
const textWidgetCls =
|
const textWidgetCls =
|
||||||
"w-full h-full md:min-w-full md:min-h-full z-[999] text-[12px] rounded-[2px] border-[1px] border-[#007bff] overflow-hidden resize-none outline-none text-base-content item-center whitespace-pre-wrap bg-white";
|
"w-full h-full md:min-w-full md:min-h-full z-[999] text-[12px] rounded-[2px] border-[1px] border-[#007bff] overflow-hidden resize-none outline-none text-base-content item-center whitespace-pre-wrap";
|
||||||
const selectWidgetCls =
|
const selectWidgetCls =
|
||||||
"w-full h-full absolute left-0 top-0 border-[1px] border-[#007bff] rounded-[2px] focus:outline-none text-base-content";
|
"w-full h-full absolute left-0 top-0 border-[1px] border-[#007bff] rounded-[2px] focus:outline-none text-base-content";
|
||||||
const widgetCls =
|
const widgetCls =
|
||||||
@@ -27,8 +29,12 @@ function PlaceholderType(props) {
|
|||||||
props.isSignYourself ||
|
props.isSignYourself ||
|
||||||
((props.isSelfSign || props.isNeedSign) &&
|
((props.isSelfSign || props.isNeedSign) &&
|
||||||
props.data?.signerObjId === props.signerObjId);
|
props.data?.signerObjId === props.signerObjId);
|
||||||
|
const isReadOnly =
|
||||||
|
props.pos.options?.isReadOnly ||
|
||||||
|
props.data?.signerObjId !== props.signerObjId;
|
||||||
|
// prefer the latest response value over any default value
|
||||||
const widgetData =
|
const widgetData =
|
||||||
props.pos?.options?.defaultValue || props.pos?.options?.response;
|
props.pos?.options?.response ?? props.pos?.options?.defaultValue ?? "";
|
||||||
const widgetTypeTranslation = t(`widgets-name.${props?.pos?.type}`);
|
const widgetTypeTranslation = t(`widgets-name.${props?.pos?.type}`);
|
||||||
const inputRef = useRef(null);
|
const inputRef = useRef(null);
|
||||||
const [widgetValue, setwidgetValue] = useState();
|
const [widgetValue, setwidgetValue] = useState();
|
||||||
@@ -56,16 +62,13 @@ function PlaceholderType(props) {
|
|||||||
[]
|
[]
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
if (widgetData) {
|
// keep displayed value in sync with the stored response
|
||||||
setwidgetValue(widgetData);
|
setwidgetValue(widgetData);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (props.pos?.options?.hint) {
|
if (props.pos?.options?.hint) {
|
||||||
setHint(props.pos?.options.hint);
|
setHint(props.pos?.options.hint);
|
||||||
} else if (props.pos?.options?.validation?.type) {
|
} else if (props.pos?.options?.validation?.type) {
|
||||||
checkRegularExpress(props.pos?.options?.validation?.type, setHint);
|
checkRegularExpress(props.pos?.options?.validation?.type, setHint);
|
||||||
} else {
|
|
||||||
setHint(props.pos?.type);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
@@ -77,7 +80,8 @@ function PlaceholderType(props) {
|
|||||||
color: fontColor,
|
color: fontColor,
|
||||||
fontFamily: "Arial, sans-serif"
|
fontFamily: "Arial, sans-serif"
|
||||||
}}
|
}}
|
||||||
className={`${selectWidgetCls} overflow-hidden`}
|
className={`${isReadOnly ? `select-none` : ``} ${selectWidgetCls} overflow-hidden`}
|
||||||
|
disabled={isReadOnly}
|
||||||
onClick={onClick}
|
onClick={onClick}
|
||||||
ref={ref}
|
ref={ref}
|
||||||
>
|
>
|
||||||
@@ -148,41 +152,42 @@ function PlaceholderType(props) {
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
case "checkbox":
|
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 (
|
return (
|
||||||
<div style={{ zIndex: props.isSignYourself && "99" }}>
|
<div
|
||||||
{props.pos.options?.values?.map((data, ind) => {
|
className={checkBoxWrapperClass}
|
||||||
return (
|
style={{ zIndex: props.isSignYourself && "99" }}
|
||||||
<div key={ind} className="select-none-cls pointer-events-none">
|
>
|
||||||
<label
|
{props.pos.options?.values?.map((data, ind) => (
|
||||||
htmlFor={`checkbox-${props.pos.key + ind}`}
|
<div key={ind} className="select-none-cls pointer-events-none">
|
||||||
style={{ fontSize: fontSize, color: fontColor }}
|
<label
|
||||||
className={`mb-0 flex items-center gap-1 ${
|
htmlFor={`checkbox-${props.pos.key + ind}`}
|
||||||
ind > 0 ? "mt-[3px]" : "mt-[0px]"
|
style={{ fontSize: fontSize, color: fontColor }}
|
||||||
}`}
|
className={`mb-0 flex items-center gap-1`}
|
||||||
>
|
>
|
||||||
<input
|
<input
|
||||||
id={`checkbox-${props.pos.key + ind}`}
|
id={`checkbox-${props.pos.key + ind}`}
|
||||||
style={{
|
style={{ width: fontSize, height: fontSize }}
|
||||||
width: fontSize,
|
className="op-checkbox rounded-[1px]"
|
||||||
height: fontSize
|
disabled={props.isNeedSign && isReadOnly}
|
||||||
}}
|
type="checkbox"
|
||||||
className="op-checkbox rounded-[1px]"
|
readOnly
|
||||||
disabled={
|
checked={!!selectCheckbox(ind, selectedCheckbox)}
|
||||||
props.isNeedSign &&
|
/>
|
||||||
(props.pos.options?.isReadOnly ||
|
{!props.pos.options?.isHideLabel && (
|
||||||
props.data?.signerObjId !== props.signerObjId)
|
<span className="leading-none">{data}</span>
|
||||||
}
|
)}
|
||||||
type="checkbox"
|
</label>
|
||||||
readOnly
|
</div>
|
||||||
checked={!!selectCheckbox(ind, selectedCheckbox)}
|
))}
|
||||||
/>
|
|
||||||
{!props.pos.options?.isHideLabel && (
|
|
||||||
<span className="leading-none">{data}</span>
|
|
||||||
)}
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
case textInputWidget:
|
case textInputWidget:
|
||||||
@@ -192,24 +197,15 @@ function PlaceholderType(props) {
|
|||||||
placeholder={hint || t("widgets-name.text")}
|
placeholder={hint || t("widgets-name.text")}
|
||||||
rows={1}
|
rows={1}
|
||||||
value={widgetValue}
|
value={widgetValue}
|
||||||
className={`${
|
className={`${textWidgetCls} ${isReadOnly ? "select-none" : ""}`}
|
||||||
props.pos.options?.isReadOnly ||
|
|
||||||
props.data?.signerObjId !== props.signerObjId
|
|
||||||
? "select-none"
|
|
||||||
: textWidgetCls
|
|
||||||
}`}
|
|
||||||
style={{
|
style={{
|
||||||
fontSize: fontSize,
|
fontSize: fontSize,
|
||||||
color: fontColor,
|
color: fontColor,
|
||||||
background: props.data?.blockColor,
|
background: isReadOnly ? props.data?.blockColor : "white",
|
||||||
pointerEvents: "none"
|
pointerEvents: "none"
|
||||||
}}
|
}}
|
||||||
readOnly
|
readOnly
|
||||||
disabled={
|
disabled={props.isNeedSign && isReadOnly}
|
||||||
props.isNeedSign &&
|
|
||||||
(props.pos.options?.isReadOnly ||
|
|
||||||
props.data?.signerObjId !== props.signerObjId)
|
|
||||||
}
|
|
||||||
cols="50"
|
cols="50"
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
@@ -217,13 +213,31 @@ function PlaceholderType(props) {
|
|||||||
<span>{hint || widgetTypeTranslation}</span>
|
<span>{hint || widgetTypeTranslation}</span>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
case cellsWidget: {
|
||||||
|
const count = props.pos.options?.cellCount || 5;
|
||||||
|
const cells = (widgetValue || "").split("");
|
||||||
|
const height = "100%";
|
||||||
|
const handleCellResize = (newCount) => {
|
||||||
|
if (props.setCellCount) props.setCellCount(props.pos.key, newCount);
|
||||||
|
};
|
||||||
|
return (
|
||||||
|
<CellsWidget
|
||||||
|
count={count}
|
||||||
|
height={height}
|
||||||
|
value={cells.join("")}
|
||||||
|
editable={props.isPlaceholder}
|
||||||
|
resizable={props.isPlaceholder}
|
||||||
|
onCellCountChange={handleCellResize}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
case "dropdown":
|
case "dropdown":
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
style={textWidgetStyle}
|
style={textWidgetStyle}
|
||||||
className="select-none-cls flex justify-between items-center"
|
className="select-none-cls flex justify-between items-center"
|
||||||
>
|
>
|
||||||
{widgetData || hint || widgetTypeTranslation}
|
{widgetData || t("choose-one")}
|
||||||
<i className="fa-light fa-circle-chevron-down mr-1 "></i>
|
<i className="fa-light fa-circle-chevron-down mr-1 "></i>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
@@ -259,13 +273,15 @@ function PlaceholderType(props) {
|
|||||||
placeholder={hint || widgetTypeTranslation}
|
placeholder={hint || widgetTypeTranslation}
|
||||||
rows={1}
|
rows={1}
|
||||||
value={widgetValue}
|
value={widgetValue}
|
||||||
className={textWidgetCls}
|
className={`${textWidgetCls} ${isReadOnly ? "select-none" : ""}`}
|
||||||
style={{
|
style={{
|
||||||
fontSize: fontSize,
|
fontSize: fontSize,
|
||||||
color: fontColor,
|
color: fontColor,
|
||||||
|
background: isReadOnly ? props.data?.blockColor : "white",
|
||||||
pointerEvents: "none"
|
pointerEvents: "none"
|
||||||
}}
|
}}
|
||||||
cols="50"
|
cols="50"
|
||||||
|
disabled={props.isNeedSign && isReadOnly}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<div className="flex h-full select-none-cls" style={textWidgetStyle}>
|
<div className="flex h-full select-none-cls" style={textWidgetStyle}>
|
||||||
@@ -280,13 +296,15 @@ function PlaceholderType(props) {
|
|||||||
placeholder={hint || widgetTypeTranslation}
|
placeholder={hint || widgetTypeTranslation}
|
||||||
rows={1}
|
rows={1}
|
||||||
value={widgetValue}
|
value={widgetValue}
|
||||||
className={textWidgetCls}
|
className={`${textWidgetCls} ${isReadOnly ? "select-none" : ""}`}
|
||||||
style={{
|
style={{
|
||||||
fontSize: fontSize,
|
fontSize: fontSize,
|
||||||
color: fontColor,
|
color: fontColor,
|
||||||
|
background: isReadOnly ? props.data?.blockColor : "white",
|
||||||
pointerEvents: "none"
|
pointerEvents: "none"
|
||||||
}}
|
}}
|
||||||
cols="50"
|
cols="50"
|
||||||
|
disabled={props.isNeedSign && isReadOnly}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<div style={textWidgetStyle} className="select-none-cls">
|
<div style={textWidgetStyle} className="select-none-cls">
|
||||||
@@ -301,13 +319,15 @@ function PlaceholderType(props) {
|
|||||||
placeholder={hint || widgetTypeTranslation}
|
placeholder={hint || widgetTypeTranslation}
|
||||||
rows={1}
|
rows={1}
|
||||||
value={widgetValue}
|
value={widgetValue}
|
||||||
className={textWidgetCls}
|
className={`${textWidgetCls} ${isReadOnly ? "select-none" : ""}`}
|
||||||
style={{
|
style={{
|
||||||
fontSize: fontSize,
|
fontSize: fontSize,
|
||||||
color: fontColor,
|
color: fontColor,
|
||||||
|
background: isReadOnly ? props.data?.blockColor : "white",
|
||||||
pointerEvents: "none"
|
pointerEvents: "none"
|
||||||
}}
|
}}
|
||||||
cols="50"
|
cols="50"
|
||||||
|
disabled={props.isNeedSign && isReadOnly}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<div style={textWidgetStyle} className="select-none-cls">
|
<div style={textWidgetStyle} className="select-none-cls">
|
||||||
@@ -405,15 +425,15 @@ function PlaceholderType(props) {
|
|||||||
placeholder={hint || widgetTypeTranslation}
|
placeholder={hint || widgetTypeTranslation}
|
||||||
rows={1}
|
rows={1}
|
||||||
value={widgetValue}
|
value={widgetValue}
|
||||||
className={textWidgetCls}
|
className={`${textWidgetCls} ${isReadOnly ? "select-none" : ""}`}
|
||||||
style={{
|
style={{
|
||||||
fontSize: fontSize,
|
fontSize: fontSize,
|
||||||
color: fontColor,
|
color: fontColor,
|
||||||
fontFamily: "Arial, sans-serif",
|
background: isReadOnly ? props.data?.blockColor : "white",
|
||||||
pointerEvents: "none"
|
pointerEvents: "none"
|
||||||
}}
|
}}
|
||||||
disabled
|
|
||||||
cols="1"
|
cols="1"
|
||||||
|
disabled={props.isNeedSign && isReadOnly}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<div style={textWidgetStyle} className="select-none-cls">
|
<div style={textWidgetStyle} className="select-none-cls">
|
||||||
@@ -421,46 +441,39 @@ function PlaceholderType(props) {
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
case radioButtonWidget:
|
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 (
|
return (
|
||||||
<div>
|
<div className={radioWrapperClass}>
|
||||||
{props.pos.options?.values.map((data, ind) => {
|
{props.pos.options?.values.map((data, ind) => (
|
||||||
return (
|
<div key={ind} className="select-none-cls pointer-events-none">
|
||||||
<div key={ind} className="select-none-cls pointer-events-none">
|
<label
|
||||||
<label
|
htmlFor={`radio-${props.pos.key + ind}`}
|
||||||
htmlFor={`radio-${props.pos.key + ind}`}
|
style={{ fontSize: fontSize, color: fontColor }}
|
||||||
style={{
|
className="text-xs mb-0 flex items-center gap-1"
|
||||||
fontSize: fontSize,
|
>
|
||||||
color: fontColor,
|
<input
|
||||||
marginTop: ind > 0 ? "5px" : "0px"
|
readOnly
|
||||||
}}
|
id={`radio-${props.pos.key + ind}`}
|
||||||
className="text-xs mb-0 flex items-center gap-1 "
|
style={{ width: fontSize, height: fontSize, lineHeight: 2 }}
|
||||||
>
|
className={`op-radio rounded-full border-black appearance-none bg-white inline-block align-middle relative ${
|
||||||
<input
|
handleRadioCheck(data) ? "checked-radio" : ""
|
||||||
readOnly
|
}`}
|
||||||
id={`radio-${props.pos.key + ind}`}
|
type="radio"
|
||||||
style={{
|
disabled={props.isNeedSign && isReadOnly}
|
||||||
width: fontSize,
|
checked={handleRadioCheck(data)}
|
||||||
height: fontSize,
|
/>
|
||||||
lineHeight: 2
|
{!props.pos.options?.isHideLabel && (
|
||||||
}}
|
<span className="leading-none">{data}</span>
|
||||||
className={`op-radio rounded-full border- border-black appearance-none bg-white inline-block align-middle relative ${
|
)}
|
||||||
handleRadioCheck(data) ? "checked-radio" : ""
|
</label>
|
||||||
}`}
|
</div>
|
||||||
type="radio"
|
))}
|
||||||
disabled={
|
|
||||||
props.isNeedSign &&
|
|
||||||
(props.pos.options?.isReadOnly ||
|
|
||||||
props.data?.signerObjId !== props.signerObjId)
|
|
||||||
}
|
|
||||||
checked={handleRadioCheck(data)}
|
|
||||||
/>
|
|
||||||
{!props.pos.options?.isHideLabel && (
|
|
||||||
<span className="leading-none">{data}</span>
|
|
||||||
)}
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
case textWidget:
|
case textWidget:
|
||||||
@@ -474,7 +487,8 @@ function PlaceholderType(props) {
|
|||||||
style={{
|
style={{
|
||||||
fontFamily: "Arial, sans-serif",
|
fontFamily: "Arial, sans-serif",
|
||||||
fontSize: fontSize,
|
fontSize: fontSize,
|
||||||
color: fontColor
|
color: fontColor,
|
||||||
|
background: "white"
|
||||||
}}
|
}}
|
||||||
cols="50"
|
cols="50"
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -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) => {
|
const checkSignedSigners = (data) => {
|
||||||
let checkSign = [];
|
let checkSign = [];
|
||||||
//condition to handle quick send flow and using normal request sign flow
|
//condition to handle quick send flow and using normal request sign flow
|
||||||
@@ -91,73 +91,71 @@ function RenderPdf(props) {
|
|||||||
: [];
|
: [];
|
||||||
return (
|
return (
|
||||||
checkSign.length === 0 &&
|
checkSign.length === 0 &&
|
||||||
data?.placeHolder?.map((placeData, key) => {
|
data?.placeHolder?.map((placeData, key) => (
|
||||||
return (
|
<React.Fragment key={key}>
|
||||||
<React.Fragment key={key}>
|
{placeData.pageNumber === props.pageNumber &&
|
||||||
{placeData.pageNumber === props.pageNumber &&
|
placeData.pos.map(
|
||||||
placeData.pos.map((pos, ind) => {
|
(pos, ind) =>
|
||||||
return (
|
pos && (
|
||||||
pos && (
|
<React.Fragment key={ind}>
|
||||||
<React.Fragment key={ind}>
|
<Placeholder
|
||||||
<Placeholder
|
pos={pos}
|
||||||
pos={pos}
|
handleSignYourselfImageResize={handleImageResize}
|
||||||
handleSignYourselfImageResize={handleImageResize}
|
index={props.pageNumber}
|
||||||
index={props.pageNumber}
|
xyPosition={props.signerPos}
|
||||||
xyPosition={props.signerPos}
|
setXyPosition={props.setSignerPos}
|
||||||
setXyPosition={props.setSignerPos}
|
data={data}
|
||||||
data={data}
|
setIsResize={props.setIsResize}
|
||||||
setIsResize={props.setIsResize}
|
isShowBorder={props.isSelfSign}
|
||||||
isShowBorder={props.isSelfSign}
|
isAlllowModify={props.isAlllowModify}
|
||||||
isAlllowModify={props.isAlllowModify}
|
signerObjId={props.signerObjectId}
|
||||||
signerObjId={props.signerObjectId}
|
isShowDropdown={true}
|
||||||
isShowDropdown={true}
|
isNeedSign={props.pdfRequest}
|
||||||
isNeedSign={props.pdfRequest}
|
isSelfSign={true}
|
||||||
isSelfSign={true}
|
isSignYourself={false}
|
||||||
isSignYourself={false}
|
posWidth={posWidth}
|
||||||
posWidth={posWidth}
|
posHeight={posHeight}
|
||||||
posHeight={posHeight}
|
isDragging={props.isDragging}
|
||||||
isDragging={props.isDragging}
|
pdfDetails={props.pdfDetails}
|
||||||
pdfDetails={props.pdfDetails}
|
unSignedWidgetId={props.unSignedWidgetId}
|
||||||
unSignedWidgetId={props.unSignedWidgetId}
|
setCurrWidgetsDetails={props.setCurrWidgetsDetails}
|
||||||
setCurrWidgetsDetails={props.setCurrWidgetsDetails}
|
uniqueId={props.uniqueId}
|
||||||
uniqueId={props.uniqueId}
|
scale={props.scale}
|
||||||
scale={props.scale}
|
containerWH={props.containerWH}
|
||||||
containerWH={props.containerWH}
|
pdfOriginalWH={props.pdfOriginalWH}
|
||||||
pdfOriginalWH={props.pdfOriginalWH}
|
pageNumber={props.pageNumber}
|
||||||
pageNumber={props.pageNumber}
|
ispublicTemplate={props.ispublicTemplate}
|
||||||
ispublicTemplate={props.ispublicTemplate}
|
handleUserDetails={props.handleUserDetails}
|
||||||
handleUserDetails={props.handleUserDetails}
|
isResize={props.isResize}
|
||||||
isResize={props.isResize}
|
setIsAgreeTour={props.setIsAgreeTour}
|
||||||
setIsAgreeTour={props.setIsAgreeTour}
|
isAgree={props.isAgree}
|
||||||
isAgree={props.isAgree}
|
handleTabDrag={props.handleTabDrag}
|
||||||
handleTabDrag={props.handleTabDrag}
|
handleStop={props.handleStop}
|
||||||
handleStop={props.handleStop}
|
setUniqueId={props.setUniqueId}
|
||||||
setUniqueId={props.setUniqueId}
|
setIsSelectId={props.setIsSelectId}
|
||||||
setIsSelectId={props.setIsSelectId}
|
handleDeleteSign={props.handleDeleteSign}
|
||||||
handleDeleteSign={props.handleDeleteSign}
|
setIsPageCopy={props.setIsPageCopy}
|
||||||
setIsPageCopy={props.setIsPageCopy}
|
handleTextSettingModal={props.handleTextSettingModal}
|
||||||
handleTextSettingModal={props.handleTextSettingModal}
|
setIsCheckbox={props.setIsCheckbox}
|
||||||
setIsCheckbox={props.setIsCheckbox}
|
isFreeResize={false}
|
||||||
isFreeResize={false}
|
isOpenSignPad={true}
|
||||||
isOpenSignPad={true}
|
assignedWidgetId={props.assignedWidgetId}
|
||||||
assignedWidgetId={props.assignedWidgetId}
|
isApplyAll={true}
|
||||||
isApplyAll={true}
|
setCellCount={props.setCellCount}
|
||||||
setFontSize={props.setFontSize}
|
setFontSize={props.setFontSize}
|
||||||
fontSize={props.fontSize}
|
fontSize={props.fontSize}
|
||||||
fontColor={props.fontColor}
|
fontColor={props.fontColor}
|
||||||
setFontColor={props.setFontColor}
|
setFontColor={props.setFontColor}
|
||||||
setRequestSignTour={props.setRequestSignTour}
|
setRequestSignTour={props.setRequestSignTour}
|
||||||
calculateFontsize={calculateFontsize}
|
calculateFontsize={calculateFontsize}
|
||||||
currWidgetsDetails={props?.currWidgetsDetails}
|
currWidgetsDetails={props?.currWidgetsDetails}
|
||||||
setTempSignerId={props.setTempSignerId}
|
setTempSignerId={props.setTempSignerId}
|
||||||
/>
|
/>
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
)
|
)
|
||||||
);
|
)}
|
||||||
})}
|
</React.Fragment>
|
||||||
</React.Fragment>
|
))
|
||||||
);
|
|
||||||
})
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -172,148 +170,138 @@ function RenderPdf(props) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
const pdfDataBase64 = `data:application/pdf;base64,${props.pdfBase64Url}`;
|
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 handlePageLoadSuccess = (page) => {
|
||||||
const containerWidth = props.divRef.current.offsetWidth; // Get container width
|
if (isMobile) {
|
||||||
const viewport = page.getViewport({ scale: 1 });
|
const containerWidth = props.divRef.current.offsetWidth; // Get container width
|
||||||
const scale = containerWidth / viewport.width; // Scale to fit container width
|
const viewport = page.getViewport({ scale: 1 });
|
||||||
const scaleHeight = viewport.height * scale;
|
const scale = containerWidth / viewport.width; // Scale to fit container width
|
||||||
setScaledHeight(scaleHeight);
|
const scaleHeight = viewport.height * scale;
|
||||||
|
setScaledHeight(scaleHeight);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{props.successEmail && (
|
{props.successEmail && (
|
||||||
<Alert type={"success"}>{t("success-email-alert")}</Alert>
|
<Alert type={"success"}>{t("success-email-alert")}</Alert>
|
||||||
)}
|
)}
|
||||||
{isMobile ? (
|
<RSC
|
||||||
<RSC
|
style={{
|
||||||
|
position: "relative",
|
||||||
|
boxShadow: "rgba(17, 12, 46, 0.15) 0px 48px 100px 0px",
|
||||||
|
height: isMobile
|
||||||
|
? isGuestSigner
|
||||||
|
? window.innerHeight - 49 // 49 is height of header
|
||||||
|
: scaledHeight
|
||||||
|
: `${window.innerHeight}px`,
|
||||||
|
zIndex: 0
|
||||||
|
}}
|
||||||
|
noScrollY={isMobile ? props.scale === 1 : false}
|
||||||
|
noScrollX={props.scale === 1}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
data-tut={isMobile ? "reactourForth" : undefined}
|
||||||
|
className={
|
||||||
|
isMobile
|
||||||
|
? `${isGuestSigner ? "30px" : ""} border-[0.1px] border-[#ebe8e8] overflow-x-auto`
|
||||||
|
: ""
|
||||||
|
}
|
||||||
style={{
|
style={{
|
||||||
position: "relative",
|
width:
|
||||||
boxShadow: "rgba(17, 12, 46, 0.15) 0px 48px 100px 0px",
|
props.containerWH?.width && props.containerWH?.width * props.scale
|
||||||
//49 is height of header
|
|
||||||
height: isGuestSigner ? window.innerHeight - 49 : scaledHeight,
|
|
||||||
zIndex: 0
|
|
||||||
}}
|
}}
|
||||||
noScrollY={props.scale === 1 ? true : false}
|
ref={props.drop}
|
||||||
noScrollX={props.scale === 1 ? true : false}
|
id="container"
|
||||||
>
|
>
|
||||||
<div
|
{props.pdfLoad !== false &&
|
||||||
data-tut="reactourForth"
|
props.containerWH?.width &&
|
||||||
className={`${
|
props.pdfOriginalWH.length > 0 && (
|
||||||
isGuestSigner ? "30px" : ""
|
<>
|
||||||
} border-[0.1px] border-[#ebe8e8] overflow-x-auto`}
|
{props.pdfRequest || props.isSelfSign
|
||||||
style={{
|
? // request sign, guest sign,
|
||||||
width:
|
props.signerPos?.map((data, key) => (
|
||||||
props.containerWH?.width &&
|
|
||||||
props.containerWH?.width * props.scale
|
|
||||||
}}
|
|
||||||
ref={props.drop}
|
|
||||||
id="container"
|
|
||||||
>
|
|
||||||
{props.containerWH?.width &&
|
|
||||||
props.pdfOriginalWH.length > 0 &&
|
|
||||||
(props.pdfRequest || props.isSelfSign
|
|
||||||
? props.signerPos?.map((data, key) => {
|
|
||||||
return (
|
|
||||||
<React.Fragment key={key}>
|
<React.Fragment key={key}>
|
||||||
{checkSignedSigners(data)}
|
{checkSignedSigners(data)}
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
);
|
))
|
||||||
})
|
: props.placeholder // placeholdersign document, draft document, create template, draft template
|
||||||
: props.placeholder // placeholder mobile
|
? props.signerPos?.map((data, ind) => (
|
||||||
? props.signerPos?.map((data, ind) => {
|
|
||||||
return (
|
|
||||||
<React.Fragment key={ind}>
|
<React.Fragment key={ind}>
|
||||||
{data?.placeHolder &&
|
{data?.placeHolder &&
|
||||||
data?.placeHolder.map((placeData, index) => {
|
data?.placeHolder.map((placeData, index) => (
|
||||||
return (
|
<React.Fragment key={index}>
|
||||||
<React.Fragment key={index}>
|
{placeData.pageNumber === props.pageNumber &&
|
||||||
{placeData.pageNumber === props.pageNumber &&
|
placeData.pos.map((pos) => (
|
||||||
placeData.pos.map((pos) => {
|
<React.Fragment key={pos.key}>
|
||||||
return (
|
<Placeholder
|
||||||
<React.Fragment key={pos.key}>
|
pos={pos}
|
||||||
<Placeholder
|
setIsPageCopy={props.setIsPageCopy}
|
||||||
pos={pos}
|
handleDeleteSign={
|
||||||
setIsPageCopy={props.setIsPageCopy}
|
props.handleDeleteSign
|
||||||
handleDeleteSign={
|
}
|
||||||
props.handleDeleteSign
|
handleTabDrag={props.handleTabDrag}
|
||||||
}
|
handleStop={props.handleStop}
|
||||||
handleTabDrag={props.handleTabDrag}
|
handleSignYourselfImageResize={
|
||||||
handleStop={props.handleStop}
|
handleImageResize
|
||||||
handleSignYourselfImageResize={
|
}
|
||||||
handleImageResize
|
index={props.pageNumber}
|
||||||
}
|
xyPosition={props.signerPos}
|
||||||
index={props.pageNumber}
|
setXyPosition={props.setSignerPos}
|
||||||
xyPosition={props.signerPos}
|
data={data}
|
||||||
setXyPosition={props.setSignerPos}
|
setIsResize={props.setIsResize}
|
||||||
data={data}
|
setShowDropdown={props.setShowDropdown}
|
||||||
setIsResize={props.setIsResize}
|
isShowBorder={true}
|
||||||
setShowDropdown={
|
isPlaceholder={true}
|
||||||
props.setShowDropdown
|
setUniqueId={props.setUniqueId}
|
||||||
}
|
handleLinkUser={props.handleLinkUser}
|
||||||
isShowBorder={true}
|
isSignYourself={false}
|
||||||
isPlaceholder={true}
|
posWidth={posWidth}
|
||||||
setUniqueId={props.setUniqueId}
|
posHeight={posHeight}
|
||||||
handleLinkUser={
|
isDragging={props.isDragging}
|
||||||
props.handleLinkUser
|
setIsValidate={props.setIsValidate}
|
||||||
}
|
setIsRadio={props.setIsRadio}
|
||||||
isSignYourself={false}
|
setIsCheckbox={props.setIsCheckbox}
|
||||||
posWidth={posWidth}
|
setCurrWidgetsDetails={
|
||||||
posHeight={posHeight}
|
props.setCurrWidgetsDetails
|
||||||
isDragging={props.isDragging}
|
}
|
||||||
setIsValidate={props.setIsValidate}
|
handleNameModal={props.handleNameModal}
|
||||||
setIsRadio={props.setIsRadio}
|
setTempSignerId={props.setTempSignerId}
|
||||||
setIsCheckbox={props.setIsCheckbox}
|
uniqueId={props.uniqueId}
|
||||||
setCurrWidgetsDetails={
|
handleTextSettingModal={
|
||||||
props.setCurrWidgetsDetails
|
props.handleTextSettingModal
|
||||||
}
|
}
|
||||||
handleNameModal={
|
scale={props.scale}
|
||||||
props.handleNameModal
|
containerWH={props.containerWH}
|
||||||
}
|
pdfOriginalWH={props.pdfOriginalWH}
|
||||||
setTempSignerId={
|
pageNumber={props.pageNumber}
|
||||||
props.setTempSignerId
|
setIsSelectId={props.setIsSelectId}
|
||||||
}
|
fontSize={props.fontSize}
|
||||||
uniqueId={props.uniqueId}
|
setFontSize={props.setFontSize}
|
||||||
handleTextSettingModal={
|
setCellCount={props.setCellCount}
|
||||||
props.handleTextSettingModal
|
fontColor={props.fontColor}
|
||||||
}
|
setFontColor={props.setFontColor}
|
||||||
scale={props.scale}
|
isResize={props.isResize}
|
||||||
containerWH={props.containerWH}
|
unSignedWidgetId={
|
||||||
pdfOriginalWH={props.pdfOriginalWH}
|
props.unSignedWidgetId
|
||||||
pageNumber={props.pageNumber}
|
}
|
||||||
setIsSelectId={props.setIsSelectId}
|
isFreeResize={true}
|
||||||
fontSize={props.fontSize}
|
calculateFontsize={calculateFontsize}
|
||||||
setFontSize={props.setFontSize}
|
currWidgetsDetails={
|
||||||
fontColor={props.fontColor}
|
props?.currWidgetsDetails
|
||||||
setFontColor={props.setFontColor}
|
}
|
||||||
isResize={props.isResize}
|
/>
|
||||||
unSignedWidgetId={
|
</React.Fragment>
|
||||||
props.unSignedWidgetId
|
))}
|
||||||
}
|
</React.Fragment>
|
||||||
isFreeResize={true}
|
))}
|
||||||
calculateFontsize={
|
|
||||||
calculateFontsize
|
|
||||||
}
|
|
||||||
currWidgetsDetails={
|
|
||||||
props?.currWidgetsDetails
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</React.Fragment>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</React.Fragment>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
);
|
))
|
||||||
})
|
: !props.pdfDetails?.[0]?.IsCompleted && // signyourself flow
|
||||||
: !props.pdfDetails?.[0]?.IsCompleted &&
|
props.xyPosition?.map((data, ind) => (
|
||||||
props.xyPosition?.map((data, ind) => {
|
|
||||||
return (
|
|
||||||
<React.Fragment key={ind}>
|
<React.Fragment key={ind}>
|
||||||
{data.pageNumber === props.pageNumber &&
|
{data.pageNumber === props.pageNumber &&
|
||||||
data.pos.map((pos, id) => {
|
data.pos.map(
|
||||||
return (
|
(pos, id) =>
|
||||||
pos && (
|
pos && (
|
||||||
<Placeholder
|
<Placeholder
|
||||||
key={id}
|
key={id}
|
||||||
@@ -359,247 +347,43 @@ function RenderPdf(props) {
|
|||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
);
|
)}
|
||||||
})}
|
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
);
|
))}
|
||||||
}))}
|
</>
|
||||||
{/* Mobile */}
|
)}
|
||||||
<Document
|
<Document
|
||||||
error={<p className="mx-2">{t("failed-to-load-refresh-page")}</p>}
|
error={<p className="mx-2">{t("failed-to-load-refresh-page")}</p>}
|
||||||
onLoadError={() => props.setPdfLoad(false)}
|
onLoadError={(e) => {
|
||||||
loading={t("loading-doc")}
|
console.log("PDF load error", e);
|
||||||
onLoadSuccess={props.pageDetails}
|
props.setPdfLoad(false);
|
||||||
onClick={() =>
|
|
||||||
props.setCurrWidgetsDetails && props.setCurrWidgetsDetails({})
|
|
||||||
}
|
|
||||||
file={pdfDataBase64}
|
|
||||||
>
|
|
||||||
<Page
|
|
||||||
onLoadSuccess={handlePageLoadSuccess}
|
|
||||||
scale={props.scale || 1}
|
|
||||||
key={props.index}
|
|
||||||
pageNumber={props.pageNumber}
|
|
||||||
width={props.containerWH.width}
|
|
||||||
renderAnnotationLayer={false}
|
|
||||||
renderTextLayer={false}
|
|
||||||
onGetAnnotationsError={(error) => {
|
|
||||||
console.log("annotation error", error);
|
|
||||||
}}
|
|
||||||
className="select-none touch-callout-none"
|
|
||||||
/>
|
|
||||||
</Document>
|
|
||||||
</div>
|
|
||||||
</RSC>
|
|
||||||
) : (
|
|
||||||
<RSC
|
|
||||||
style={{
|
|
||||||
position: "relative",
|
|
||||||
boxShadow: "rgba(17, 12, 46, 0.15) 0px 48px 100px 0px",
|
|
||||||
height: window.innerHeight + "px",
|
|
||||||
zIndex: 0
|
|
||||||
}}
|
|
||||||
noScrollY={false}
|
|
||||||
noScrollX={props.scale === 1 ? true : false}
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
style={{
|
|
||||||
width:
|
|
||||||
props.containerWH?.width &&
|
|
||||||
props.containerWH?.width * props.scale
|
|
||||||
}}
|
}}
|
||||||
ref={props.drop}
|
loading={t("loading-doc")}
|
||||||
id="container"
|
onLoadSuccess={(pdf) => {
|
||||||
|
props.setPdfLoad(true);
|
||||||
|
props.pageDetails(pdf);
|
||||||
|
}}
|
||||||
|
onClick={() =>
|
||||||
|
props.setCurrWidgetsDetails && props.setCurrWidgetsDetails({})
|
||||||
|
}
|
||||||
|
file={pdfDataBase64}
|
||||||
>
|
>
|
||||||
{props.pdfLoad &&
|
<Page
|
||||||
props.containerWH?.width &&
|
key={props.index}
|
||||||
props.pdfOriginalWH.length > 0 &&
|
onLoadSuccess={handlePageLoadSuccess}
|
||||||
(props.pdfRequest || props.isSelfSign //pdf request sign flow
|
width={props.containerWH.width}
|
||||||
? props.signerPos?.map((data, key) => {
|
scale={props.scale || 1}
|
||||||
return (
|
className={isMobile ? "select-none touch-callout-none" : "-z-[1]"}
|
||||||
<React.Fragment key={key}>
|
pageNumber={props.pageNumber}
|
||||||
{checkSignedSigners(data)}
|
renderAnnotationLayer={false}
|
||||||
</React.Fragment>
|
renderTextLayer={false}
|
||||||
);
|
onGetAnnotationsError={(error) => {
|
||||||
})
|
console.log("annotation error", error);
|
||||||
: props.placeholder //placeholder and template flow
|
}}
|
||||||
? props.signerPos.map((data, ind) => {
|
/>
|
||||||
return (
|
</Document>
|
||||||
<React.Fragment key={ind}>
|
</div>
|
||||||
{data?.placeHolder &&
|
</RSC>
|
||||||
data?.placeHolder.map((placeData, index) => {
|
|
||||||
return (
|
|
||||||
<React.Fragment key={index}>
|
|
||||||
{placeData.pageNumber === props.pageNumber &&
|
|
||||||
placeData.pos.map((pos) => {
|
|
||||||
return (
|
|
||||||
<React.Fragment key={pos.key}>
|
|
||||||
<Placeholder
|
|
||||||
pos={pos}
|
|
||||||
setIsPageCopy={props.setIsPageCopy}
|
|
||||||
handleDeleteSign={
|
|
||||||
props.handleDeleteSign
|
|
||||||
}
|
|
||||||
handleTabDrag={props.handleTabDrag}
|
|
||||||
handleStop={props.handleStop}
|
|
||||||
handleSignYourselfImageResize={
|
|
||||||
handleImageResize
|
|
||||||
}
|
|
||||||
index={props.pageNumber}
|
|
||||||
xyPosition={props.signerPos}
|
|
||||||
setXyPosition={props.setSignerPos}
|
|
||||||
data={data}
|
|
||||||
setIsResize={props.setIsResize}
|
|
||||||
setShowDropdown={
|
|
||||||
props.setShowDropdown
|
|
||||||
}
|
|
||||||
isShowBorder={true}
|
|
||||||
isPlaceholder={true}
|
|
||||||
setUniqueId={props.setUniqueId}
|
|
||||||
handleLinkUser={
|
|
||||||
props.handleLinkUser
|
|
||||||
}
|
|
||||||
isSignYourself={false}
|
|
||||||
posWidth={posWidth}
|
|
||||||
posHeight={posHeight}
|
|
||||||
isDragging={props.isDragging}
|
|
||||||
setIsValidate={props.setIsValidate}
|
|
||||||
setIsRadio={props.setIsRadio}
|
|
||||||
setIsCheckbox={props.setIsCheckbox}
|
|
||||||
setCurrWidgetsDetails={
|
|
||||||
props.setCurrWidgetsDetails
|
|
||||||
}
|
|
||||||
handleNameModal={
|
|
||||||
props.handleNameModal
|
|
||||||
}
|
|
||||||
setTempSignerId={
|
|
||||||
props.setTempSignerId
|
|
||||||
}
|
|
||||||
uniqueId={props.uniqueId}
|
|
||||||
handleTextSettingModal={
|
|
||||||
props.handleTextSettingModal
|
|
||||||
}
|
|
||||||
scale={props.scale}
|
|
||||||
containerWH={props.containerWH}
|
|
||||||
pdfOriginalWH={props.pdfOriginalWH}
|
|
||||||
pageNumber={props.pageNumber}
|
|
||||||
setIsSelectId={props.setIsSelectId}
|
|
||||||
fontSize={props.fontSize}
|
|
||||||
setFontSize={props.setFontSize}
|
|
||||||
fontColor={props.fontColor}
|
|
||||||
setFontColor={props.setFontColor}
|
|
||||||
isResize={props.isResize}
|
|
||||||
unSignedWidgetId={
|
|
||||||
props.unSignedWidgetId
|
|
||||||
}
|
|
||||||
isFreeResize={true}
|
|
||||||
calculateFontsize={
|
|
||||||
calculateFontsize
|
|
||||||
}
|
|
||||||
currWidgetsDetails={
|
|
||||||
props?.currWidgetsDetails
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</React.Fragment>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</React.Fragment>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</React.Fragment>
|
|
||||||
);
|
|
||||||
})
|
|
||||||
: !props.pdfDetails?.[0]?.IsCompleted &&
|
|
||||||
props.xyPosition?.map((data, ind) => {
|
|
||||||
// signyourself flow
|
|
||||||
return (
|
|
||||||
<React.Fragment key={ind}>
|
|
||||||
{data.pageNumber === props.pageNumber &&
|
|
||||||
data.pos.map((pos) => {
|
|
||||||
return (
|
|
||||||
<React.Fragment key={pos.key}>
|
|
||||||
<Placeholder
|
|
||||||
pos={pos}
|
|
||||||
setIsPageCopy={props.setIsPageCopy}
|
|
||||||
handleDeleteSign={props.handleDeleteSign}
|
|
||||||
handleTabDrag={props.handleTabDrag}
|
|
||||||
handleStop={(event, dragElement) =>
|
|
||||||
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
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</React.Fragment>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</React.Fragment>
|
|
||||||
);
|
|
||||||
}))}
|
|
||||||
{/* large device */}
|
|
||||||
{/* this component for render pdf document is in middle of the component */}
|
|
||||||
<Document
|
|
||||||
error={<p className="mx-2">{t("failed-to-load-refresh-page")}</p>}
|
|
||||||
onLoadError={() => props.setPdfLoad(false)}
|
|
||||||
loading={t("loading-doc")}
|
|
||||||
onLoadSuccess={props.pageDetails}
|
|
||||||
onClick={() =>
|
|
||||||
props.setCurrWidgetsDetails && props.setCurrWidgetsDetails({})
|
|
||||||
}
|
|
||||||
file={pdfDataBase64}
|
|
||||||
>
|
|
||||||
<Page
|
|
||||||
key={props.index}
|
|
||||||
width={props.containerWH.width}
|
|
||||||
scale={props.scale || 1}
|
|
||||||
className={"-z-[1]"} // when user zoom-in in tablet widgets move backward that's why pass -z-[1]
|
|
||||||
pageNumber={props.pageNumber}
|
|
||||||
renderAnnotationLayer={false}
|
|
||||||
renderTextLayer={false}
|
|
||||||
onGetAnnotationsError={(error) => {
|
|
||||||
console.log("annotation error", error);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</Document>
|
|
||||||
</div>
|
|
||||||
</RSC>
|
|
||||||
)}
|
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import {
|
|||||||
isMobile,
|
isMobile,
|
||||||
radioButtonWidget,
|
radioButtonWidget,
|
||||||
textInputWidget,
|
textInputWidget,
|
||||||
|
cellsWidget,
|
||||||
textWidget,
|
textWidget,
|
||||||
widgets
|
widgets
|
||||||
} from "../../constant/Utils";
|
} from "../../constant/Utils";
|
||||||
@@ -37,6 +38,10 @@ function WidgetComponent(props) {
|
|||||||
type: "BOX",
|
type: "BOX",
|
||||||
item: { type: "BOX", id: 7, text: textInputWidget }
|
item: { type: "BOX", id: 7, text: textInputWidget }
|
||||||
});
|
});
|
||||||
|
const [, cells] = useDrag({
|
||||||
|
type: "BOX",
|
||||||
|
item: { type: "BOX", id: 17, text: cellsWidget }
|
||||||
|
});
|
||||||
const [, initials] = useDrag({
|
const [, initials] = useDrag({
|
||||||
type: "BOX",
|
type: "BOX",
|
||||||
item: { type: "BOX", id: 8, text: "initials" }
|
item: { type: "BOX", id: 8, text: "initials" }
|
||||||
@@ -89,6 +94,7 @@ function WidgetComponent(props) {
|
|||||||
date,
|
date,
|
||||||
text,
|
text,
|
||||||
textInput,
|
textInput,
|
||||||
|
cells,
|
||||||
checkbox,
|
checkbox,
|
||||||
dropdown,
|
dropdown,
|
||||||
radioButton,
|
radioButton,
|
||||||
@@ -132,7 +138,9 @@ function WidgetComponent(props) {
|
|||||||
);
|
);
|
||||||
const filterWidgets = widget.filter(
|
const filterWidgets = widget.filter(
|
||||||
(data) =>
|
(data) =>
|
||||||
!["dropdown", radioButtonWidget, textInputWidget].includes(data.type)
|
!["dropdown", radioButtonWidget, textInputWidget].includes(
|
||||||
|
data.type
|
||||||
|
)
|
||||||
);
|
);
|
||||||
const textWidgetData = widget.filter((data) => data.type !== textWidget);
|
const textWidgetData = widget.filter((data) => data.type !== textWidget);
|
||||||
const updateWidgets = props.isSignYourself
|
const updateWidgets = props.isSignYourself
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import RegexParser from "regex-parser";
|
|||||||
import {
|
import {
|
||||||
signatureTypes,
|
signatureTypes,
|
||||||
textInputWidget,
|
textInputWidget,
|
||||||
|
cellsWidget,
|
||||||
textWidget
|
textWidget
|
||||||
} from "../../constant/Utils";
|
} from "../../constant/Utils";
|
||||||
import { fontColorArr, fontsizeArr } from "../../constant/Utils";
|
import { fontColorArr, fontsizeArr } from "../../constant/Utils";
|
||||||
@@ -19,7 +20,8 @@ const WidgetNameModal = (props) => {
|
|||||||
status: "required",
|
status: "required",
|
||||||
hint: "",
|
hint: "",
|
||||||
textvalidate: "",
|
textvalidate: "",
|
||||||
isReadOnly: false
|
isReadOnly: false,
|
||||||
|
cellCount: 5
|
||||||
});
|
});
|
||||||
const [isValid, setIsValid] = useState(true);
|
const [isValid, setIsValid] = useState(true);
|
||||||
const statusArr = ["Required", "Optional"];
|
const statusArr = ["Required", "Optional"];
|
||||||
@@ -51,12 +53,14 @@ const WidgetNameModal = (props) => {
|
|||||||
props.defaultdata?.options?.validation?.type === "regex"
|
props.defaultdata?.options?.validation?.type === "regex"
|
||||||
? props.defaultdata?.options?.validation?.pattern
|
? props.defaultdata?.options?.validation?.pattern
|
||||||
: props.defaultdata?.options?.validation?.type || "",
|
: props.defaultdata?.options?.validation?.type || "",
|
||||||
isReadOnly: props.defaultdata?.options?.isReadOnly || false
|
isReadOnly: props.defaultdata?.options?.isReadOnly || false,
|
||||||
|
cellCount: props.defaultdata?.options?.cellCount || 5
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
setFormdata({
|
setFormdata({
|
||||||
...formdata,
|
...formdata,
|
||||||
name: props.defaultdata?.options?.name || ""
|
name: props.defaultdata?.options?.name || "",
|
||||||
|
cellCount: props.defaultdata?.options?.cellCount || 5
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -83,7 +87,9 @@ const WidgetNameModal = (props) => {
|
|||||||
props.handleData(data, props.defaultdata?.type);
|
props.handleData(data, props.defaultdata?.type);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
const isTextInput = props.defaultdata?.type === textInputWidget;
|
const isTextInput = [textInputWidget, cellsWidget].includes(
|
||||||
|
props.defaultdata?.type
|
||||||
|
);
|
||||||
const { isReadOnly, defaultValue, status } = formdata;
|
const { isReadOnly, defaultValue, status } = formdata;
|
||||||
// If it’s a text‐input widget, enforce that read-only fields have
|
// If it’s a text‐input widget, enforce that read-only fields have
|
||||||
// either a defaultValue or an "optional" status.
|
// either a defaultValue or an "optional" status.
|
||||||
@@ -104,7 +110,8 @@ const WidgetNameModal = (props) => {
|
|||||||
defaultValue: "",
|
defaultValue: "",
|
||||||
status: "required",
|
status: "required",
|
||||||
hint: "",
|
hint: "",
|
||||||
textvalidate: ""
|
textvalidate: "",
|
||||||
|
cellCount: 5
|
||||||
});
|
});
|
||||||
setSignatureType(signTypes);
|
setSignatureType(signTypes);
|
||||||
}
|
}
|
||||||
@@ -125,7 +132,11 @@ const WidgetNameModal = (props) => {
|
|||||||
} else {
|
} else {
|
||||||
setIsValid(true);
|
setIsValid(true);
|
||||||
}
|
}
|
||||||
setFormdata({ ...formdata, [e.target.name]: e.target.value });
|
const val =
|
||||||
|
props.defaultdata?.type === cellsWidget
|
||||||
|
? e.target.value.slice(0, formdata.cellCount)
|
||||||
|
: e.target.value;
|
||||||
|
setFormdata({ ...formdata, [e.target.name]: val });
|
||||||
};
|
};
|
||||||
|
|
||||||
function handleValidation(type) {
|
function handleValidation(type) {
|
||||||
@@ -136,6 +147,8 @@ const WidgetNameModal = (props) => {
|
|||||||
return "/^\\d+$/";
|
return "/^\\d+$/";
|
||||||
case "text":
|
case "text":
|
||||||
return "/^[a-zA-Zs]+$/";
|
return "/^[a-zA-Zs]+$/";
|
||||||
|
case "ssn":
|
||||||
|
return "^\\d{3}-\\d{2}-\\d{4}$";
|
||||||
default:
|
default:
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
@@ -163,7 +176,7 @@ const WidgetNameModal = (props) => {
|
|||||||
<form
|
<form
|
||||||
onSubmit={handleSubmit}
|
onSubmit={handleSubmit}
|
||||||
className={`${
|
className={`${
|
||||||
props.defaultdata?.type === textInputWidget
|
[textInputWidget, cellsWidget].includes(props.defaultdata?.type)
|
||||||
? "pt-0"
|
? "pt-0"
|
||||||
: ["signature", "initials"].includes(props.defaultdata?.type)
|
: ["signature", "initials"].includes(props.defaultdata?.type)
|
||||||
? "pt-2"
|
? "pt-2"
|
||||||
@@ -187,7 +200,21 @@ const WidgetNameModal = (props) => {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{props.defaultdata?.type === textInputWidget && (
|
{props.defaultdata?.type === cellsWidget && (
|
||||||
|
<div className="mb-[0.75rem] text-[13px]">
|
||||||
|
<label htmlFor="cellCount">{t("cell-count")}</label>
|
||||||
|
<input
|
||||||
|
className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs"
|
||||||
|
type="number"
|
||||||
|
min="1"
|
||||||
|
name="cellCount"
|
||||||
|
value={formdata.cellCount}
|
||||||
|
onChange={(e) => handleChange(e)}
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{[textInputWidget, cellsWidget].includes(props.defaultdata?.type) && (
|
||||||
<>
|
<>
|
||||||
<div className="mb-[0.75rem]">
|
<div className="mb-[0.75rem]">
|
||||||
<label htmlFor="name" className="text-[13px]">
|
<label htmlFor="name" className="text-[13px]">
|
||||||
@@ -199,6 +226,11 @@ const WidgetNameModal = (props) => {
|
|||||||
value={formdata.defaultValue}
|
value={formdata.defaultValue}
|
||||||
onChange={(e) => handledefaultChange(e)}
|
onChange={(e) => handledefaultChange(e)}
|
||||||
autoComplete="off"
|
autoComplete="off"
|
||||||
|
maxLength={
|
||||||
|
props.defaultdata?.type === cellsWidget
|
||||||
|
? formdata.cellCount
|
||||||
|
: undefined
|
||||||
|
}
|
||||||
onBlur={() => {
|
onBlur={() => {
|
||||||
if (isValid === false) {
|
if (isValid === false) {
|
||||||
setFormdata({ ...formdata, defaultValue: "" });
|
setFormdata({ ...formdata, defaultValue: "" });
|
||||||
@@ -250,7 +282,9 @@ const WidgetNameModal = (props) => {
|
|||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
{[textInputWidget].includes(props.defaultdata?.type) && (
|
{[textInputWidget, cellsWidget].includes(
|
||||||
|
props.defaultdata?.type
|
||||||
|
) && (
|
||||||
<div className="flex items-center">
|
<div className="flex items-center">
|
||||||
<input
|
<input
|
||||||
id="isReadOnly"
|
id="isReadOnly"
|
||||||
@@ -265,7 +299,7 @@ const WidgetNameModal = (props) => {
|
|||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
<label className="ml-1 mb-0" htmlFor="isreadonly">
|
<label className="ml-1.5 mb-0 capitalize text-[13px]" htmlFor="isreadonly">
|
||||||
{t("read-only")}
|
{t("read-only")}
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
@@ -317,6 +351,7 @@ const WidgetNameModal = (props) => {
|
|||||||
{[
|
{[
|
||||||
textInputWidget,
|
textInputWidget,
|
||||||
textWidget,
|
textWidget,
|
||||||
|
cellsWidget,
|
||||||
"name",
|
"name",
|
||||||
"company",
|
"company",
|
||||||
"job title",
|
"job title",
|
||||||
|
|||||||
@@ -15,9 +15,11 @@ import {
|
|||||||
radioButtonWidget,
|
radioButtonWidget,
|
||||||
selectCheckbox,
|
selectCheckbox,
|
||||||
textInputWidget,
|
textInputWidget,
|
||||||
|
cellsWidget,
|
||||||
textWidget,
|
textWidget,
|
||||||
years
|
years
|
||||||
} from "../../constant/Utils";
|
} from "../../constant/Utils";
|
||||||
|
import CellsWidget from "./CellsWidget";
|
||||||
import DatePicker from "react-datepicker";
|
import DatePicker from "react-datepicker";
|
||||||
import "react-datepicker/dist/react-datepicker.css";
|
import "react-datepicker/dist/react-datepicker.css";
|
||||||
import SignatureCanvas from "react-signature-canvas";
|
import SignatureCanvas from "react-signature-canvas";
|
||||||
@@ -93,7 +95,6 @@ function WidgetsValueModal(props) {
|
|||||||
const [isTab, setIsTab] = useState("");
|
const [isTab, setIsTab] = useState("");
|
||||||
const [textWidth, setTextWidth] = useState(0);
|
const [textWidth, setTextWidth] = useState(0);
|
||||||
const [textHeight, setTextHeight] = useState(0);
|
const [textHeight, setTextHeight] = useState(0);
|
||||||
const [signatureType, setSignatureType] = useState("");
|
|
||||||
const [isSignTypes, setIsSignTypes] = useState(true);
|
const [isSignTypes, setIsSignTypes] = useState(true);
|
||||||
const [typedSignature, setTypedSignature] = useState("");
|
const [typedSignature, setTypedSignature] = useState("");
|
||||||
const [selectDate, setSelectDate] = useState({});
|
const [selectDate, setSelectDate] = useState({});
|
||||||
@@ -119,13 +120,33 @@ function WidgetsValueModal(props) {
|
|||||||
const currentUserName = jsonSender && jsonSender?.name;
|
const currentUserName = jsonSender && jsonSender?.name;
|
||||||
const widgetTypeTranslation = t(`widgets-name.${currWidgetsDetails?.type}`);
|
const widgetTypeTranslation = t(`widgets-name.${currWidgetsDetails?.type}`);
|
||||||
const [widgetValue, setWidgetValue] = useState(
|
const [widgetValue, setWidgetValue] = useState(
|
||||||
currWidgetsDetails?.options?.response ||
|
currWidgetsDetails.type !== "checkbox" &&
|
||||||
currWidgetsDetails?.options?.defaultValue
|
(currWidgetsDetails?.options?.response ||
|
||||||
|
currWidgetsDetails?.options?.defaultValue)
|
||||||
);
|
);
|
||||||
const [selectedCheckbox, setSelectedCheckbox] = useState(
|
const [cellsValue, setCellsValue] = useState(() => {
|
||||||
currWidgetsDetails?.options?.response ||
|
const count = currWidgetsDetails?.options?.cellCount || 5;
|
||||||
|
const val =
|
||||||
|
currWidgetsDetails?.options?.response ||
|
||||||
currWidgetsDetails?.options?.defaultValue ||
|
currWidgetsDetails?.options?.defaultValue ||
|
||||||
[]
|
"";
|
||||||
|
return Array.from({ length: count }, (_, i) => val[i] || "");
|
||||||
|
});
|
||||||
|
const cellRefs = useRef([]);
|
||||||
|
|
||||||
|
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]);
|
||||||
|
const [selectedCheckbox, setSelectedCheckbox] = useState(
|
||||||
|
currWidgetsDetails.type === "checkbox" &&
|
||||||
|
(currWidgetsDetails?.options?.response ||
|
||||||
|
currWidgetsDetails?.options?.defaultValue ||
|
||||||
|
[])
|
||||||
);
|
);
|
||||||
const [startDate, setStartDate] = useState(
|
const [startDate, setStartDate] = useState(
|
||||||
currWidgetsDetails?.options?.response
|
currWidgetsDetails?.options?.response
|
||||||
@@ -156,34 +177,6 @@ function WidgetsValueModal(props) {
|
|||||||
setHint(currWidgetsDetails?.type);
|
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
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, [currWidgetsDetails]); // Added currWidgetsDetails to dependency array for reset logic
|
}, [currWidgetsDetails]); // Added currWidgetsDetails to dependency array for reset logic
|
||||||
|
|
||||||
@@ -403,7 +396,6 @@ function WidgetsValueModal(props) {
|
|||||||
const tab = signatureTypes?.[getIndex].name;
|
const tab = signatureTypes?.[getIndex].name;
|
||||||
if (tab === "draw") {
|
if (tab === "draw") {
|
||||||
setIsTab("draw");
|
setIsTab("draw");
|
||||||
setSignatureType("draw");
|
|
||||||
} else if (tab === "upload") {
|
} else if (tab === "upload") {
|
||||||
setIsImageSelect(true);
|
setIsImageSelect(true);
|
||||||
setIsTab("uploadImage");
|
setIsTab("uploadImage");
|
||||||
@@ -449,7 +441,32 @@ function WidgetsValueModal(props) {
|
|||||||
setTypedSignature("");
|
setTypedSignature("");
|
||||||
}
|
}
|
||||||
} else {
|
} 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
|
//function for set signature url
|
||||||
@@ -583,7 +600,7 @@ function WidgetsValueModal(props) {
|
|||||||
if (isTab === "mysignature") {
|
if (isTab === "mysignature") {
|
||||||
setSignature("");
|
setSignature("");
|
||||||
if (currWidgetsDetails?.type === "initials") {
|
if (currWidgetsDetails?.type === "initials") {
|
||||||
handleSaveSignature(signatureType, "initials");
|
handleSaveSignature(isTab, "initials");
|
||||||
} else {
|
} else {
|
||||||
handleSaveSignature(null, "default");
|
handleSaveSignature(null, "default");
|
||||||
}
|
}
|
||||||
@@ -604,13 +621,13 @@ function WidgetsValueModal(props) {
|
|||||||
} else {
|
} else {
|
||||||
setSignature("");
|
setSignature("");
|
||||||
canvasRef?.current?.clear();
|
canvasRef?.current?.clear();
|
||||||
handleSaveSignature(signatureType);
|
handleSaveSignature(isTab);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
setPenColor("blue");
|
setPenColor("blue");
|
||||||
} else {
|
} else {
|
||||||
setSignature("");
|
setSignature("");
|
||||||
handleSaveImage(signatureType);
|
handleSaveImage();
|
||||||
}
|
}
|
||||||
setIsImageSelect(false);
|
setIsImageSelect(false);
|
||||||
setIsDefaultSign(false);
|
setIsDefaultSign(false);
|
||||||
@@ -649,24 +666,21 @@ function WidgetsValueModal(props) {
|
|||||||
}, [fontSelect]);
|
}, [fontSelect]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (
|
if (currWidgetsDetails?.options?.response) {
|
||||||
["signature", "initials"].includes(currWidgetsDetails?.type) &&
|
const url = currWidgetsDetails?.options?.response;
|
||||||
widgetValue
|
if (["signature", "initials"].includes(currWidgetsDetails?.type)) {
|
||||||
) {
|
if (isTab === "draw" && currWidgetsDetails?.signatureType === "draw") {
|
||||||
if (isTab === "draw" && currWidgetsDetails?.signatureType === "draw") {
|
setSignature(url);
|
||||||
setSignature(widgetValue);
|
// Load the default signature after the component mounts
|
||||||
} else if (isTab === "uploadImage" && currWidgetsDetails?.ImageType) {
|
if (canvasRef.current) {
|
||||||
setImage({ imgType: currWidgetsDetails?.ImageType, src: widgetValue });
|
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") {
|
if (isTab === "type") {
|
||||||
const trimmedName = typedSignature
|
const trimmedName = typedSignature
|
||||||
@@ -953,6 +967,65 @@ function WidgetsValueModal(props) {
|
|||||||
uniqueId
|
uniqueId
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
const handleCellsInput = (e, idx) => {
|
||||||
|
const val = e.target.value.slice(0, 1);
|
||||||
|
const updated = [...cellsValue];
|
||||||
|
updated[idx] = val;
|
||||||
|
setCellsValue(updated);
|
||||||
|
const combined = updated.join("");
|
||||||
|
setWidgetValue(combined);
|
||||||
|
onChangeInput(
|
||||||
|
combined,
|
||||||
|
currWidgetsDetails?.key,
|
||||||
|
xyPosition,
|
||||||
|
props.index,
|
||||||
|
setXyPosition,
|
||||||
|
uniqueId
|
||||||
|
);
|
||||||
|
if (val) {
|
||||||
|
if (idx < cellRefs.current.length - 1) {
|
||||||
|
cellRefs.current[idx + 1]?.focus();
|
||||||
|
}
|
||||||
|
} else if (idx > 0) {
|
||||||
|
// move focus back when a cell becomes empty
|
||||||
|
cellRefs.current[idx - 1]?.focus();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const handleCellsKeyDown = (e, idx) => {
|
||||||
|
if (e.key === "Backspace" && !cellsValue[idx] && idx > 0) {
|
||||||
|
e.preventDefault();
|
||||||
|
const updated = [...cellsValue];
|
||||||
|
updated[idx - 1] = "";
|
||||||
|
const combined = updated.join("");
|
||||||
|
setCellsValue(updated);
|
||||||
|
setWidgetValue(combined);
|
||||||
|
onChangeInput(
|
||||||
|
combined,
|
||||||
|
currWidgetsDetails?.key,
|
||||||
|
xyPosition,
|
||||||
|
props.index,
|
||||||
|
setXyPosition,
|
||||||
|
uniqueId
|
||||||
|
);
|
||||||
|
cellRefs.current[idx - 1]?.focus();
|
||||||
|
}
|
||||||
|
if (e.key === "Delete") {
|
||||||
|
e.preventDefault();
|
||||||
|
const updated = [...cellsValue];
|
||||||
|
updated[idx] = "";
|
||||||
|
const combined = updated.join("");
|
||||||
|
setCellsValue(updated);
|
||||||
|
setWidgetValue(combined);
|
||||||
|
onChangeInput(
|
||||||
|
combined,
|
||||||
|
currWidgetsDetails?.key,
|
||||||
|
xyPosition,
|
||||||
|
props.index,
|
||||||
|
setXyPosition,
|
||||||
|
uniqueId
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
//function is used to show widgets on modal according to selected widget type checkbox/date/radio/drodown/textbox/signature/image
|
//function is used to show widgets on modal according to selected widget type checkbox/date/radio/drodown/textbox/signature/image
|
||||||
const getWidgetType = (type) => {
|
const getWidgetType = (type) => {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
@@ -983,7 +1056,6 @@ function WidgetsValueModal(props) {
|
|||||||
setIsDefaultSign(true);
|
setIsDefaultSign(true);
|
||||||
setIsImageSelect(true);
|
setIsImageSelect(true);
|
||||||
setIsTab("mysignature");
|
setIsTab("mysignature");
|
||||||
setSignatureType("");
|
|
||||||
setImage();
|
setImage();
|
||||||
}}
|
}}
|
||||||
className={`${
|
className={`${
|
||||||
@@ -1003,7 +1075,6 @@ function WidgetsValueModal(props) {
|
|||||||
setIsDefaultSign(true);
|
setIsDefaultSign(true);
|
||||||
setIsImageSelect(true);
|
setIsImageSelect(true);
|
||||||
setIsTab("mysignature");
|
setIsTab("mysignature");
|
||||||
setSignatureType("");
|
|
||||||
setImage();
|
setImage();
|
||||||
}}
|
}}
|
||||||
className={`${
|
className={`${
|
||||||
@@ -1040,7 +1111,6 @@ function WidgetsValueModal(props) {
|
|||||||
setIsDefaultSign(false);
|
setIsDefaultSign(false);
|
||||||
setIsImageSelect(true);
|
setIsImageSelect(true);
|
||||||
setIsTab("uploadImage");
|
setIsTab("uploadImage");
|
||||||
setSignatureType("");
|
|
||||||
}}
|
}}
|
||||||
className={`${
|
className={`${
|
||||||
isTab === "uploadImage" && `${isTabCls}`
|
isTab === "uploadImage" && `${isTabCls}`
|
||||||
@@ -1057,7 +1127,6 @@ function WidgetsValueModal(props) {
|
|||||||
setIsDefaultSign(false);
|
setIsDefaultSign(false);
|
||||||
setIsImageSelect(false);
|
setIsImageSelect(false);
|
||||||
setIsTab("type");
|
setIsTab("type");
|
||||||
setSignatureType("");
|
|
||||||
setImage();
|
setImage();
|
||||||
}}
|
}}
|
||||||
className={`${
|
className={`${
|
||||||
@@ -1326,69 +1395,66 @@ function WidgetsValueModal(props) {
|
|||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
<div>
|
<div className="mx-3 mb-6 mt-3">
|
||||||
<div className="relative flex flex-row items-center justify-between">
|
<p>{t("at-least-one-signature-type")}</p>
|
||||||
<div className="text-base-content font-bold text-lg">
|
|
||||||
{t("signature")}
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
className="text-[1.5rem] cursor-pointer"
|
|
||||||
onClick={handleCancelBtn}
|
|
||||||
>
|
|
||||||
×
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="mx-3 mb-6 mt-3">
|
|
||||||
<p>{t("at-least-one-signature-type")}</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
case "checkbox":
|
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 (
|
return (
|
||||||
<div className="border-[1px] border-gray-300 rounded-[2px] pt-1 px-2.5">
|
<div
|
||||||
{currWidgetsDetails?.options?.values?.map((data, ind) => {
|
className={`border-[1px] border-gray-300 rounded-[2px] pt-1 px-2.5 ${checkBoxWrapperClass}`}
|
||||||
return (
|
>
|
||||||
<div key={ind} className=" select-none-cls">
|
{currWidgetsDetails?.options?.values?.map((data, ind) => (
|
||||||
<label
|
<div key={ind} className=" select-none-cls">
|
||||||
htmlFor={`checkbox-${currWidgetsDetails?.key + ind}`}
|
<label
|
||||||
className="text-xs flex items-center gap-1"
|
htmlFor={`checkbox-${currWidgetsDetails?.key + ind}`}
|
||||||
>
|
className="text-xs flex items-center gap-1"
|
||||||
<input
|
>
|
||||||
id={`checkbox-${currWidgetsDetails?.key + ind}`}
|
<input
|
||||||
className={`${
|
id={`checkbox-${currWidgetsDetails?.key + ind}`}
|
||||||
ind === 0 ? "mt-0" : "mt-[5px]"
|
className={`${
|
||||||
} op-checkbox op-checkbox-xs rounded-[1px] mt-1`}
|
ind === 0 ? "mt-0" : "mt-[5px]"
|
||||||
type="checkbox"
|
} op-checkbox op-checkbox-xs rounded-[1px] mt-1`}
|
||||||
checked={!!selectCheckbox(ind, selectedCheckbox)}
|
type="checkbox"
|
||||||
onChange={(e) => {
|
checked={!!selectCheckbox(ind, selectedCheckbox)}
|
||||||
if (e.target.checked) {
|
onChange={(e) => {
|
||||||
const maxRequired =
|
if (e.target.checked) {
|
||||||
currWidgetsDetails?.options?.validation
|
const maxRequired =
|
||||||
?.maxRequiredCount;
|
currWidgetsDetails?.options?.validation
|
||||||
const maxCountInt =
|
?.maxRequiredCount;
|
||||||
maxRequired && parseInt(maxRequired);
|
const maxCountInt =
|
||||||
if (maxCountInt > 0) {
|
maxRequired && parseInt(maxRequired);
|
||||||
if (
|
if (maxCountInt > 0) {
|
||||||
selectedCheckbox &&
|
if (
|
||||||
selectedCheckbox?.length <= maxCountInt - 1
|
selectedCheckbox &&
|
||||||
) {
|
selectedCheckbox?.length <= maxCountInt - 1
|
||||||
handleCheckboxValue(e.target.checked, ind);
|
) {
|
||||||
}
|
|
||||||
} else {
|
|
||||||
handleCheckboxValue(e.target.checked, ind);
|
handleCheckboxValue(e.target.checked, ind);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
handleCheckboxValue(e.target.checked, ind);
|
handleCheckboxValue(e.target.checked, ind);
|
||||||
}
|
}
|
||||||
}}
|
} else {
|
||||||
/>
|
handleCheckboxValue(e.target.checked, ind);
|
||||||
{data}
|
}
|
||||||
</label>
|
}}
|
||||||
</div>
|
/>
|
||||||
);
|
{data}
|
||||||
})}
|
</label>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
case textInputWidget:
|
case textInputWidget:
|
||||||
@@ -1401,6 +1467,19 @@ function WidgetsValueModal(props) {
|
|||||||
className={textInputcls}
|
className={textInputcls}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
case cellsWidget:
|
||||||
|
return (
|
||||||
|
<CellsWidget
|
||||||
|
count={cellsValue.length}
|
||||||
|
height="100%"
|
||||||
|
value={cellsValue.join("")}
|
||||||
|
editable={true}
|
||||||
|
resizable={false}
|
||||||
|
onChange={handleCellsInput}
|
||||||
|
onKeyDown={handleCellsKeyDown}
|
||||||
|
inputRefs={cellRefs}
|
||||||
|
/>
|
||||||
|
);
|
||||||
case "dropdown":
|
case "dropdown":
|
||||||
return (
|
return (
|
||||||
<select
|
<select
|
||||||
@@ -1418,18 +1497,11 @@ function WidgetsValueModal(props) {
|
|||||||
>
|
>
|
||||||
{currWidgetsDetails?.options?.name}
|
{currWidgetsDetails?.options?.name}
|
||||||
</option>
|
</option>
|
||||||
|
{currWidgetsDetails?.options?.values?.map((data, ind) => (
|
||||||
{currWidgetsDetails?.options?.values?.map((data, ind) => {
|
<option key={ind} value={data}>
|
||||||
return (
|
{data}
|
||||||
<option
|
</option>
|
||||||
// style={{ fontSize: fontSize, color: fontColor }}
|
))}
|
||||||
key={ind}
|
|
||||||
value={data}
|
|
||||||
>
|
|
||||||
{data}
|
|
||||||
</option>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</select>
|
</select>
|
||||||
);
|
);
|
||||||
case "name":
|
case "name":
|
||||||
@@ -1529,30 +1601,38 @@ function WidgetsValueModal(props) {
|
|||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
case radioButtonWidget:
|
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 (
|
return (
|
||||||
<div className="border-[1px] border-gray-300 rounded-[2px] pt-1 px-2.5">
|
<div
|
||||||
{currWidgetsDetails?.options?.values.map((data, ind) => {
|
className={`border-[1px] border-gray-300 rounded-[2px] pt-1 px-2.5 ${radioWrapperClass}`}
|
||||||
return (
|
>
|
||||||
<div key={ind} className="select-none-cls">
|
{currWidgetsDetails?.options?.values.map((data, ind) => (
|
||||||
<label
|
<div key={ind} className="select-none-cls">
|
||||||
htmlFor={`radio-${currWidgetsDetails?.key + ind}`}
|
<label
|
||||||
className="cursor-pointer flex items-center text-sm gap-1"
|
htmlFor={`radio-${currWidgetsDetails?.key + ind}`}
|
||||||
>
|
className="cursor-pointer flex items-center text-sm gap-1"
|
||||||
<input
|
>
|
||||||
id={`radio-${currWidgetsDetails?.key + ind}`}
|
<input
|
||||||
className={`op-radio op-radio-xs mt-1`}
|
id={`radio-${currWidgetsDetails?.key + ind}`}
|
||||||
type="radio"
|
className={`op-radio op-radio-xs mt-1`}
|
||||||
value={data}
|
type="radio"
|
||||||
checked={handleRadioCheck(data)}
|
value={data}
|
||||||
onChange={(e) => {
|
checked={handleRadioCheck(data)}
|
||||||
handleCheckRadio(e.target.value);
|
onChange={(e) => {
|
||||||
}}
|
handleCheckRadio(e.target.value);
|
||||||
/>
|
}}
|
||||||
<span>{data}</span>
|
/>
|
||||||
</label>
|
<span>{data}</span>
|
||||||
</div>
|
</label>
|
||||||
);
|
</div>
|
||||||
})}
|
))}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
case textWidget:
|
case textWidget:
|
||||||
@@ -1590,15 +1670,9 @@ function WidgetsValueModal(props) {
|
|||||||
const minCount =
|
const minCount =
|
||||||
currWidgetsDetails?.options?.validation?.minRequiredCount;
|
currWidgetsDetails?.options?.validation?.minRequiredCount;
|
||||||
const parseMin = minCount && parseInt(minCount);
|
const parseMin = minCount && parseInt(minCount);
|
||||||
//get maximum required count if exist
|
if (parseMin > 0) {
|
||||||
const maxCount =
|
|
||||||
currWidgetsDetails?.options?.validation?.maxRequiredCount;
|
|
||||||
const parseMax = maxCount && parseInt(maxCount);
|
|
||||||
if (parseMin > 0 && parseMax > 0) {
|
|
||||||
isRequired = true;
|
isRequired = true;
|
||||||
}
|
}
|
||||||
} else if (isRadio) {
|
|
||||||
isRequired = true;
|
|
||||||
} else {
|
} else {
|
||||||
isRequired = currWidgetsDetails.options?.status === "required";
|
isRequired = currWidgetsDetails.options?.status === "required";
|
||||||
}
|
}
|
||||||
@@ -1799,11 +1873,60 @@ function WidgetsValueModal(props) {
|
|||||||
setUniqueId(tempSignerId);
|
setUniqueId(tempSignerId);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
//function is used to excecute on click finish button functionality
|
||||||
const handleFinish = () => {
|
const handleFinish = () => {
|
||||||
props?.finishDocument();
|
props?.finishDocument();
|
||||||
dispatch(setIsShowModal({}));
|
dispatch(setIsShowModal({}));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!isSave) {
|
||||||
|
handleFinishButton();
|
||||||
|
}
|
||||||
|
}, [isSave]);
|
||||||
|
//'handleFinishButton' function is used to show finish button click on any widge if all required widgtes 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 (
|
return (
|
||||||
<>
|
<>
|
||||||
<ModalUi
|
<ModalUi
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ export const isTabAndMobile = window.innerWidth < 1023;
|
|||||||
export const textInputWidget = "text input";
|
export const textInputWidget = "text input";
|
||||||
export const textWidget = "text";
|
export const textWidget = "text";
|
||||||
export const radioButtonWidget = "radio button";
|
export const radioButtonWidget = "radio button";
|
||||||
|
export const cellsWidget = "cells";
|
||||||
export function getEnv() {
|
export function getEnv() {
|
||||||
return window?.RUNTIME_ENV || {};
|
return window?.RUNTIME_ENV || {};
|
||||||
}
|
}
|
||||||
@@ -257,6 +258,7 @@ export const widgets = [
|
|||||||
{ type: "date", icon: "fa-light fa-calendar-days", iconSize: "20px" },
|
{ type: "date", icon: "fa-light fa-calendar-days", iconSize: "20px" },
|
||||||
{ type: textWidget, icon: "fa-light fa-text-width", iconSize: "20px" },
|
{ type: textWidget, icon: "fa-light fa-text-width", iconSize: "20px" },
|
||||||
{ type: textInputWidget, icon: "fa-light fa-font", iconSize: "21px" },
|
{ type: textInputWidget, icon: "fa-light fa-font", iconSize: "21px" },
|
||||||
|
{ type: cellsWidget, icon: "fa-light fa-table-cells", iconSize: "20px" },
|
||||||
{ type: "checkbox", icon: "fa-light fa-square-check", iconSize: "22px" },
|
{ type: "checkbox", icon: "fa-light fa-square-check", iconSize: "22px" },
|
||||||
{
|
{
|
||||||
type: "dropdown",
|
type: "dropdown",
|
||||||
@@ -349,6 +351,15 @@ export const addWidgetOptions = (type, signer, widgetValue) => {
|
|||||||
};
|
};
|
||||||
case textInputWidget:
|
case textInputWidget:
|
||||||
return { ...status, name: "Text", isReadOnly: false };
|
return { ...status, name: "Text", isReadOnly: false };
|
||||||
|
case cellsWidget:
|
||||||
|
return {
|
||||||
|
...status,
|
||||||
|
name: "Cells",
|
||||||
|
cellCount: 5,
|
||||||
|
defaultValue: "",
|
||||||
|
validation: { type: "", pattern: "" },
|
||||||
|
isReadOnly: false
|
||||||
|
};
|
||||||
case "initials":
|
case "initials":
|
||||||
return { ...status, name: "Initials" };
|
return { ...status, name: "Initials" };
|
||||||
case "name":
|
case "name":
|
||||||
@@ -416,6 +427,14 @@ export const addWidgetSelfsignOptions = (type, getWidgetValue, owner) => {
|
|||||||
return { name: "Checkbox" };
|
return { name: "Checkbox" };
|
||||||
case textWidget:
|
case textWidget:
|
||||||
return { name: "Text" };
|
return { name: "Text" };
|
||||||
|
case cellsWidget:
|
||||||
|
return {
|
||||||
|
name: "Cells",
|
||||||
|
cellCount: 5,
|
||||||
|
defaultValue: "",
|
||||||
|
validation: { type: "", pattern: "" },
|
||||||
|
isReadOnly: false
|
||||||
|
};
|
||||||
case "initials":
|
case "initials":
|
||||||
return { name: "Initials" };
|
return { name: "Initials" };
|
||||||
case "name":
|
case "name":
|
||||||
@@ -486,6 +505,8 @@ export const defaultWidthHeight = (type) => {
|
|||||||
return { width: 15, height: 19 };
|
return { width: 15, height: 19 };
|
||||||
case textInputWidget:
|
case textInputWidget:
|
||||||
return { width: 150, height: 19 };
|
return { width: 150, height: 19 };
|
||||||
|
case cellsWidget:
|
||||||
|
return { width: 112, height: 22 };
|
||||||
case "dropdown":
|
case "dropdown":
|
||||||
return { width: 120, height: 22 };
|
return { width: 120, height: 22 };
|
||||||
case "initials":
|
case "initials":
|
||||||
@@ -685,7 +706,7 @@ export const signPdfFun = async (
|
|||||||
export const randomId = () => {
|
export const randomId = () => {
|
||||||
// 1. Grab a cryptographically-secure 32-bit random value
|
// 1. Grab a cryptographically-secure 32-bit random value
|
||||||
const randomBytes = crypto.getRandomValues(new Uint32Array(1));
|
const randomBytes = crypto.getRandomValues(new Uint32Array(1));
|
||||||
const raw = randomBytes[0]; // 0 … 4 294 967 295
|
const raw = randomBytes[0]; // 0 … 4 294 967 295
|
||||||
|
|
||||||
// 2. Collapse into a 90 000 000-wide band (0…89 999 999), then shift to 10 000 000…99 999 999
|
// 2. Collapse into a 90 000 000-wide band (0…89 999 999), then shift to 10 000 000…99 999 999
|
||||||
const eightDigit = 10_000_000 + (raw % 90_000_000);
|
const eightDigit = 10_000_000 + (raw % 90_000_000);
|
||||||
@@ -863,7 +884,8 @@ export const onChangeInput = (
|
|||||||
initial,
|
initial,
|
||||||
dateFormat,
|
dateFormat,
|
||||||
fontSize,
|
fontSize,
|
||||||
fontColor
|
fontColor,
|
||||||
|
isDateReadOnly
|
||||||
) => {
|
) => {
|
||||||
const isSigners = xyPosition.some((data) => data.signerPtr);
|
const isSigners = xyPosition.some((data) => data.signerPtr);
|
||||||
let filterSignerPos;
|
let filterSignerPos;
|
||||||
@@ -892,6 +914,7 @@ export const onChangeInput = (
|
|||||||
response: value,
|
response: value,
|
||||||
fontSize: fontSize,
|
fontSize: fontSize,
|
||||||
fontColor: fontColor,
|
fontColor: fontColor,
|
||||||
|
isReadOnly: isDateReadOnly || false,
|
||||||
validation: {
|
validation: {
|
||||||
type: "date-format",
|
type: "date-format",
|
||||||
format: dateFormat // This indicates the required date format explicitly.
|
format: dateFormat // This indicates the required date format explicitly.
|
||||||
@@ -969,7 +992,6 @@ export const onChangeInput = (
|
|||||||
setXyPosition(updatePlaceholder);
|
setXyPosition(updatePlaceholder);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
//function to increase height of text area on press enter
|
//function to increase height of text area on press enter
|
||||||
export const onChangeHeightOfTextArea = (
|
export const onChangeHeightOfTextArea = (
|
||||||
height,
|
height,
|
||||||
@@ -1213,8 +1235,8 @@ export function onSaveSign(
|
|||||||
}
|
}
|
||||||
return obj;
|
return obj;
|
||||||
});
|
});
|
||||||
//condition when user click on apply(signature,image,typed signature or defaullt signature) all widgets on signature pad for same widgets
|
//condition when draw/upload signature/initials then apply it all related to widgets (signature,image,typed signature or default signature)
|
||||||
if (isAutoSign) {
|
if (isApplyAll || isAutoSign) {
|
||||||
const updatedArray = updateXYposition.map((page) => ({
|
const updatedArray = updateXYposition.map((page) => ({
|
||||||
...page,
|
...page,
|
||||||
pos: page.pos.map(
|
pos: page.pos.map(
|
||||||
@@ -1233,26 +1255,6 @@ export function onSaveSign(
|
|||||||
)
|
)
|
||||||
}));
|
}));
|
||||||
return updatedArray;
|
return updatedArray;
|
||||||
} //condition when user edit signature/initial then updated signature apply all existing drawn signatures
|
|
||||||
else if (isApplyAll) {
|
|
||||||
const updatedArray = updateXYposition.map((page) => ({
|
|
||||||
...page,
|
|
||||||
pos: page.pos.map(
|
|
||||||
(item) =>
|
|
||||||
item.SignUrl && item.type === widgetsType
|
|
||||||
? {
|
|
||||||
...item,
|
|
||||||
Width: posWidth,
|
|
||||||
Height: posHeight,
|
|
||||||
SignUrl: signatureImg,
|
|
||||||
...(type && { signatureType: type }),
|
|
||||||
options: { ...item.options, response: signatureImg },
|
|
||||||
...(typedSignature && { typeSignature: typedSignature })
|
|
||||||
}
|
|
||||||
: item // Otherwise, keep it unchanged
|
|
||||||
)
|
|
||||||
}));
|
|
||||||
return updatedArray;
|
|
||||||
} else {
|
} else {
|
||||||
return updateXYposition;
|
return updateXYposition;
|
||||||
}
|
}
|
||||||
@@ -1361,35 +1363,13 @@ export function onSaveImage(
|
|||||||
}
|
}
|
||||||
return obj;
|
return obj;
|
||||||
});
|
});
|
||||||
//condition when user click on apply(stamp) all widgets on signature pad for same widgets
|
//condition when user upload(stamp) then apply it all related to widgets
|
||||||
if (isAutoSign) {
|
if (isApplyAll || isAutoSign) {
|
||||||
const updatedArray = updateXYposition.map((page) => ({
|
const updatedArray = updateXYposition.map((page) => ({
|
||||||
...page,
|
...page,
|
||||||
pos: page.pos.map(
|
pos: page.pos.map(
|
||||||
(item) =>
|
(item) =>
|
||||||
item.type === widgetsType
|
item.type === widgetsType && item.type !== "image"
|
||||||
? {
|
|
||||||
...item,
|
|
||||||
Width: getIMGWH.newWidth,
|
|
||||||
Height: getIMGWH.newHeight,
|
|
||||||
SignUrl: image.src,
|
|
||||||
ImageType: image.imgType,
|
|
||||||
options: {
|
|
||||||
...item.options,
|
|
||||||
response: image.src
|
|
||||||
}
|
|
||||||
}
|
|
||||||
: item // Otherwise, keep it unchanged
|
|
||||||
)
|
|
||||||
}));
|
|
||||||
return updatedArray;
|
|
||||||
} //condition when user edit stamp then updated signature apply all existing drawn signatures
|
|
||||||
else if (isApplyAll) {
|
|
||||||
const updatedArray = updateXYposition.map((page) => ({
|
|
||||||
...page,
|
|
||||||
pos: page.pos.map(
|
|
||||||
(item) =>
|
|
||||||
item.SignUrl && item.type === widgetsType && item.type !== "image"
|
|
||||||
? {
|
? {
|
||||||
...item,
|
...item,
|
||||||
Width: getIMGWH.newWidth,
|
Width: getIMGWH.newWidth,
|
||||||
@@ -1655,6 +1635,7 @@ export const multiSignEmbed = async (
|
|||||||
const WidgetsTypeTextExist = [
|
const WidgetsTypeTextExist = [
|
||||||
textWidget,
|
textWidget,
|
||||||
textInputWidget,
|
textInputWidget,
|
||||||
|
cellsWidget,
|
||||||
"name",
|
"name",
|
||||||
"company",
|
"company",
|
||||||
"job title",
|
"job title",
|
||||||
@@ -1668,9 +1649,10 @@ export const multiSignEmbed = async (
|
|||||||
const color = position?.options?.fontColor;
|
const color = position?.options?.fontColor;
|
||||||
const updateColorInRgb = getWidgetsFontColor(color);
|
const updateColorInRgb = getWidgetsFontColor(color);
|
||||||
const fontSize = parseInt(position?.options?.fontSize || 12);
|
const fontSize = parseInt(position?.options?.fontSize || 12);
|
||||||
const widgetTypeExist = [
|
const isTextTypeWidget = [
|
||||||
textWidget,
|
textWidget,
|
||||||
textInputWidget,
|
textInputWidget,
|
||||||
|
cellsWidget,
|
||||||
"name",
|
"name",
|
||||||
"company",
|
"company",
|
||||||
"job title",
|
"job title",
|
||||||
@@ -1678,36 +1660,48 @@ export const multiSignEmbed = async (
|
|||||||
"email"
|
"email"
|
||||||
].includes(position.type);
|
].includes(position.type);
|
||||||
if (position.type === "checkbox") {
|
if (position.type === "checkbox") {
|
||||||
let checkboxGapFromTop, isCheck;
|
// Determine layout mode: 'vertical' (default) or 'horizontal'
|
||||||
let y = yPos(position) + 2;
|
// const isHorizontal = position.layout === "horizontal";
|
||||||
//calculate checkbox size to draw on pdf
|
const isHorizontal =
|
||||||
const checkboxSize = fontSize - 1;
|
position?.options?.layout === "horizontal" ? true : false;
|
||||||
//calculate gap between checkbox and options
|
// Initial “cursor” positions
|
||||||
const checkboxTextGapFromLeft = fontSize + 5;
|
let currentX = xPos(position);
|
||||||
|
let currentY = yPos(position) + 2;
|
||||||
|
// Size and spacing settings
|
||||||
|
const checkboxSize = fontSize - 1; // checkbox diameter
|
||||||
|
const checkboxTextGapFromLeft = fontSize + 5; // gap between box and its label
|
||||||
|
const verticalGap = fontSize + 3.2; // gap between two rows (vertical layout)
|
||||||
|
let horizontalGap = 0; // will compute after drawing each label
|
||||||
if (position?.options?.values.length > 0) {
|
if (position?.options?.values.length > 0) {
|
||||||
position?.options?.values.forEach((item, ind) => {
|
position.options.values.forEach((item, ind) => {
|
||||||
const checkboxRandomId = "checkbox" + randomId();
|
// 1. Advance the “cursor” on second+ iteration
|
||||||
if (
|
|
||||||
position?.options?.response &&
|
|
||||||
position?.options?.response?.length > 0
|
|
||||||
) {
|
|
||||||
isCheck = position?.options?.response?.includes(ind);
|
|
||||||
} else if (position?.options?.defaultValue) {
|
|
||||||
isCheck = position?.options?.defaultValue?.includes(ind);
|
|
||||||
}
|
|
||||||
const checkbox = form.createCheckBox(checkboxRandomId);
|
|
||||||
if (ind > 0) {
|
if (ind > 0) {
|
||||||
y = y + checkboxGapFromTop;
|
if (isHorizontal) {
|
||||||
} else {
|
currentX += horizontalGap;
|
||||||
checkboxGapFromTop = fontSize + 3.2;
|
} else {
|
||||||
|
currentY += verticalGap;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 2. Determine whether this checkbox should be checked
|
||||||
|
let isCheck = false;
|
||||||
|
if (
|
||||||
|
position.options.response &&
|
||||||
|
position.options.response.length > 0
|
||||||
|
) {
|
||||||
|
isCheck = position.options.response.includes(ind);
|
||||||
|
} else if (position.options.defaultValue) {
|
||||||
|
isCheck = position.options.defaultValue.includes(ind);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!position?.options?.isHideLabel) {
|
// 3. Draw the label (if labels are not hidden)
|
||||||
// below line of code is used to embed label with radio button in pdf
|
if (!position.options.isHideLabel) {
|
||||||
|
const labelX = currentX + checkboxTextGapFromLeft;
|
||||||
|
const labelY = currentY - 3;
|
||||||
|
|
||||||
const optionsPosition = compensateRotation(
|
const optionsPosition = compensateRotation(
|
||||||
page.getRotation().angle,
|
page.getRotation().angle,
|
||||||
xPos(position) + checkboxTextGapFromLeft,
|
labelX,
|
||||||
y - 3,
|
labelY,
|
||||||
1,
|
1,
|
||||||
getSize,
|
getSize,
|
||||||
fontSize,
|
fontSize,
|
||||||
@@ -1717,98 +1711,134 @@ export const multiSignEmbed = async (
|
|||||||
);
|
);
|
||||||
page.drawText(item, optionsPosition);
|
page.drawText(item, optionsPosition);
|
||||||
}
|
}
|
||||||
|
// 4. Create and place the actual checkbox
|
||||||
|
const checkboxRandomId = "checkbox" + randomId();
|
||||||
|
const checkbox = form.createCheckBox(checkboxRandomId);
|
||||||
let checkboxObj = {
|
let checkboxObj = {
|
||||||
x: xPos(position),
|
x: currentX,
|
||||||
y: y,
|
y: currentY,
|
||||||
width: checkboxSize,
|
width: checkboxSize,
|
||||||
height: checkboxSize
|
height: checkboxSize
|
||||||
};
|
};
|
||||||
checkboxObj = getWidgetPosition(page, checkboxObj, 1, getSize);
|
checkboxObj = getWidgetPosition(page, checkboxObj, 1, getSize);
|
||||||
checkbox.addToPage(page, checkboxObj);
|
checkbox.addToPage(page, checkboxObj);
|
||||||
|
// 5. Check or uncheck as needed, then make read‐only
|
||||||
//applied which checkbox should be checked
|
|
||||||
if (isCheck) {
|
if (isCheck) {
|
||||||
checkbox.check();
|
checkbox.check();
|
||||||
} else {
|
} else {
|
||||||
checkbox.uncheck();
|
checkbox.uncheck();
|
||||||
}
|
}
|
||||||
checkbox.enableReadOnly();
|
checkbox.enableReadOnly();
|
||||||
|
// 6. If horizontal layout, compute how far to shift next checkbox‐circle
|
||||||
|
if (isHorizontal) {
|
||||||
|
// Measure the width of this label text at `fontSize`
|
||||||
|
const textWidth = font.widthOfTextAtSize(item, fontSize);
|
||||||
|
// Next checkbox should come after: [box] + gap + [label text] + extra 10pt padding
|
||||||
|
horizontalGap =
|
||||||
|
checkboxSize + checkboxTextGapFromLeft + textWidth;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} else if (widgetTypeExist) {
|
} else if (isTextTypeWidget) {
|
||||||
let textContent;
|
let textContent = "";
|
||||||
if (position?.options?.response) {
|
if (position?.options?.response) {
|
||||||
textContent = position.options?.response;
|
textContent = position.options?.response;
|
||||||
} else if (position?.options?.defaultValue) {
|
} else if (position?.options?.defaultValue) {
|
||||||
textContent = position?.options?.defaultValue;
|
textContent = position?.options?.defaultValue;
|
||||||
}
|
}
|
||||||
const fixedWidth = widgetWidth; // Set your fixed width
|
if (position.type === cellsWidget) {
|
||||||
const isNewOnEnterLineExist = textContent.includes("\n");
|
const cellCount =
|
||||||
|
position?.options?.cellCount || textContent.length || 1;
|
||||||
// Function to break text into lines based on the fixed width
|
const charWidth = widgetWidth / cellCount;
|
||||||
const NewbreakTextIntoLines = (textContent, width) => {
|
const y = yPos(position) - 4;
|
||||||
const lines = [];
|
for (let i = 0; i < cellCount; i++) {
|
||||||
let currentLine = "";
|
const ch = textContent[i] || "";
|
||||||
|
const charX =
|
||||||
for (const word of textContent.split(" ")) {
|
xPos(position) +
|
||||||
//get text line width
|
charWidth * i +
|
||||||
const lineWidth = font.widthOfTextAtSize(
|
(charWidth - font.widthOfTextAtSize(ch, fontSize)) / 2;
|
||||||
`${currentLine} ${word}`,
|
const textPosition = compensateRotation(
|
||||||
fontSize
|
page.getRotation().angle,
|
||||||
|
charX,
|
||||||
|
y,
|
||||||
|
1,
|
||||||
|
getSize,
|
||||||
|
fontSize,
|
||||||
|
updateColorInRgb,
|
||||||
|
font,
|
||||||
|
page
|
||||||
);
|
);
|
||||||
//check text content line width is less or equal to container width
|
if (ch) page.drawText(ch, textPosition);
|
||||||
if (lineWidth <= width) {
|
|
||||||
currentLine += ` ${word}`;
|
|
||||||
} else {
|
|
||||||
lines.push(currentLine.trim());
|
|
||||||
currentLine = `${word}`;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
lines.push(currentLine.trim());
|
|
||||||
return lines;
|
|
||||||
};
|
|
||||||
// Function to break text into lines based on when user go next line on press enter button
|
|
||||||
const breakTextIntoLines = (textContent, width) => {
|
|
||||||
const lines = [];
|
|
||||||
for (const word of textContent.split("\n")) {
|
|
||||||
const lineWidth = font.widthOfTextAtSize(`${word}`, fontSize);
|
|
||||||
//checking string length to container width
|
|
||||||
//if string length is less then container width it means user press enter button
|
|
||||||
if (lineWidth <= width) {
|
|
||||||
lines.push(word);
|
|
||||||
}
|
|
||||||
//else adjust text content according to width and send it in new line
|
|
||||||
else {
|
|
||||||
const newLine = NewbreakTextIntoLines(word, width);
|
|
||||||
lines.push(...newLine);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
const fixedWidth = widgetWidth; // Set your fixed width
|
||||||
|
const isNewOnEnterLineExist = textContent.includes("\n");
|
||||||
|
|
||||||
return lines;
|
// Function to break text into lines based on the fixed width
|
||||||
};
|
const NewbreakTextIntoLines = (textContent, width) => {
|
||||||
//check if text content have `\n` string it means user press enter to go next line and handle condition
|
const lines = [];
|
||||||
//else auto adjust text content according to container width
|
let currentLine = "";
|
||||||
const lines = isNewOnEnterLineExist
|
|
||||||
? breakTextIntoLines(textContent, fixedWidth)
|
for (const word of textContent.split(" ")) {
|
||||||
: NewbreakTextIntoLines(textContent, fixedWidth);
|
//get text line width
|
||||||
// Set initial y-coordinate for the first line
|
const lineWidth = font.widthOfTextAtSize(
|
||||||
let x = xPos(position);
|
`${currentLine} ${word}`,
|
||||||
let y = yPos(position) - 4;
|
fontSize
|
||||||
// Embed each line on the page
|
);
|
||||||
for (const line of lines) {
|
//check text content line width is less or equal to container width
|
||||||
const textPosition = compensateRotation(
|
if (lineWidth <= width) {
|
||||||
page.getRotation().angle,
|
currentLine += ` ${word}`;
|
||||||
x,
|
} else {
|
||||||
y,
|
lines.push(currentLine.trim());
|
||||||
1,
|
currentLine = `${word}`;
|
||||||
getSize,
|
}
|
||||||
fontSize,
|
}
|
||||||
updateColorInRgb,
|
lines.push(currentLine.trim());
|
||||||
font,
|
return lines;
|
||||||
page
|
};
|
||||||
);
|
// Function to break text into lines based on when user go next line on press enter button
|
||||||
page.drawText(line, textPosition);
|
const breakTextIntoLines = (textContent, width) => {
|
||||||
y += 18; // Adjust the line height as needed
|
const lines = [];
|
||||||
|
for (const word of textContent.split("\n")) {
|
||||||
|
const lineWidth = font.widthOfTextAtSize(`${word}`, fontSize);
|
||||||
|
//checking string length to container width
|
||||||
|
//if string length is less then container width it means user press enter button
|
||||||
|
if (lineWidth <= width) {
|
||||||
|
lines.push(word);
|
||||||
|
}
|
||||||
|
//else adjust text content according to width and send it in new line
|
||||||
|
else {
|
||||||
|
const newLine = NewbreakTextIntoLines(word, width);
|
||||||
|
lines.push(...newLine);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return lines;
|
||||||
|
};
|
||||||
|
//check if text content have `\n` string it means user press enter to go next line and handle condition
|
||||||
|
//else auto adjust text content according to container width
|
||||||
|
const lines = isNewOnEnterLineExist
|
||||||
|
? breakTextIntoLines(textContent, fixedWidth)
|
||||||
|
: NewbreakTextIntoLines(textContent, fixedWidth);
|
||||||
|
// Set initial y-coordinate for the first line
|
||||||
|
let x = xPos(position);
|
||||||
|
let y = yPos(position) - 4;
|
||||||
|
// Embed each line on the page
|
||||||
|
for (const line of lines) {
|
||||||
|
const textPosition = compensateRotation(
|
||||||
|
page.getRotation().angle,
|
||||||
|
x,
|
||||||
|
y,
|
||||||
|
1,
|
||||||
|
getSize,
|
||||||
|
fontSize,
|
||||||
|
updateColorInRgb,
|
||||||
|
font,
|
||||||
|
page
|
||||||
|
);
|
||||||
|
page.drawText(line, textPosition);
|
||||||
|
y += 18; // Adjust the line height as needed
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else if (position.type === "dropdown") {
|
} else if (position.type === "dropdown") {
|
||||||
const dropdownRandomId = "dropdown" + randomId();
|
const dropdownRandomId = "dropdown" + randomId();
|
||||||
@@ -1848,33 +1878,47 @@ export const multiSignEmbed = async (
|
|||||||
} else if (position.type === radioButtonWidget) {
|
} else if (position.type === radioButtonWidget) {
|
||||||
const radioRandomId = "radio" + randomId();
|
const radioRandomId = "radio" + randomId();
|
||||||
const radioGroup = form.createRadioGroup(radioRandomId);
|
const radioGroup = form.createRadioGroup(radioRandomId);
|
||||||
//draw radio button on document and options if hide label is enable
|
|
||||||
let radioButtonFromTop;
|
|
||||||
//getting radio buttons options text font size
|
//getting radio buttons options text font size
|
||||||
const optionsFontSize = fontSize;
|
const optionsFontSize = fontSize; // font size for option text
|
||||||
//calculate value of gap between radio button and options
|
const radioTextGapFromLeft = fontSize + 6; // gap between circle and its label
|
||||||
const radioTextGapFromLeft = fontSize + 6;
|
const radioSize = fontSize; // circle diameter (square of width×height)
|
||||||
//getting radio button font size
|
// Initial “cursor” positions (from your existing helpers)
|
||||||
const radioSize = fontSize;
|
let currentX = xPos(position) + 2;
|
||||||
//getting position of radio widget in y direction
|
let currentY = yPos(position);
|
||||||
let y = yPos(position);
|
// Vertical gap between two radio‐rows
|
||||||
//on the basic of option's length create radio button and message
|
const verticalGap = fontSize + 6;
|
||||||
|
// We’ll compute horizontalGap on the fly—after drawing each label
|
||||||
|
// Initialize to zero (will be set after first option is placed)
|
||||||
|
let horizontalGap = 0;
|
||||||
|
// Determine layout mode: 'vertical' or 'horizontal'.
|
||||||
|
// (You mentioned “add one variable called layout” – here we read it from position.layout.)
|
||||||
|
const isHorizontal =
|
||||||
|
position?.options?.layout === "horizontal" ? true : false;
|
||||||
|
// Loop through each option in the group
|
||||||
if (position?.options?.values.length > 0) {
|
if (position?.options?.values.length > 0) {
|
||||||
position?.options?.values.forEach((item, ind) => {
|
position.options.values.forEach((item, ind) => {
|
||||||
|
// 1. Advance cursor on second+ iteration
|
||||||
if (ind > 0) {
|
if (ind > 0) {
|
||||||
y = y + radioButtonFromTop;
|
if (isHorizontal) {
|
||||||
} else {
|
// Move to the right by horizontalGap
|
||||||
radioButtonFromTop = fontSize + 6;
|
currentX += horizontalGap;
|
||||||
|
} else {
|
||||||
|
// Move down by verticalGap (vertical stacking)
|
||||||
|
currentY += verticalGap;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
// 2. Draw the label text (if not hidden)
|
||||||
if (!position?.options?.isHideLabel) {
|
if (!position?.options?.isHideLabel) {
|
||||||
// below line of code is used to embed label with radio button in pdf
|
// Compute where to draw the text (just to the right of the circle)
|
||||||
|
const labelX = currentX + radioTextGapFromLeft;
|
||||||
|
const labelY = currentY - 2;
|
||||||
const optionsPosition = compensateRotation(
|
const optionsPosition = compensateRotation(
|
||||||
page.getRotation().angle,
|
page.getRotation().angle,
|
||||||
xPos(position) + radioTextGapFromLeft,
|
labelX,
|
||||||
y - 2,
|
labelY,
|
||||||
1,
|
1,
|
||||||
getSize,
|
getSize,
|
||||||
fontSize,
|
optionsFontSize,
|
||||||
updateColorInRgb,
|
updateColorInRgb,
|
||||||
font,
|
font,
|
||||||
page
|
page
|
||||||
@@ -1882,22 +1926,33 @@ export const multiSignEmbed = async (
|
|||||||
|
|
||||||
page.drawText(item, optionsPosition);
|
page.drawText(item, optionsPosition);
|
||||||
}
|
}
|
||||||
|
// 3. Place the radio‐circle itself at (currentX, currentY)
|
||||||
let radioObj = {
|
let radioObj = {
|
||||||
x: xPos(position) + 2,
|
x: currentX,
|
||||||
y: y,
|
y: currentY,
|
||||||
width: radioSize,
|
width: radioSize,
|
||||||
height: radioSize
|
height: radioSize
|
||||||
};
|
};
|
||||||
|
|
||||||
radioObj = getWidgetPosition(page, radioObj, 1, getSize);
|
radioObj = getWidgetPosition(page, radioObj, 1, getSize);
|
||||||
radioGroup.addOptionToPage(item, page, radioObj);
|
radioGroup.addOptionToPage(item, page, radioObj);
|
||||||
|
// 4. If horizontal layout, re-compute horizontalGap for next iteration:
|
||||||
|
if (isHorizontal) {
|
||||||
|
// Measure how wide the label text is, so we know how far to shift next circle
|
||||||
|
const textWidth = font.widthOfTextAtSize(item, optionsFontSize);
|
||||||
|
// radioSize = the circle. radioTextGapFromLeft = gap between circle and label.
|
||||||
|
// Add a small extra padding (e.g. 10pt) before placing next circle.
|
||||||
|
horizontalGap = radioSize + radioTextGapFromLeft + textWidth;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
// 5. Pre‐select a value if provided
|
||||||
if (position?.options?.response) {
|
if (position?.options?.response) {
|
||||||
radioGroup.select(position.options?.response);
|
radioGroup.select(position.options?.response);
|
||||||
} else if (position?.options?.defaultValue) {
|
} else if (position?.options?.defaultValue) {
|
||||||
radioGroup.select(position?.options?.defaultValue);
|
radioGroup.select(position?.options?.defaultValue);
|
||||||
}
|
}
|
||||||
|
// 6. Set to read‐only (if required)
|
||||||
radioGroup.enableReadOnly();
|
radioGroup.enableReadOnly();
|
||||||
} else {
|
} else {
|
||||||
const signature = {
|
const signature = {
|
||||||
@@ -3180,6 +3235,9 @@ export const checkRegularExpress = (validateType, setValidatePlaceholder) => {
|
|||||||
case "text":
|
case "text":
|
||||||
setValidatePlaceholder("please enter text");
|
setValidatePlaceholder("please enter text");
|
||||||
break;
|
break;
|
||||||
|
case "ssn":
|
||||||
|
setValidatePlaceholder("123-45-6789");
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
setValidatePlaceholder("please enter value");
|
setValidatePlaceholder("please enter value");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -186,6 +186,14 @@ export default function reportJson(id) {
|
|||||||
btnIcon: "fa-light fa-envelope",
|
btnIcon: "fa-light fa-envelope",
|
||||||
redirectUrl: "",
|
redirectUrl: "",
|
||||||
action: "saveastemplate"
|
action: "saveastemplate"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
btnId: "8440",
|
||||||
|
btnLabel: "Fix & resend",
|
||||||
|
hoverLabel: "Fix & resend",
|
||||||
|
btnIcon: "fa-light fa-paper-plane",
|
||||||
|
redirectUrl: "",
|
||||||
|
action: "recreatedocument"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ import {
|
|||||||
mailTemplate,
|
mailTemplate,
|
||||||
updateDateWidgetsRes,
|
updateDateWidgetsRes,
|
||||||
widgetDataValue,
|
widgetDataValue,
|
||||||
getOriginalWH
|
getOriginalWH,
|
||||||
} from "../constant/Utils";
|
} from "../constant/Utils";
|
||||||
import Header from "../components/pdf/PdfHeader";
|
import Header from "../components/pdf/PdfHeader";
|
||||||
import RenderPdf from "../components/pdf/RenderPdf";
|
import RenderPdf from "../components/pdf/RenderPdf";
|
||||||
@@ -159,6 +159,9 @@ function PdfRequestFiles(
|
|||||||
const [assignedWidgetId, setAssignedWidgetId] = useState([]);
|
const [assignedWidgetId, setAssignedWidgetId] = useState([]);
|
||||||
const [showSignPagenumber, setShowSignPagenumber] = useState([]);
|
const [showSignPagenumber, setShowSignPagenumber] = useState([]);
|
||||||
const [owner, setOwner] = useState({});
|
const [owner, setOwner] = useState({});
|
||||||
|
const [currentIndex, setCurrentIndex] = useState(0);
|
||||||
|
const [formData, setFormData] = useState([]);
|
||||||
|
const [vacantRole, setVacantRole] = useState();
|
||||||
const [, drop] = useDrop({
|
const [, drop] = useDrop({
|
||||||
accept: "BOX",
|
accept: "BOX",
|
||||||
drop: (item, monitor) => addPositionOfSignature(item, monitor),
|
drop: (item, monitor) => addPositionOfSignature(item, monitor),
|
||||||
@@ -624,6 +627,7 @@ function PdfRequestFiles(
|
|||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.log("err in get email verification ", err);
|
console.log("err in get email verification ", err);
|
||||||
setHandleError(t("something-went-wrong-mssg"));
|
setHandleError(t("something-went-wrong-mssg"));
|
||||||
|
setIsUiLoading(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//check if isEmailVerified then go on next step
|
//check if isEmailVerified then go on next step
|
||||||
@@ -634,7 +638,6 @@ function PdfRequestFiles(
|
|||||||
);
|
);
|
||||||
if (checkUser && checkUser.length > 0) {
|
if (checkUser && checkUser.length > 0) {
|
||||||
let checkboxExist,
|
let checkboxExist,
|
||||||
requiredRadio,
|
|
||||||
showAlert = false,
|
showAlert = false,
|
||||||
widgetKey,
|
widgetKey,
|
||||||
radioExist,
|
radioExist,
|
||||||
@@ -705,39 +708,12 @@ function PdfRequestFiles(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//condition to check radio widget exist or not
|
//else condition to check all type widget data fill or not except checkbox
|
||||||
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 {
|
else {
|
||||||
//get all required type widgets except checkbox and radio
|
//get all required type widgets except checkbox and radio
|
||||||
const requiredWidgets = checkUser[0].placeHolder[i].pos.filter(
|
const requiredWidgets = checkUser[0].placeHolder[i].pos.filter(
|
||||||
(position) =>
|
(position) =>
|
||||||
position.options?.status === "required" &&
|
position.options?.status === "required" &&
|
||||||
position.type !== radioButtonWidget &&
|
|
||||||
position.type !== "checkbox"
|
position.type !== "checkbox"
|
||||||
);
|
);
|
||||||
if (requiredWidgets && requiredWidgets?.length > 0) {
|
if (requiredWidgets && requiredWidgets?.length > 0) {
|
||||||
@@ -745,16 +721,13 @@ function PdfRequestFiles(
|
|||||||
for (let i = 0; i < requiredWidgets?.length; i++) {
|
for (let i = 0; i < requiredWidgets?.length; i++) {
|
||||||
checkSigned = requiredWidgets[i]?.options?.response;
|
checkSigned = requiredWidgets[i]?.options?.response;
|
||||||
if (!checkSigned) {
|
if (!checkSigned) {
|
||||||
const checkSignUrl = requiredWidgets[i]?.pos?.SignUrl;
|
let checkDefaultSigned =
|
||||||
if (!checkSignUrl) {
|
requiredWidgets[i]?.options?.defaultValue;
|
||||||
let checkDefaultSigned =
|
if (!checkDefaultSigned && !showAlert) {
|
||||||
requiredWidgets[i]?.options?.defaultValue;
|
showAlert = true;
|
||||||
if (!checkDefaultSigned && !showAlert) {
|
widgetKey = requiredWidgets[i].key;
|
||||||
showAlert = true;
|
TourPageNumber = updatePage;
|
||||||
widgetKey = requiredWidgets[i].key;
|
setminRequiredCount(null);
|
||||||
TourPageNumber = updatePage;
|
|
||||||
setminRequiredCount(null);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -766,20 +739,12 @@ function PdfRequestFiles(
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (checkboxExist && requiredCheckbox && showAlert) {
|
if (showAlert) {
|
||||||
setUnSignedWidgetId(widgetKey);
|
|
||||||
setPageNumber(TourPageNumber);
|
|
||||||
setWidgetsTour(true);
|
|
||||||
} else if (radioExist && showAlert) {
|
|
||||||
setUnSignedWidgetId(widgetKey);
|
|
||||||
setPageNumber(TourPageNumber);
|
|
||||||
setWidgetsTour(true);
|
|
||||||
} else if (showAlert) {
|
|
||||||
setUnSignedWidgetId(widgetKey);
|
setUnSignedWidgetId(widgetKey);
|
||||||
setPageNumber(TourPageNumber);
|
setPageNumber(TourPageNumber);
|
||||||
setWidgetsTour(true);
|
setWidgetsTour(true);
|
||||||
|
setIsUiLoading(false);
|
||||||
} else {
|
} else {
|
||||||
setIsUiLoading(true);
|
|
||||||
// `widgets` is Used to return widgets details with page number of current user
|
// `widgets` is Used to return widgets details with page number of current user
|
||||||
const widgets = checkUser?.[0]?.placeHolder;
|
const widgets = checkUser?.[0]?.placeHolder;
|
||||||
let pdfArrBuffer;
|
let pdfArrBuffer;
|
||||||
@@ -855,16 +820,19 @@ function PdfRequestFiles(
|
|||||||
isSuccessRoute,
|
isSuccessRoute,
|
||||||
contactId
|
contactId
|
||||||
);
|
);
|
||||||
const index = pdfDetails?.[0]?.Signers.findIndex(
|
const index =
|
||||||
(x) => x.objectId === signerObjectId
|
updatedDoc.updatedPdfDetails?.[0]?.Signers.findIndex(
|
||||||
);
|
(x) => x.objectId === contactId
|
||||||
|
);
|
||||||
const newIndex = index + 1;
|
const newIndex = index + 1;
|
||||||
const usermail = {
|
const usermail = {
|
||||||
Email: pdfDetails?.[0]?.Placeholders[newIndex]?.email || ""
|
Email:
|
||||||
|
updatedDoc.updatedPdfDetails?.[0]?.Placeholders[newIndex]
|
||||||
|
?.email || ""
|
||||||
};
|
};
|
||||||
const user = usermail?.Email
|
const user = usermail?.Email
|
||||||
? usermail
|
? usermail
|
||||||
: pdfDetails?.[0]?.Signers[newIndex];
|
: updatedDoc.updatedPdfDetails?.[0]?.Signers[newIndex];
|
||||||
if (
|
if (
|
||||||
sendmail !== "false" &&
|
sendmail !== "false" &&
|
||||||
sendInOrder
|
sendInOrder
|
||||||
@@ -1023,6 +991,7 @@ function PdfRequestFiles(
|
|||||||
isShow: true,
|
isShow: true,
|
||||||
alertMessage: t("something-went-wrong-mssg")
|
alertMessage: t("something-went-wrong-mssg")
|
||||||
});
|
});
|
||||||
|
setIsUiLoading(false);
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.log("err in embedsign", err);
|
console.log("err in embedsign", err);
|
||||||
@@ -1036,6 +1005,7 @@ function PdfRequestFiles(
|
|||||||
}
|
}
|
||||||
|
|
||||||
const handleSignPdf = async () => {
|
const handleSignPdf = async () => {
|
||||||
|
setIsUiLoading(true);
|
||||||
await embedWidgetsData();
|
await embedWidgetsData();
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1254,7 +1224,8 @@ function PdfRequestFiles(
|
|||||||
setRequestSignTour(true);
|
setRequestSignTour(true);
|
||||||
if (isDontShow) {
|
if (isDontShow) {
|
||||||
const isEnableOTP = pdfDetails?.[0]?.IsEnableOTP || false;
|
const isEnableOTP = pdfDetails?.[0]?.IsEnableOTP || false;
|
||||||
if (!isEnableOTP) {
|
const sessionToken = localStorage.getItem("accesstoken");
|
||||||
|
if (!isEnableOTP && !sessionToken) {
|
||||||
try {
|
try {
|
||||||
await axios.post(
|
await axios.post(
|
||||||
`${localStorage.getItem("baseUrl")}functions/updatecontacttour`,
|
`${localStorage.getItem("baseUrl")}functions/updatecontacttour`,
|
||||||
@@ -1651,12 +1622,6 @@ function PdfRequestFiles(
|
|||||||
);
|
);
|
||||||
setSignerPos(updatesignerPos);
|
setSignerPos(updatesignerPos);
|
||||||
}
|
}
|
||||||
|
|
||||||
// if (dragTypeValue === "dropdown") {
|
|
||||||
// setShowDropdown(true);
|
|
||||||
// } else if (dragTypeValue === "checkbox") {
|
|
||||||
// setIsCheckbox(true);
|
|
||||||
// } else
|
|
||||||
if (
|
if (
|
||||||
[textWidget, "name", "company", "job title", "email"].includes(
|
[textWidget, "name", "company", "job title", "email"].includes(
|
||||||
dragTypeValue
|
dragTypeValue
|
||||||
@@ -1756,7 +1721,6 @@ function PdfRequestFiles(
|
|||||||
setShowSignPagenumber(sortedPagenumber);
|
setShowSignPagenumber(sortedPagenumber);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DndProvider backend={HTML5Backend}>
|
<DndProvider backend={HTML5Backend}>
|
||||||
<Title
|
<Title
|
||||||
@@ -1828,6 +1792,7 @@ function PdfRequestFiles(
|
|||||||
{!requestSignTour &&
|
{!requestSignTour &&
|
||||||
isAgree &&
|
isAgree &&
|
||||||
signerObjectId &&
|
signerObjectId &&
|
||||||
|
!alreadySign &&
|
||||||
requestSignTourFunction()}
|
requestSignTourFunction()}
|
||||||
<Tour
|
<Tour
|
||||||
showNumber={false}
|
showNumber={false}
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ import {
|
|||||||
multiSignEmbed,
|
multiSignEmbed,
|
||||||
addWidgetOptions,
|
addWidgetOptions,
|
||||||
textInputWidget,
|
textInputWidget,
|
||||||
|
cellsWidget,
|
||||||
textWidget,
|
textWidget,
|
||||||
radioButtonWidget,
|
radioButtonWidget,
|
||||||
color,
|
color,
|
||||||
@@ -1417,7 +1418,8 @@ function PlaceHolderSign() {
|
|||||||
deleteOption,
|
deleteOption,
|
||||||
status,
|
status,
|
||||||
defaultValue,
|
defaultValue,
|
||||||
isHideLabel
|
isHideLabel,
|
||||||
|
layout
|
||||||
) => {
|
) => {
|
||||||
const filterSignerPos = signerPos.filter((data) => data.Id === uniqueId);
|
const filterSignerPos = signerPos.filter((data) => data.Id === uniqueId);
|
||||||
if (filterSignerPos.length > 0) {
|
if (filterSignerPos.length > 0) {
|
||||||
@@ -1453,6 +1455,7 @@ function PlaceHolderSign() {
|
|||||||
name: dropdownName,
|
name: dropdownName,
|
||||||
values: dropdownOptions,
|
values: dropdownOptions,
|
||||||
status: status,
|
status: status,
|
||||||
|
layout: layout,
|
||||||
isReadOnly: isReadOnly || false,
|
isReadOnly: isReadOnly || false,
|
||||||
isHideLabel: isHideLabel || false,
|
isHideLabel: isHideLabel || false,
|
||||||
defaultValue: defaultValue,
|
defaultValue: defaultValue,
|
||||||
@@ -1492,6 +1495,7 @@ function PlaceHolderSign() {
|
|||||||
maxRequiredCount: maxCount
|
maxRequiredCount: maxCount
|
||||||
},
|
},
|
||||||
defaultValue: defaultValue,
|
defaultValue: defaultValue,
|
||||||
|
layout: layout,
|
||||||
isReadOnly: isReadOnly || false,
|
isReadOnly: isReadOnly || false,
|
||||||
isHideLabel: isHideLabel || false,
|
isHideLabel: isHideLabel || false,
|
||||||
fontSize:
|
fontSize:
|
||||||
@@ -1590,6 +1594,36 @@ function PlaceHolderSign() {
|
|||||||
isReadOnly: defaultdata?.isReadOnly || false
|
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:
|
||||||
|
isSubscribe && inputype
|
||||||
|
? {
|
||||||
|
type: inputype,
|
||||||
|
pattern:
|
||||||
|
inputype === "regex" ? defaultdata.textvalidate : ""
|
||||||
|
}
|
||||||
|
: {},
|
||||||
|
fontSize:
|
||||||
|
fontSize || currWidgetsDetails?.options?.fontSize || 12,
|
||||||
|
fontColor:
|
||||||
|
fontColor ||
|
||||||
|
currWidgetsDetails?.options?.fontColor ||
|
||||||
|
"black",
|
||||||
|
isReadOnly: defaultdata?.isReadOnly || false
|
||||||
|
}
|
||||||
|
};
|
||||||
} else if (["signature"].includes(position.type)) {
|
} else if (["signature"].includes(position.type)) {
|
||||||
return {
|
return {
|
||||||
...position,
|
...position,
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import React, { useEffect, useState } from "react";
|
import React, { useEffect, useState, useRef } from "react";
|
||||||
import ReportTable from "../primitives/GetReportDisplay";
|
import ReportTable from "../primitives/GetReportDisplay";
|
||||||
import Parse from "parse";
|
import Parse from "parse";
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
@@ -27,12 +27,17 @@ const Report = () => {
|
|||||||
const [isImport, setIsImport] = useState(false);
|
const [isImport, setIsImport] = useState(false);
|
||||||
const abortController = new AbortController();
|
const abortController = new AbortController();
|
||||||
const docPerPage = 10;
|
const docPerPage = 10;
|
||||||
|
const [searchTerm, setSearchTerm] = useState("");
|
||||||
|
const [mobileSearchOpen, setMobileSearchOpen] = useState(false);
|
||||||
|
const debounceTimer = useRef(null);
|
||||||
|
|
||||||
// below useEffect is call when id param change
|
// below useEffect is call when id param change
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setReportName("");
|
setReportName("");
|
||||||
setList([]);
|
setList([]);
|
||||||
getReportData();
|
setSearchTerm("");
|
||||||
|
setMobileSearchOpen(false);
|
||||||
|
getReportData(0, docPerPage, "");
|
||||||
|
|
||||||
// Function returned from useEffect is called on unmount
|
// Function returned from useEffect is called on unmount
|
||||||
return () => {
|
return () => {
|
||||||
@@ -48,7 +53,7 @@ const Report = () => {
|
|||||||
// below useEffect call when isNextRecord state is true and fetch next record
|
// below useEffect call when isNextRecord state is true and fetch next record
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (isNextRecord) {
|
if (isNextRecord) {
|
||||||
getReportData(List.length, 20);
|
getReportData(List.length, 20, searchTerm);
|
||||||
}
|
}
|
||||||
// eslint-disable-next-line
|
// eslint-disable-next-line
|
||||||
}, [isNextRecord]);
|
}, [isNextRecord]);
|
||||||
@@ -56,7 +61,46 @@ const Report = () => {
|
|||||||
const handleDontShow = (isChecked) => {
|
const handleDontShow = (isChecked) => {
|
||||||
setIsDontShow(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);
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error("Search error:", err);
|
||||||
|
}
|
||||||
|
}, 300);
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
return () => {
|
||||||
|
if (debounceTimer.current) {
|
||||||
|
clearTimeout(debounceTimer.current);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}, []);
|
||||||
|
const getReportData = async (skipUserRecord = 0, limit = 20, term = searchTerm) => {
|
||||||
// setIsLoader(true);
|
// setIsLoader(true);
|
||||||
const json = reportJson(id);
|
const json = reportJson(id);
|
||||||
if (json) {
|
if (json) {
|
||||||
@@ -77,6 +121,9 @@ const Report = () => {
|
|||||||
const skipRecord = id === "4Hhwbp482K" ? 0 : skipUserRecord;
|
const skipRecord = id === "4Hhwbp482K" ? 0 : skipUserRecord;
|
||||||
const limitRecord = id === "4Hhwbp482K" ? 200 : limit;
|
const limitRecord = id === "4Hhwbp482K" ? 200 : limit;
|
||||||
const params = { reportId: id, skip: skipRecord, limit: limitRecord };
|
const params = { reportId: id, skip: skipRecord, limit: limitRecord };
|
||||||
|
if (term) {
|
||||||
|
params.searchTerm = term;
|
||||||
|
}
|
||||||
const url = `${localStorage.getItem("baseUrl")}functions/getReport`;
|
const url = `${localStorage.getItem("baseUrl")}functions/getReport`;
|
||||||
const res = await axios.post(url, params, {
|
const res = await axios.post(url, params, {
|
||||||
headers: headers,
|
headers: headers,
|
||||||
@@ -197,6 +244,10 @@ const Report = () => {
|
|||||||
report_help={reporthelp}
|
report_help={reporthelp}
|
||||||
tourData={tourData}
|
tourData={tourData}
|
||||||
isDontShow={isDontShow}
|
isDontShow={isDontShow}
|
||||||
|
mobileSearchOpen={mobileSearchOpen}
|
||||||
|
setMobileSearchOpen={setMobileSearchOpen}
|
||||||
|
searchTerm={searchTerm}
|
||||||
|
handleSearchChange={handleSearchChange}
|
||||||
isImport={isImport}
|
isImport={isImport}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import {
|
|||||||
randomId,
|
randomId,
|
||||||
getDate,
|
getDate,
|
||||||
textWidget,
|
textWidget,
|
||||||
|
cellsWidget,
|
||||||
convertPdfArrayBuffer,
|
convertPdfArrayBuffer,
|
||||||
textInputWidget,
|
textInputWidget,
|
||||||
fetchImageBase64,
|
fetchImageBase64,
|
||||||
@@ -356,9 +357,13 @@ function SignYourSelf() {
|
|||||||
);
|
);
|
||||||
const dragTypeValue = item?.text ? item.text : monitor.type;
|
const dragTypeValue = item?.text ? item.text : monitor.type;
|
||||||
const widgetValue = getWidgetValue(dragTypeValue);
|
const widgetValue = getWidgetValue(dragTypeValue);
|
||||||
const widgetTypeExist = ["name", "company", "job title", "email"].includes(
|
const widgetTypeExist = [
|
||||||
dragTypeValue
|
"name",
|
||||||
);
|
"company",
|
||||||
|
"job title",
|
||||||
|
"email",
|
||||||
|
cellsWidget
|
||||||
|
].includes(dragTypeValue);
|
||||||
const containerScale = getContainerScale(
|
const containerScale = getContainerScale(
|
||||||
pdfOriginalWH,
|
pdfOriginalWH,
|
||||||
pageNumber,
|
pageNumber,
|
||||||
@@ -439,6 +444,7 @@ function SignYourSelf() {
|
|||||||
[
|
[
|
||||||
textInputWidget,
|
textInputWidget,
|
||||||
textWidget,
|
textWidget,
|
||||||
|
cellsWidget,
|
||||||
"name",
|
"name",
|
||||||
"company",
|
"company",
|
||||||
"job title",
|
"job title",
|
||||||
@@ -931,7 +937,8 @@ function SignYourSelf() {
|
|||||||
deleteOption,
|
deleteOption,
|
||||||
status,
|
status,
|
||||||
defaultValue,
|
defaultValue,
|
||||||
isHideLabel
|
isHideLabel,
|
||||||
|
layout
|
||||||
) => {
|
) => {
|
||||||
const getPageNumer = xyPosition.filter(
|
const getPageNumer = xyPosition.filter(
|
||||||
(data) => data.pageNumber === pageNumber
|
(data) => data.pageNumber === pageNumber
|
||||||
@@ -939,6 +946,8 @@ function SignYourSelf() {
|
|||||||
if (getPageNumer.length > 0) {
|
if (getPageNumer.length > 0) {
|
||||||
const getXYdata = getPageNumer[0].pos;
|
const getXYdata = getPageNumer[0].pos;
|
||||||
const getPosData = getXYdata;
|
const getPosData = getXYdata;
|
||||||
|
const widgetLayout =
|
||||||
|
currWidgetsDetails?.type === "checkbox" ? { layout: layout } : {};
|
||||||
const addSignPos = getPosData.map((position) => {
|
const addSignPos = getPosData.map((position) => {
|
||||||
if (position.key === currWidgetsDetails?.key) {
|
if (position.key === currWidgetsDetails?.key) {
|
||||||
if (addOption) {
|
if (addOption) {
|
||||||
@@ -962,6 +971,7 @@ function SignYourSelf() {
|
|||||||
...position.options,
|
...position.options,
|
||||||
name: dropdownName,
|
name: dropdownName,
|
||||||
values: dropdownOptions,
|
values: dropdownOptions,
|
||||||
|
...widgetLayout,
|
||||||
isReadOnly: isReadOnly,
|
isReadOnly: isReadOnly,
|
||||||
isHideLabel: isHideLabel || false,
|
isHideLabel: isHideLabel || false,
|
||||||
fontSize:
|
fontSize:
|
||||||
@@ -1028,6 +1038,19 @@ function SignYourSelf() {
|
|||||||
handleTextSettingModal(false);
|
handleTextSettingModal(false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const setCellCount = (key, newCount) => {
|
||||||
|
const getPageNumer = xyPosition.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
|
||||||
|
);
|
||||||
|
const updateXYposition = xyPosition.map((obj, ind) =>
|
||||||
|
ind === index ? { ...obj, pos: updatePos } : obj
|
||||||
|
);
|
||||||
|
setXyPosition(updateXYposition);
|
||||||
|
}
|
||||||
|
};
|
||||||
const clickOnZoomIn = () => {
|
const clickOnZoomIn = () => {
|
||||||
onClickZoomIn(scale, zoomPercent, setScale, setZoomPercent);
|
onClickZoomIn(scale, zoomPercent, setScale, setZoomPercent);
|
||||||
};
|
};
|
||||||
@@ -1289,6 +1312,7 @@ function SignYourSelf() {
|
|||||||
pdfBase64Url={pdfBase64Url}
|
pdfBase64Url={pdfBase64Url}
|
||||||
fontSize={fontSize}
|
fontSize={fontSize}
|
||||||
setFontSize={setFontSize}
|
setFontSize={setFontSize}
|
||||||
|
setCellCount={setCellCount}
|
||||||
fontColor={fontColor}
|
fontColor={fontColor}
|
||||||
setFontColor={setFontColor}
|
setFontColor={setFontColor}
|
||||||
isResize={isResize}
|
isResize={isResize}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import React, { useEffect, useState, useRef } from "react";
|
import { useEffect, useState, useRef } from "react";
|
||||||
import RenderAllPdfPage from "../components/pdf/RenderAllPdfPage";
|
import RenderAllPdfPage from "../components/pdf/RenderAllPdfPage";
|
||||||
import { useParams, useNavigate } from "react-router";
|
import { useParams, useNavigate } from "react-router";
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
@@ -22,6 +22,7 @@ import {
|
|||||||
defaultWidthHeight,
|
defaultWidthHeight,
|
||||||
addWidgetOptions,
|
addWidgetOptions,
|
||||||
textInputWidget,
|
textInputWidget,
|
||||||
|
cellsWidget,
|
||||||
radioButtonWidget,
|
radioButtonWidget,
|
||||||
getContainerScale,
|
getContainerScale,
|
||||||
convertBase64ToFile,
|
convertBase64ToFile,
|
||||||
@@ -1274,7 +1275,8 @@ const TemplatePlaceholder = () => {
|
|||||||
deleteOption,
|
deleteOption,
|
||||||
status,
|
status,
|
||||||
defaultValue,
|
defaultValue,
|
||||||
isHideLabel
|
isHideLabel,
|
||||||
|
layout
|
||||||
) => {
|
) => {
|
||||||
const filterSignerPos = signerPos.filter((data) => data.Id === uniqueId);
|
const filterSignerPos = signerPos.filter((data) => data.Id === uniqueId);
|
||||||
if (filterSignerPos.length > 0) {
|
if (filterSignerPos.length > 0) {
|
||||||
@@ -1313,6 +1315,7 @@ const TemplatePlaceholder = () => {
|
|||||||
name: dropdownName,
|
name: dropdownName,
|
||||||
values: dropdownOptions,
|
values: dropdownOptions,
|
||||||
status: status,
|
status: status,
|
||||||
|
layout: layout,
|
||||||
defaultValue: defaultValue,
|
defaultValue: defaultValue,
|
||||||
isReadOnly: isReadOnly || false,
|
isReadOnly: isReadOnly || false,
|
||||||
isHideLabel: isHideLabel || false,
|
isHideLabel: isHideLabel || false,
|
||||||
@@ -1351,6 +1354,7 @@ const TemplatePlaceholder = () => {
|
|||||||
minRequiredCount: minCount,
|
minRequiredCount: minCount,
|
||||||
maxRequiredCount: maxCount
|
maxRequiredCount: maxCount
|
||||||
},
|
},
|
||||||
|
layout: layout,
|
||||||
isReadOnly: isReadOnly || false,
|
isReadOnly: isReadOnly || false,
|
||||||
defaultValue: defaultValue,
|
defaultValue: defaultValue,
|
||||||
isHideLabel: isHideLabel || false,
|
isHideLabel: isHideLabel || false,
|
||||||
@@ -1451,6 +1455,36 @@ const TemplatePlaceholder = () => {
|
|||||||
"black"
|
"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)) {
|
} else if (["signature"].includes(position.type)) {
|
||||||
return {
|
return {
|
||||||
...position,
|
...position,
|
||||||
@@ -1510,6 +1544,22 @@ const TemplatePlaceholder = () => {
|
|||||||
setIsRadio(false);
|
setIsRadio(false);
|
||||||
setIsCheckbox(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 = () => {
|
const clickOnZoomIn = () => {
|
||||||
onClickZoomIn(scale, zoomPercent, setScale, setZoomPercent);
|
onClickZoomIn(scale, zoomPercent, setScale, setZoomPercent);
|
||||||
@@ -1828,6 +1878,7 @@ const TemplatePlaceholder = () => {
|
|||||||
pdfBase64Url={pdfBase64Url}
|
pdfBase64Url={pdfBase64Url}
|
||||||
fontSize={fontSize}
|
fontSize={fontSize}
|
||||||
setFontSize={setFontSize}
|
setFontSize={setFontSize}
|
||||||
|
setCellCount={setCellCount}
|
||||||
fontColor={fontColor}
|
fontColor={fontColor}
|
||||||
setFontColor={setFontColor}
|
setFontColor={setFontColor}
|
||||||
isResize={isResize}
|
isResize={isResize}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import ModalUi from "./ModalUi";
|
|||||||
import AddSigner from "../components/AddSigner";
|
import AddSigner from "../components/AddSigner";
|
||||||
import {
|
import {
|
||||||
emailRegex,
|
emailRegex,
|
||||||
|
iconColor,
|
||||||
} from "../constant/const";
|
} from "../constant/const";
|
||||||
import Alert from "./Alert";
|
import Alert from "./Alert";
|
||||||
import Tooltip from "./Tooltip";
|
import Tooltip from "./Tooltip";
|
||||||
@@ -907,7 +908,6 @@ const ReportTable = (props) => {
|
|||||||
setActLoader({});
|
setActLoader({});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleUpdateExpiry = async (e, item) => {
|
const handleUpdateExpiry = async (e, item) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
@@ -1314,7 +1314,6 @@ const ReportTable = (props) => {
|
|||||||
try {
|
try {
|
||||||
const params = { docId: doc?.objectId };
|
const params = { docId: doc?.objectId };
|
||||||
const templateRes = await Parse.Cloud.run("saveastemplate", params);
|
const templateRes = await Parse.Cloud.run("saveastemplate", params);
|
||||||
// console.log("templateRes ", templateRes);
|
|
||||||
setTemplateId(templateRes?.id);
|
setTemplateId(templateRes?.id);
|
||||||
setIsSuccess({ [doc.objectId]: true });
|
setIsSuccess({ [doc.objectId]: true });
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
@@ -1394,6 +1393,12 @@ const ReportTable = (props) => {
|
|||||||
setActLoader({});
|
setActLoader({});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const restrictBtn = (item, act) => {
|
||||||
|
return item.IsSignyourself && act.action === "recreatedocument"
|
||||||
|
? true
|
||||||
|
: false;
|
||||||
|
};
|
||||||
return (
|
return (
|
||||||
<div className="relative">
|
<div className="relative">
|
||||||
{Object.keys(actLoader)?.length > 0 && (
|
{Object.keys(actLoader)?.length > 0 && (
|
||||||
@@ -1449,6 +1454,23 @@ const ReportTable = (props) => {
|
|||||||
className="cursor-pointer fa-light fa-square-plus text-accent text-[30px] md:text-[35px]"
|
className="cursor-pointer fa-light fa-square-plus text-accent text-[30px] md:text-[35px]"
|
||||||
></i>
|
></i>
|
||||||
)}
|
)}
|
||||||
|
{/* Search input */}
|
||||||
|
<div className="hidden md:block p-2">
|
||||||
|
<input
|
||||||
|
type="search"
|
||||||
|
value={props.searchTerm}
|
||||||
|
onChange={props.handleSearchChange}
|
||||||
|
placeholder={t('search.documents')}
|
||||||
|
className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-64 text-xs"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<button
|
||||||
|
className="md:hidden p-2 flex justify-center items-center focus:outline-none rounded-md hover:bg-gray-200 text-[18px]"
|
||||||
|
aria-label="Search"
|
||||||
|
onClick={() => props.setMobileSearchOpen(!props.mobileSearchOpen)}
|
||||||
|
>
|
||||||
|
<i style={{ color: `${iconColor}` }} className="fa-solid fa-magnifying-glass"></i>
|
||||||
|
</button>
|
||||||
<ModalUi
|
<ModalUi
|
||||||
isOpen={isModal?.export}
|
isOpen={isModal?.export}
|
||||||
title={t("bulk-import")}
|
title={t("bulk-import")}
|
||||||
@@ -1536,6 +1558,17 @@ const ReportTable = (props) => {
|
|||||||
</ModalUi>
|
</ModalUi>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
{props.mobileSearchOpen && (
|
||||||
|
<div className="top-full left-0 w-full bg-white px-4 py-2 shadow-md md:hidden">
|
||||||
|
<input
|
||||||
|
type="search"
|
||||||
|
value={props.searchTerm}
|
||||||
|
onChange={props.handleSearchChange}
|
||||||
|
placeholder="Search documents…"
|
||||||
|
className="op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content w-full text-xs"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
<div
|
<div
|
||||||
className={`overflow-auto w-full border-b ${
|
className={`overflow-auto w-full border-b ${
|
||||||
props.List?.length > 0
|
props.List?.length > 0
|
||||||
@@ -1837,33 +1870,39 @@ const ReportTable = (props) => {
|
|||||||
{isOption[item.objectId] &&
|
{isOption[item.objectId] &&
|
||||||
act.action === "option" && (
|
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">
|
<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) => (
|
{act.subaction?.map(
|
||||||
<li
|
(subact) =>
|
||||||
key={subact.btnId}
|
!restrictBtn(
|
||||||
onClick={() =>
|
item,
|
||||||
handleActionBtn(
|
subact
|
||||||
subact,
|
) && (
|
||||||
item
|
<li
|
||||||
)
|
key={subact.btnId}
|
||||||
}
|
onClick={() =>
|
||||||
title={t(
|
handleActionBtn(
|
||||||
`btnLabel.${subact.hoverLabel}`
|
subact,
|
||||||
)}
|
item
|
||||||
>
|
)
|
||||||
<span>
|
}
|
||||||
<i
|
title={t(
|
||||||
className={`${subact.btnIcon} mr-1.5`}
|
`btnLabel.${subact.hoverLabel}`
|
||||||
></i>
|
)}
|
||||||
{subact.btnLabel && (
|
>
|
||||||
<span className="text-[13px] capitalize font-medium">
|
<span>
|
||||||
{t(
|
<i
|
||||||
`btnLabel.${subact.btnLabel}`
|
className={`${subact.btnIcon} mr-1.5`}
|
||||||
|
></i>
|
||||||
|
{subact.btnLabel && (
|
||||||
|
<span className="text-[13px] capitalize font-medium">
|
||||||
|
{t(
|
||||||
|
`btnLabel.${subact.btnLabel}`
|
||||||
|
)}
|
||||||
|
</span>
|
||||||
)}
|
)}
|
||||||
</span>
|
</span>
|
||||||
)}
|
</li>
|
||||||
</span>
|
)
|
||||||
</li>
|
)}
|
||||||
))}
|
|
||||||
</ul>
|
</ul>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -15,8 +15,6 @@ async function deductcount(docsCount, extUserId) {
|
|||||||
async function sendMail(document, publicUrl) {
|
async function sendMail(document, publicUrl) {
|
||||||
//sessionToken
|
//sessionToken
|
||||||
const baseUrl = new URL(publicUrl);
|
const baseUrl = new URL(publicUrl);
|
||||||
|
|
||||||
// console.log("pdfDetails", pdfDetails);
|
|
||||||
const timeToCompleteDays = document?.TimeToCompleteDays || 15;
|
const timeToCompleteDays = document?.TimeToCompleteDays || 15;
|
||||||
const ExpireDate = new Date(document.createdAt);
|
const ExpireDate = new Date(document.createdAt);
|
||||||
ExpireDate.setDate(ExpireDate.getDate() + timeToCompleteDays);
|
ExpireDate.setDate(ExpireDate.getDate() + timeToCompleteDays);
|
||||||
@@ -168,9 +166,9 @@ async function batchQuery(userId, Documents, Ip, parseConfig, type, publicUrl) {
|
|||||||
})),
|
})),
|
||||||
ACL: Acl,
|
ACL: Acl,
|
||||||
SentToOthers: true,
|
SentToOthers: true,
|
||||||
RemindOnceInEvery: x.RemindOnceInEvery || 5,
|
RemindOnceInEvery: x.RemindOnceInEvery ? parseInt(x.RemindOnceInEvery) : 5,
|
||||||
AutomaticReminders: x.AutomaticReminders || false,
|
AutomaticReminders: x.AutomaticReminders || false,
|
||||||
TimeToCompleteDays: x.TimeToCompleteDays || 15,
|
TimeToCompleteDays: x.TimeToCompleteDays ? parseInt(x.TimeToCompleteDays) : 15,
|
||||||
OriginIp: Ip,
|
OriginIp: Ip,
|
||||||
DocSentAt: { __type: 'Date', iso: isoDate },
|
DocSentAt: { __type: 'Date', iso: isoDate },
|
||||||
IsEnableOTP: x?.IsEnableOTP || false,
|
IsEnableOTP: x?.IsEnableOTP || false,
|
||||||
@@ -231,6 +229,7 @@ export default async function createBatchDocs(request) {
|
|||||||
const sessionToken = request.headers?.sessiontoken;
|
const sessionToken = request.headers?.sessiontoken;
|
||||||
const type = request.headers?.type || 'quicksend';
|
const type = request.headers?.type || 'quicksend';
|
||||||
const Documents = JSON.parse(strDocuments);
|
const Documents = JSON.parse(strDocuments);
|
||||||
|
|
||||||
const Ip = request?.headers?.['x-real-ip'] || '';
|
const Ip = request?.headers?.['x-real-ip'] || '';
|
||||||
// Access the host from the headers
|
// Access the host from the headers
|
||||||
const publicUrl = request.headers.public_url;
|
const publicUrl = request.headers.public_url;
|
||||||
|
|||||||
@@ -2,19 +2,26 @@ import { cloudServerUrl } from '../../Utils.js';
|
|||||||
import reportJson from './reportsJson.js';
|
import reportJson from './reportsJson.js';
|
||||||
import axios from 'axios';
|
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) {
|
export default async function getReport(request) {
|
||||||
const reportId = request.params.reportId;
|
const reportId = request.params.reportId;
|
||||||
const limit = request.params.limit;
|
const limit = request.params.limit;
|
||||||
const skip = request.params.skip;
|
const skip = request.params.skip;
|
||||||
|
const searchTerm = request.params.searchTerm || '';
|
||||||
|
|
||||||
const serverUrl = cloudServerUrl; //process.env.SERVER_URL;
|
const serverUrl = cloudServerUrl; //process.env.SERVER_URL;
|
||||||
const appId = process.env.APP_ID;
|
const appId = process.env.APP_ID;
|
||||||
const masterKey = process.env.MASTER_KEY;
|
const masterKey = process.env.MASTER_KEY;
|
||||||
|
const sessionToken = request.headers['sessiontoken'] || request.headers['x-parse-session-token'];
|
||||||
try {
|
try {
|
||||||
const userRes = await axios.get(serverUrl + '/users/me', {
|
const userRes = await axios.get(serverUrl + '/users/me', {
|
||||||
headers: {
|
headers: {
|
||||||
'X-Parse-Application-Id': appId,
|
'X-Parse-Application-Id': appId,
|
||||||
'X-Parse-Session-Token': request.headers['sessiontoken'],
|
'X-Parse-Session-Token': sessionToken,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
const userId = userRes.data && userRes.data.objectId;
|
const userId = userRes.data && userRes.data.objectId;
|
||||||
@@ -25,7 +32,7 @@ export default async function getReport(request) {
|
|||||||
const { params, keys } = json;
|
const { params, keys } = json;
|
||||||
const orderBy = '-updatedAt';
|
const orderBy = '-updatedAt';
|
||||||
const strKeys = keys.join();
|
const strKeys = keys.join();
|
||||||
let strParams = JSON.stringify(params);
|
let paramsObj = { ...params };
|
||||||
if (reportId == '6TeaPr321t') {
|
if (reportId == '6TeaPr321t') {
|
||||||
const extUserQuery = new Parse.Query('contracts_Users');
|
const extUserQuery = new Parse.Query('contracts_Users');
|
||||||
extUserQuery.equalTo('Email', userRes.data.email);
|
extUserQuery.equalTo('Email', userRes.data.email);
|
||||||
@@ -36,8 +43,8 @@ export default async function getReport(request) {
|
|||||||
if (_extUser?.TeamIds && _extUser.TeamIds?.length > 0) {
|
if (_extUser?.TeamIds && _extUser.TeamIds?.length > 0) {
|
||||||
let teamArr = [];
|
let teamArr = [];
|
||||||
_extUser?.TeamIds?.forEach(x => (teamArr = [...teamArr, ...x.Ancestors]));
|
_extUser?.TeamIds?.forEach(x => (teamArr = [...teamArr, ...x.Ancestors]));
|
||||||
strParams = JSON.stringify({
|
paramsObj = {
|
||||||
...params,
|
...paramsObj,
|
||||||
$or: [
|
$or: [
|
||||||
{ SharedWith: { $in: teamArr } },
|
{ SharedWith: { $in: teamArr } },
|
||||||
{
|
{
|
||||||
@@ -55,15 +62,23 @@ export default async function getReport(request) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
});
|
};
|
||||||
} else {
|
} else {
|
||||||
strParams = JSON.stringify({
|
paramsObj = {
|
||||||
...params,
|
...paramsObj,
|
||||||
CreatedBy: { __type: 'Pointer', className: '_User', objectId: userId },
|
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 = {
|
const headers = {
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
'X-Parse-Application-Id': appId,
|
'X-Parse-Application-Id': appId,
|
||||||
|
|||||||
@@ -14,11 +14,14 @@ export default async function recreateDocument(request) {
|
|||||||
if (!doc) {
|
if (!doc) {
|
||||||
throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'Document not found');
|
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 _docRes = doc?.toJSON();
|
||||||
const { objectId, SignedUrl, AuditTrail, ACL, DeclineBy, DeclineReason, ...docRes } = _docRes;
|
const { objectId, SignedUrl, AuditTrail, ACL, DeclineBy, DeclineReason, ...docRes } = _docRes;
|
||||||
const createDoc = new Parse.Object('contracts_Document');
|
const createDoc = new Parse.Object('contracts_Document');
|
||||||
Object.entries(docRes).forEach(([key, value]) => {
|
Object.entries(docRes).forEach(([key, value]) => {
|
||||||
if (key === 'IsDeclined') {
|
if (key === 'IsDeclined' || key === 'IsCompleted') {
|
||||||
createDoc.set(key, false);
|
createDoc.set(key, false);
|
||||||
} else {
|
} else {
|
||||||
createDoc.set(key, value);
|
createDoc.set(key, value);
|
||||||
|
|||||||
@@ -123,6 +123,8 @@ export default function reportJson(id, userId) {
|
|||||||
'TimeToCompleteDays',
|
'TimeToCompleteDays',
|
||||||
'IsSignyourself',
|
'IsSignyourself',
|
||||||
'IsCompleted',
|
'IsCompleted',
|
||||||
|
'ExpiryDate',
|
||||||
|
'IsSignyourself',
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
// declined documents report
|
// declined documents report
|
||||||
|
|||||||
@@ -53,10 +53,16 @@ const makeEmail = async (
|
|||||||
const isSecure =
|
const isSecure =
|
||||||
new URL(url)?.protocol === 'https:' && new URL(url)?.hostname !== 'localhost';
|
new URL(url)?.protocol === 'https:' && new URL(url)?.hostname !== 'localhost';
|
||||||
if (isSecure) {
|
if (isSecure) {
|
||||||
https.get(url, async function (response) {
|
https
|
||||||
response.pipe(Pdf);
|
.get(url, async function (response) {
|
||||||
response.on('end', () => resolve('success'));
|
response.pipe(Pdf);
|
||||||
});
|
Pdf.on('finish', () => resolve('success'));
|
||||||
|
Pdf.on('error', () => resolve('error'));
|
||||||
|
})
|
||||||
|
.on('error', e => {
|
||||||
|
console.error(`error: ${e.message}`);
|
||||||
|
resolve('error');
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
const httpsAgent = new https.Agent({ rejectUnauthorized: false }); // Disable SSL validation
|
const httpsAgent = new https.Agent({ rejectUnauthorized: false }); // Disable SSL validation
|
||||||
axios
|
axios
|
||||||
|
|||||||
Reference in New Issue
Block a user