init receiver ui with react
This commit is contained in:
278
EnvelopeGenerator.Web/Client/receiver-ui-react/src/App.js
Normal file
278
EnvelopeGenerator.Web/Client/receiver-ui-react/src/App.js
Normal file
@@ -0,0 +1,278 @@
|
||||
import "./App.css";
|
||||
import { useRef, useState } from "react";
|
||||
import Drop from "./Drop";
|
||||
import { Document, Page, pdfjs } from "react-pdf";
|
||||
import { PDFDocument, rgb } from "pdf-lib";
|
||||
import { blobToURL } from "./utils/Utils";
|
||||
import PagingControl from "./components/PagingControl";
|
||||
import { AddSigDialog } from "./components/AddSigDialog";
|
||||
import { Header } from "./Header";
|
||||
import { BigButton } from "./components/BigButton";
|
||||
import DraggableSignature from "./components/DraggableSignature";
|
||||
import DraggableText from "./components/DraggableText";
|
||||
import dayjs from "dayjs";
|
||||
|
||||
pdfjs.GlobalWorkerOptions.workerSrc = `//cdnjs.cloudflare.com/ajax/libs/pdf.js/${pdfjs.version}/pdf.worker.js`;
|
||||
|
||||
function downloadURI(uri, name) {
|
||||
var link = document.createElement("a");
|
||||
link.download = name;
|
||||
link.href = uri;
|
||||
document.body.appendChild(link);
|
||||
link.click();
|
||||
document.body.removeChild(link);
|
||||
}
|
||||
|
||||
function App() {
|
||||
const styles = {
|
||||
container: {
|
||||
maxWidth: 900,
|
||||
margin: "0 auto",
|
||||
},
|
||||
sigBlock: {
|
||||
display: "inline-block",
|
||||
border: "1px solid #000",
|
||||
},
|
||||
documentBlock: {
|
||||
maxWidth: 800,
|
||||
margin: "20px auto",
|
||||
marginTop: 8,
|
||||
border: "1px solid #999",
|
||||
},
|
||||
controls: {
|
||||
maxWidth: 800,
|
||||
margin: "0 auto",
|
||||
marginTop: 8,
|
||||
},
|
||||
};
|
||||
const [pdf, setPdf] = useState(null);
|
||||
const [autoDate, setAutoDate] = useState(true);
|
||||
const [signatureURL, setSignatureURL] = useState(null);
|
||||
const [position, setPosition] = useState(null);
|
||||
const [signatureDialogVisible, setSignatureDialogVisible] = useState(false);
|
||||
const [textInputVisible, setTextInputVisible] = useState(false);
|
||||
const [pageNum, setPageNum] = useState(0);
|
||||
const [totalPages, setTotalPages] = useState(0);
|
||||
const [pageDetails, setPageDetails] = useState(null);
|
||||
const documentRef = useRef(null);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Header />
|
||||
<div style={styles.container}>
|
||||
{signatureDialogVisible ? (
|
||||
<AddSigDialog
|
||||
autoDate={autoDate}
|
||||
setAutoDate={setAutoDate}
|
||||
onClose={() => setSignatureDialogVisible(false)}
|
||||
onConfirm={(url) => {
|
||||
setSignatureURL(url);
|
||||
setSignatureDialogVisible(false);
|
||||
}}
|
||||
/>
|
||||
) : null}
|
||||
|
||||
{!pdf ? (
|
||||
<Drop
|
||||
onLoaded={async (files) => {
|
||||
const URL = await blobToURL(files[0]);
|
||||
setPdf(URL);
|
||||
}}
|
||||
/>
|
||||
) : null}
|
||||
{pdf ? (
|
||||
<div>
|
||||
<div style={styles.controls}>
|
||||
{!signatureURL ? (
|
||||
<BigButton
|
||||
marginRight={8}
|
||||
title={"Add signature"}
|
||||
onClick={() => setSignatureDialogVisible(true)}
|
||||
/>
|
||||
) : null}
|
||||
|
||||
<BigButton
|
||||
marginRight={8}
|
||||
title={"Add Date"}
|
||||
onClick={() => setTextInputVisible("date")}
|
||||
/>
|
||||
|
||||
<BigButton
|
||||
marginRight={8}
|
||||
title={"Add Text"}
|
||||
onClick={() => setTextInputVisible(true)}
|
||||
/>
|
||||
<BigButton
|
||||
marginRight={8}
|
||||
title={"Reset"}
|
||||
onClick={() => {
|
||||
setTextInputVisible(false);
|
||||
setSignatureDialogVisible(false);
|
||||
setSignatureURL(null);
|
||||
setPdf(null);
|
||||
setTotalPages(0);
|
||||
setPageNum(0);
|
||||
setPageDetails(null);
|
||||
}}
|
||||
/>
|
||||
{pdf ? (
|
||||
<BigButton
|
||||
marginRight={8}
|
||||
inverted={true}
|
||||
title={"Download"}
|
||||
onClick={() => {
|
||||
downloadURI(pdf, "file.pdf");
|
||||
}}
|
||||
/>
|
||||
) : null}
|
||||
</div>
|
||||
<div ref={documentRef} style={styles.documentBlock}>
|
||||
{textInputVisible ? (
|
||||
<DraggableText
|
||||
initialText={
|
||||
textInputVisible === "date"
|
||||
? dayjs().format("M/d/YYYY")
|
||||
: null
|
||||
}
|
||||
onCancel={() => setTextInputVisible(false)}
|
||||
onEnd={setPosition}
|
||||
onSet={async (text) => {
|
||||
const { originalHeight, originalWidth } = pageDetails;
|
||||
const scale = originalWidth / documentRef.current.clientWidth;
|
||||
|
||||
const y =
|
||||
documentRef.current.clientHeight -
|
||||
(position.y +
|
||||
(12 * scale) -
|
||||
position.offsetY -
|
||||
documentRef.current.offsetTop);
|
||||
const x =
|
||||
position.x -
|
||||
166 -
|
||||
position.offsetX -
|
||||
documentRef.current.offsetLeft;
|
||||
|
||||
// new XY in relation to actual document size
|
||||
const newY =
|
||||
(y * originalHeight) / documentRef.current.clientHeight;
|
||||
const newX =
|
||||
(x * originalWidth) / documentRef.current.clientWidth;
|
||||
|
||||
const pdfDoc = await PDFDocument.load(pdf);
|
||||
|
||||
const pages = pdfDoc.getPages();
|
||||
const firstPage = pages[pageNum];
|
||||
|
||||
firstPage.drawText(text, {
|
||||
x: newX,
|
||||
y: newY,
|
||||
size: 20 * scale,
|
||||
});
|
||||
|
||||
const pdfBytes = await pdfDoc.save();
|
||||
const blob = new Blob([new Uint8Array(pdfBytes)]);
|
||||
|
||||
const URL = await blobToURL(blob);
|
||||
setPdf(URL);
|
||||
setPosition(null);
|
||||
setTextInputVisible(false);
|
||||
}}
|
||||
/>
|
||||
) : null}
|
||||
{signatureURL ? (
|
||||
<DraggableSignature
|
||||
url={signatureURL}
|
||||
onCancel={() => {
|
||||
setSignatureURL(null);
|
||||
}}
|
||||
onSet={async () => {
|
||||
const { originalHeight, originalWidth } = pageDetails;
|
||||
const scale = originalWidth / documentRef.current.clientWidth;
|
||||
|
||||
const y =
|
||||
documentRef.current.clientHeight -
|
||||
(position.y -
|
||||
position.offsetY +
|
||||
64 -
|
||||
documentRef.current.offsetTop);
|
||||
const x =
|
||||
position.x -
|
||||
160 -
|
||||
position.offsetX -
|
||||
documentRef.current.offsetLeft;
|
||||
|
||||
// new XY in relation to actual document size
|
||||
const newY =
|
||||
(y * originalHeight) / documentRef.current.clientHeight;
|
||||
const newX =
|
||||
(x * originalWidth) / documentRef.current.clientWidth;
|
||||
|
||||
const pdfDoc = await PDFDocument.load(pdf);
|
||||
|
||||
const pages = pdfDoc.getPages();
|
||||
const firstPage = pages[pageNum];
|
||||
|
||||
const pngImage = await pdfDoc.embedPng(signatureURL);
|
||||
const pngDims = pngImage.scale( scale * .3);
|
||||
|
||||
firstPage.drawImage(pngImage, {
|
||||
x: newX,
|
||||
y: newY,
|
||||
width: pngDims.width,
|
||||
height: pngDims.height,
|
||||
});
|
||||
|
||||
if (autoDate) {
|
||||
firstPage.drawText(
|
||||
`Signed ${dayjs().format(
|
||||
"M/d/YYYY HH:mm:ss ZZ"
|
||||
)}`,
|
||||
{
|
||||
x: newX,
|
||||
y: newY - 10,
|
||||
size: 14 * scale,
|
||||
color: rgb(0.074, 0.545, 0.262),
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
const pdfBytes = await pdfDoc.save();
|
||||
const blob = new Blob([new Uint8Array(pdfBytes)]);
|
||||
|
||||
const URL = await blobToURL(blob);
|
||||
setPdf(URL);
|
||||
setPosition(null);
|
||||
setSignatureURL(null);
|
||||
}}
|
||||
onEnd={setPosition}
|
||||
/>
|
||||
) : null}
|
||||
<Document
|
||||
file={pdf}
|
||||
onLoadSuccess={(data) => {
|
||||
setTotalPages(data.numPages);
|
||||
}}
|
||||
>
|
||||
<Page
|
||||
pageNumber={pageNum + 1}
|
||||
width={800}
|
||||
height={1200}
|
||||
onLoadSuccess={(data) => {
|
||||
setPageDetails(data);
|
||||
}}
|
||||
/>
|
||||
</Document>
|
||||
</div>
|
||||
<PagingControl
|
||||
pageNum={pageNum}
|
||||
setPageNum={setPageNum}
|
||||
totalPages={totalPages}
|
||||
/>
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default App;
|
||||
Reference in New Issue
Block a user