feat: implement multiple checkbox feature , hint for input placeholder,dd/mm/yyyy format ,fix isssue of user details popup open onclick widgets

This commit is contained in:
RaktimaNXG
2024-02-28 15:56:42 +05:30
parent 0fe7937808
commit f9eff12f94
11 changed files with 774 additions and 583 deletions
@@ -88,6 +88,7 @@ function PdfRequestFiles() {
const [containerWH, setContainerWH] = useState({});
const [validateAlert, setValidateAlert] = useState(false);
const [widgetsTour, setWidgetsTour] = useState(false);
const [minRequiredCount, setminRequiredCount] = useState();
const divRef = useRef(null);
const isMobile = window.innerWidth < 767;
const rowLevel =
@@ -300,28 +301,53 @@ function PdfRequestFiles() {
(data) => data.signerObjId === signerObjectId
);
if (checkUser && checkUser.length > 0) {
let unSignUrlData;
let unSignUrlData,
checkboxExist,
isReadOnly,
minCountAlert = false,
checkboxKey;
for (let i = 0; i < checkUser[0].placeHolder.length; i++) {
unSignUrlData = checkUser[0].placeHolder[i].pos.filter(
(pos) => !pos?.SignUrl && !pos.options.response
checkboxExist = checkUser[0].placeHolder[i].pos.some(
(data) => data.type === "checkbox"
);
}
let checkboxExist;
let optionRequiredCheckbox;
checkboxExist = unSignUrlData.some((data) => data.type === "checkbox");
if (checkboxExist) {
optionRequiredCheckbox = unSignUrlData.filter(
(data) => data.options.status !== "Optional"
);
if (checkboxExist) {
isReadOnly = checkUser[0].placeHolder[i].pos.filter(
(position) => !position.options.isReadOnly
);
if (isReadOnly && isReadOnly.length > 0) {
for (let i = 0; i < isReadOnly.length; i++) {
const minCount =
isReadOnly[i].options.validation?.minRequiredCount;
const response = isReadOnly[i].options?.response?.length;
const defaultValue = isReadOnly[i].options?.defaultValue?.length;
if (!response) {
if (!defaultValue) {
if (!minCountAlert) {
minCountAlert = true;
checkboxKey = isReadOnly[i].key;
setminRequiredCount(minCount);
}
}
} else if (minCount > 0 && minCount > response) {
if (!minCountAlert) {
minCountAlert = true;
checkboxKey = isReadOnly[i].key;
setminRequiredCount(minCount);
}
}
}
}
} else {
unSignUrlData = checkUser[0].placeHolder[i].pos.filter(
(pos) => !pos?.SignUrl && !pos.options.response
);
}
}
if (
checkboxExist &&
optionRequiredCheckbox &&
optionRequiredCheckbox.length > 0
) {
setUnSignedWidgetId(optionRequiredCheckbox[0].key);
if (checkboxExist && isReadOnly && minCountAlert) {
setUnSignedWidgetId(checkboxKey);
setWidgetsTour(true);
} else if (!checkboxExist && unSignUrlData && unSignUrlData.length > 0) {
setUnSignedWidgetId(unSignUrlData[0].key);
@@ -403,8 +429,9 @@ function PdfRequestFiles() {
const tourConfig = [
{
selector: '[data-tut="IsSigned"]',
content:
"Ensure this field is accurately filled and meets all requirements.",
content: minRequiredCount
? `Please confirm that you have selected at least ${minRequiredCount} checkboxes.`
: "Ensure this field is accurately filled and meets all requirements.",
position: "top",
style: { fontSize: "13px" }
}
@@ -35,6 +35,7 @@ import PlaceholderCopy from "./component/PlaceholderCopy";
import TourContentWithBtn from "../premitives/TourContentWithBtn";
import Title from "./component/Title";
import ModalUi from "../premitives/ModalUi";
import DropdownWidgetOption from "./WidgetComponent/dropdownWidgetOption";
//For signYourself inProgress section signer can add sign and complete doc sign.
function SignYourSelf() {
@@ -86,6 +87,8 @@ function SignYourSelf() {
const [showAlreadySignDoc, setShowAlreadySignDoc] = useState({
status: false
});
const [currWidgetsDetails, setCurrWidgetsDetails] = useState([]);
const [isCheckbox, setIsCheckbox] = useState(false);
const [widgetType, setWidgetType] = useState("");
const [pdfLoadFail, setPdfLoadFail] = useState({
status: false,
@@ -348,7 +351,6 @@ function SignYourSelf() {
option = {
name: "",
values: [],
status: "Read only",
response: true,
validation: {}
};
@@ -544,16 +546,18 @@ function SignYourSelf() {
dragTypeValue === "initials"
) {
setIsSignPad(true);
setSignKey(key);
}
if (dragTypeValue === "stamp" || dragTypeValue === "image") {
setIsStamp(true);
} else if (dragTypeValue === "initials") {
setIsInitial(true);
} else if (dragTypeValue === "checkbox") {
setIsCheckbox(true);
}
setWidgetType(dragTypeValue);
setSelectWidgetId(key);
setSignKey(key);
};
//function for send placeholder's co-ordinate(x,y) position embed signature url or stamp url
@@ -897,6 +901,63 @@ function SignYourSelf() {
}
};
const handleSaveWidgetsOptions = (
dropdownName,
dropdownOptions,
minCount,
maxCount,
isReadOnly,
addOption,
deleteOption
) => {
const getPageNumer = xyPostion.filter(
(data) => data.pageNumber === pageNumber
);
if (getPageNumer.length > 0) {
const getXYdata = getPageNumer[0].pos;
const getPosData = getXYdata;
const addSignPos = getPosData.map((position) => {
if (position.key === signKey) {
if (addOption) {
return {
...position,
Height: position.Height
? position.Height + 15
: defaultWidthHeight(widgetType).height + 15
};
} else if (deleteOption) {
return {
...position,
Height: position.Height
? position.Height - 15
: defaultWidthHeight(widgetType).height - 15
};
} else {
return {
...position,
options: {
...position.options,
name: dropdownName,
values: dropdownOptions,
isReadOnly: isReadOnly,
response: []
}
};
}
}
return position;
});
const updateXYposition = xyPostion.map((obj, ind) => {
if (ind === index) {
return { ...obj, pos: addSignPos };
}
return obj;
});
setXyPostion(updateXYposition);
}
};
return (
<DndProvider backend={HTML5Backend}>
<Title title={"Self Sign"} />
@@ -1031,7 +1092,16 @@ function SignYourSelf() {
</button>
</div>
</ModalUi>
<DropdownWidgetOption
type="checkbox"
title="Checkbox"
showDropdown={isCheckbox}
setShowDropdown={setIsCheckbox}
handleSaveWidgetsOptions={handleSaveWidgetsOptions}
currWidgetsDetails={currWidgetsDetails}
setCurrWidgetsDetails={setCurrWidgetsDetails}
isSignYourself={true}
/>
<PlaceholderCopy
isPageCopy={isPageCopy}
setIsPageCopy={setIsPageCopy}
@@ -1062,7 +1132,7 @@ function SignYourSelf() {
setIsStamp={setIsStamp}
widgetType={widgetType}
/>
{/* render email component to send email after finish signature on document */}
{/*render email component to send email after finish signature on document */}
<EmailComponent
isEmail={isEmail}
pdfUrl={pdfUrl}
@@ -1122,6 +1192,8 @@ function SignYourSelf() {
setWidgetType={setWidgetType}
setSelectWidgetId={setSelectWidgetId}
selectWidgetId={selectWidgetId}
setIsCheckbox={setIsCheckbox}
setCurrWidgetsDetails={setCurrWidgetsDetails}
/>
)}
</div>
@@ -22,7 +22,8 @@ import {
randomId,
addZIndex,
createDocument,
defaultWidthHeight
defaultWidthHeight,
addWidgetOptions
} from "../utils/Utils";
import RenderPdf from "./component/renderPdf";
import "../css/AddUser.css";
@@ -84,6 +85,7 @@ const TemplatePlaceholder = () => {
const [selectWidgetId, setSelectWidgetId] = useState("");
const [isValidate, setIsValidate] = useState(false);
const [textValidate, setTextValidate] = useState("");
const [hint, setHint] = useState("");
const [pdfLoadFail, setPdfLoadFail] = useState({
status: false,
type: "load"
@@ -170,6 +172,7 @@ const TemplatePlaceholder = () => {
const [isDontShow, setIsDontShow] = useState(false);
const [isDragging, setIsDragging] = useState(false);
const [currWidgetsDetails, setCurrWidgetsDetails] = useState([]);
const [isCheckbox, setIsCheckbox] = useState(false);
const checkboxType = ["Optional", "Required", "Read only"];
const senderUser =
localStorage.getItem(
@@ -348,154 +351,6 @@ const TemplatePlaceholder = () => {
getSignerPos(item, monitor);
};
const addWidgetOptions = (type) => {
let option = {};
switch (type) {
case "signature":
option = {
name: "",
values: [],
status: "",
response: "",
validation: {}
};
return option;
case "stamp":
option = {
name: "",
values: [],
status: "",
response: "",
validation: {}
};
return option;
case "checkbox":
option = {
name: "",
values: [],
status: "Optional",
response: false,
validation: {}
};
return option;
case "text":
option = {
name: "",
values: [],
status: "",
response: "",
validation: {}
};
return option;
case "initials":
option = {
name: "",
values: [],
status: "",
response: "",
validation: {}
};
return option;
case "name":
option = {
name: "",
values: [],
status: "",
response: "",
validation: {
type: "text",
pattern: ""
}
};
return option;
case "company":
option = {
name: "",
values: [],
status: "",
response: "",
validation: {
type: "text",
pattern: ""
}
};
return option;
case "job title":
option = {
name: "",
values: [],
status: "",
response: "",
validation: {
type: "text",
pattern: ""
}
};
return option;
case "date":
option = {
name: "",
values: [],
status: "",
response: getDate()
};
return option;
case "image":
option = {
name: "",
values: [],
status: "",
response: "",
validation: {}
};
return option;
case "email":
option = {
name: "",
values: [],
status: "",
response: "",
validation: {
type: "email",
pattern: ""
}
};
return option;
case "dropdown":
option = {
name: "",
values: [],
status: "",
response: "",
validation: {}
};
return option;
case "radio":
option = {
name: "",
values: [],
status: "",
response: "",
validation: {}
};
return option;
case "label":
option = {
name: "",
values: [],
status: "",
response: "",
validation: {}
};
return option;
}
};
// `getSignerPos` is used to get placeholder position when user place it and save it in array
const getSignerPos = (item, monitor) => {
if (uniqueId) {
@@ -625,7 +480,8 @@ const TemplatePlaceholder = () => {
if (dragTypeValue === "dropdown") {
setShowDropdown(true);
} else if (dragTypeValue === "checkbox") {
setIsCheckboxRequired(true);
// setIsCheckboxRequired(true);
setIsCheckbox(true);
} else if (dragTypeValue === "radio") {
setIsRadio(true);
}
@@ -1187,6 +1043,7 @@ const TemplatePlaceholder = () => {
...position,
options: {
...position.options,
hint: hint,
validation: {
type: regexType ? regularExpression : "regex",
pattern: !regexType ? regularExpression : ""
@@ -1222,6 +1079,9 @@ const TemplatePlaceholder = () => {
const handleSaveWidgetsOptions = (
dropdownName,
dropdownOptions,
minCount,
maxCount,
isReadOnly,
addOption,
deleteOption
) => {
@@ -1265,6 +1125,36 @@ const TemplatePlaceholder = () => {
}
};
}
} else if (widgetType === "checkbox") {
if (addOption) {
return {
...position,
Height: position.Height
? position.Height + 15
: defaultWidthHeight(widgetType).height + 15
};
} else if (deleteOption) {
return {
...position,
Height: position.Height
? position.Height - 15
: defaultWidthHeight(widgetType).height - 15
};
} else {
return {
...position,
options: {
...position.options,
name: dropdownName,
values: dropdownOptions,
validation: {
minRequiredCount: minCount,
maxRequiredCount: maxCount
},
isReadOnly: isReadOnly
}
};
}
} else {
return {
...position,
@@ -1475,6 +1365,7 @@ const TemplatePlaceholder = () => {
setIsValidate={setIsValidate}
handleValidateInput={handleValidateInput}
isValidate={isValidate}
setHint={setHint}
setTextValidate={setTextValidate}
textValidate={textValidate}
/>
@@ -1487,6 +1378,15 @@ const TemplatePlaceholder = () => {
currWidgetsDetails={currWidgetsDetails}
setCurrWidgetsDetails={setCurrWidgetsDetails}
/>
<DropdownWidgetOption
type="checkbox"
title="Checkbox"
showDropdown={isCheckbox}
setShowDropdown={setIsCheckbox}
handleSaveWidgetsOptions={handleSaveWidgetsOptions}
currWidgetsDetails={currWidgetsDetails}
setCurrWidgetsDetails={setCurrWidgetsDetails}
/>
<DropdownWidgetOption
type="dropdown"
title="Dropdown options"
@@ -1561,6 +1461,7 @@ const TemplatePlaceholder = () => {
setIsValidate={setIsValidate}
setSelectWidgetId={setSelectWidgetId}
selectWidgetId={selectWidgetId}
setIsCheckbox={setIsCheckbox}
/>
)}
</div>
@@ -6,8 +6,10 @@ function DropdownWidgetOption(props) {
"option-1",
"option-2"
]);
const [minCount, setMinCount] = useState(0);
const [maxCount, setMaxCount] = useState(0);
const [dropdownName, setDropdownName] = useState(props.type);
const [isReadOnly, setIsReadOnly] = useState(false);
useEffect(() => {
if (
@@ -16,6 +18,13 @@ function DropdownWidgetOption(props) {
) {
setDropdownName(props.currWidgetsDetails?.options?.name);
setDropdownOptionList(props.currWidgetsDetails?.options?.values);
setMinCount(
props.currWidgetsDetails?.options?.validation?.minRequiredCount
);
setMaxCount(
props.currWidgetsDetails?.options?.validation?.maxRequiredCount
);
setIsReadOnly(props.currWidgetsDetails?.options?.isReadOnly);
}
}, [props.currWidgetsDetails]);
@@ -30,7 +39,7 @@ function DropdownWidgetOption(props) {
const handleAddInput = () => {
const flage = true;
setDropdownOptionList((prevInputs) => [...prevInputs, ""]);
props.handleSaveWidgetsOptions(null, null, flage, false);
props.handleSaveWidgetsOptions(null, null, null, null, null, flage, false);
};
const handleDeleteInput = (ind) => {
@@ -39,14 +48,23 @@ function DropdownWidgetOption(props) {
(data, index) => index !== ind
);
setDropdownOptionList(getUpdatedOptions);
props.handleSaveWidgetsOptions(null, null, false, flage);
props.handleSaveWidgetsOptions(null, null, null, null, null, false, flage);
};
const handleSaveOption = () => {
props.handleSaveWidgetsOptions(dropdownName, dropdownOptionList);
props.handleSaveWidgetsOptions(
dropdownName,
dropdownOptionList,
minCount,
maxCount,
isReadOnly
);
props.setShowDropdown(false);
setDropdownOptionList(["option-1", "option-2"]);
setDropdownName(props.type);
props.setCurrWidgetsDetails([]);
setIsReadOnly(false);
setMinCount(0);
setMaxCount(0);
};
return (
@@ -58,6 +76,20 @@ function DropdownWidgetOption(props) {
closeOff={true}
>
<div style={{ height: "100%", padding: 20 }}>
{props.type === "checkbox" && !props.isSignYourself && (
<>
<input
type="checkbox"
checked={isReadOnly}
onChange={(e) => {
setIsReadOnly(e.target.checked);
}}
/>
<label style={{ marginLeft: "10px" }}>Is read only</label>
</>
)}
<form
onSubmit={(e) => {
e.preventDefault();
@@ -65,6 +97,31 @@ function DropdownWidgetOption(props) {
}}
>
<div className="dropdownContainer">
{props.type === "checkbox" && !props.isSignYourself && (
<>
<label style={{ fontSize: "13px", fontWeight: "600" }}>
Minimun required count
</label>
<input
required
defaultValue={0}
value={minCount}
onChange={(e) => setMinCount(e.target.value)}
className="drodown-input"
/>
<label style={{ fontSize: "13px", fontWeight: "600" }}>
Maximum required count
</label>
<input
required
defaultValue={0}
value={maxCount}
onChange={(e) => setMaxCount(e.target.value)}
className="drodown-input"
/>
</>
)}
<label style={{ fontSize: "13px", fontWeight: "600" }}>Name</label>
<input
required
@@ -12,6 +12,34 @@ function InputValidation(props) {
}}
title={"Validation"}
>
<div style={{ height: "100%", padding: "10px 20px" }}>
<div className="validateText">
<label
style={{
marginRight: "5px",
fontSize: "14px",
fontWeight: "500"
}}
>
Hint:
</label>
<div style={{ position: "relative" }}>
<input
value={props.hint}
style={{
position: "absolute",
top: "0",
left: "0",
height: "100%",
padding: 10
}}
placeholder="Enter hint"
className="drodown-input validateInputText"
onChange={(e) => props.setHint(e.target.value)}
/>
</div>
</div>
</div>
<div style={{ height: "100%", padding: 20 }}>
<div className="validateText">
<label
@@ -23,7 +51,6 @@ function InputValidation(props) {
>
Regular expression:
</label>
<div style={{ position: "relative" }}>
<input
value={props.textValidate}
@@ -55,7 +82,6 @@ function InputValidation(props) {
</select>
</div>
</div>
<div
style={{
height: "1px",
@@ -10,12 +10,15 @@ import "../LegaDrive/LegaDrive.css";
function Placeholder(props) {
const [isDraggingEnabled, setDraggingEnabled] = useState(true);
const [isShowDateFormat, setIsShowDateFormat] = useState(false);
const [selectDate, setSelectDate] = useState();
const [selectDate, setSelectDate] = useState({
date: moment(new Date().getTime()).format("MM/DD/YYYY"),
format: "MM/dd/YYYY"
});
const [dateFormat, setDateFormat] = useState([]);
const [saveDateFormat, setSaveDateFormat] = useState("");
const dateFormatArr = [
"L",
// "DD/MM/YYYY",
"DD-MM-YYYY",
"YYYY-MM-DD",
"MM.DD.YYYY",
"MM-DD-YYYY",
@@ -29,6 +32,8 @@ function Placeholder(props) {
switch (data) {
case "L":
return "MM/dd/yyyy";
case "DD-MM-YYYY":
return "dd-MM-yyyy";
case "DD/MM/YYYY":
return "dd/MM/yyyy";
case "LL":
@@ -52,7 +57,13 @@ function Placeholder(props) {
const changeDateFormat = () => {
const updateDate = [];
dateFormatArr.map((data) => {
const date = new Date(selectDate?.date);
let date;
if (selectDate.format === "dd-MM-yyyy") {
const [day, month, year] = selectDate.date.split("-");
date = new Date(`${year}-${month}-${day}`);
} else {
date = new Date(selectDate?.date);
}
const milliseconds = date.getTime();
const newDate = moment(milliseconds).format(data);
const dateObj = {
@@ -142,8 +153,12 @@ function Placeholder(props) {
!props.isDragging &&
props.pos.type !== "label"
) {
props.handleLinkUser(props.data.Id);
props.setUniqueId(props.data.Id);
// props.handleLinkUser(props.data.Id);
// props.setUniqueId(props.data.Id);
if (props.pos.key === props.selectWidgetId) {
props.handleLinkUser(props.data.Id);
props.setUniqueId(props.data.Id);
}
} else if (!props.pos.type) {
if (
!props.pos.type &&
@@ -166,6 +181,23 @@ function Placeholder(props) {
}
};
const handleWidgetsOnclick = () => {
if (props.pos.type === "radio") {
props.setIsRadio(true);
} else if (props.pos.type === "dropdown") {
props?.setShowDropdown(true);
}
if (props.pos.type === "checkbox") {
props?.setIsCheckbox(true);
} else if (props.pos.type === "text") {
props.setIsValidate(true);
}
props.setSignKey(props.pos.key);
props.setUniqueId(props.data.Id);
props.setWidgetType(props.pos.type);
props.setCurrWidgetsDetails(props.pos);
};
const PlaceholderIcon = () => {
return (
props.isShowBorder && (
@@ -178,36 +210,11 @@ function Placeholder(props) {
<i
onClick={(e) => {
e.stopPropagation();
if (props.pos.type === "checkbox") {
props.setIsCheckboxRequired(true);
} else if (props.pos.type === "radio") {
props.setIsRadio(true);
} else if (props.pos.type === "dropdown") {
props?.setShowDropdown(true);
} else {
props.setIsValidate(true);
}
props.setSignKey(props.pos.key);
props.setUniqueId(props.data.Id);
props.setWidgetType(props.pos.type);
props.setCurrWidgetsDetails(props.pos);
handleWidgetsOnclick();
}}
onTouchEnd={(e) => {
e.stopPropagation();
if (props.pos.type === "checkbox") {
props.setIsCheckboxRequired(true);
}
if (props.pos.type === "radio") {
props.setIsRadio(true);
} else {
props.setIsValidate(true);
}
props.setSignKey(props.pos.key);
props.setUniqueId(props.data.Id);
props.setWidgetType(props.pos.type);
props.setCurrWidgetsDetails(props.pos);
handleWidgetsOnclick();
}}
className="fa-solid fa-gear settingIcon"
style={{
@@ -428,8 +435,8 @@ function Placeholder(props) {
bounds="parent"
className="signYourselfBlock"
style={{
border: "1px solid #007bff",
borderRadius: "2px",
border: props.pos.type !== "checkbox" && "1px solid #007bff",
borderRadius: props.pos.type !== "checkbox" && "2px",
textAlign:
props.pos.type !== "name" &&
props.pos.type !== "company" &&
@@ -447,7 +454,9 @@ function Placeholder(props) {
: props?.pos?.zIndex
? props.pos.zIndex
: "5",
background: props.data ? props.data.blockColor : "rgb(203 233 237)"
background: props.data
? props.pos.type !== "checkbox" && props.data.blockColor
: props.pos.type !== "checkbox" && "rgb(203 233 237)"
}}
onDrag={() => {
setDraggingEnabled(true);
@@ -17,6 +17,7 @@ function PlaceholderType(props) {
isChecked: false,
selectValue: ""
});
const [selectedCheckbox, setSelectedCheckbox] = useState([]);
const validateExpression = (regexValidation) => {
let regexObject = regexValidation;
@@ -86,7 +87,9 @@ function PlaceholderType(props) {
}
}
useEffect(() => {
if (props.pos?.options?.validation?.type) {
if (props.pos?.options?.hint) {
setValidatePlaceholder(props.pos?.options.hint);
} else if (props.pos?.options?.validation?.type) {
checkRegularExpress(props.pos?.options?.validation?.type);
}
}, []);
@@ -99,22 +102,74 @@ function PlaceholderType(props) {
}, []);
useEffect(() => {
if (props.pos?.type && props.pos.type === "radio" && props.isNeedSign) {
const isCheckedValue = isCheckedRadio?.selectValue
? isCheckedRadio.selectValue
: selectedCheckbox;
if (props.pos?.type && props.pos.type === "checkbox") {
let isDefaultValue;
if (props.isNeedSign) {
isDefaultValue = props.pos.options?.defaultValue;
}
if (isDefaultValue && isDefaultValue.length > 0) {
onChangeInput(
isCheckedValue,
props.pos.key,
props.xyPostion,
props.index,
props.setXyPostion,
props.data && props.data.Id,
false,
null,
null,
null,
true
);
} else {
onChangeInput(
isCheckedValue,
props.pos.key,
props.xyPostion,
props.index,
props.setXyPostion,
props.data && props.data.Id,
false,
null,
props.isPlaceholder,
isCheckedRadio.selectedKey
);
}
} else if (props.pos?.type && props.pos.type === "radio") {
onChangeInput(
isCheckedRadio.selectValue,
isCheckedValue,
props.pos.key,
props.xyPostion,
props.index,
props.setXyPostion,
props.data && props.data.Id,
false
false,
null
);
}
}, [isCheckedRadio]);
//for handle default checked options
useEffect(() => {
if (props.pos?.type && props.pos.type === "checkbox" && props.isNeedSign) {
const isDefaultValue = props.pos.options?.defaultValue;
setSelectedCheckbox(isDefaultValue);
}
}, []);
useEffect(() => {
if (props.pos?.type && props.pos.type === "date") {
if (props.selectDate) {
const updateDate = new Date(props.saveDateFormat);
let updateDate;
if (props.selectDate.format === "dd-MM-yyyy") {
const [day, month, year] = props.saveDateFormat.split("-");
updateDate = new Date(`${year}-${month}-${day}`);
} else {
updateDate = new Date(props.saveDateFormat);
}
// const updateDate = new Date(props.saveDateFormat);
setStartDate(updateDate);
const dateObj = {
date: props.saveDateFormat,
@@ -206,6 +261,30 @@ function PlaceholderType(props) {
}
};
//function for show checked checkbox
const selectCheckbox = (ind) => {
const res = props.pos.options?.response;
const defaultCheck = props.pos.options?.defaultValue;
if (res) {
const isSelectIndex = res.indexOf(ind);
if (isSelectIndex > -1) {
return true;
} else {
return false;
}
// }
} else if (defaultCheck) {
const isSelectIndex = defaultCheck.indexOf(ind);
if (isSelectIndex > -1) {
return true;
} else {
return false;
}
} else {
return false;
}
};
switch (props.pos.type) {
case "signature":
return props.pos.SignUrl ? (
@@ -219,21 +298,15 @@ function PlaceholderType(props) {
}}
/>
) : (
<div
style={{
fontSize: "10px",
color: "black",
justifyContent: "center"
}}
>
<div>{props.pos.type}</div>
<div style={{ fontSize: 11, color: "black", justifyContent: "center" }}>
{props?.handleUserName &&
props?.handleUserName(props?.data.Id, props?.data.Role)}
props?.handleUserName(
props?.data.Id,
props?.data.Role,
props.pos.type
)}
</div>
);
case "stamp":
return props.pos.SignUrl ? (
<img
@@ -246,60 +319,104 @@ function PlaceholderType(props) {
}}
/>
) : (
<div
style={{
fontSize: "12px",
color: "black",
justifyContent: "center"
}}
>
<div>{props.pos.type}</div>
<div style={{ fontSize: 11, color: "black", justifyContent: "center" }}>
{props?.handleUserName &&
props?.handleUserName(props?.data.Id, props?.data.Role)}
props?.handleUserName(
props?.data.Id,
props?.data.Role,
props.pos.type
)}
</div>
);
case "checkbox":
return (
<input
className="inputPlaceholder"
style={{ outlineColor: "#007bff" }}
type="checkbox"
defaultChecked={props.pos?.options?.status === "Read only"}
disabled={
props.isNeedSign && props.data?.signerObjId !== props.signerObjId
? true
: props.isNeedSign &&
props.pos?.options?.status === "Read only" &&
true
// : props.isPlaceholder
}
onBlur={handleInputBlur}
checked={handleChecked()}
onChange={(e) => {
let isChecked = e.target.checked;
if (props.isPlaceholder) {
if (props.pos?.options?.status === "Read only") {
setCheckedValue(true);
isChecked = true;
} else {
setCheckedValue(false);
isChecked = false;
}
}
// <input
// className="inputPlaceholder"
// style={{ outlineColor: "#007bff" }}
// type="checkbox"
// defaultChecked={props.pos?.options?.status === "Read only"}
// disabled={
// props.isNeedSign && props.data?.signerObjId !== props.signerObjId
// ? true
// : props.isNeedSign &&
// props.pos?.options?.status === "Read only" &&
// true
// // : props.isPlaceholder
// }
// onBlur={handleInputBlur}
// checked={handleChecked()}
// onChange={(e) => {
// let isChecked = e.target.checked;
// if (props.isPlaceholder) {
// if (props.pos?.options?.status === "Read only") {
// setCheckedValue(true);
// isChecked = true;
// } else {
// setCheckedValue(false);
// isChecked = false;
// }
// }
onChangeInput(
isChecked,
props.pos.key,
props.xyPostion,
props.index,
props.setXyPostion,
props.data && props.data.Id,
false
// onChangeInput(
// isChecked,
// props.pos.key,
// props.xyPostion,
// props.index,
// props.setXyPostion,
// props.data && props.data.Id,
// false
// );
// }}
// />
<div>
{props.pos.options?.values?.map((data, ind) => {
return (
<input
key={ind}
style={{
width: props.pos.Width,
display: "flex",
justifyContent: "center",
marginBottom: "6px",
marginTop: "5px"
}}
disabled={
props.isNeedSign &&
props.pos.options?.isReadOnly &&
props.pos.options?.isReadOnly
}
type="checkbox"
checked={selectCheckbox(ind)}
onChange={(e) => {
if (e.target.checked) {
const maxRequired =
props.pos.options?.validation?.maxRequiredCount;
const maxCountInt = maxRequired && parseInt(maxRequired);
if (maxCountInt > 0) {
if (selectedCheckbox.length <= maxCountInt - 1) {
setSelectedCheckbox((prev) => [...prev, ind]);
}
} else {
setSelectedCheckbox((prev) => [...prev, ind]);
}
} else {
const removeOption = selectedCheckbox.filter(
(data) => data !== ind
);
setSelectedCheckbox(removeOption);
}
}}
onClick={() => {
setIsCheckedRadio({
isChecked: !isCheckedRadio,
selectValue: "",
selectedKey: ind
});
}}
/>
);
}}
/>
})}
</div>
);
case "text":
return props.isSignYourself ||
@@ -404,20 +521,15 @@ function PlaceholderType(props) {
}}
/>
) : (
<div
style={{
fontSize: "10px",
color: "black",
justifyContent: "center"
}}
>
<div>{props.pos.type}</div>
<div style={{ fontSize: 11, color: "black", justifyContent: "center" }}>
{props?.handleUserName &&
props?.handleUserName(props?.data.Id, props?.data.Role)}
props?.handleUserName(
props?.data.Id,
props?.data.Role,
props.pos.type
)}
</div>
);
case "name":
return props.isSignYourself ||
(props.isNeedSign && props.data?.signerObjId === props.signerObjId) ? (
@@ -457,7 +569,6 @@ function PlaceholderType(props) {
<span>{props.pos.type}</span>
</div>
);
case "company":
return props.isSignYourself ||
(props.isNeedSign && props.data?.signerObjId === props.signerObjId) ? (
@@ -496,7 +607,6 @@ function PlaceholderType(props) {
<span>{props.pos.type}</span>
</div>
);
case "job title":
return props.isSignYourself ||
(props.isNeedSign && props.data?.signerObjId === props.signerObjId) ? (
@@ -567,7 +677,6 @@ function PlaceholderType(props) {
/>
</div>
);
case "image":
return props.pos.SignUrl ? (
<img
@@ -580,17 +689,13 @@ function PlaceholderType(props) {
}}
/>
) : (
<div
style={{
fontSize: "10px",
color: "black",
justifyContent: "center"
}}
>
<div>{props.pos.type}</div>
<div style={{ fontSize: 11, color: "black", justifyContent: "center" }}>
{props?.handleUserName &&
props?.handleUserName(props?.data.Id, props?.data.Role)}
props?.handleUserName(
props?.data.Id,
props?.data.Role,
props.pos.type
)}
</div>
);
case "email":
@@ -649,6 +754,7 @@ function PlaceholderType(props) {
marginTop: "5px"
}}
type="radio"
disabled={props.isPlaceholder}
checked={isCheckedRadio.selectValue === data}
// checked={isCheckedRadio.isChecked}
onClick={() => {
@@ -664,7 +770,29 @@ function PlaceholderType(props) {
);
case "label":
return (
// <textarea
// onChange={(e) => {
// onChangeInput(
// e.target.value,
// props.pos.key,
// props.xyPostion,
// props.index,
// props.setXyPostion,
// props.data && props.data?.Id,
// false
// );
// }}
// className="labelTextArea"
// cols="50"
// style={{
// zIndex: "99",
// height: "100%",
// width: "100%",
// resize: "none"
// }}
// />
<textarea
rows={1}
onChange={(e) => {
onChangeInput(
e.target.value,
@@ -678,12 +806,6 @@ function PlaceholderType(props) {
}}
className="labelTextArea"
cols="50"
style={{
zIndex: "99",
height: "100%",
width: "100%",
resize: "none"
}}
/>
);
default:
@@ -63,7 +63,8 @@ function RenderPdf({
setCurrWidgetsDetails,
setSelectWidgetId,
selectWidgetId,
unSignedWidgetId
unSignedWidgetId,
setIsCheckbox
}) {
const isMobile = window.innerWidth < 767;
const newWidth = containerWH.width;
@@ -283,23 +284,46 @@ function RenderPdf({
);
};
const handleUserName = (Id, Role) => {
const handleUserName = (Id, Role, type) => {
if (Id) {
const checkSign = signersdata.find((sign) => sign.Id === Id);
if (checkSign?.Name) {
return (
<>
<div style={{ color: "black", fontSize: 11 }}>
<div style={{ color: "black", fontSize: 8, fontWeight: "500" }}>
{checkSign?.Name}
</div>
<div style={{ color: "black", fontSize: 11 }}> {`(${Role})`} </div>
{type && (
<div style={{ fontWeight: "700", fontSize: 11 }}>{type}</div>
)}
<div style={{ color: "black", fontSize: 8, fontWeight: "500" }}>
{`(${Role})`}
</div>
</>
);
} else {
return <div style={{ color: "black", fontSize: 11 }}> {Role} </div>;
return (
<>
{type && (
<div style={{ fontWeight: "700", fontSize: 11 }}>{type}</div>
)}
<div style={{ color: "black", fontSize: 8, fontWeight: "500" }}>
{Role}
</div>
</>
);
}
} else {
return <div style={{ color: "black", fontSize: 11 }}> {Role} </div>;
return (
<>
{type && (
<div style={{ fontWeight: "700", fontSize: 11 }}>{type}</div>
)}
<div style={{ color: "black", fontSize: 8, fontWeight: "500" }}>
{Role}
</div>
</>
);
}
};
@@ -370,6 +394,7 @@ function RenderPdf({
setIsValidate={setIsValidate}
setWidgetType={setWidgetType}
setIsRadio={setIsRadio}
setIsCheckbox={setIsCheckbox}
setCurrWidgetsDetails={
setCurrWidgetsDetails
}
@@ -549,6 +574,7 @@ function RenderPdf({
setIsValidate={setIsValidate}
setWidgetType={setWidgetType}
setIsRadio={setIsRadio}
setIsCheckbox={setIsCheckbox}
setCurrWidgetsDetails={
setCurrWidgetsDetails
}
@@ -1,6 +1,5 @@
import React, { useState, useRef, useEffect } from "react";
import axios from "axios";
import moment from "moment";
import Parse from "parse";
import "../css/./signature.css";
import { PDFDocument } from "pdf-lib";
@@ -26,7 +25,8 @@ import {
addZIndex,
randomId,
defaultWidthHeight,
multiSignEmbed
multiSignEmbed,
addWidgetOptions
} from "../utils/Utils";
import RenderPdf from "./component/renderPdf";
import { useNavigate } from "react-router-dom";
@@ -102,7 +102,8 @@ function PlaceHolderSign() {
const [isRadio, setIsRadio] = useState(false);
const [currWidgetsDetails, setCurrWidgetsDetails] = useState([]);
const [selectWidgetId, setSelectWidgetId] = useState("");
const [isCheckbox, setIsCheckbox] = useState(false);
const [hint, setHint] = useState("");
const color = [
"#93a3db",
"#e6c3db",
@@ -126,6 +127,7 @@ function PlaceHolderSign() {
isOver: !!monitor.isOver()
})
});
const [{ isDragSign }, dragSignature] = useDrag({
type: "BOX",
item: {
@@ -315,163 +317,11 @@ function PlaceHolderSign() {
}
};
const getDate = () => {
const date = new Date();
const milliseconds = date.getTime();
const newDate = moment(milliseconds).format("MM/DD/YYYY");
return newDate;
};
const addWidgetOptions = (type) => {
let option = {};
switch (type) {
case "signature":
option = {
name: "",
values: [],
status: "",
response: "",
validation: {}
};
return option;
case "stamp":
option = {
name: "",
values: [],
status: "",
response: "",
validation: {}
};
return option;
case "checkbox":
option = {
name: "",
values: [],
status: "Optional",
response: false,
validation: {}
};
return option;
case "text":
option = {
name: "",
values: [],
status: "",
response: "",
validation: {}
};
return option;
case "initials":
option = {
name: "",
values: [],
status: "",
response: "",
validation: {}
};
return option;
case "name":
option = {
name: "",
values: [],
status: "",
response: "",
validation: {
type: "text",
pattern: ""
}
};
return option;
case "company":
option = {
name: "",
values: [],
status: "",
response: "",
validation: {
type: "text",
pattern: ""
}
};
return option;
case "job title":
option = {
name: "",
values: [],
status: "",
response: "",
validation: {
type: "text",
pattern: ""
}
};
return option;
case "date":
option = {
name: "",
values: [],
status: "",
response: getDate()
};
return option;
case "image":
option = {
name: "",
values: [],
status: "",
response: "",
validation: {}
};
return option;
case "email":
option = {
name: "",
values: [],
status: "",
response: "",
validation: {
type: "email",
pattern: ""
}
};
return option;
case "dropdown":
option = {
name: "",
values: [],
status: "",
response: "",
validation: {}
};
return option;
case "radio":
option = {
name: "",
values: [],
status: "",
response: "",
validation: {}
};
return option;
case "label":
option = {
name: "",
values: [],
status: "",
response: "",
validation: {}
};
return option;
}
};
//function for setting position after drop signature button over pdf
const addPositionOfSignature = (item, monitor) => {
getSignerPos(item, monitor);
};
const getSignerPos = (item, monitor) => {
// setSignerObjId("");
// setContractName("");
@@ -636,7 +486,8 @@ function PlaceHolderSign() {
if (dragTypeValue === "dropdown") {
setShowDropdown(true);
} else if (dragTypeValue === "checkbox") {
setIsCheckboxRequired(true);
// setIsCheckboxRequired(true);
setIsCheckbox(true);
} else if (dragTypeValue === "radio") {
setIsRadio(true);
}
@@ -864,7 +715,6 @@ function PlaceHolderSign() {
// Save the Parse File if needed
const pdfData = await pdfFile.save();
const pdfUrl = pdfData.url();
return pdfUrl;
} catch (e) {
@@ -1100,6 +950,9 @@ function PlaceHolderSign() {
const handleSaveWidgetsOptions = (
dropdownName,
dropdownOptions,
minCount,
maxCount,
isReadOnly,
addOption,
deleteOption
) => {
@@ -1142,6 +995,36 @@ function PlaceHolderSign() {
}
};
}
} else if (widgetType === "checkbox") {
if (addOption) {
return {
...position,
Height: position.Height
? position.Height + 15
: defaultWidthHeight(widgetType).height + 15
};
} else if (deleteOption) {
return {
...position,
Height: position.Height
? position.Height - 15
: defaultWidthHeight(widgetType).height - 15
};
} else {
return {
...position,
options: {
...position.options,
name: dropdownName,
values: dropdownOptions,
validation: {
minRequiredCount: minCount,
maxRequiredCount: maxCount
},
isReadOnly: isReadOnly
}
};
}
} else {
return {
...position,
@@ -1313,6 +1196,7 @@ function PlaceHolderSign() {
...position,
options: {
...position.options,
hint: hint,
validation: {
type: regexType ? regularExpression : "regex",
pattern: !regexType ? regularExpression : ""
@@ -1573,7 +1457,7 @@ function PlaceHolderSign() {
</div>
</ModalUi>
{/* checkbox widget status component */}
<CheckboxStatus
{/* <CheckboxStatus
setSelectRequiredType={setSelectRequiredType}
selectRequiredType={selectRequiredType}
isCheckboxRequired={isCheckboxRequired}
@@ -1581,11 +1465,13 @@ function PlaceHolderSign() {
handleApplyWidgetsStatus={handleApplyWidgetsStatus}
currWidgetsDetails={currWidgetsDetails}
setCurrWidgetsDetails={setCurrWidgetsDetails}
/>
/> */}
<InputValidation
setIsValidate={setIsValidate}
handleValidateInput={handleValidateInput}
isValidate={isValidate}
hint={hint}
setHint={setHint}
setTextValidate={setTextValidate}
textValidate={textValidate}
/>
@@ -1609,6 +1495,15 @@ function PlaceHolderSign() {
currWidgetsDetails={currWidgetsDetails}
setCurrWidgetsDetails={setCurrWidgetsDetails}
/>
<DropdownWidgetOption
type="checkbox"
title="Checkbox"
showDropdown={isCheckbox}
setShowDropdown={setIsCheckbox}
handleSaveWidgetsOptions={handleSaveWidgetsOptions}
currWidgetsDetails={currWidgetsDetails}
setCurrWidgetsDetails={setCurrWidgetsDetails}
/>
<DropdownWidgetOption
type="dropdown"
title="Dropdown options"
@@ -1667,6 +1562,7 @@ function PlaceHolderSign() {
setIsValidate={setIsValidate}
setWidgetType={setWidgetType}
setIsRadio={setIsRadio}
setIsCheckbox={setIsCheckbox}
setCurrWidgetsDetails={setCurrWidgetsDetails}
setSelectWidgetId={setSelectWidgetId}
selectWidgetId={selectWidgetId}
@@ -866,17 +866,16 @@ option {
.labelTextArea {
font-size: 0.8rem;
letter-spacing: 1px;
padding: 10px;
max-width: 100%;
line-height: 1.5;
/* border: 1px solid #ccc;
box-shadow: 1px 1px 1px #999; */
border: 1px solid #007bff;
border-radius: 2px;
font-family: inherit;
font-size: 12px;
min-width: 100%;
min-height: 100%;
border: 1px solid #007bff;
outline: none;
z-index: 999;
border-radius: 2px;
resize: none;
}
.labelTextArea:focus {
+154 -98
View File
@@ -1,5 +1,6 @@
import axios from "axios";
import { rgb } from "pdf-lib";
import moment from "moment";
import { themeColor } from "./ThemeColor/backColor";
export const isMobile = window.innerWidth < 767;
@@ -82,6 +83,10 @@ export const addInitialData = (signerPos, setXyPostion, value, userId) => {
}
});
};
const handleDefaultValue = (ind, defaultValue) => {
const updateDefault = defaultValue.filter((data) => data !== ind);
return updateDefault;
};
export const onChangeInput = (
value,
signKey,
@@ -90,7 +95,10 @@ export const onChangeInput = (
setXyPostion,
userId,
initial,
dateFormat
dateFormat,
isPlaceholder,
selectedKey,
isDefaultEmpty
) => {
const isSigners = xyPostion.some((data) => data.signerPtr);
let filterSignerPos;
@@ -98,9 +106,7 @@ export const onChangeInput = (
if (userId) {
filterSignerPos = xyPostion.filter((data) => data.Id === userId);
}
const getPlaceHolder = filterSignerPos[0]?.placeHolder;
if (initial) {
const xyData = addInitialData(xyPostion, setXyPostion, value, userId);
setXyPostion(xyData);
@@ -108,7 +114,6 @@ export const onChangeInput = (
const getPageNumer = getPlaceHolder.filter(
(data) => data.pageNumber === index
);
if (getPageNumer.length > 0) {
const getXYdata = getPageNumer[0].pos;
const getPosData = getXYdata;
@@ -126,10 +131,38 @@ export const onChangeInput = (
}
}
};
} else if (isPlaceholder) {
return {
...position,
options: {
...position.options,
defaultValue: value
}
};
} else if (selectedKey) {
return {
...position,
options: {
...position.options,
response: value,
defaultValue: handleDefaultValue(
selectedKey,
position.options.defaultValue
)
}
};
} else if (isDefaultEmpty) {
return {
...position,
options: {
...position.options,
response: value,
defaultValue: []
}
};
} else {
return {
...position,
options: {
...position.options,
response: value
@@ -139,7 +172,6 @@ export const onChangeInput = (
}
return position;
});
const newUpdateSignPos = getPlaceHolder.map((obj) => {
if (obj.pageNumber === index) {
return { ...obj, pos: addSignPos };
@@ -256,6 +288,51 @@ export const widgets = [
}
];
const getDate = () => {
const date = new Date();
const milliseconds = date.getTime();
const newDate = moment(milliseconds).format("MM/DD/YYYY");
return newDate;
};
export const addWidgetOptions = (type) => {
const defaultOpt = {
name: "",
status: "required"
};
switch (type) {
case "signature":
return defaultOpt;
case "stamp":
return defaultOpt;
case "checkbox":
return defaultOpt;
case "text":
return defaultOpt;
case "initials":
return defaultOpt;
case "name":
return { ...defaultOpt, validation: { type: "text", pattern: "" } };
case "company":
return { ...defaultOpt, validation: { type: "text", pattern: "" } };
case "job title":
return { ...defaultOpt, validation: { type: "text", pattern: "" } };
case "date":
return { ...defaultOpt, response: getDate() };
case "image":
return defaultOpt;
case "email":
return { ...defaultOpt, validation: { type: "email", pattern: "" } };
case "dropdown":
return defaultOpt;
case "radio":
return defaultOpt;
case "label":
return defaultOpt;
default:
return {};
}
};
export const getWidgetType = (item, marginLeft) => {
return (
<>
@@ -309,100 +386,37 @@ export const getWidgetType = (item, marginLeft) => {
};
export const defaultWidthHeight = (type) => {
let obj;
switch (type) {
case "signature":
obj = {
width: 150,
height: 60
};
return obj;
return { width: 150, height: 60 };
case "stamp":
obj = {
width: 150,
height: 60
};
return obj;
return { width: 150, height: 60 };
case "checkbox":
obj = {
width: 15,
height: 15
};
return obj;
return { width: 15, height: 15 };
case "text":
obj = {
width: 150,
height: 25
};
return obj;
return { width: 150, height: 25 };
case "dropdown":
obj = {
width: 120,
height: 22
};
return obj;
return { width: 120, height: 22 };
case "initials":
obj = {
width: 50,
height: 50
};
return obj;
return { width: 50, height: 50 };
case "name":
obj = {
width: 150,
height: 25
};
return obj;
return { width: 150, height: 25 };
case "company":
obj = {
width: 150,
height: 25
};
return obj;
return { width: 150, height: 25 };
case "job title":
obj = {
width: 150,
height: 25
};
return obj;
return { width: 150, height: 25 };
case "date":
obj = {
width: 100,
height: 20
};
return obj;
return { width: 100, height: 20 };
case "image":
obj = {
width: 150,
height: 60
};
return obj;
return { width: 70, height: 70 };
case "email":
obj = {
width: 150,
height: 20
};
return obj;
return { width: 150, height: 20 };
case "radio":
obj = {
width: 15,
height: 30
};
return obj;
return { width: 15, height: 30 };
case "label":
obj = {
width: 150,
height: 17
};
return obj;
return { width: 150, height: 17 };
default:
obj = {
width: 150,
height: 60
};
return obj;
return { width: 150, height: 60 };
}
};
@@ -1020,7 +1034,7 @@ export const multiSignEmbed = async (
}
};
const yPos = (pos) => {
const yPos = (pos, ind) => {
const resizePos = pos.yPosition;
if (signyourself) {
if (isMobile) {
@@ -1054,7 +1068,12 @@ export const multiSignEmbed = async (
return page.getHeight() - y - scaleHeight;
}
} else {
const widgetHeight = imgData.type === "radio" ? 10 : scaleHeight;
const widgetHeight =
imgData.type === "radio"
? 10
: imgData.type === "checkbox"
? 10
: scaleHeight;
return page.getHeight() - resizePos - widgetHeight;
// - scaleHeight;
}
@@ -1072,21 +1091,58 @@ export const multiSignEmbed = async (
"label"
].includes(imgData.type);
if (imgData.type === "checkbox") {
const checkBox = form.createCheckBox(randomboxId);
let addYPosition, isCheck;
checkBox.addToPage(page, {
x: xPos(imgData),
y: yPos(imgData),
width: scaleWidth,
height: scaleHeight
});
if (imgData.options.response) {
checkBox.check();
} else {
checkBox.uncheck();
if (imgData?.options?.values.length > 0) {
imgData?.options?.values.forEach((item, ind) => {
const checkboxRandomId = "checkbox" + randomId();
let yPosition;
const height = 10;
if (imgData?.options?.response) {
isCheck = imgData?.options?.response?.includes(ind);
} else if (imgData?.options?.defaultValue) {
isCheck = imgData?.options?.defaultValue?.includes(ind);
}
const checkbox = form.createCheckBox(checkboxRandomId);
if (ind > 0) {
yPosition = yPos(imgData, ind) - addYPosition;
addYPosition = addYPosition + height + 10;
} else {
yPosition = yPos(imgData, ind);
addYPosition = height + 10;
}
checkbox.addToPage(page, {
x: xPos(imgData),
y: yPosition,
width: height,
height: height
});
if (isCheck) {
checkbox.check();
} else {
checkbox.uncheck();
}
checkbox.enableReadOnly();
});
}
checkBox.enableReadOnly();
// const checkBox = form.createCheckBox(randomboxId);
// checkBox.addToPage(page, {
// x: xPos(imgData),
// y: yPos(imgData),
// width: scaleWidth,
// height: scaleHeight
// });
// if (imgData.options.response) {
// checkBox.check();
// } else {
// checkBox.uncheck();
// }
// checkBox.enableReadOnly();
} else if (widgetTypeExist) {
const font = await pdfDoc.embedFont("Helvetica");
const fontSize = 12;