Files
sign/apps/web/components/editor/pdf-editor.tsx

121 lines
4.4 KiB
TypeScript
Raw Normal View History

import { useState } from "react";
2023-04-04 22:02:32 +00:00
import dynamic from "next/dynamic";
import Link from "next/link";
import { useRouter } from "next/router";
import { createField } from "@documenso/features/editor";
2023-04-04 22:02:32 +00:00
import { createOrUpdateField, deleteField } from "@documenso/lib/api";
import { NEXT_PUBLIC_WEBAPP_URL } from "@documenso/lib/constants";
import FieldTypeSelector from "./field-type-selector";
2023-04-04 22:02:32 +00:00
import RecipientSelector from "./recipient-selector";
2023-03-27 13:07:35 +02:00
import { InformationCircleIcon } from "@heroicons/react/24/outline";
2023-04-04 22:02:32 +00:00
const stc = require("string-to-color");
2023-02-13 16:58:25 +01:00
const PDFViewer = dynamic(() => import("./pdf-viewer"), {
ssr: false,
});
export default function PDFEditor(props: any) {
const router = useRouter();
2023-02-14 12:28:33 +01:00
const [fields, setFields] = useState<any[]>(props.document.Field);
const [selectedRecipient, setSelectedRecipient]: any = useState();
const [selectedFieldType, setSelectedFieldType] = useState();
const noRecipients =
2023-04-04 22:02:32 +00:00
props?.document.Recipient.length === 0 || props?.document.Recipient.every((e: any) => !e.email);
2023-02-13 16:58:25 +01:00
2023-02-13 18:04:44 +01:00
function onPositionChangedHandler(position: any, id: any) {
if (!position) return;
2023-02-14 13:06:49 +01:00
const movedField = fields.find((e) => e.id == id);
2023-02-22 20:09:30 +01:00
movedField.positionX = position.x.toFixed(0);
movedField.positionY = position.y.toFixed(0);
createOrUpdateField(props.document, movedField);
2023-02-13 18:04:44 +01:00
// no instant redraw neccessary, postion information for saving or later rerender is enough
// setFields(newFields);
}
2023-02-14 17:04:53 +01:00
function onDeleteHandler(id: any) {
const field = fields.find((e) => e.id == id);
const fieldIndex = fields.map((item) => item.id).indexOf(id);
if (fieldIndex > -1) {
2023-02-15 13:28:29 +01:00
const fieldWithoutRemoved = [...fields];
const removedField = fieldWithoutRemoved.splice(fieldIndex, 1);
setFields(fieldWithoutRemoved);
deleteField(field).catch((err) => {
setFields(fieldWithoutRemoved.concat(removedField));
});
2023-02-14 17:04:53 +01:00
}
}
2023-02-13 16:58:25 +01:00
return (
2023-02-13 18:04:44 +01:00
<>
2023-02-22 20:09:30 +01:00
<div>
2023-04-04 17:46:23 +02:00
<div hidden={!noRecipients} className="rounded-md bg-yellow-50 p-4">
2023-03-27 13:07:35 +02:00
<div className="flex">
<div className="flex-shrink-0">
2023-04-04 22:02:32 +00:00
<InformationCircleIcon className="h-5 w-5 text-yellow-400" aria-hidden="true" />
2023-03-27 13:07:35 +02:00
</div>
<div className="ml-3 flex-1 md:flex md:justify-between">
2023-04-04 17:46:23 +02:00
<p className="text-sm text-yellow-700">
2023-04-04 22:02:32 +00:00
This document does not have any recipients. Add recipients to create fields.
2023-03-27 13:07:35 +02:00
</p>
<p className="mt-3 text-sm md:mt-0 md:ml-6">
<Link
2023-04-04 22:02:32 +00:00
href={NEXT_PUBLIC_WEBAPP_URL + "/documents/" + props.document.id + "/recipients"}
className="whitespace-nowrap font-medium text-yellow-700 hover:text-yellow-600">
2023-03-27 13:07:35 +02:00
Add Recipients
<span aria-hidden="true"> &rarr;</span>
</Link>
</p>
</div>
</div>
</div>
2023-02-22 20:09:30 +01:00
<PDFViewer
2023-03-07 16:34:51 +01:00
style={{
2023-04-04 17:46:23 +02:00
cursor: !noRecipients
? `url("https://place-hold.it/110x64/37f095/FFFFFF&text=${selectedFieldType}") 55 32, auto`
: "",
2023-03-07 16:34:51 +01:00
}}
2023-02-22 20:09:30 +01:00
readonly={false}
document={props.document}
fields={fields}
onPositionChanged={onPositionChangedHandler}
onDelete={onDeleteHandler}
pdfUrl={`${NEXT_PUBLIC_WEBAPP_URL}/api/documents/${router.query.id}`}
onMouseUp={(e: any, page: number) => {
e.preventDefault();
e.stopPropagation();
}}
onMouseDown={(e: any, page: number) => {
2023-03-09 14:09:16 +01:00
if (e.button === 0) addField(e, page);
2023-04-04 22:02:32 +00:00
}}></PDFViewer>
2023-02-22 20:09:30 +01:00
<div
hidden={noRecipients}
2023-04-04 22:02:32 +00:00
className="fixed left-0 top-1/3 max-w-xs rounded-md border border-slate-300 bg-white py-4 pr-5">
2023-04-04 22:10:30 +00:00
<RecipientSelector
recipients={props?.document?.Recipient}
onChange={setSelectedRecipient}
/>
2023-02-22 20:09:30 +01:00
<hr className="m-3 border-slate-300"></hr>
2023-04-04 22:10:30 +00:00
<FieldTypeSelector
selectedRecipient={selectedRecipient}
onChange={setSelectedFieldType}
/>
2023-02-22 17:23:51 +01:00
</div>
</div>
2023-02-13 18:04:44 +01:00
</>
2023-02-13 16:58:25 +01:00
);
2023-02-22 20:09:30 +01:00
function addField(e: any, page: number) {
2023-02-28 18:46:24 +01:00
if (!selectedRecipient) return;
if (!selectedFieldType) return;
2023-04-04 17:46:23 +02:00
if (noRecipients) return;
2023-02-28 18:46:24 +01:00
2023-04-04 22:02:32 +00:00
const signatureField = createField(e, page, selectedRecipient, selectedFieldType);
2023-02-22 20:09:30 +01:00
createOrUpdateField(props?.document, signatureField).then((res) => {
setFields((prevState) => [...prevState, res]);
2023-02-22 20:09:30 +01:00
});
}
2023-02-13 16:58:25 +01:00
}