31-10-2023

This commit is contained in:
Jonathan Jenne 2023-10-31 09:05:24 +01:00
parent b5e0908149
commit dc24ae3631
10 changed files with 435 additions and 264 deletions

View File

@ -3,17 +3,14 @@
Public Class EnvelopeReceiver Public Class EnvelopeReceiver
Public Property Id As Integer Public Property Id As Integer
Public Property UserId As Integer Public Property UserId As Integer
Public Property Signature As String
Public Property Name As String Public Property Name As String
Public Property Company As String = "" Public Property Company As String = ""
Public Property JobTitle As String = "" Public Property JobTitle As String = ""
Public Property Email As String Public Property Email As String
Public ReadOnly Property Signature As String
Get
Return StringEx.GetChecksum(Email.ToUpper)
End Get
End Property
Public ReadOnly Property HasId As Boolean Public ReadOnly Property HasId As Boolean
Get Get
Return Id > 0 Return Id > 0
@ -23,4 +20,8 @@ Public Class EnvelopeReceiver
Public Property Sequence As Integer = 0 Public Property Sequence As Integer = 0
Public Property PrivateMessage As String = "" Public Property PrivateMessage As String = ""
Public Property AccessCode As String = "" Public Property AccessCode As String = ""
Public Function GetSignature() As String
Return StringEx.GetChecksum(Email.ToUpper)
End Function
End Class End Class

View File

@ -8,8 +8,10 @@
''' <returns>The EnvelopeKey</returns> ''' <returns>The EnvelopeKey</returns>
Public Shared Function EncodeEnvelopeReceiverId(pEnvelopeUuid As String, pReceiverSignature As String) As String Public Shared Function EncodeEnvelopeReceiverId(pEnvelopeUuid As String, pReceiverSignature As String) As String
Dim oString = $"{pEnvelopeUuid}::{pReceiverSignature}" Dim oString = $"{pEnvelopeUuid}::{pReceiverSignature}"
'TODO: Verschlüsseln Dim oBytes = Text.Encoding.UTF8.GetBytes(oString)
Return oString Dim oBase64String = Convert.ToBase64String(oBytes)
Return oBase64String
End Function End Function
''' <summary> ''' <summary>
@ -18,13 +20,14 @@
''' <param name="pEnvelopeReceiverId">The EnvelopeKey</param> ''' <param name="pEnvelopeReceiverId">The EnvelopeKey</param>
''' <returns>A tuple containing EnvelopeUUID and Receiver Signature</returns> ''' <returns>A tuple containing EnvelopeUUID and Receiver Signature</returns>
Public Shared Function DecodeEnvelopeReceiverId(pEnvelopeReceiverId As String) As Tuple(Of String, String) Public Shared Function DecodeEnvelopeReceiverId(pEnvelopeReceiverId As String) As Tuple(Of String, String)
Dim oSplit = pEnvelopeReceiverId.Split(New String() {"::"}, StringSplitOptions.None) Dim oBytes = Convert.FromBase64String(pEnvelopeReceiverId)
'TODO: Entschlüsseln Dim oString = Text.Encoding.UTF8.GetString(oBytes)
Dim oSplit = oString.Split(New String() {"::"}, StringSplitOptions.None)
Return New Tuple(Of String, String)(oSplit(0), oSplit(1)) Return New Tuple(Of String, String)(oSplit(0), oSplit(1))
End Function End Function
Public Shared Function GetEnvelopeURL(pHost As String, pEnvelopeUuid As String, pReceiverSignature As String) As String Public Shared Function GetEnvelopeURL(pHost As String, pEnvelopeUuid As String, pReceiverSignature As String) As String
Dim oEnvelopeUserReference As String = EncodeEnvelopeReceiverId(pEnvelopeUuid, pReceiverSignature) Dim oEnvelopeUserReference As String = EncodeEnvelopeReceiverId(pEnvelopeUuid, pReceiverSignature)
Dim oURL As String = String.Format("{0}/EnvelopeKey/{1}", pHost.Trim(), oEnvelopeUserReference) Dim oURL As String = String.Format("{0}/EnvelopeKey/{1}", pHost.Trim(), oEnvelopeUserReference)
Return oURL Return oURL

View File

@ -6,12 +6,14 @@ Imports DigitalData.Modules.Logging
Public Class EnvelopeModel Public Class EnvelopeModel
Inherits BaseModel Inherits BaseModel
Private UserModel As UserModel Private ReadOnly UserModel As UserModel
Private ReadOnly ReceiverModel As ReceiverModel
Public Sub New(pState As State) Public Sub New(pState As State)
MyBase.New(pState) MyBase.New(pState)
UserModel = New UserModel(pState) UserModel = New UserModel(pState)
ReceiverModel = New ReceiverModel(pState)
End Sub End Sub
Private Function ToEnvelope(pRow As DataRow) As Envelope Private Function ToEnvelope(pRow As DataRow) As Envelope
@ -29,6 +31,7 @@ Public Class EnvelopeModel
} }
oEnvelope.User = UserModel.SelectUser(oEnvelope.UserId) oEnvelope.User = UserModel.SelectUser(oEnvelope.UserId)
oEnvelope.Receivers = ReceiverModel.ListEnvelopeReceivers(oEnvelope.Id)
Return oEnvelope Return oEnvelope
End Function End Function

View File

@ -14,7 +14,8 @@ Public Class ReceiverModel
.Id = pRow.ItemEx("GUID", 0), .Id = pRow.ItemEx("GUID", 0),
.Email = pRow.ItemEx("EMAIL_ADDRESS", ""), .Email = pRow.ItemEx("EMAIL_ADDRESS", ""),
.Name = pRow.ItemEx("NAME", ""), .Name = pRow.ItemEx("NAME", ""),
.Sequence = pRow.ItemEx("SEQUENCE", 0) .Sequence = pRow.ItemEx("SEQUENCE", 0),
.Signature = pRow.ItemEx("SIGNATURE", "")
} }
End Function End Function
@ -40,7 +41,7 @@ Public Class ReceiverModel
Dim oCommand = New SqlCommand(oSql) Dim oCommand = New SqlCommand(oSql)
oCommand.Parameters.Add("EMAIL", SqlDbType.NVarChar).Value = pReceiver.Email oCommand.Parameters.Add("EMAIL", SqlDbType.NVarChar).Value = pReceiver.Email
oCommand.Parameters.Add("SIGNATURE", SqlDbType.NVarChar).Value = pReceiver.Signature oCommand.Parameters.Add("SIGNATURE", SqlDbType.NVarChar).Value = pReceiver.GetSignature()
Dim oResult = Database.ExecuteNonQuery(oCommand) Dim oResult = Database.ExecuteNonQuery(oCommand)
If oResult = True Then If oResult = True Then

View File

@ -12,6 +12,31 @@ namespace EnvelopeGenerator.Web.Handler
{ {
public class FileHandler public class FileHandler
{ {
public class PostResult
{
readonly bool Ok = true;
readonly string ErrorMessage = "";
readonly ErrorType ErrorType = ErrorType.None;
public PostResult()
{
Ok = true;
}
public PostResult(ErrorType errorType, string errorMessage)
{
Ok = false;
ErrorType = errorType;
ErrorMessage = errorMessage;
}
}
public enum ErrorType
{
None,
ServerError
}
/// <summary> /// <summary>
/// URL: GET /api/envelope/{envelopeKey} /// URL: GET /api/envelope/{envelopeKey}
/// ///
@ -76,7 +101,10 @@ namespace EnvelopeGenerator.Web.Handler
{ {
// Better error handling & reporting // Better error handling & reporting
logger.Error(e); logger.Error(e);
return Results.Problem(); return Results.Problem(
statusCode: 500,
detail: e.Message,
type: ErrorType.ServerError.ToString());
} }
} }
@ -91,11 +119,11 @@ namespace EnvelopeGenerator.Web.Handler
// Load Envelope from EnvelopeKey // Load Envelope from EnvelopeKey
string envelopeKey = EnsureValidEnvelopeKey(logger, ctx.Request); string envelopeKey = EnsureValidEnvelopeKey(logger, ctx.Request);
EnvelopeResponse r = database.LoadEnvelope(envelopeKey); EnvelopeResponse response = database.LoadEnvelope(envelopeKey);
// Get the document Index // Get the document Index
int documentId = EnsureValidDocumentIndex(logger, ctx.Request); int documentId = EnsureValidDocumentIndex(logger, ctx.Request);
var document = GetDocument(r.Envelope, documentId); var document = GetDocument(response.Envelope, documentId);
using FileStream fs = new(document.Filepath, FileMode.Open); using FileStream fs = new(document.Filepath, FileMode.Open);
await ctx.Request.Body.CopyToAsync(fs); await ctx.Request.Body.CopyToAsync(fs);
@ -107,7 +135,10 @@ namespace EnvelopeGenerator.Web.Handler
{ {
// Better error handling & reporting // Better error handling & reporting
logger.Error(e); logger.Error(e);
return Results.Problem(); return Results.Problem(
statusCode: 500,
detail: e.Message,
type: ErrorType.ServerError.ToString());
} }
} }
@ -151,10 +182,17 @@ namespace EnvelopeGenerator.Web.Handler
{ {
// Better error handling & reporting // Better error handling & reporting
logger.Error(e); logger.Error(e);
return Results.Problem(); return Results.Problem(
statusCode: 500,
detail: e.Message,
type: ErrorType.ServerError.ToString());
} }
} }
#region Private
private State GetState(LogConfig LogConfig, MSSQLServer Database) private State GetState(LogConfig LogConfig, MSSQLServer Database)
{ {
return new State return new State
@ -235,5 +273,8 @@ namespace EnvelopeGenerator.Web.Handler
return document; return document;
} }
#endregion
} }
} }

View File

@ -8,17 +8,31 @@
<ul> <ul>
@foreach (var envelope in envelopes) @foreach (var envelope in envelopes)
{ {
<li><a href="/EnvelopeKey/@Helpers.EncodeEnvelopeReceiverId(envelope.Uuid, "DDA3F6FA6605965DAC6FCF5AC518C78CDA11086584FED872BE146E987976F829")">Envelope @envelope.Id</a></li> <li><a href="/EnvelopeKey/@getEnvelopeKey(envelope)">@envelope.Title</a></li>
} }
</ul> </ul>
@code { @code {
public List<Envelope> envelopes = new(); public List<Envelope> envelopes = new();
// List envelopes delivered to j.jenne@digitaldata.works
public int receiverId = 11;
string? getReceiverSignature(Envelope envelope)
{
var receiver = envelope.Receivers.Where(r => r.Id == receiverId).SingleOrDefault();
return receiver?.Signature;
}
string getEnvelopeKey(Envelope envelope)
{
return Helpers.EncodeEnvelopeReceiverId(envelope.Uuid, getReceiverSignature(envelope));
}
protected override void OnInitialized() protected override void OnInitialized()
{ {
// Test // Test
envelopes = Database.LoadEnvelopes(11); envelopes = Database.LoadEnvelopes(receiverId);
} }

View File

@ -59,42 +59,82 @@ export class App {
} }
public static async handleClick(eventType: string) { public static async handleClick(eventType: string) {
let result = false;
switch (eventType) { switch (eventType) {
case "RESET": case "RESET":
await App.handleReset(null) result = await App.handleReset(null)
if (result == true) {
alert("Dokument zurückgesetzt!");
} else {
alert("Fehler beim Zurücksetzen des Dokuments!")
}
break; break;
case "FINISH": case "FINISH":
await App.handleFinish(null) result = await App.handleFinish(null)
if (result == true) {
// TODO: Redirect to success page
alert("Dokument erfolgreich signiert!")
} else {
alert("Fehler beim Abschließen des Dokuments!")
}
break; break;
} }
} }
public static async handleFinish(event: any) { public static async handleFinish(event: any): Promise<boolean> {
await App.Instance.save(); // Save changes before doing anything
try {
await App.Instance.save();
} catch (e) {
console.error(e);
return false;
}
// Export annotation data and save to database // Export annotation data and save to database
const json = await App.Instance.exportInstantJSON() try {
console.log(json); const json = await App.Instance.exportInstantJSON()
console.log(JSON.stringify(json)); const postEnvelopeResult: boolean = await App.Network.postEnvelope(App.envelopeKey, App.currentDocument.id, JSON.stringify(json))
const result: boolean = await App.Network.postEnvelope(App.envelopeKey, App.currentDocument.id, JSON.stringify(json))
if (result == true) { if (postEnvelopeResult === false) {
alert("Dokument erfolgreich signiert!") return false;
}
} catch (e) {
console.error(e);
return false;
} }
// Flatten the annotations and save the document to disk // Flatten the annotations and save the document to disk
/* try {
const buffer = await App.Instance.exportPDF({ flatten: true }); const buffer = await App.Instance.exportPDF({ flatten: true });
const result = await App.Network.postDocument(App.envelopeKey, App.currentDocument.id, buffer); const postDocumentResult: boolean = await App.Network.postDocument(App.envelopeKey, App.currentDocument.id, buffer);
console.log(result)
*/ if (postDocumentResult === false) {
return false;
}
} catch (e) {
console.error(e);
return false;
}
return true;
} }
public static async handleReset(event: any) { public static async handleReset(event: any): Promise<boolean> {
if (confirm("Wollen Sie das Dokument und alle erstellten Signaturen zurücksetzen?")) { if (confirm("Wollen Sie das Dokument und alle erstellten Signaturen zurücksetzen?")) {
const result = App.Annotation.deleteAnnotations(App.Instance) const result = App.Annotation.deleteAnnotations(App.Instance)
return true;
} else {
return true;
} }
} }
@ -202,18 +242,34 @@ class Network {
} }
public postDocument(envelopeKey: string, documentId: number, buffer: ArrayBuffer): Promise<any> { public postDocument(envelopeKey: string, documentId: number, buffer: ArrayBuffer): Promise<any> {
return fetch(`/api/document/${envelopeKey}/${documentId}`, { credentials: "include", method: "POST", body: buffer }) const url = `/api/document/${envelopeKey}/${documentId}`;
.then(res => res.json()); const options: RequestInit = {
credentials: "include",
method: "POST",
body: buffer
}
console.debug("PostDocument/Calling url: " + url)
return fetch(url, options)
.then(this.handleResponse)
.then((res: Response) => {
if (!res.ok) {
return false;
};
return true;
});
} }
public postEnvelope(envelopeKey: string, documentId: number, jsonString: string): Promise<boolean> { public postEnvelope(envelopeKey: string, documentId: number, jsonString: string): Promise<boolean> {
const url = `/api/envelope/${envelopeKey}?index=${documentId}`;
const options: RequestInit = { const options: RequestInit = {
credentials: "include", credentials: "include",
method: "POST", method: "POST",
body: jsonString body: jsonString
} }
return fetch(`/api/envelope/${envelopeKey}?index=${documentId}`, options) console.debug("PostEnvelope/Calling url: " + url)
return fetch(url, options)
.then(this.handleResponse) .then(this.handleResponse)
.then((res: Response) => { .then((res: Response) => {
if (!res.ok) { if (!res.ok) {
@ -297,18 +353,20 @@ class UI {
{ {
type: "custom", type: "custom",
id: "button-reset", id: "button-reset",
className: "button-reset",
title: "Zurücksetzen", title: "Zurücksetzen",
onPress() { onPress() {
callback("RESET") callback("RESET")
}, },
icon: `<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor" class="bi bi-arrow-counterclockwise" viewBox="0 0 16 16"> icon: `<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor" class="bi bi-arrow-counterclockwise" viewBox="0 0 16 16">
<path fill-rule="evenodd" d="M8 3a5 5 0 1 1-4.546 2.914.5.5 0 0 0-.908-.417A6 6 0 1 0 8 2v1z"/> <path fill-rule="evenodd" d="M8 3a5 5 0 1 1-4.546 2.914.5.5 0 0 0-.908-.417A6 6 0 1 0 8 2v1z"/>
<path d="M8 4.466V.534a.25.25 0 0 0-.41-.192L5.23 2.308a.25.25 0 0 0 0 .384l2.36 1.966A.25.25 0 0 0 8 4.466z"/> <path d="M8 4.466V.534a.25.25 0 0 0-.41-.192L5.23 2.308a.25.25 0 0 0 0 .384l2.36 1.966A.25.25 0 0 0 8 4.466z"/>
</svg>` </svg>`
}, },
{ {
type: "custom", type: "custom",
id: "button-finish", id: "button-finish",
className: "button-finish",
title: "Abschließen", title: "Abschließen",
onPress() { onPress() {
callback("FINISH") callback("FINISH")

View File

@ -5103,6 +5103,7 @@ interface IImageAnnotation extends AnnotationProperties {
imageAttachmentId: string | null; imageAttachmentId: string | null;
isSignature: boolean; isSignature: boolean;
xfdfAppearanceStream: string | null; xfdfAppearanceStream: string | null;
xfdfAppearanceStreamOriginalPageRotation: number | null;
} }
declare class ImageAnnotation<T extends IImageAnnotation = IImageAnnotation> extends Annotation<T> { declare class ImageAnnotation<T extends IImageAnnotation = IImageAnnotation> extends Annotation<T> {
description: null | string; description: null | string;
@ -5111,6 +5112,7 @@ declare class ImageAnnotation<T extends IImageAnnotation = IImageAnnotation> ext
imageAttachmentId: string; imageAttachmentId: string;
isSignature: boolean; isSignature: boolean;
xfdfAppearanceStream: null | string; xfdfAppearanceStream: null | string;
xfdfAppearanceStreamOriginalPageRotation: null | number;
static defaultValues: IObject; static defaultValues: IObject;
static readableName: string; static readableName: string;
} }
@ -6067,197 +6069,6 @@ type SerializedAdditionalActionsType = {
}; };
}; };
type Glyph = {
c: string;
rect: Rect;
};
declare const SearchType: {
readonly TEXT: "text";
readonly PRESET: "preset";
readonly REGEX: "regex";
};
type ISearchType = (typeof SearchType)[keyof typeof SearchType];
declare function toJSON(bookmark: Bookmark): BookmarkJSON;
type ID$1 = string;
type BookmarkProps = {
id: ID$1 | null;
pdfBookmarkId: ID$1 | null;
name: string | null;
sortKey: number | null;
action: Action | null;
};
declare const Bookmark_base: Record$1.Factory<BookmarkProps>;
declare class Bookmark extends Bookmark_base {
id: ID$1;
action: Action;
static toSerializableObject: typeof toJSON;
static fromSerializableObject: (bookmark: BookmarkJSON) => Bookmark;
}
type Rotation$1 = 0 | 90 | 180 | 270;
type AddPageConfiguration = {
backgroundColor: Color;
pageWidth: number;
pageHeight: number;
rotateBy: Rotation$1;
insets?: Rect;
};
type OperationAttachment = string | File | Blob;
type min = number;
type max = number;
type Range = [min, max];
type ImportPageIndex = Array<number | Range>;
type DocumentMetadata = {
title?: string;
author?: string;
};
type NonSerializableDocumentOperations = {
type: 'removePages';
pageIndexes: Array<number>;
} | {
type: 'duplicatePages';
pageIndexes: Array<number>;
} | {
type: 'movePages';
pageIndexes: Array<number>;
afterPageIndex: number;
} | {
type: 'movePages';
pageIndexes: Array<number>;
beforePageIndex: number;
} | {
type: 'rotatePages';
pageIndexes: Array<number>;
rotateBy: Rotation$1;
} | {
type: 'keepPages';
pageIndexes: Array<number>;
} | {
type: 'importDocument';
afterPageIndex: number;
treatImportedDocumentAsOnePage?: boolean;
document: OperationAttachment;
importedPageIndexes?: ImportPageIndex;
} | {
type: 'importDocument';
beforePageIndex: number;
treatImportedDocumentAsOnePage?: boolean;
document: OperationAttachment;
importedPageIndexes?: ImportPageIndex;
} | {
type: 'applyInstantJson';
instantJson: Record<string, any>;
dataFilePath: OperationAttachment;
} | {
type: 'applyXfdf';
xfdf: string;
ignorePageRotation?: boolean;
dataFilePath: OperationAttachment;
} | {
type: 'flattenAnnotations';
pageIndexes?: Array<number>;
annotationIds?: string[];
} | {
type: 'setPageLabel';
pageIndexes?: Array<number>;
pageLabel?: string;
} | {
type: 'performOcr';
pageIndexes?: Array<number> | 'all';
language: string;
} | {
type: 'applyRedactions';
} | {
type: 'updateMetadata';
metadata: DocumentMetadata;
};
type DocumentOperation = (AddPageConfiguration & {
type: 'addPage';
afterPageIndex: number;
}) | (AddPageConfiguration & {
type: 'addPage';
beforePageIndex: number;
}) | {
type: 'cropPages';
pageIndexes?: Array<number>;
cropBox: Rect;
} | NonSerializableDocumentOperations;
type BaseFormFieldJSON = {
v: 1;
pdfObjectId?: number | null;
annotationIds: Array<string>;
name: string;
label: string;
flags?: FormFieldFlags;
id: string;
additionalActions?: SerializedAdditionalActionsType;
group?: IGroup;
permissions?: IPermissions;
};
type ChoiceFormFieldJSON = BaseFormFieldJSON & {
type: 'pspdfkit/form-field/listbox' | 'pspdfkit/form-field/combobox';
options: Array<FormOptionJSON>;
multiSelect: boolean;
commitOnChange: boolean;
defaultValues: Array<string>;
};
type ListBoxFormFieldJSON = ChoiceFormFieldJSON & {
type: 'pspdfkit/form-field/listbox';
};
type DoNotSpellCheckPropertyPair = XOR<Record<'doNotSpellCheck', boolean>, Record<'doNotSpellcheck', boolean>>;
type ComboBoxFormFieldJSON = ChoiceFormFieldJSON & {
type: 'pspdfkit/form-field/combobox';
edit: boolean;
} & DoNotSpellCheckPropertyPair;
type CheckBoxFormFieldJSON = BaseFormFieldJSON & {
type: 'pspdfkit/form-field/checkbox';
options: Array<FormOptionJSON>;
defaultValues: Array<string>;
};
type RadioButtonFormFieldJSON = BaseFormFieldJSON & {
type: 'pspdfkit/form-field/radio';
options: Array<FormOptionJSON>;
noToggleToOff: boolean;
radiosInUnison: boolean;
defaultValue: string;
};
type TextFormFieldJSON = BaseFormFieldJSON & {
type: 'pspdfkit/form-field/text';
password: boolean;
maxLength?: number | null;
doNotScroll: boolean;
multiLine: boolean;
defaultValue: string;
comb: boolean;
} & DoNotSpellCheckPropertyPair;
type ButtonFormFieldJSON = BaseFormFieldJSON & {
type: 'pspdfkit/form-field/button';
buttonLabel: string | null;
};
type SignatureFormFieldJSON = BaseFormFieldJSON & {
type: 'pspdfkit/form-field/signature';
};
type FormFieldJSON = ListBoxFormFieldJSON | ComboBoxFormFieldJSON | RadioButtonFormFieldJSON | CheckBoxFormFieldJSON | TextFormFieldJSON | ButtonFormFieldJSON | SignatureFormFieldJSON;
type OCGLayer = {
name: string;
ocgId: number;
radioGroup?: number;
};
type OCGCollection = {
name?: string;
ocgId?: number;
layers: OCGLayer[];
};
type OCG = OCGLayer | OCGCollection;
type OCGVisibilityState = {
visibleOCGIds: number[];
};
type IRectJSON = [left: number, top: number, width: number, height: number]; type IRectJSON = [left: number, top: number, width: number, height: number];
type BaseAnnotationJSON = { type BaseAnnotationJSON = {
@ -6294,6 +6105,7 @@ type ImageAnnotationJSON = Omit<BaseAnnotationJSON, 'type'> & {
rotation: number; rotation: number;
isSignature?: boolean; isSignature?: boolean;
xfdfAppearanceStream?: string; xfdfAppearanceStream?: string;
xfdfAppearanceStreamOriginalPageRotation?: number;
}; };
type ShapeAnnotationJSON = Omit<BaseAnnotationJSON, 'type'> & { type ShapeAnnotationJSON = Omit<BaseAnnotationJSON, 'type'> & {
strokeWidth: number; strokeWidth: number;
@ -6403,6 +6215,7 @@ type StampAnnotationJSON = Omit<BaseAnnotationJSON, 'type'> & {
subtitle: string | null; subtitle: string | null;
rotation: number | null; rotation: number | null;
xfdfAppearanceStream?: string; xfdfAppearanceStream?: string;
xfdfAppearanceStreamOriginalPageRotation?: number;
kind?: StampKind; kind?: StampKind;
}; };
type TextAnnotationJSON = Omit<BaseAnnotationJSON, 'type'> & { type TextAnnotationJSON = Omit<BaseAnnotationJSON, 'type'> & {
@ -6458,6 +6271,63 @@ type CommentMarkerAnnotationJSON = Omit<BaseAnnotationJSON, 'type'> & {
}; };
type AnnotationJSONUnion = TextMarkupAnnotationJSON | TextAnnotationJSON | WidgetAnnotationJSON | RedactionAnnotationJSON | StampAnnotationJSON | NoteAnnotationJSON | LinkAnnotationJSON | InkAnnotationJSON | RectangleAnnotationJSON | PolylineAnnotationJSON | PolygonAnnotationJSON | LineAnnotationJSON | EllipseAnnotationJSON | ImageAnnotationJSON | UnknownAnnotationJSON | MediaAnnotationJSON | CommentMarkerAnnotationJSON; type AnnotationJSONUnion = TextMarkupAnnotationJSON | TextAnnotationJSON | WidgetAnnotationJSON | RedactionAnnotationJSON | StampAnnotationJSON | NoteAnnotationJSON | LinkAnnotationJSON | InkAnnotationJSON | RectangleAnnotationJSON | PolylineAnnotationJSON | PolygonAnnotationJSON | LineAnnotationJSON | EllipseAnnotationJSON | ImageAnnotationJSON | UnknownAnnotationJSON | MediaAnnotationJSON | CommentMarkerAnnotationJSON;
type BaseFormFieldJSON = {
v: 1;
pdfObjectId?: number | null;
annotationIds: Array<string>;
name: string;
label: string;
flags?: FormFieldFlags;
id: string;
additionalActions?: SerializedAdditionalActionsType;
group?: IGroup;
permissions?: IPermissions;
};
type ChoiceFormFieldJSON = BaseFormFieldJSON & {
type: 'pspdfkit/form-field/listbox' | 'pspdfkit/form-field/combobox';
options: Array<FormOptionJSON>;
multiSelect: boolean;
commitOnChange: boolean;
defaultValues: Array<string>;
};
type ListBoxFormFieldJSON = ChoiceFormFieldJSON & {
type: 'pspdfkit/form-field/listbox';
};
type DoNotSpellCheckPropertyPair = XOR<Record<'doNotSpellCheck', boolean>, Record<'doNotSpellcheck', boolean>>;
type ComboBoxFormFieldJSON = ChoiceFormFieldJSON & {
type: 'pspdfkit/form-field/combobox';
edit: boolean;
} & DoNotSpellCheckPropertyPair;
type CheckBoxFormFieldJSON = BaseFormFieldJSON & {
type: 'pspdfkit/form-field/checkbox';
options: Array<FormOptionJSON>;
defaultValues: Array<string>;
};
type RadioButtonFormFieldJSON = BaseFormFieldJSON & {
type: 'pspdfkit/form-field/radio';
options: Array<FormOptionJSON>;
noToggleToOff: boolean;
radiosInUnison: boolean;
defaultValue: string;
};
type TextFormFieldJSON = BaseFormFieldJSON & {
type: 'pspdfkit/form-field/text';
password: boolean;
maxLength?: number | null;
doNotScroll: boolean;
multiLine: boolean;
defaultValue: string;
comb: boolean;
} & DoNotSpellCheckPropertyPair;
type ButtonFormFieldJSON = BaseFormFieldJSON & {
type: 'pspdfkit/form-field/button';
buttonLabel: string | null;
};
type SignatureFormFieldJSON = BaseFormFieldJSON & {
type: 'pspdfkit/form-field/signature';
};
type FormFieldJSON = ListBoxFormFieldJSON | ComboBoxFormFieldJSON | RadioButtonFormFieldJSON | CheckBoxFormFieldJSON | TextFormFieldJSON | ButtonFormFieldJSON | SignatureFormFieldJSON;
type SerializedJSON = { type SerializedJSON = {
skippedPdfObjectIds?: number[]; skippedPdfObjectIds?: number[];
annotations?: AnnotationJSONUnion[]; annotations?: AnnotationJSONUnion[];
@ -6479,6 +6349,113 @@ type InstantJSON = SerializedJSON & {
}; };
}; };
type Rotation$1 = 0 | 90 | 180 | 270;
type AddPageConfiguration = {
backgroundColor: Color;
pageWidth: number;
pageHeight: number;
rotateBy: Rotation$1;
insets?: Rect;
};
type OperationAttachment = string | File | Blob;
type min = number;
type max = number;
type Range = [min, max];
type ImportPageIndex = Array<number | Range>;
type DocumentMetadata = {
title?: string;
author?: string;
};
type NonSerializableDocumentOperations = {
type: 'removePages';
pageIndexes: Array<number>;
} | {
type: 'duplicatePages';
pageIndexes: Array<number>;
} | {
type: 'movePages';
pageIndexes: Array<number>;
afterPageIndex: number;
} | {
type: 'movePages';
pageIndexes: Array<number>;
beforePageIndex: number;
} | {
type: 'rotatePages';
pageIndexes: Array<number>;
rotateBy: Rotation$1;
} | {
type: 'keepPages';
pageIndexes: Array<number>;
} | {
type: 'importDocument';
afterPageIndex: number;
treatImportedDocumentAsOnePage?: boolean;
document: OperationAttachment;
importedPageIndexes?: ImportPageIndex;
} | {
type: 'importDocument';
beforePageIndex: number;
treatImportedDocumentAsOnePage?: boolean;
document: OperationAttachment;
importedPageIndexes?: ImportPageIndex;
} | {
type: 'applyInstantJson';
instantJson: Record<string, any>;
dataFilePath: OperationAttachment;
} | {
type: 'applyXfdf';
xfdf: string;
ignorePageRotation?: boolean;
dataFilePath: OperationAttachment;
} | {
type: 'flattenAnnotations';
pageIndexes?: Array<number>;
annotationIds?: string[];
} | {
type: 'setPageLabel';
pageIndexes?: Array<number>;
pageLabel?: string;
} | {
type: 'performOcr';
pageIndexes?: Array<number> | 'all';
language: string;
} | {
type: 'applyRedactions';
} | {
type: 'updateMetadata';
metadata: DocumentMetadata;
};
type DocumentOperation = (AddPageConfiguration & {
type: 'addPage';
afterPageIndex: number;
}) | (AddPageConfiguration & {
type: 'addPage';
beforePageIndex: number;
}) | {
type: 'cropPages';
pageIndexes?: Array<number>;
cropBox: Rect;
} | NonSerializableDocumentOperations;
declare function toJSON(bookmark: Bookmark): BookmarkJSON;
type ID$1 = string;
type BookmarkProps = {
id: ID$1 | null;
pdfBookmarkId: ID$1 | null;
name: string | null;
sortKey: number | null;
action: Action | null;
};
declare const Bookmark_base: Record$1.Factory<BookmarkProps>;
declare class Bookmark extends Bookmark_base {
id: ID$1;
action: Action;
static toSerializableObject: typeof toJSON;
static fromSerializableObject: (bookmark: BookmarkJSON) => Bookmark;
}
declare const SearchPattern: { declare const SearchPattern: {
readonly CREDIT_CARD_NUMBER: "credit_card_number"; readonly CREDIT_CARD_NUMBER: "credit_card_number";
readonly DATE: "date"; readonly DATE: "date";
@ -6496,6 +6473,13 @@ declare const SearchPattern: {
}; };
type ISearchPattern = (typeof SearchPattern)[keyof typeof SearchPattern]; type ISearchPattern = (typeof SearchPattern)[keyof typeof SearchPattern];
declare const SearchType: {
readonly TEXT: "text";
readonly PRESET: "preset";
readonly REGEX: "regex";
};
type ISearchType = (typeof SearchType)[keyof typeof SearchType];
declare const ProductId: { declare const ProductId: {
SharePoint: string; SharePoint: string;
Salesforce: string; Salesforce: string;
@ -6546,6 +6530,11 @@ type SignatureAppearance = {
watermarkImage?: Blob | File; watermarkImage?: Blob | File;
}; };
type Glyph = {
c: string;
rect: Rect;
};
declare const TextLineElementKind: { declare const TextLineElementKind: {
P: string; P: string;
TH: string; TH: string;
@ -7114,7 +7103,7 @@ declare class InstantClient {
userId: string | null | undefined; userId: string | null | undefined;
} }
declare const allowedToolbarTypes: ("distance" | "note" | "comment" | "text" | "zoom-in" | "zoom-out" | "link" | "search" | "ellipse" | "image" | "line" | "polygon" | "polyline" | "spacer" | "arrow" | "highlighter" | "undo" | "redo" | "callout" | "debug" | "signature" | "custom" | "print" | "rectangle" | "ink" | "stamp" | "cloudy-rectangle" | "dashed-rectangle" | "cloudy-ellipse" | "dashed-ellipse" | "cloudy-polygon" | "dashed-polygon" | "text-highlighter" | "perimeter" | "ellipse-area" | "rectangle-area" | "polygon-area" | "sidebar-thumbnails" | "sidebar-document-outline" | "sidebar-annotations" | "sidebar-bookmarks" | "pager" | "multi-annotations-selection" | "pan" | "zoom-mode" | "annotate" | "ink-eraser" | "document-editor" | "document-crop" | "export-pdf" | "layout-config" | "marquee-zoom" | "responsive-group" | "redact-text-highlighter" | "redact-rectangle" | "document-comparison" | "measure" | "form-creator" | "content-editor")[]; declare const allowedToolbarTypes: ("distance" | "note" | "comment" | "text" | "zoom-in" | "zoom-out" | "link" | "search" | "ellipse" | "image" | "line" | "polygon" | "polyline" | "spacer" | "arrow" | "highlighter" | "undo" | "redo" | "callout" | "custom" | "print" | "rectangle" | "ink" | "stamp" | "cloudy-rectangle" | "dashed-rectangle" | "cloudy-ellipse" | "dashed-ellipse" | "cloudy-polygon" | "dashed-polygon" | "text-highlighter" | "perimeter" | "ellipse-area" | "rectangle-area" | "polygon-area" | "sidebar-thumbnails" | "sidebar-document-outline" | "sidebar-annotations" | "sidebar-bookmarks" | "pager" | "multi-annotations-selection" | "pan" | "zoom-mode" | "annotate" | "ink-eraser" | "signature" | "document-editor" | "document-crop" | "export-pdf" | "debug" | "layout-config" | "marquee-zoom" | "responsive-group" | "redact-text-highlighter" | "redact-rectangle" | "document-comparison" | "measure" | "form-creator" | "content-editor")[];
type ToolbarItemType = ToolItemType | (typeof allowedToolbarTypes)[number]; type ToolbarItemType = ToolItemType | (typeof allowedToolbarTypes)[number];
type ToolbarItem = Omit<ToolItem, 'type'> & { type ToolbarItem = Omit<ToolItem, 'type'> & {
@ -7494,7 +7483,6 @@ declare class Instance {
textLinesForPageIndex: (pageIndex: number) => Promise<List<TextLine>>; textLinesForPageIndex: (pageIndex: number) => Promise<List<TextLine>>;
getMarkupAnnotationText: (annotation: TextMarkupAnnotationsUnion) => Promise<string>; getMarkupAnnotationText: (annotation: TextMarkupAnnotationsUnion) => Promise<string>;
getTextFromRects: (pageIndex: number, rects: List<Rect>) => Promise<string>; getTextFromRects: (pageIndex: number, rects: List<Rect>) => Promise<string>;
getDocumentPermissions: () => Promise<Record<IDocumentPermissions, boolean>>;
currentZoomLevel: number; currentZoomLevel: number;
maximumZoomLevel: number; maximumZoomLevel: number;
minimumZoomLevel: number; minimumZoomLevel: number;
@ -7535,9 +7523,6 @@ declare class Instance {
setAnnotationCreatorName: (annotationCreatorName?: string | null) => void; setAnnotationCreatorName: (annotationCreatorName?: string | null) => void;
setOnWidgetAnnotationCreationStart: (callback: OnWidgetAnnotationCreationStartCallback) => void; setOnWidgetAnnotationCreationStart: (callback: OnWidgetAnnotationCreationStartCallback) => void;
setOnCommentCreationStart: (callback: OnCommentCreationStartCallback) => void; setOnCommentCreationStart: (callback: OnCommentCreationStartCallback) => void;
getOCGs: () => Promise<OCG[]>;
getOCGVisibilityState: () => Promise<OCGVisibilityState>;
setOCGVisibilityState: (visibilityState: OCGVisibilityState) => Promise<void>;
contentWindow: Window; contentWindow: Window;
contentDocument: Document; contentDocument: Document;
readonly viewState: ViewState; readonly viewState: ViewState;
@ -7603,7 +7588,7 @@ declare class Instance {
setDocumentEditorFooterItems: (stateOrFunction: DocumentEditorFooterItem[] | SetDocumentEditorFooterFunction) => void; setDocumentEditorFooterItems: (stateOrFunction: DocumentEditorFooterItem[] | SetDocumentEditorFooterFunction) => void;
setDocumentEditorToolbarItems: (stateOrFunction: DocumentEditorToolbarItem[] | SetDocumentEditorToolbarFunction) => void; setDocumentEditorToolbarItems: (stateOrFunction: DocumentEditorToolbarItem[] | SetDocumentEditorToolbarFunction) => void;
getSignaturesInfo: () => Promise<SignaturesInfo>; getSignaturesInfo: () => Promise<SignaturesInfo>;
signDocument: (arg0: SignatureCreationData | null, arg1?: TwoStepSignatureCallback | SigningServiceData) => Promise<void>; signDocument: (arg0: SignatureCreationData | null | undefined, arg1: TwoStepSignatureCallback | SigningServiceData | undefined) => Promise<void>;
applyOperations: (operations: Array<DocumentOperation>) => Promise<void>; applyOperations: (operations: Array<DocumentOperation>) => Promise<void>;
exportPDFWithOperations: (arg0: Array<DocumentOperation>) => Promise<ArrayBuffer>; exportPDFWithOperations: (arg0: Array<DocumentOperation>) => Promise<ArrayBuffer>;
applyRedactions: () => Promise<void>; applyRedactions: () => Promise<void>;
@ -7787,7 +7772,6 @@ type StandaloneConfiguration = SharedConfiguration & {
isSalesforce?: boolean; isSalesforce?: boolean;
productId?: IProductId; productId?: IProductId;
processorEngine?: IProcessorEngine; processorEngine?: IProcessorEngine;
dynamicFonts?: string;
}; };
type Configuration = ServerConfiguration | StandaloneConfiguration; type Configuration = ServerConfiguration | StandaloneConfiguration;
@ -8079,6 +8063,7 @@ interface IStampAnnotation extends AnnotationProperties {
subtitle: string | null; subtitle: string | null;
color: Color | null; color: Color | null;
xfdfAppearanceStream: string | null; xfdfAppearanceStream: string | null;
xfdfAppearanceStreamOriginalPageRotation: number | null;
} }
declare class StampAnnotation<T extends IStampAnnotation = IStampAnnotation> extends Annotation<T> { declare class StampAnnotation<T extends IStampAnnotation = IStampAnnotation> extends Annotation<T> {
stampType: StampKind; stampType: StampKind;
@ -8086,6 +8071,7 @@ declare class StampAnnotation<T extends IStampAnnotation = IStampAnnotation> ext
subtitle: null | string; subtitle: null | string;
color: null | Color; color: null | Color;
xfdfAppearanceStream: null | string; xfdfAppearanceStream: null | string;
xfdfAppearanceStreamOriginalPageRotation: null | number;
static defaultValues: IObject; static defaultValues: IObject;
static readableName: string; static readableName: string;
} }

View File

@ -97,10 +97,11 @@ var App = /** @class */ (function () {
}; };
App.handleClick = function (eventType) { App.handleClick = function (eventType) {
return __awaiter(this, void 0, void 0, function () { return __awaiter(this, void 0, void 0, function () {
var _a; var result, _a;
return __generator(this, function (_b) { return __generator(this, function (_b) {
switch (_b.label) { switch (_b.label) {
case 0: case 0:
result = false;
_a = eventType; _a = eventType;
switch (_a) { switch (_a) {
case "RESET": return [3 /*break*/, 1]; case "RESET": return [3 /*break*/, 1];
@ -109,11 +110,24 @@ var App = /** @class */ (function () {
return [3 /*break*/, 5]; return [3 /*break*/, 5];
case 1: return [4 /*yield*/, App.handleReset(null)]; case 1: return [4 /*yield*/, App.handleReset(null)];
case 2: case 2:
_b.sent(); result = _b.sent();
if (result == true) {
alert("Dokument zurückgesetzt!");
}
else {
alert("Fehler beim Zurücksetzen des Dokuments!");
}
return [3 /*break*/, 5]; return [3 /*break*/, 5];
case 3: return [4 /*yield*/, App.handleFinish(null)]; case 3: return [4 /*yield*/, App.handleFinish(null)];
case 4: case 4:
_b.sent(); result = _b.sent();
if (result == true) {
// TODO: Redirect to success page
alert("Dokument erfolgreich signiert!");
}
else {
alert("Fehler beim Abschließen des Dokuments!");
}
return [3 /*break*/, 5]; return [3 /*break*/, 5];
case 5: return [2 /*return*/]; case 5: return [2 /*return*/];
} }
@ -122,24 +136,52 @@ var App = /** @class */ (function () {
}; };
App.handleFinish = function (event) { App.handleFinish = function (event) {
return __awaiter(this, void 0, void 0, function () { return __awaiter(this, void 0, void 0, function () {
var json, result; var e_2, json, postEnvelopeResult, e_3, buffer, postDocumentResult, e_4;
return __generator(this, function (_a) { return __generator(this, function (_a) {
switch (_a.label) { switch (_a.label) {
case 0: return [4 /*yield*/, App.Instance.save()]; case 0:
_a.trys.push([0, 2, , 3]);
return [4 /*yield*/, App.Instance.save()];
case 1: case 1:
_a.sent(); _a.sent();
return [4 /*yield*/, App.Instance.exportInstantJSON()]; return [3 /*break*/, 3];
case 2: case 2:
json = _a.sent(); e_2 = _a.sent();
console.log(json); console.error(e_2);
console.log(JSON.stringify(json)); return [2 /*return*/, false];
return [4 /*yield*/, App.Network.postEnvelope(App.envelopeKey, App.currentDocument.id, JSON.stringify(json))];
case 3: case 3:
result = _a.sent(); _a.trys.push([3, 6, , 7]);
if (result == true) { return [4 /*yield*/, App.Instance.exportInstantJSON()];
alert("Dokument erfolgreich signiert!"); case 4:
json = _a.sent();
return [4 /*yield*/, App.Network.postEnvelope(App.envelopeKey, App.currentDocument.id, JSON.stringify(json))];
case 5:
postEnvelopeResult = _a.sent();
if (postEnvelopeResult === false) {
return [2 /*return*/, false];
} }
return [2 /*return*/]; return [3 /*break*/, 7];
case 6:
e_3 = _a.sent();
console.error(e_3);
return [2 /*return*/, false];
case 7:
_a.trys.push([7, 10, , 11]);
return [4 /*yield*/, App.Instance.exportPDF({ flatten: true })];
case 8:
buffer = _a.sent();
return [4 /*yield*/, App.Network.postDocument(App.envelopeKey, App.currentDocument.id, buffer)];
case 9:
postDocumentResult = _a.sent();
if (postDocumentResult === false) {
return [2 /*return*/, false];
}
return [3 /*break*/, 11];
case 10:
e_4 = _a.sent();
console.error(e_4);
return [2 /*return*/, false];
case 11: return [2 /*return*/, true];
} }
}); });
}); });
@ -148,8 +190,12 @@ var App = /** @class */ (function () {
return __awaiter(this, void 0, void 0, function () { return __awaiter(this, void 0, void 0, function () {
var result; var result;
return __generator(this, function (_a) { return __generator(this, function (_a) {
if (confirm("Wollen Sie das Dokument und alle erstellten Signaturen zur<EFBFBD>cksetzen?")) { if (confirm("Wollen Sie das Dokument und alle erstellten Signaturen zurücksetzen?")) {
result = App.Annotation.deleteAnnotations(App.Instance); result = App.Annotation.deleteAnnotations(App.Instance);
return [2 /*return*/, true];
}
else {
return [2 /*return*/, true];
} }
return [2 /*return*/]; return [2 /*return*/];
}); });
@ -272,16 +318,32 @@ var Network = /** @class */ (function () {
.then(function (res) { return res.arrayBuffer(); }); .then(function (res) { return res.arrayBuffer(); });
}; };
Network.prototype.postDocument = function (envelopeKey, documentId, buffer) { Network.prototype.postDocument = function (envelopeKey, documentId, buffer) {
return fetch("/api/document/".concat(envelopeKey, "/").concat(documentId), { credentials: "include", method: "POST", body: buffer }) var url = "/api/document/".concat(envelopeKey, "/").concat(documentId);
.then(function (res) { return res.json(); }); var options = {
credentials: "include",
method: "POST",
body: buffer
};
console.debug("PostDocument/Calling url: " + url);
return fetch(url, options)
.then(this.handleResponse)
.then(function (res) {
if (!res.ok) {
return false;
}
;
return true;
});
}; };
Network.prototype.postEnvelope = function (envelopeKey, documentId, jsonString) { Network.prototype.postEnvelope = function (envelopeKey, documentId, jsonString) {
var url = "/api/envelope/".concat(envelopeKey, "?index=").concat(documentId);
var options = { var options = {
credentials: "include", credentials: "include",
method: "POST", method: "POST",
body: jsonString body: jsonString
}; };
return fetch("/api/envelope/".concat(envelopeKey, "?index=").concat(documentId), options) console.debug("PostEnvelope/Calling url: " + url);
return fetch(url, options)
.then(this.handleResponse) .then(this.handleResponse)
.then(function (res) { .then(function (res) {
if (!res.ok) { if (!res.ok) {
@ -321,16 +383,18 @@ var UI = /** @class */ (function () {
{ {
type: "custom", type: "custom",
id: "button-reset", id: "button-reset",
title: "Zur<75>cksetzen", className: "button-reset",
title: "Zurücksetzen",
onPress: function () { onPress: function () {
callback("RESET"); callback("RESET");
}, },
icon: "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"20\" height=\"20\" fill=\"currentColor\" class=\"bi bi-arrow-counterclockwise\" viewBox=\"0 0 16 16\">\n <path fill-rule=\"evenodd\" d=\"M8 3a5 5 0 1 1-4.546 2.914.5.5 0 0 0-.908-.417A6 6 0 1 0 8 2v1z\"/>\n <path d=\"M8 4.466V.534a.25.25 0 0 0-.41-.192L5.23 2.308a.25.25 0 0 0 0 .384l2.36 1.966A.25.25 0 0 0 8 4.466z\"/>\n </svg>" icon: "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"20\" height=\"20\" fill=\"currentColor\" class=\"bi bi-arrow-counterclockwise\" viewBox=\"0 0 16 16\">\n <path fill-rule=\"evenodd\" d=\"M8 3a5 5 0 1 1-4.546 2.914.5.5 0 0 0-.908-.417A6 6 0 1 0 8 2v1z\"/>\n <path d=\"M8 4.466V.534a.25.25 0 0 0-.41-.192L5.23 2.308a.25.25 0 0 0 0 .384l2.36 1.966A.25.25 0 0 0 8 4.466z\"/>\n </svg>"
}, },
{ {
type: "custom", type: "custom",
id: "button-finish", id: "button-finish",
title: "Abschlie<69>en", className: "button-finish",
title: "Abschließen",
onPress: function () { onPress: function () {
callback("FINISH"); callback("FINISH");
}, },

File diff suppressed because one or more lines are too long