diff --git a/microfrontends/SignDocuments/package-lock.json b/microfrontends/SignDocuments/package-lock.json index 98359a78d..2c4f6bc78 100644 --- a/microfrontends/SignDocuments/package-lock.json +++ b/microfrontends/SignDocuments/package-lock.json @@ -30,6 +30,7 @@ "react-dom": "^18.2.0", "react-draggable": "^4.4.6", "react-helmet": "^6.1.0", + "react-konva": "^18.2.10", "react-pdf": "^7.4.0", "react-rnd": "^10.4.1", "react-router-dom": "^6.16.0", @@ -6442,6 +6443,14 @@ "@types/react": "*" } }, + "node_modules/@types/react-reconciler": { + "version": "0.28.8", + "resolved": "https://registry.npmjs.org/@types/react-reconciler/-/react-reconciler-0.28.8.tgz", + "integrity": "sha512-SN9c4kxXZonFhbX4hJrZy37yw9e7EIxcpHCxQv5JUS18wDE5ovkQKlqQEkufdJCCMfuI9BnjUJvhYeJ9x5Ra7g==", + "dependencies": { + "@types/react": "*" + } + }, "node_modules/@types/react-transition-group": { "version": "4.4.7", "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.7.tgz", @@ -12523,6 +12532,17 @@ "set-function-name": "^2.0.1" } }, + "node_modules/its-fine": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/its-fine/-/its-fine-1.1.1.tgz", + "integrity": "sha512-v1Ia1xl20KbuSGlwoaGsW0oxsw8Be+TrXweidxD9oT/1lAh6O3K3/GIM95Tt6WCiv6W+h2M7RB1TwdoAjQyyKw==", + "dependencies": { + "@types/react-reconciler": "^0.28.0" + }, + "peerDependencies": { + "react": ">=18.0" + } + }, "node_modules/jake": { "version": "10.8.7", "resolved": "https://registry.npmjs.org/jake/-/jake-10.8.7.tgz", @@ -14685,6 +14705,26 @@ "node": ">= 8" } }, + "node_modules/konva": { + "version": "9.3.2", + "resolved": "https://registry.npmjs.org/konva/-/konva-9.3.2.tgz", + "integrity": "sha512-I4CFGVbWKpzgYi1I0pmoHz8iYfmGc/A61yfltzcuBHMFuBwDsR2VnQo4+eFQ1dGyEAmHcdvTumJ871KqkhuGng==", + "funding": [ + { + "type": "patreon", + "url": "https://www.patreon.com/lavrton" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/konva" + }, + { + "type": "github", + "url": "https://github.com/sponsors/lavrton" + } + ], + "peer": true + }, "node_modules/language-subtag-registry": { "version": "0.3.22", "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.22.tgz", @@ -17904,6 +17944,36 @@ "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" }, + "node_modules/react-konva": { + "version": "18.2.10", + "resolved": "https://registry.npmjs.org/react-konva/-/react-konva-18.2.10.tgz", + "integrity": "sha512-ohcX1BJINL43m4ynjZ24MxFI1syjBdrXhqVxYVDw2rKgr3yuS0x/6m1Y2Z4sl4T/gKhfreBx8KHisd0XC6OT1g==", + "funding": [ + { + "type": "patreon", + "url": "https://www.patreon.com/lavrton" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/konva" + }, + { + "type": "github", + "url": "https://github.com/sponsors/lavrton" + } + ], + "dependencies": { + "@types/react-reconciler": "^0.28.2", + "its-fine": "^1.1.1", + "react-reconciler": "~0.29.0", + "scheduler": "^0.23.0" + }, + "peerDependencies": { + "konva": "^8.0.1 || ^7.2.5 || ^9.0.0", + "react": ">=18.0.0", + "react-dom": ">=18.0.0" + } + }, "node_modules/react-lifecycles-compat": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz", @@ -17950,6 +18020,21 @@ "node": ">=6" } }, + "node_modules/react-reconciler": { + "version": "0.29.0", + "resolved": "https://registry.npmjs.org/react-reconciler/-/react-reconciler-0.29.0.tgz", + "integrity": "sha512-wa0fGj7Zht1EYMRhKWwoo1H9GApxYLBuhoAuXN0TlltESAjDssB+Apf0T/DngVqaMyPypDmabL37vw/2aRM98Q==", + "dependencies": { + "loose-envify": "^1.1.0", + "scheduler": "^0.23.0" + }, + "engines": { + "node": ">=0.10.0" + }, + "peerDependencies": { + "react": "^18.2.0" + } + }, "node_modules/react-refresh": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.11.0.tgz", diff --git a/microfrontends/SignDocuments/package.json b/microfrontends/SignDocuments/package.json index 1eae68515..b1b4f8eba 100644 --- a/microfrontends/SignDocuments/package.json +++ b/microfrontends/SignDocuments/package.json @@ -26,6 +26,7 @@ "react-dom": "^18.2.0", "react-draggable": "^4.4.6", "react-helmet": "^6.1.0", + "react-konva": "^18.2.10", "react-pdf": "^7.4.0", "react-rnd": "^10.4.1", "react-router-dom": "^6.16.0", diff --git a/microfrontends/SignDocuments/src/Component/DebugUi.js b/microfrontends/SignDocuments/src/Component/DebugUi.js new file mode 100644 index 000000000..94ff9bdf8 --- /dev/null +++ b/microfrontends/SignDocuments/src/Component/DebugUi.js @@ -0,0 +1,432 @@ +import React, { useEffect, useState, useRef } from "react"; +import RenderAllPdfPage from "./component/renderAllPdfPage"; +import "../css/./signature.css"; +import { pdfNewWidthFun } from "../utils/Utils"; +import "../css/AddUser.css"; +import Title from "./component/Title"; +import ModalUi from "../premitives/ModalUi"; +import RenderDebugPdf from "./component/RenderDebugPdf"; +import { pdfjs } from "react-pdf"; +import Alert from "../premitives/Alert"; + +function processDimensions(x, y, width, height) { + if (width < 0) { + x -= Math.abs(width); + width = Math.abs(width); + } + + if (height < 0) { + y -= Math.abs(height); + height = Math.abs(height); + } + + return { + x: Math.floor(x), + y: Math.floor(y), + width: Math.floor(width), + height: Math.floor(height) + }; +} +const DebugUi = () => { + const divRef = useRef(null); + const isMobile = window.innerWidth < 767; + const [pdf, setPdf] = useState(""); + const [isModal, setIsModal] = useState(true); + const [allPages, setAllPages] = useState(null); + const [pageNumber, setPageNumber] = useState(1); + const [pdfNewWidth, setPdfNewWidth] = useState(); + const [containerWH, setContainerWH] = useState(); + const [pdfOriginalWidth, setPdfOriginalWidth] = useState(); + const [pdfLoadFail, setPdfLoadFail] = useState({ + status: false, + type: "load" + }); + const [pdfDetails, setPdfDetails] = useState({ + name: "", + pdftype: "", + totalPages: "", + currentPage: 1, + x: 0, + y: 0, + base64: "" + }); + const [hoverCoordinates, setHoverCoordinates] = useState({ x: 0, y: 0 }); + const [drawing, setDrawing] = useState(false); + const [pdfDimension, setPdfDimension] = useState({ width: 0, height: 0 }); + const [annotations, setAnnotations] = useState([]); + const [newAnnotation, setNewAnnotation] = useState([]); + const [copied, setCopied] = useState(false); + useEffect(() => { + if (divRef.current) { + const pdfWidth = pdfNewWidthFun(divRef); + setPdfNewWidth(pdfWidth); + setContainerWH({ + width: divRef.current.offsetWidth, + height: divRef.current.offsetHeight + }); + } + }, [divRef.current]); + + useEffect(() => { + if (pdf && pdf.name) { + const fetchPdfMetadata = async () => { + try { + const pdfDataURL = URL.createObjectURL(pdf); // Convert File to data URL + console.log("pdfDataURL ", pdfDataURL); + const pdfInfo = await pdfjs.getDocument({ url: pdfDataURL }).promise; + const pdfType = await inferPdfType(pdfInfo); + setPdfDetails((prevDetails) => ({ + ...prevDetails, + pdftype: pdfType + })); + } catch (error) { + console.error("Error fetching PDF metadata:", error); + } + }; + + fetchPdfMetadata(); + } + }, [pdf]); + + const inferPdfType = async (pdf) => { + try { + const firstPage = await pdf.getPage(1); + const scale = 1; + const { width, height } = firstPage.getViewport({ scale }); + setPdfDimension({ width: width, height: height }); + + // Assuming a standard DPI of 72, you can adjust this value if needed + const dpi = 72; + + const widthInInches = width / dpi; + const heightInInches = height / dpi; + + const isA1 = widthInInches > 23.39 && heightInInches > 16.54; + const isA2 = widthInInches > 16.54 && heightInInches > 11.69; + const isA3 = widthInInches > 11.69 && heightInInches > 8.27; + const isA4 = widthInInches > 8.27 && heightInInches > 5.83; + const isLegal = widthInInches > 8.5 && heightInInches > 14; + const isLetter = widthInInches > 8.5 && heightInInches > 11; + const isLedger = widthInInches > 11 && heightInInches > 17; + + if (isA1) return "A1"; + if (isA2) return "A2"; + if (isA3) return "A3"; + if (isA4) return "A4"; + if (isLegal) return "Legal"; + if (isLetter) return "Letter"; + if (isLedger) return "Ledger"; + + return "Unknown"; + } catch (error) { + console.error("Error getting page dimensions:", error); + return "Unknown"; + } + }; + + const handleSubmit = (e) => { + e.preventDefault(); + setIsModal(false); + setPdfDetails((prevData) => ({ ...prevData, name: pdf?.name })); + }; + + //function for get pdf page details + const pageDetails = async ({ numPages }) => { + const load = { + status: true + }; + setPdfDetails((prevDetails) => ({ ...prevDetails, totalPages: numPages })); + setPdfLoadFail(load); + }; + + const handleMouseMoveDiv = (event) => { + setHoverCoordinates({ + x: event.nativeEvent.offsetX, + y: event.nativeEvent.offsetY + }); + }; + const handleMouseDown = (event) => { + if (newAnnotation.length === 0) { + const { x, y } = event.target.getStage().getPointerPosition(); + setNewAnnotation([{ x, y, width: 0, height: 0, key: "0" }]); + } + }; + + const handleMouseUp = (event) => { + if (newAnnotation.length === 1) { + const sx = newAnnotation[0].x; + const sy = newAnnotation[0].y; + const { x, y } = event.target.getStage().getPointerPosition(); + const result = processDimensions(sx, sy, x - sx, y - sy); + const annotationToAdd = { ...result, key: annotations.length + 1 }; + annotations.push(annotationToAdd); + setNewAnnotation([]); + setAnnotations(annotations); + setPdfDetails((prevDetails) => ({ + ...prevDetails, + x: result.x, + y: result.y + })); + } + }; + + const handleMouseMove = (event) => { + if (newAnnotation.length === 1) { + const sx = newAnnotation[0].x; + const sy = newAnnotation[0].y; + const { x, y } = event.target.getStage().getPointerPosition(); + setNewAnnotation([ + { + x: sx, + y: sy, + width: x - sx, + height: y - sy, + key: "0" + } + ]); + } + }; + + const annotationsToDraw = [...annotations, ...newAnnotation]; + + const handlePageLoadSuccess = (page) => { + setPdfDetails((prevDetails) => ({ + ...prevDetails, + currentPage: page.pageNumber + })); + }; + + const copytoclipboard = (text) => { + navigator.clipboard.writeText(text); + setCopied(true); + setTimeout(() => { + setCopied(false); + }, 1500); // Reset copied state after 1.5 seconds + }; + const handleFileChange = (files) => { + const file = files[0]; + setPdf(file); + + if (file && file.type === "application/pdf") { + const reader = new FileReader(); + + reader.onloadend = () => { + const base64String = reader.result.split(",")[1]; + setPdfDetails((prevdata) => ({ ...prevdata, base64: base64String })); + }; + + reader.readAsDataURL(file); + } + }; + const handleDelete = (key) => { + const updateAnnotations = annotations.filter((x) => x.key !== key); + setAnnotations(updateAnnotations); + }; + return ( +
+ {` ["x": ${coord.x}, "y": ${coord.y}, "w": ${coord.width}, "h": ${coord.height}]`}
+
+
+ copytoclipboard(
+ `["x": ${coord.x}, "y": ${coord.y}, "w": ${coord.width}, "h": ${coord.height}]`
+ )
+ }
+ >
+
+
+ handleDelete(coord.key)}
+ >
+
+
+
-