feat: implement initial signature feature, fix signature drag and sign-your self issue

This commit is contained in:
RaktimaNXG
2024-01-24 18:01:06 +05:30
parent 1f16123865
commit ad5776cfba
12 changed files with 661 additions and 405 deletions
@@ -8,7 +8,6 @@ import "../css/signature.css";
import axios from "axios";
import { toDataUrl } from "../utils/toDataUrl";
const ManageSign = () => {
let appName;
const [penColor, setPenColor] = useState("blue");
@@ -50,7 +49,7 @@ const ManageSign = () => {
const userId = {
__type: "Pointer",
className: "_User",
objectId: User.objectId,
objectId: User.objectId
};
const strObj = JSON.stringify(userId);
const url =
@@ -59,7 +58,7 @@ const ManageSign = () => {
const headers = {
"Content-Type": "application/json",
"X-Parse-Application-Id": localStorage.getItem("parseAppId"),
"X-Parse-Application-Id": localStorage.getItem("parseAppId")
// "X-Parse-Session-Token": localStorage.getItem("accesstoken"),
};
const res = await axios
@@ -142,7 +141,6 @@ const ManageSign = () => {
if (!signName) {
setNameWarning(true);
} else if (!isvalue) {
setWarning(true);
setTimeout(() => setWarning(false), 1000);
@@ -173,7 +171,7 @@ const ManageSign = () => {
await saveEntry({
name: signName,
url: imgUrl.data.imageUrl,
initialsUrl: initialsUrl,
initialsUrl: initialsUrl
});
}
}
@@ -199,14 +197,14 @@ const ManageSign = () => {
const config = {
headers: {
"content-type": "multipart/form-data",
"X-Parse-Application-Id": localStorage.getItem("parseAppId"),
"X-Parse-Application-Id": localStorage.getItem("parseAppId")
},
onUploadProgress: function (progressEvent) {
let percentCompleted = Math.round(
(progressEvent.loaded * 100) / progressEvent.total
);
// setpercentage(percentCompleted);
},
}
};
const response = await axios
.post(url, formData, config)
@@ -241,12 +239,12 @@ const ManageSign = () => {
UserId: {
__type: "Pointer",
className: "_User",
objectId: User.objectId,
},
objectId: User.objectId
}
};
const headers = {
"Content-Type": "application/json",
"X-Parse-Application-Id": localStorage.getItem("parseAppId"),
"X-Parse-Application-Id": localStorage.getItem("parseAppId")
// "X-Parse-Session-Token": localStorage.getItem("accesstoken"),
};
const res = await axios
@@ -279,12 +277,12 @@ const ManageSign = () => {
UserId: {
__type: "Pointer",
className: "_User",
objectId: User.objectId,
},
objectId: User.objectId
}
};
const headers = {
"Content-Type": "application/json",
"X-Parse-Application-Id": localStorage.getItem("parseAppId"),
"X-Parse-Application-Id": localStorage.getItem("parseAppId")
// "X-Parse-Session-Token": localStorage.getItem("accesstoken"),
};
const res = await axios
@@ -320,7 +318,7 @@ const ManageSign = () => {
<div
style={{
maxHeight: "500px",
overflow: "auto",
overflow: "auto"
}}
>
{isSuccess && (
@@ -337,7 +335,7 @@ const ManageSign = () => {
className="mainDiv"
style={{
width: "100%",
paddingRight: "10px",
paddingRight: "10px"
}}
>
<div style={{ margin: 20 }}>
@@ -346,7 +344,7 @@ const ManageSign = () => {
fontWeight: "700",
fontSize: 15,
color: "#000",
paddingBottom: 8,
paddingBottom: 8
}}
>
Manage Signature
@@ -357,7 +355,7 @@ const ManageSign = () => {
style={{
fontSize: 12,
position: "relative",
paddingBottom: 5,
paddingBottom: 5
}}
>
Signer's Name
@@ -386,7 +384,7 @@ const ManageSign = () => {
height: 35,
padding: "6px 12px",
marginBottom: 10,
fontSize: 12,
fontSize: 12
}}
required
onFocus={() => setNameWarning(false)}
@@ -397,7 +395,7 @@ const ManageSign = () => {
htmlFor="imgoverview"
style={{
fontSize: 12,
paddingBottom: 5,
paddingBottom: 5
}}
>
Signature/Image
@@ -412,7 +410,7 @@ const ManageSign = () => {
flexDirection: "row",
justifyContent: "space-between",
width: "50%",
paddingLeft: 10,
paddingLeft: 10
}}
>
<div
@@ -422,7 +420,7 @@ const ManageSign = () => {
justifyContent: "space-around",
alignItems: "center",
gap: 10,
marginBottom: 10,
marginBottom: 10
}}
>
<>
@@ -458,7 +456,7 @@ const ManageSign = () => {
position: "relative",
border: "2px solid #888",
marginBottom: 6,
marginBottom: 6
}}
className="signatureCanvas"
>
@@ -468,7 +466,7 @@ const ManageSign = () => {
style={{
width: "100%",
height: "100%",
objectFit: "contain",
objectFit: "contain"
}}
/>
</div>
@@ -479,7 +477,7 @@ const ManageSign = () => {
canvasProps={{
width: "456px",
height: "180px",
className: "signatureCanvas",
className: "signatureCanvas"
}}
backgroundColor="rgb(255, 255, 255)"
onEnd={() =>
@@ -492,7 +490,7 @@ const ManageSign = () => {
style={{
display: "flex",
flexDirection: "row",
justifyContent: "space-between",
justifyContent: "space-between"
// width: 460,
}}
className="penContainer"
@@ -513,10 +511,10 @@ const ManageSign = () => {
key === 0 && penColor === "blue"
? "2px solid blue"
: key === 1 && penColor === "red"
? "2px solid red"
: key === 2 && penColor === "black"
? "2px solid black"
: "2px solid white",
? "2px solid red"
: key === 2 && penColor === "black"
? "2px solid black"
: "2px solid white"
}}
onClick={() => {
if (key === 0) {
@@ -579,9 +577,9 @@ const ManageSign = () => {
position: "relative",
border: "2px solid #888",
marginBottom: 6,
marginBottom: 6
}}
className="signatureCanvas"
className="intialSignature"
>
<img
alt="preview image"
@@ -589,7 +587,7 @@ const ManageSign = () => {
style={{
width: "100%",
height: "100%",
objectFit: "contain",
objectFit: "contain"
}}
/>
</div>
@@ -598,9 +596,7 @@ const ManageSign = () => {
ref={initailsRef}
penColor={initialPen}
canvasProps={{
width: "456px",
height: "180px",
className: "signatureCanvas",
className: "intialSignature"
}}
backgroundColor="rgb(255, 255, 255)"
onEnd={() =>
@@ -613,8 +609,7 @@ const ManageSign = () => {
style={{
display: "flex",
flexDirection: "row",
justifyContent: "space-between",
// width: 460,
justifyContent: "space-between"
}}
className="penContainer"
>
@@ -624,7 +619,7 @@ const ManageSign = () => {
{allColor.map((data, key) => {
return (
<img
alt="pen"
alt="pen"
style={{
border: "none",
margin: "5px",
@@ -632,10 +627,10 @@ const ManageSign = () => {
key === 0 && initialPen === "blue"
? "2px solid blue"
: key === 1 && initialPen === "red"
? "2px solid red"
: key === 2 && initialPen === "black"
? "2px solid black"
: "2px solid white",
? "2px solid red"
: key === 2 && initialPen === "black"
? "2px solid black"
: "2px solid white"
}}
onClick={() => {
if (key === 0) {
@@ -74,6 +74,8 @@ function PdfRequestFiles() {
isCertificate: false,
isModal: false
});
const [myInitial, setMyInitial] = useState("");
const [isInitial, setIsInitial] = useState(false);
const [pdfLoadFail, setPdfLoadFail] = useState({
status: false,
type: "load"
@@ -270,6 +272,7 @@ function PdfRequestFiles() {
if (res[0] && res.length > 0) {
setDefaultSignImg(res[0].ImageURL);
setMyInitial(res[0]?.Initials);
}
const loadObj = {
@@ -450,7 +453,11 @@ function PdfRequestFiles() {
//function for save button to save signature or image url
const saveSign = (isDefaultSign, width, height) => {
const isTypeText = width && height ? true : false;
const signatureImg = isDefaultSign ? defaultSignImg : signature;
const signatureImg = isDefaultSign
? isDefaultSign === "initials"
? myInitial
: defaultSignImg
: signature;
let imgWH = { width: width ? width : "", height: height ? height : "" };
setIsSignPad(false);
setIsImageSelect(false);
@@ -805,6 +812,10 @@ function PdfRequestFiles() {
onSaveImage={saveImage}
onSaveSign={saveSign}
defaultSign={defaultSignImg}
myInitial={myInitial}
isInitial={isInitial}
setIsInitial={setIsInitial}
setIsStamp={setIsStamp}
/>
{/* pdf header which contain funish back button */}
<Header
@@ -846,6 +857,7 @@ function PdfRequestFiles() {
pdfLoadFail={pdfLoadFail}
setSignerPos={setSignerPos}
containerWH={containerWH}
setIsInitial={setIsInitial}
/>
)}
</div>
@@ -18,7 +18,8 @@ import {
pdfNewWidthFun,
addDefaultSignatureImg,
onImageSelect,
calculateInitialWidthHeight
calculateInitialWidthHeight,
defaultWidthHeight
} from "../utils/Utils";
import { useParams } from "react-router-dom";
import Tour from "reactour";
@@ -62,6 +63,8 @@ function SignYourSelf() {
const [successEmail, setSuccessEmail] = useState(false);
const imageRef = useRef(null);
const [documentStatus, setDocumentStatus] = useState({ isCompleted: false });
const [myInitial, setMyInitial] = useState("");
const [isInitial, setIsInitial] = useState(false);
const [isLoading, setIsLoading] = useState({
isLoad: true,
message: "This might take some time"
@@ -86,7 +89,6 @@ function SignYourSelf() {
});
const [isAlert, setIsAlert] = useState({ isShow: false, alertMessage: "" });
const [isDontShow, setIsDontShow] = useState(false);
const [initial, setInitial] = useState("");
const divRef = useRef(null);
const nodeRef = useRef(null);
const [{ isOver }, drop] = useDrop({
@@ -249,7 +251,7 @@ function SignYourSelf() {
const res = json.results;
if (res[0] && res.length > 0) {
setDefaultSignImg(res[0].ImageURL);
setInitial(res[0]?.Initials);
setMyInitial(res[0]?.Initials);
}
})
.catch((err) => {
@@ -323,48 +325,55 @@ function SignYourSelf() {
(data) => data.pageNumber === pageNumber
);
const dragTypeValue = item?.text ? item.text : monitor.type;
const widgetValue =
monitor.type === "name"
dragTypeValue === "name"
? pdfDetails[0].ExtUserPtr.Name
: monitor.type === "company"
: dragTypeValue === "company"
? pdfDetails[0].ExtUserPtr.Company
: monitor.type === "job title"
: dragTypeValue === "job title"
? pdfDetails[0].ExtUserPtr.JobTitle
: monitor.type === "checkbox"
? true
: "";
: dragTypeValue === "email"
? pdfDetails[0].ExtUserPtr.Email
: dragTypeValue === "checkbox"
? true
: "";
if (item === "onclick") {
dropObj = {
xPosition: window.innerWidth / 2 - 100,
yPosition: window.innerHeight / 2 - 60,
isDrag: false,
isStamp: monitor.type === "stamp" && true,
isStamp:
(dragTypeValue === "stamp" || dragTypeValue === "image") && true,
key: key,
type: monitor.type,
type: dragTypeValue,
yBottom: window.innerHeight / 2 - 60,
// SignUrl: monitor.type === "initials" && initial,
widgetValue: widgetValue,
Width:
monitor.type === "name" ||
monitor.type === "company" ||
monitor.type === "job title"
? calculateInitialWidthHeight(monitor.type, widgetValue).getWidth
: "",
dragTypeValue === "name" ||
dragTypeValue === "company" ||
dragTypeValue === "job title" ||
dragTypeValue === "email" ||
dragTypeValue === "initials"
? calculateInitialWidthHeight(dragTypeValue, widgetValue).getWidth
: dragTypeValue === "initials"
? defaultWidthHeight(dragTypeValue).width
: "",
Height:
monitor.type === "company" ||
monitor.type === "name" ||
monitor.type === "job title"
? calculateInitialWidthHeight(monitor.type, widgetValue).getHeight
: ""
dragTypeValue === "company" ||
dragTypeValue === "name" ||
dragTypeValue === "job title" ||
dragTypeValue === "email" ||
dragTypeValue === "initials"
? calculateInitialWidthHeight(dragTypeValue, widgetValue).getHeight
: dragTypeValue === "initials"
? defaultWidthHeight(dragTypeValue).height
: ""
};
dropData.push(dropObj);
if (monitor) {
setIsStamp(true);
} else {
setIsStamp(false);
}
} else {
const offset = monitor.getClientOffset();
//adding and updating drop position in array when user drop signature button in div
@@ -375,49 +384,39 @@ function SignYourSelf() {
const x = offset.x - containerRect.left;
const y = offset.y - containerRect.top;
const ybottom = containerRect.bottom - offset.y;
const widgetData =
item.text === "name"
? pdfDetails[0].ExtUserPtr.Name
: item.text === "company"
? pdfDetails[0].ExtUserPtr.Company
: item.text === "job title"
? pdfDetails[0].ExtUserPtr.JobTitle
: item.text === "checkbox"
? true
: "";
dropObj = {
xPosition: signBtnPosition[0] ? x - signBtnPosition[0].xPos : x,
yPosition: signBtnPosition[0] ? y - signBtnPosition[0].yPos : y,
isDrag: false,
isStamp: item.text === "stamp" && true,
isStamp:
(dragTypeValue === "stamp" || dragTypeValue === "image") && true,
key: key,
firstXPos: signBtnPosition[0] && signBtnPosition[0].xPos,
firstYPos: signBtnPosition[0] && signBtnPosition[0].yPos,
yBottom: ybottom,
type: item.text,
// SignUrl: item.text === "initials" && initial,
widgetValue: widgetData,
type: dragTypeValue,
widgetValue: widgetValue,
Width:
item.text === "name" ||
item.text === "company" ||
item.text === "job title"
? calculateInitialWidthHeight(item.text, widgetData).getWidth
: "",
dragTypeValue === "name" ||
dragTypeValue === "company" ||
dragTypeValue === "job title" ||
dragTypeValue === "email"
? calculateInitialWidthHeight(dragTypeValue, widgetValue).getWidth
: defaultWidthHeight(dragTypeValue).width,
Height:
item.text === "company" ||
item.text === "name" ||
item.text === "job title"
? calculateInitialWidthHeight(item.text, widgetData).getHeight
: ""
dragTypeValue === "company" ||
dragTypeValue === "name" ||
dragTypeValue === "job title" ||
dragTypeValue === "email"
? calculateInitialWidthHeight(dragTypeValue, widgetValue).getHeight
: dragTypeValue === "initials"
? defaultWidthHeight(dragTypeValue).height
: ""
};
dropData.push(dropObj);
if (isDragStamp || isDragStampSS) {
setIsStamp(true);
} else {
setIsStamp(false);
}
}
if (filterDropPos.length > 0) {
const index = xyPostion.findIndex((object) => {
@@ -432,10 +431,6 @@ function SignYourSelf() {
pos: newSignPos
};
xyPostion.splice(index, 1, xyPos);
if (isDragSign || isDragSignatureSS || isDragStamp || isDragStampSS) {
setIsSignPad(true);
setSignKey(key);
}
// }
} else {
@@ -444,11 +439,22 @@ function SignYourSelf() {
pos: dropData
};
setXyPostion((prev) => [...prev, xyPos]);
}
if (isDragSign || isDragSignatureSS || isDragStamp || isDragStampSS) {
setIsSignPad(true);
setSignKey(key);
}
if (
dragTypeValue === "signature" ||
dragTypeValue === "stamp" ||
dragTypeValue === "image" ||
dragTypeValue === "initials"
) {
setIsSignPad(true);
setSignKey(key);
}
if (dragTypeValue === "stamp" || dragTypeValue === "image") {
setIsStamp(true);
} else if (dragTypeValue === "initials") {
setIsInitial(true);
}
};
@@ -574,24 +580,13 @@ function SignYourSelf() {
const getPosData = getXYdata;
const addSign = getPosData.map((url, ind) => {
if (url.key === dragKey) {
if (type === "initials") {
return {
...url,
xPosition: dragElement.x,
yPosition: dragElement.y,
isDrag: true,
yBottom: ybottom,
SignUrl: initial
};
} else {
return {
...url,
xPosition: dragElement.x,
yPosition: dragElement.y,
isDrag: true,
yBottom: ybottom
};
}
return {
...url,
xPosition: dragElement.x,
yPosition: dragElement.y,
isDrag: true,
yBottom: ybottom
};
}
return url;
});
@@ -646,7 +641,11 @@ function SignYourSelf() {
//function for save button to save signature or image url
const saveSign = (isDefaultSign, width, height) => {
const isTypeText = width && height ? true : false;
const signatureImg = isDefaultSign ? defaultSignImg : signature;
const signatureImg = isDefaultSign
? isDefaultSign === "initials"
? myInitial
: defaultSignImg
: signature;
let imgWH = { width: width ? width : "", height: height ? height : "" };
setIsSignPad(false);
setIsImageSelect(false);
@@ -937,6 +936,10 @@ function SignYourSelf() {
onSaveImage={saveImage}
onSaveSign={saveSign}
defaultSign={defaultSignImg}
myInitial={myInitial}
isInitial={isInitial}
setIsInitial={setIsInitial}
setIsStamp={setIsStamp}
/>
{/* render email component to send email after finish signature on document */}
<EmailComponent
@@ -994,6 +997,7 @@ function SignYourSelf() {
index={index}
containerWH={containerWH}
setIsPageCopy={setIsPageCopy}
setIsInitial={setIsInitial}
/>
)}
</div>
@@ -1001,36 +1005,40 @@ function SignYourSelf() {
{/*if document is not completed then render signature and stamp button in the right side */}
{/*else document is completed then render signed by signer name in the right side */}
{!documentStatus.isCompleted ? (
<div>
<FieldsComponent
dataTut="reactourFirst"
pdfUrl={pdfUrl}
dragSignature={dragSignature}
signRef={signRef}
handleDivClick={handleDivClick}
handleMouseLeave={handleMouseLeave}
isDragSign={isDragSign}
themeColor={themeColor}
dragStamp={dragStamp}
dragRef={dragRef}
isDragStamp={isDragStamp}
isDragSignatureSS={isDragSignatureSS}
dragSignatureSS={dragSignatureSS}
dragStampSS={dragStampSS}
handleAllDelete={handleAllDelete}
xyPostion={xyPostion}
isSignYourself={true}
addPositionOfSignature={addPositionOfSignature}
isMailSend={false}
initial={initial}
/>
</div>
) : (
<div>
<Signedby pdfDetails={pdfDetails[0]} />
</div>
)}
<div
style={{ maxHeight: window.innerHeight - 70 + "px" }}
className="autoSignScroll"
>
{!documentStatus.isCompleted ? (
<div>
<FieldsComponent
dataTut="reactourFirst"
pdfUrl={pdfUrl}
dragSignature={dragSignature}
signRef={signRef}
handleDivClick={handleDivClick}
handleMouseLeave={handleMouseLeave}
isDragSign={isDragSign}
themeColor={themeColor}
dragStamp={dragStamp}
dragRef={dragRef}
isDragStamp={isDragStamp}
isDragSignatureSS={isDragSignatureSS}
dragSignatureSS={dragSignatureSS}
dragStampSS={dragStampSS}
handleAllDelete={handleAllDelete}
xyPostion={xyPostion}
isSignYourself={true}
addPositionOfSignature={addPositionOfSignature}
isMailSend={false}
/>
</div>
) : (
<div>
<Signedby pdfDetails={pdfDetails[0]} />
</div>
)}
</div>
</div>
)}
</DndProvider>
@@ -4,26 +4,27 @@ import { getWidgetType } from "../../utils/Utils";
function AllWidgets(props) {
return props.updateWidgets.map((item, ind) => {
return (
<div
key={ind}
onClick={() =>
props.addPositionOfSignature &&
props.addPositionOfSignature("onclick", item)
}
ref={(element) => {
if (!props.isMobile) {
item.ref(element);
if (element) {
if (props?.signRef) {
props.signRef.current = element;
<div key={ind} style={{ marginBottom: "10px" }}>
<div
onClick={() =>
props.addPositionOfSignature &&
props.addPositionOfSignature("onclick", item)
}
ref={(element) => {
if (!props.isMobile) {
item.ref(element);
if (element) {
if (props?.signRef) {
props.signRef.current = element;
}
}
}
}
}}
onMouseMove={props?.handleDivClick}
onMouseDown={props?.handleMouseLeave}
>
{item.ref && getWidgetType(item, props?.marginLeft)}
}}
onMouseMove={props?.handleDivClick}
onMouseDown={props?.handleMouseLeave}
>
{item.ref && getWidgetType(item, props?.marginLeft)}
</div>
</div>
);
});
@@ -2,7 +2,7 @@ import React, { useState } from "react";
import BorderResize from "../component/borderResize";
import PlaceholderBorder from "./placeholderBorder";
import { Rnd } from "react-rnd";
import { defaultWidthHeight } from "../../utils/Utils";
import { defaultWidthHeight, isMobile } from "../../utils/Utils";
import PlaceholderType from "./placeholderType";
function Placeholder(props) {
@@ -16,7 +16,8 @@ function Placeholder(props) {
props.pos.type === "name" ||
props.pos.type === "company" ||
props.pos.type === "job title" ||
props.pos.type === "date"
props.pos.type === "date" ||
props.pos.type === "email"
) {
setDraggingEnabled(false);
}
@@ -25,11 +26,16 @@ function Placeholder(props) {
if (
props.pos.type === "signature" ||
props.pos.type === "stamp" ||
props.pos.type === "initials"
props.pos.type === "image"
) {
props.setIsSignPad(true);
props.setSignKey(props.pos.key);
props.setIsStamp(props.pos.isStamp);
} else if (props.pos.type === "initials") {
props.setIsSignPad(true);
props.setSignKey(props.pos.key);
props.setIsStamp(props.pos.isStamp);
props.setIsInitial(true);
}
} else {
props.setIsSignPad(true);
@@ -66,6 +72,82 @@ function Placeholder(props) {
}
};
const PlaceholderIcon = () => {
return (
props.isShowBorder && (
<>
{props.isPlaceholder && (
<i
data-tut="reactourLinkUser"
className="fa-regular fa-user signUserIcon"
onClick={(e) => {
e.stopPropagation();
props.handleLinkUser(props.data.Id);
props.setUniqueId(props.data.Id);
}}
onTouchEnd={(e) => {
e.stopPropagation();
props.handleLinkUser(props.data.Id);
props.setUniqueId(props.data.Id);
}}
style={{
color: "#188ae2"
}}
></i>
)}
<i
className="fa-regular fa-copy signCopy"
onClick={(e) => {
if (props.data) {
props.setSignerObjId(props.data.signerObjId);
}
e.stopPropagation();
props.setIsPageCopy(true);
props.setSignKey(props.pos.key);
}}
onTouchEnd={(e) => {
if (props.data) {
props.setSignerObjId(props.data.signerObjId);
}
e.stopPropagation();
props.setIsPageCopy(true);
props.setSignKey(props.pos.key);
}}
style={{
color: "#188ae2"
}}
></i>
<i
className="fa-regular fa-circle-xmark signCloseBtn"
onClick={(e) => {
e.stopPropagation();
if (props.data) {
props.handleDeleteSign(props.pos.key, props.data.Id);
} else {
props.handleDeleteSign(props.pos.key);
props.setIsStamp(false);
}
}}
onTouchEnd={(e) => {
e.stopPropagation();
if (props.data) {
props.handleDeleteSign(props.pos.key, props.data.Id);
} else {
props.handleDeleteSign(props.pos.key);
props.setIsStamp(false);
}
}}
style={{
color: "#188ae2"
}}
></i>
</>
)
);
};
return (
<Rnd
// ref={nodeRef}
@@ -178,111 +260,63 @@ function Placeholder(props) {
pos={props.pos}
/>
)}
<div
style={{
left: props.xPos(props.pos, props.isSignYourself),
top: props.yPos(props.pos, props.isSignYourself),
width: props.posWidth(props.pos, props.isSignYourself),
height: props.posHeight(props.pos, props.isSignYourself),
zIndex: "10"
}}
onTouchEnd={(e) => {
props.isNeedSign && props.data?.signerObjId === props.signerObjId
? handlePlaceholderClick()
: props.isPlaceholder
{isMobile ? (
<div
style={{
left: props.xPos(props.pos, props.isSignYourself),
top: props.yPos(props.pos, props.isSignYourself),
width: props.posWidth(props.pos, props.isSignYourself),
height: props.posHeight(props.pos, props.isSignYourself),
zIndex: "10"
}}
onTouchEnd={(e) => {
props.isNeedSign && props.data?.signerObjId === props.signerObjId
? handlePlaceholderClick()
: props.isSignYourself && handlePlaceholderClick();
}}
>
{props.isShowBorder && (
<>
{props.isPlaceholder && (
<i
data-tut="reactourLinkUser"
className="fa-regular fa-user signUserIcon"
onClick={(e) => {
e.stopPropagation();
props.handleLinkUser(props.data.Id);
props.setUniqueId(props.data.Id);
}}
onTouchEnd={(e) => {
e.stopPropagation();
props.handleLinkUser(props.data.Id);
props.setUniqueId(props.data.Id);
}}
style={{
color: "#188ae2"
}}
></i>
)}
: props.isPlaceholder
? handlePlaceholderClick()
: props.isSignYourself && handlePlaceholderClick();
}}
>
<PlaceholderIcon />
<PlaceholderType
pos={props.pos}
xyPostion={props.xyPostion}
index={props.index}
setXyPostion={props.setXyPostion}
data={props.data}
setSignKey={props.setSignKey}
isShowDropdown={props?.isShowDropdown}
isPlaceholder={props.isPlaceholder}
isSignYourself={props.isSignYourself}
signerObjId={props.signerObjId}
handleUserName={props.handleUserName}
setDraggingEnabled={setDraggingEnabled}
pdfDetails={props?.pdfDetails && props?.pdfDetails[0]}
isNeedSign={props.isNeedSign}
/>
</div>
) : (
<>
<PlaceholderIcon />
<i
className="fa-regular fa-copy signCopy"
onClick={(e) => {
if (props.data) {
props.setSignerObjId(props.data.signerObjId);
}
e.stopPropagation();
props.setIsPageCopy(true);
props.setSignKey(props.pos.key);
}}
onTouchEnd={(e) => {
if (props.data) {
props.setSignerObjId(props.data.signerObjId);
}
e.stopPropagation();
props.setIsPageCopy(true);
props.setSignKey(props.pos.key);
}}
style={{
color: "#188ae2"
}}
></i>
<i
className="fa-regular fa-circle-xmark signCloseBtn"
onClick={(e) => {
e.stopPropagation();
if (props.data) {
props.handleDeleteSign(props.pos.key, props.data.Id);
} else {
props.handleDeleteSign(props.pos.key);
props.setIsStamp(false);
}
}}
onTouchEnd={(e) => {
e.stopPropagation();
if (props.data) {
props.handleDeleteSign(props.pos.key, props.data.Id);
} else {
props.handleDeleteSign(props.pos.key);
props.setIsStamp(false);
}
}}
style={{
color: "#188ae2"
}}
></i>
</>
)}
<PlaceholderType
pos={props.pos}
xyPostion={props.xyPostion}
index={props.index}
setXyPostion={props.setXyPostion}
data={props.data}
setSignKey={props.setSignKey}
isShowDropdown={props?.isShowDropdown}
isPlaceholder={props.isPlaceholder}
isSignYourself={props.isSignYourself}
signerObjId={props.signerObjId}
handleUserName={props.handleUserName}
setDraggingEnabled={setDraggingEnabled}
pdfDetails={props?.pdfDetails && props?.pdfDetails[0]}
isNeedSign={props.isNeedSign}
/>
</div>
<PlaceholderType
pos={props.pos}
xyPostion={props.xyPostion}
index={props.index}
setXyPostion={props.setXyPostion}
data={props.data}
setSignKey={props.setSignKey}
isShowDropdown={props?.isShowDropdown}
isPlaceholder={props.isPlaceholder}
isSignYourself={props.isSignYourself}
signerObjId={props.signerObjId}
handleUserName={props.handleUserName}
setDraggingEnabled={setDraggingEnabled}
pdfDetails={props?.pdfDetails && props?.pdfDetails[0]}
isNeedSign={props.isNeedSign}
/>
</>
)}
</Rnd>
);
}
@@ -308,6 +308,63 @@ function PlaceholderType(props) {
/>
);
case "image":
return props.pos.SignUrl ? (
<img
alt="signimg"
src={props.pos.SignUrl}
style={{
width: "99%",
height: "100%",
objectFit: "contain"
}}
/>
) : (
<div
style={{
fontSize: "10px",
color: "black",
justifyContent: "center"
}}
>
<div>{props.pos.type}</div>
{props?.handleUserName &&
props?.handleUserName(props?.data.Id, props?.data.Role)}
</div>
);
case "email":
return props.isSignYourself ||
(props.isNeedSign && props.data?.signerObjId === props.signerObjId) ? (
<input
className="inputPlaceholder"
type="text"
placeholder="email"
value={props.pos.widgetValue && props.pos.widgetValue}
onBlur={handleInputBlur}
onChange={(e) =>
onChangeInput(
e.target.value,
props.pos.key,
props.xyPostion,
props.index,
props.setXyPostion,
props.data && props.data.signerObjId,
false
)
}
/>
) : (
<div
style={{
color: "black",
fontSize: "14px"
}}
>
<span>{props.pos.type}</span>
</div>
);
default:
return props.pos.SignUrl ? (
<div style={{ pointerEvents: "none" }}>
@@ -37,8 +37,7 @@ function FieldsComponent({
signerPos,
handleRoleChange,
handleOnBlur,
title,
initial
title
}) {
const [isSignersModal, setIsSignersModal] = useState(false);
@@ -123,14 +122,35 @@ function FieldsComponent({
type: "BOX",
item: {
type: "BOX",
id: 11,
id: 12,
text: "date"
},
collect: (monitor) => ({
isDragDate: !!monitor.isDragging()
})
});
const [{ isDragImage }, image] = useDrag({
type: "BOX",
item: {
type: "BOX",
id: 13,
text: "image"
},
collect: (monitor) => ({
isDragImage: !!monitor.isDragging()
})
});
const [{ isDragEmail }, email] = useDrag({
type: "BOX",
item: {
type: "BOX",
id: 14,
text: "email"
},
collect: (monitor) => ({
isDragEmail: !!monitor.isDragging()
})
});
const isMobile = window.innerWidth < 767;
const scrollContainerRef = useRef(null);
const [widget, setWidget] = useState([]);
@@ -164,17 +184,16 @@ function FieldsComponent({
name,
company,
jobTitle,
date
date,
image,
email
];
const getWidgetArray = widgets;
const newUpdateSigner = getWidgetArray.map((obj, ind) => {
return { ...obj, ref: widgetRef[ind] };
});
const removeInitial = newUpdateSigner.filter(
(widgetData) => widgetData.type !== "initials"
);
setWidget(initial ? newUpdateSigner : removeInitial);
setWidget(newUpdateSigner);
}, []);
const filterWidgets = widget.filter((data) => data.type !== "dropdown");
@@ -54,7 +54,8 @@ function RenderPdf({
signersdata,
setIsPageCopy,
setSignerObjId,
setShowDropdown
setShowDropdown,
setIsInitial
}) {
const isMobile = window.innerWidth < 767;
const newWidth = containerWH.width;
@@ -360,6 +361,7 @@ function RenderPdf({
handleUserName={handleAllUserName}
isDragging={false}
pdfDetails={pdfDetails}
setIsInitial={setIsInitial}
/>
</React.Fragment>
)
@@ -941,6 +943,7 @@ function RenderPdf({
posHeight={posHeight}
pdfDetails={pdfDetails[0]}
isDragging={isDragging}
setIsInitial={setIsInitial}
/>
)
);
@@ -1332,6 +1335,7 @@ function RenderPdf({
posHeight={posHeight}
pdfDetails={pdfDetails[0]}
isDragging={isDragging}
setIsInitial={setIsInitial}
/>
</React.Fragment>
)
@@ -20,7 +20,11 @@ function SignPad({
onSaveImage,
image,
defaultSign,
setSignature
setSignature,
myInitial,
isInitial,
setIsInitial,
setIsStamp
}) {
const [penColor, setPenColor] = useState("blue");
const allColor = [bluePen, redPen, blackPen];
@@ -40,19 +44,22 @@ function SignPad({
];
const [fontSelect, setFontSelect] = useState(fontOptions[0].value);
useEffect(() => {
const senderUser =
localStorage.getItem(
`Parse/${localStorage.getItem("parseAppId")}/currentUser`
) &&
localStorage.getItem(
`Parse/${localStorage.getItem("parseAppId")}/currentUser`
);
const jsonSender = JSON.parse(senderUser);
const senderUser =
localStorage.getItem(
`Parse/${localStorage.getItem("parseAppId")}/currentUser`
) &&
localStorage.getItem(
`Parse/${localStorage.getItem("parseAppId")}/currentUser`
);
const jsonSender = JSON.parse(senderUser);
const currentUserName = jsonSender && jsonSender.name;
//function for clear signature
setSignValue(currentUserName);
const currentUserName = jsonSender && jsonSender.name;
useEffect(() => {
const trimmedName = currentUserName.trim();
const firstCharacter = trimmedName.charAt(0);
const userName = isInitial ? firstCharacter : currentUserName;
setSignValue(userName);
setFontSelect("Fasthand");
}, []);
//function for clear signature image
@@ -68,6 +75,7 @@ function SignPad({
} else if (isTab === "uploadImage") {
setImage("");
}
setIsInitial(false);
};
//function for set signature url
const handleSignatureChange = (dataURL) => {
@@ -97,9 +105,13 @@ function SignPad({
<button
onClick={() => {
if (!image) {
if (isDefaultSign) {
if (isTab === "mysignature") {
setIsSignImg("");
onSaveSign(isDefaultSign);
if (isInitial) {
onSaveSign("initials");
} else {
onSaveSign("default");
}
} else {
if (isTab === "type") {
setIsSignImg("");
@@ -116,11 +128,13 @@ function SignPad({
onSaveImage();
}
setIsSignPad(false);
setIsInitial(false);
setIsImageSelect(false);
setIsDefaultSign(false);
setImage();
setIsTab("draw");
setSignValue("");
setIsStamp(false);
}}
style={{
background: themeColor(),
@@ -164,9 +178,14 @@ function SignPad({
canvasRef.current.fromDataURL(isSignImg);
}
if (isTab === "type") {
convertToImg(fontSelect, signValue);
const trimmedName = signValue ? signValue.trim() : currentUserName.trim();
const firstCharacter = trimmedName.charAt(0);
const userName = isInitial ? firstCharacter : signValue;
setSignValue(userName);
convertToImg(fontSelect, userName);
}
}, [isTab]);
//function for convert input text value in image
const convertToImg = async (fontStyle, text) => {
//get text content to convert in image
@@ -217,6 +236,12 @@ function SignPad({
setSignature(dataUrl);
};
const getFirstChar = () => {
const trimmedString = currentUserName.trim();
const firstCharacter = trimmedString.charAt(0);
const userName = isInitial ? firstCharacter : signValue;
setSignValue(userName);
};
return (
<div>
{isSignPad && (
@@ -333,7 +358,7 @@ function SignPad({
}}
></div>
</div>
{defaultSign && (
{!isInitial && defaultSign ? (
<div>
<span
onClick={() => {
@@ -361,6 +386,37 @@ function SignPad({
}}
></div>
</div>
) : (
isInitial &&
myInitial && (
<div>
<span
onClick={() => {
setIsDefaultSign(true);
setIsImageSelect(true);
setIsTab("mysignature");
setImage();
}}
style={{
color:
isTab === "mysignature"
? themeColor()
: "#515252"
}}
className="signTab"
>
My Initials
</span>
<div
style={{
border:
isTab === "mysignature"
? "1.5px solid #108783"
: "1.5px solid #ffffff"
}}
></div>
</div>
)
)}
</>
)}
@@ -373,11 +429,13 @@ function SignPad({
onClick={() => {
setPenColor("blue");
setIsSignPad(false);
setIsInitial(false);
setIsImageSelect(false);
setIsDefaultSign(false);
setImage();
setIsTab("draw");
setSignValue("");
setIsStamp(false);
}}
>
&times;
@@ -386,29 +444,33 @@ function SignPad({
<div style={{ height: "100%", padding: 20 }}>
{isDefaultSign ? (
<>
<div
style={{
border: "1.3px solid #007bff",
borderRadius: "2px",
display: "flex",
flexDirection: "column",
justifyContent: "center",
alignItems: "center",
marginBottom: 6,
cursor: "pointer"
}}
className="signatureCanvas"
>
<img
alt="stamp img"
<div style={{ display: "flex", justifyContent: "center" }}>
<div
style={{
width: "100%",
height: "100%",
background: "rgb(255, 255, 255)",
objectFit: "contain"
border: "1.3px solid #007bff",
borderRadius: "2px",
display: "flex",
flexDirection: "column",
justifyContent: "center",
alignItems: "center",
marginBottom: 6,
cursor: "pointer"
}}
src={defaultSign}
/>
className={
isInitial ? "intialSignatureCanvas" : "signatureCanvas"
}
>
<img
alt="stamp img"
style={{
width: "100%",
height: "100%",
background: "rgb(255, 255, 255)",
objectFit: "contain"
}}
src={isInitial ? myInitial : defaultSign}
/>
</div>
</div>
<div style={{ display: "flex", justifyContent: "flex-end" }}>
<SaveBtn />
@@ -416,54 +478,63 @@ function SignPad({
</>
) : isImageSelect || isStamp ? (
!image ? (
<div
style={{
border: "1.3px solid #007bff",
borderRadius: "2px",
display: "flex",
flexDirection: "column",
justifyContent: "center",
alignItems: "center",
marginBottom: 6,
cursor: "pointer"
}}
className="signatureCanvas"
onClick={() => imageRef.current.click()}
>
<input
type="file"
onChange={onImageChange}
className="filetype"
accept="image/*"
ref={imageRef}
hidden
/>
<i className="fas fa-cloud-upload-alt uploadImgLogo"></i>
<div className="uploadImg">Upload</div>
</div>
) : (
<>
<div style={{ display: "flex", justifyContent: "center" }}>
<div
style={{
border: "1.3px solid #007bff",
borderRadius: "2px",
marginBottom: 6,
overflow: "hidden"
display: "flex",
flexDirection: "column",
justifyContent: "center",
alignItems: "center",
marginBottom: 6,
cursor: "pointer"
}}
className="signatureCanvas"
className={
isInitial ? "intialSignatureCanvas" : "signatureCanvas"
}
onClick={() => imageRef.current.click()}
>
<img
alt="print img"
<input
type="file"
onChange={onImageChange}
className="filetype"
accept="image/*"
ref={imageRef}
src={image.src}
style={{
objectFit: "contain",
height: "100%",
width: "100%"
}}
hidden
/>
<i className="fas fa-cloud-upload-alt uploadImgLogo"></i>
<div className="uploadImg">Upload</div>
</div>
</div>
) : (
<>
<div style={{ display: "flex", justifyContent: "center" }}>
<div
style={{
border: "1.3px solid #007bff",
borderRadius: "2px",
marginBottom: 6,
overflow: "hidden"
}}
className={
isInitial
? "intialSignatureCanvas"
: "signatureCanvas"
}
>
<img
alt="print img"
ref={imageRef}
src={image.src}
style={{
objectFit: "contain",
height: "100%",
width: "100%"
}}
/>
</div>
</div>
<div
style={{ display: "flex", justifyContent: "flex-end" }}
@@ -481,10 +552,12 @@ function SignPad({
alignItems: "center"
}}
>
<span className="signatureText">Signature:</span>
<span className="signatureText">
{isInitial ? "Initials" : "Signature"}:
</span>
<input
maxLength={30}
maxLength={isInitial ? 3 : 30}
style={{ fontFamily: fontSelect }}
type="text"
className="signatureInput"
@@ -532,23 +605,26 @@ function SignPad({
</div>
) : (
<>
<SignatureCanvas
ref={canvasRef}
penColor={penColor}
canvasProps={{
className: "signatureCanvas",
style: {
border: "1.6px solid #007bff",
borderRadius: "2px"
<div style={{ display: "flex", justifyContent: "center" }}>
<SignatureCanvas
ref={canvasRef}
penColor={penColor}
canvasProps={{
className: isInitial
? "intialSignatureCanvas"
: "signatureCanvas",
style: {
border: "1.6px solid #007bff",
borderRadius: "2px"
}
}}
backgroundColor="rgb(255, 255, 255)"
onEnd={() =>
handleSignatureChange(canvasRef.current.toDataURL())
}
}}
backgroundColor="rgb(255, 255, 255)"
onEnd={() =>
handleSignatureChange(canvasRef.current.toDataURL())
}
dotSize={1}
/>
dotSize={1}
/>
</div>
<div
style={{
display: "flex",
@@ -341,7 +341,8 @@ function PlaceHolderSign() {
//onclick put placeholder center on pdf
xPosition: window.innerWidth / 2 - 100,
yPosition: window.innerHeight / 2 - 60,
isStamp: monitor.type === "stamp" && true,
isStamp:
(monitor.type === "stamp" || monitor.type === "image") && true,
key: key,
isDrag: false,
scale: scale,
@@ -368,7 +369,7 @@ function PlaceHolderSign() {
const dropObj = {
xPosition: signBtnPosition[0] ? x - signBtnPosition[0].xPos : x,
yPosition: signBtnPosition[0] ? y - signBtnPosition[0].yPos : y,
isStamp: isDragStamp || isDragStampSS ? true : false,
isStamp: (item.text === "stamp" || item.text === "image") && true,
key: key,
isDrag: false,
firstXPos: signBtnPosition[0] && signBtnPosition[0].xPos,
@@ -36,7 +36,7 @@
font-size: 12px;
border: 1px solid #007bff;
border-radius: 2px;
}
.inputPlaceholder:focus {
@@ -88,15 +88,29 @@
}
.signatureCanvas {
border: 2px solid #888;
background-color: rgb(255, 255, 255);
width: 460px;
height: 184px;
}
.intialSignatureCanvas {
border: 2px solid #888;
background-color: rgb(255, 255, 255);
width: 150px;
height: 150px;
}
.intialSignature {
border: 2px solid #888;
background-color: rgb(255, 255, 255);
width: 180px;
height: 180px;
}
.penContainer {
width: 460px;
width: 180px;
}
.borderResize {
@@ -131,7 +145,7 @@
.signatureBtn {
border: 1.5px solid #47a3ad;
margin-bottom: 10px;
border-radius: 3px;
display: flex;
padding: 0px;
+45 -10
View File
@@ -1,7 +1,7 @@
import axios from "axios";
import { rgb } from "pdf-lib";
import { themeColor } from "./ThemeColor/backColor";
const isMobile = window.innerWidth < 767;
export const isMobile = window.innerWidth < 767;
//calculate width and height
export const calculateInitialWidthHeight = (type, widgetData) => {
@@ -54,11 +54,15 @@ export const addInitialData = (signerPos, setXyPostion, value, signerObjId) => {
? value?.Company
: item.type === "job title"
? value?.JobTitle
: "";
: item.type === "email"
? value?.Email
: "";
if (
item.type === "name" ||
item.type === "company" ||
item.type === "job title"
item.type === "job title" ||
item.type === "email"
) {
return {
...item,
@@ -195,17 +199,27 @@ export const widgets = [
{
type: "company",
icon: "fa-solid fa-building",
iconSize: "24px"
iconSize: "25px"
},
{
type: "job title",
icon: "fa-solid fa-address-card",
iconSize: "16px"
iconSize: "17px"
},
{
type: "date",
icon: "fa-solid fa-calendar-days",
iconSize: "20px"
},
{
type: "image",
icon: "fa-solid fa-image",
iconSize: "20px"
},
{
type: "email",
icon: "fa-solid fa-envelope",
iconSize: "20px"
}
];
@@ -215,7 +229,6 @@ export const getWidgetType = (item, marginLeft) => {
<div
className="signatureBtn"
style={{
// opacity: isDragSign ? 0.5 : 1,
boxShadow:
"0 1px 3px rgba(0, 0, 0, 0.1), 0 1px 2px rgba(0, 0, 0, 0.18)",
marginLeft: marginLeft && `${marginLeft}px`
@@ -298,8 +311,8 @@ export const defaultWidthHeight = (type) => {
return obj;
case "initials":
obj = {
width: 150,
height: 60
width: 50,
height: 50
};
return obj;
case "name":
@@ -327,6 +340,18 @@ export const defaultWidthHeight = (type) => {
height: 20
};
return obj;
case "image":
obj = {
width: 150,
height: 60
};
return obj;
case "email":
obj = {
width: 50,
height: 20
};
return obj;
default:
obj = {
width: 150,
@@ -414,6 +439,7 @@ export function getHostUrl() {
export const calculateImgAspectRatio = (imgWH, pos) => {
let newWidth, newHeight;
const placeholderHeight = pos && pos.Width ? pos.Height : 60;
const aspectRatio = imgWH.width / imgWH.height;
newWidth = aspectRatio * placeholderHeight;
@@ -465,13 +491,22 @@ export function onSaveSign(
let getXYdata = xyPostion[index].pos;
const updateXYData = getXYdata.map((position) => {
if (position.key === signKey) {
if (isDefaultSign) {
if (isDefaultSign === "initials") {
let imgWH = { width: position.Width, height: position.Height };
getIMGWH = calculateImgAspectRatio(imgWH, position);
} else if (isDefaultSign === "default") {
getIMGWH = calculateImgAspectRatio(imgWH, position);
} else if (isTypeText) {
getIMGWH = { newWidth: imgWH.width, newHeight: imgWH.height };
} else {
const defaultWidth = defaultWidthHeight(position?.type).width;
const defaultHeight = defaultWidthHeight(position?.type).height;
getIMGWH = calculateImgAspectRatio(
{ width: 150, height: 60 },
{
width: defaultWidth ? defaultWidth : 150,
height: defaultHeight ? defaultHeight : 60
},
position
);
}