Compare commits

..

10 Commits

5 changed files with 173 additions and 96 deletions

View File

@@ -16,7 +16,7 @@
},
"AdminPassword": "dd",
"PSPDFKitLicenseKey_SignFlow": "y8VgCpBgUfNlpKJZC-GwjpPs-S-KFBHv4RywfHbqpBAbO0XxRuWDaMGZtIaMrXBDlndlJLk---Ve93xjI_ZR4sbFymf4Ot97yTYUMeDdL2LYXhspkEnSAtkXf9zqepNL1v_0DMibjpqXFQMkVB1y3D5xdnOg-iJuCCZEMhZ780qg04_H_nmx63uSgxjN0GJxC8YvsbnRcUZ2l_idImMvWL0HMqB5B7oEpNenasA0RK0uapFRTa7NIQok0phpTHZYKB4qvj7od2yxlytGB7qBl4-lwT70DSQ9mrLkCWbuzZ9cV9D8fDzdFXr6WoZdOYpkrUadRbsy2bhPq_ukxszDWN4JGhebo0XKUK_YfgvSlS7lFOxHNblHeC9B7gZ8T-VuQ_z1QA2JYRf1dmhSuclnW00diShIg-N0I79PWGsQE4j40XtVpyWcN9uT9hMuiRpL0LzHV4YgsgBrgKgs_moqL7f0L4-MwaS25Dx4Wcz4ttKaerLavwMM4CJHI3DNqTC5UUEG6EViFxBQtrmuAS7kiw2nWjvXO7kUA24NARtsRCphjWE4l6wSMdh7kpqhfbV7_hdb5xXYGALNPkv8En6zPpFIew8DDcOH9dgxfKMI34LLhkEWqovZW_7fXNJTEIHVpR0DSPbZrmyEwkECnbDcNzjyFk2M1fzstJj_dSotyZvS57XJK2DgojbRgXL9pncs",
"UseCSPInDev": true,
"UseCSPInDev": false,
"Content-Security-Policy": [ // The first format parameter {0} will be replaced by the nonce value.
"default-src 'self'",
"script-src 'self' 'nonce-{0}' 'unsafe-inline' 'unsafe-eval' blob: data:",

View File

@@ -1,77 +1,30 @@
class Annotation {
createAnnotations(document) {
const annotations = []
static async createAnnotations(document) {
const signatures = []
document.elements.forEach((element) => {
const [annotation, formField] = this.createAnnotationFromElement(element)
annotations.push(annotation)
annotations.push(formField)
})
for(var element of document.elements){
const [annotation, formField, annotation2, formFieldDate] = await Annotation.createSignature(element)
signatures.push(annotation)
signatures.push(formField)
signatures.push(annotation2)
signatures.push(formFieldDate)
}
return annotations
return [...signatures ]
}
async getAnnotations(instance) {
const array = await Promise.all(
Array.from({ length: instance.totalPageCount }).map((_, pageIndex) =>
instance.getAnnotations(pageIndex)
)
)
return array.flatMap((annotations) =>
annotations.reduce((acc, annotation) => acc.concat(annotation), [])
)
}
async deleteAnnotations(instance) {
const allAnnotations = await this.getAnnotations(instance)
const pageAnnotations = allAnnotations.filter(this.isSignature)
//deleting all Annotations
return await instance.delete(pageAnnotations)
}
async validateAnnotations(instance) {
const allAnnotations = await this.getAnnotations(instance)
const pageAnnotations = allAnnotations
.map((annotation) => {
return annotation
})
return true
}
isSignature(annotation) {
return !!annotation.isSignature || annotation.description == 'FRAME'
}
createAnnotationFromElement(element) {
static async createSignature(element) {
const id = PSPDFKit.generateInstantId()
const width = this.inchToPoint(element.width)
const height = this.inchToPoint(element.height)
const top = this.inchToPoint(element.top) - height / 2
const left = this.inchToPoint(element.left) - width / 2
const width = Annotation.inchToPoint(element.width)
const height = Annotation.inchToPoint(element.height)
const top = Annotation.inchToPoint(element.top) - height / 2
const left = Annotation.inchToPoint(element.left) - width / 2
const page = element.page - 1
const annotation = this.createSignatureAnnotation(
id,
width,
height,
top,
left,
page
)
const formField = new PSPDFKit.FormFields.SignatureFormField({
name: id,
annotationIds: PSPDFKit.Immutable.List([annotation.id]),
})
return [annotation, formField]
}
createSignatureAnnotation(id, width, height, top, left, pageIndex) {
//signatures
const annotation = new PSPDFKit.Annotations.WidgetAnnotation({
id: id,
pageIndex: pageIndex,
pageIndex: page,
formFieldName: id,
backgroundColor: PSPDFKit.Color.YELLOW,
blendMode: 'multiply',
@@ -83,10 +36,107 @@
}),
})
return annotation
const formField = new PSPDFKit.FormFields.SignatureFormField({
name: id,
annotationIds: PSPDFKit.Immutable.List([annotation.id]),
})
//date
var city = await getCity();
const id_date = PSPDFKit.generateInstantId()
const annotation_date = new PSPDFKit.Annotations.WidgetAnnotation({
id: id_date,
pageIndex: page,
formFieldName: id_date,
backgroundColor: PSPDFKit.Color.DarkBlue,
blendMode: 'multiply',
boundingBox: new PSPDFKit.Geometry.Rect({
width: width * 1.5,
height: height / 2,
top: top + height + 25,
left: left - width * .25,
}),
fontSize:8
})
const formFieldDate = new PSPDFKit.FormFields.TextFormField({
name: id_date,
annotationIds: PSPDFKit.Immutable.List([annotation_date.id]),
value: getLocaleDateString() + ", " + city
})
return [annotation, formField, annotation_date, formFieldDate]
}
createImageAnnotation(boundingBox, pageIndex, imageAttachmentId) {
static createTextBox(element) {
const id = PSPDFKit.generateInstantId()
const width = Annotation.inchToPoint(element.width)
const height = Annotation.inchToPoint(element.height)
const top = Annotation.inchToPoint(element.top) - height / 2
const left = Annotation.inchToPoint(element.left) - width / 2
const page = element.page - 1
//shift
top += height + 10
const annotation = new PSPDFKit.Annotations.WidgetAnnotation({
id: id,
pageIndex: page,
formFieldName: id,
backgroundColor: PSPDFKit.Color.YELLOW,
blendMode: 'multiply',
boundingBox: new PSPDFKit.Geometry.Rect({
width,
height,
top,
left,
}),
})
const formField = new PSPDFKit.FormFields.SignatureFormField({
name: id,
annotationIds: PSPDFKit.Immutable.List([annotation.id]),
})
return [annotation, formField]
}
static createText
static async getAnnotations(instance) {
const array = await Promise.all(
Array.from({ length: instance.totalPageCount }).map((_, pageIndex) =>
instance.getAnnotations(pageIndex)
)
)
return array.flatMap((annotations) =>
annotations.reduce((acc, annotation) => acc.concat(annotation), [])
)
}
static async deleteAnnotations(instance) {
const allAnnotations = await Annotation.getAnnotations(instance)
const pageAnnotations = allAnnotations.filter(Annotation.isSignature)
//deleting all Annotations
return await instance.delete(pageAnnotations)
}
static async validateAnnotations(instance) {
const allAnnotations = await Annotation.getAnnotations(instance)
const pageAnnotations = allAnnotations
.map((annotation) => {
return annotation
})
return true
}
static isSignature(annotation) {
return !!annotation.isSignature || annotation.description == 'FRAME'
}
static createImageAnnotation(boundingBox, pageIndex, imageAttachmentId) {
const frameAnnotation = new PSPDFKit.Annotations.ImageAnnotation({
pageIndex: pageIndex,
isSignature: false,
@@ -101,7 +151,7 @@
return frameAnnotation
}
async createAnnotationFrameBlob(receiverName, receiverSignature, timestamp, width, height) {
static async createAnnotationFrameBlob(receiverName, receiverSignature, timestamp, width, height) {
const canvas = document.createElement('canvas')
const scale = 4
const fontSize = 10
@@ -154,7 +204,7 @@
})
}
inchToPoint(inch) {
static inchToPoint(inch) {
return inch * 72
}
}

View File

@@ -14,9 +14,7 @@ class App {
this.container = container ?? `#${this.constructor.name.toLowerCase()}`;
this.envelopeKey = envelopeKey
this.UI = new UI()
this.Network = new Network()
this.Annotation = new Annotation()
this.Instance = null
this.currentDocument = null
@@ -49,8 +47,8 @@ class App {
const arrayBuffer = this.documentBytes
// Load PSPDFKit
this.Instance = await this.UI.loadPSPDFKit(arrayBuffer, this.container, this.licenseKey, this.locale)
this.UI.configurePSPDFKit(this.Instance, this.handleClick.bind(this))
this.Instance = await UI.loadPSPDFKit(arrayBuffer, this.container, this.licenseKey, this.locale)
UI.configurePSPDFKit(this.Instance, this.handleClick.bind(this))
this.Instance.addEventListener(
'annotations.load',
@@ -72,9 +70,7 @@ class App {
// Load annotations into PSPDFKit
try {
this.signatureCount = this.currentDocument.elements.length
const annotations = this.Annotation.createAnnotations(
this.currentDocument
)
const annotations = await Annotation.createAnnotations(this.currentDocument)
await this.Instance.create(annotations)
const openResponse = await this.Network.openDocument(this.envelopeKey)
@@ -113,7 +109,7 @@ class App {
const height = 75
const timestamp = new Date()
const imageUrl = await this.Annotation.createAnnotationFrameBlob(
const imageUrl = await Annotation.createAnnotationFrameBlob(
this.envelopeReceiver.name,
this.currentReceiver.signature,
timestamp,
@@ -125,7 +121,7 @@ class App {
const blob = await request.blob()
const imageAttachmentId = await this.Instance.createAttachment(blob)
const frameAnnotation = this.Annotation.createImageAnnotation(
const frameAnnotation = Annotation.createImageAnnotation(
new PSPDFKit.Geometry.Rect({
left: left,
top: top,
@@ -247,7 +243,7 @@ class App {
async validateAnnotations(totalSignatures) {
const annotations = await this.Annotation.getAnnotations(this.Instance)
const annotations = await Annotation.getAnnotations(this.Instance)
const filtered = annotations
.map(a => a.toJS())
.filter(a => a.isSignature)
@@ -268,7 +264,7 @@ class App {
})
if (result.isConfirmed) {
const result = await this.Annotation.deleteAnnotations(this.Instance)
const result = await Annotation.deleteAnnotations(this.Instance)
}
return result

View File

@@ -1,5 +1,5 @@
class UI {
allowedToolbarItems = [
static allowedToolbarItems = [
'sidebar-thumbnails',
'sidebar-document-ouline',
'sidebar-bookmarks',
@@ -14,14 +14,14 @@
// 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.
loadPSPDFKit(arrayBuffer, container, licenseKey, locale) {
static loadPSPDFKit(arrayBuffer, container, licenseKey, locale) {
return PSPDFKit.load({
locale: locale,
licenseKey: licenseKey,
styleSheets: ['/css/site.css'],
container: container,
document: arrayBuffer,
annotationPresets: this.getPresets(),
annotationPresets: UI.getPresets(),
electronicSignatures: {
creationModes: ['DRAW', 'TYPE', 'IMAGE'],
},
@@ -40,35 +40,35 @@
//return !annotation.isSignature;
},
customRenderers: {
Annotation: this.annotationRenderer,
Annotation: UI.annotationRenderer,
},
})
}
configurePSPDFKit(instance, handler) {
const toolbarItems = this.getToolbarItems(instance, handler)
static configurePSPDFKit(instance, handler) {
const toolbarItems = UI.getToolbarItems(instance, handler)
instance.setToolbarItems(toolbarItems)
}
annotationRenderer(data) {
static annotationRenderer(data) {
// leave everything as is
return null
}
getToolbarItems(instance, handler) {
const customItems = this.getCustomItems(handler)
const defaultItems = this.getDefaultItems(instance.toolbarItems)
static getToolbarItems(instance, handler) {
const customItems = UI.getCustomItems(handler)
const defaultItems = UI.getDefaultItems(instance.toolbarItems)
return defaultItems.concat(customItems)
}
createElementFromHTML(html) {
static createElementFromHTML(html) {
const el = document.createElement('div')
el.innerHTML = html.trim()
return el.firstChild
}
getCustomItems = function (callback) {
static getCustomItems = function (callback) {
return []
return [
{
@@ -108,11 +108,11 @@
]
}
getDefaultItems(items) {
return items.filter((item) => this.allowedToolbarItems.includes(item.type))
static getDefaultItems(items) {
return items.filter((item) => UI.allowedToolbarItems.includes(item.type))
}
getPresets() {
static getPresets() {
const annotationPresets = PSPDFKit.defaultAnnotationPresets
annotationPresets.ink = {
lineWidth: 10,

View File

@@ -1 +1,32 @@
const B64ToBuff = (base64String) => new Uint8Array(Array.from(atob(base64String), char => char.charCodeAt(0))).buffer;
const B64ToBuff = (base64String) => new Uint8Array(Array.from(atob(base64String), char => char.charCodeAt(0))).buffer;
function getCoordinates() {
return new Promise((resolve, reject) => {
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(
position => resolve(position.coords),
error => reject(error)
);
} else {
reject(new Error("Geolocation is not supported by this browser."));
}
});
}
async function getCity() {
try {
const coords = await getCoordinates();
const response = await fetch(`https://nominatim.openstreetmap.org/reverse?format=json&lat=${coords.latitude}&lon=${coords.longitude}`);
const data = await response.json();
if (data && data.address) {
const city = data.address.city || data.address.town || data.address.village || data.address.hamlet;
const postalCode = data.address.postcode;
return postalCode + ' ' + city || '';
}
} catch {
return '';
}
}
const getLocaleDateString = _ => new Date().toLocaleDateString('de-DE')