import PSPDFKitType, { AnnotationsUnion, SignatureFormField as SignatureFormFieldType } from "./index"; import { Instance, WidgetAnnotation, ToolbarItem } from "./index"; import { EnvelopeResponse, Envelope, User, Element, Document, IFunction } from "./interfaces"; declare const PSPDFKit: typeof PSPDFKitType const { List } = PSPDFKit.Immutable; const { Rect } = PSPDFKit.Geometry; const { SignatureFormField } = PSPDFKit.FormFields; const { DRAW, TYPE } = PSPDFKit.ElectronicSignatureCreationMode; const { DISABLED } = PSPDFKit.AutoSaveMode; export class App { public static Instance: Instance; public static currentDocument: Document; public static envelopeKey: string; public static ui: UI; // This function will be called in the ShowEnvelope.razor page // and will trigger loading of the Editor Interface public static async loadPDFFromUrl(container: string, envelopeKey: string) { App.ui = new UI(); console.debug("Loading PSPDFKit.."); const envelopeObject: EnvelopeResponse = await App.loadData(`/api/get-data/${envelopeKey}`); App.envelopeKey = envelopeKey; App.currentDocument = envelopeObject.envelope.documents[0]; let arrayBuffer try { arrayBuffer = await App.loadDocument(`/api/download/${envelopeKey}?id=${App.currentDocument.id}`); } catch (e) { console.error(e) } App.Instance = await App.loadPSPDFKit(arrayBuffer, container) App.configurePSPDFKit(this.Instance) console.debug(envelopeObject.envelope); console.debug("PSPDFKit configured!"); const annotations: any[] = []; App.currentDocument.elements.forEach(function (element: Element) { console.log("Creating annotation for element", element.id) const [annotation, formField] = App.createAnnotationFromElement(element) annotations.push(annotation); annotations.push(formField); }) const createdAnnotations = await App.Instance.create(annotations) console.debug(createdAnnotations) } private static inchToPoint(inch: number): number { return inch * 72; } // Makes a call to the supplied url and fetches the binary response as an array buffer private static loadDocument(url: string): Promise { return fetch(url, { credentials: "include" }) .then(res => res.arrayBuffer()); } // Makes a call to the supplied url and fetches the json response as an object private static loadData(url: string): Promise { return fetch(url, { credentials: "include" }) .then(res => res.json()); } private static postDocument(url: string, buffer: ArrayBuffer): Promise { return fetch(url, { credentials: "include", method: "POST", body: buffer }) .then(res => res.json()); } // Load the PSPDFKit UI by setting a target element as the container to render in // and a arraybuffer which represents the document that should be displayed. private static loadPSPDFKit(arrayBuffer: ArrayBuffer, container: string): Promise { return PSPDFKit.load({ container: container, document: arrayBuffer, autoSaveMode: DISABLED, annotationPresets: App.ui.getPresets(), electronicSignatures: { creationModes: [DRAW, TYPE] }, isEditableAnnotation: function (annotation: WidgetAnnotation) { // Check if the annotation is a signature // This will allow new signatures, but not allow edits. return !annotation.isSignature; } }) } private static configurePSPDFKit(instance: Instance) { instance.addEventListener("annotations.load", (loadedAnnotations) => { console.log("annotations loaded", loadedAnnotations.toJS()); }) instance.addEventListener("annotations.change", () => { console.log("annotations changed") }) instance.addEventListener("annotations.create", async (createdAnnotations) => { console.log("annotations created", createdAnnotations.toJS()); }) const filteredItems: Array = instance.toolbarItems .filter((item) => App.ui.allowedToolbarItems.includes(item.type)) instance.setToolbarItems(filteredItems.concat(App.ui.getToolbarItems(App.handleClick))) } public static async handleClick(eventType: string) { switch (eventType) { case "RESET": await App.handleReset(null) break; case "FINISH": await App.handleFinish(null) break; } } public static async handleFinish(event: any) { await App.Instance.save(); const json = await App.Instance.exportInstantJSON() console.log(json); const buffer = await App.Instance.exportPDF({ flatten: true }); await App.uploadDocument(buffer, App.envelopeKey, App.currentDocument.id); alert("Signatur wird gespeichert!") } public static async handleReset(event: any) { if (confirm("Wollen Sie das Dokument und alle erstellten Signaturen zurücksetzen?")) { for (let i = 0; i < App.Instance.totalPageCount; i++) { const annotations = await App.Instance.getAnnotations(i) annotations.forEach((annotation) => { //console.log(annotation) // TODO: Delete only create signatures //App.Instance.delete(annotation.id) }) } } } private static async uploadDocument(buffer: ArrayBuffer, envelopeKey: string, documentId: number) { const result = await App.postDocument(`/api/upload/${envelopeKey}/${documentId}`, buffer); console.log(result) } private static async downloadDocument() { const buffer = await App.Instance.exportPDF({ flatten: true }); const supportsDownloadAttribute = HTMLAnchorElement.prototype.hasOwnProperty("download"); const blob = new Blob([buffer], { type: "application/pdf" }); if (!supportsDownloadAttribute) { const reader = new FileReader(); reader.onloadend = function () { const dataUrl = reader.result; downloadPdf(dataUrl); }; reader.readAsDataURL(blob); } else { const objectUrl = window.URL.createObjectURL(blob); downloadPdf(objectUrl); window.URL.revokeObjectURL(objectUrl); } function downloadPdf(blob) { const a = document.createElement("a"); a.href = blob; a.style.display = "none"; a.download = "download.pdf"; a.setAttribute("download", "download.pdf"); document.body.appendChild(a); a.click(); document.body.removeChild(a); } } private static createAnnotationFromElement(element: Element): [annotation: WidgetAnnotation, formField: SignatureFormFieldType] { const id = PSPDFKit.generateInstantId() console.log("Creating Annotation", id) const width = App.inchToPoint(element.width) const height = App.inchToPoint(element.height) const top = App.inchToPoint(element.top) - (height / 2) const left = App.inchToPoint(element.left) - (width / 2) const page = element.page - 1 const annotation: WidgetAnnotation = App.createSignatureAnnotation(id, width, height, top, left, page) console.log(annotation) const formField = new SignatureFormField({ name: id, annotationIds: List([annotation.id]) }) console.log(formField) return [annotation, formField] } private static createSignatureAnnotation(id: string, width: number, height: number, top: number, left: number, pageIndex: number): WidgetAnnotation { const annotation = new PSPDFKit.Annotations.WidgetAnnotation({ id: id, pageIndex: pageIndex, formFieldName: id, boundingBox: new Rect({ width, height, top, left }) }) return annotation } } class UI { constructor() { } public allowedToolbarItems: string[] = [ "sidebar-thumbnails", "sidebar-document-ouline", "sidebar-bookmarks", "pager", "pan", "zoom-out", "zoom-in", "zoom-mode", "spacer", "search" ] public getToolbarItems = function (callback: any) { const customItems: ToolbarItem[] = [ { type: "custom", id: "button-reset", title: "Zurücksetzen", onPress() { callback("RESET") }, icon: ` ` }, { type: "custom", id: "button-finish", title: "Abschließen", onPress() { callback("FINISH") }, icon: ` ` } ] return customItems } public getPresets() { const annotationPresets = PSPDFKit.defaultAnnotationPresets; annotationPresets.ink = { lineWidth: 10 }; annotationPresets.widget = { readOnly: true } return annotationPresets; } }