mirror of
https://github.com/OpenSignLabs/OpenSign.git
synced 2026-08-17 21:25:54 +02:00
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:
@@ -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 {
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user