Merge branch 'master' of http://git.dd:3000/AppStd/EnvelopeGenerator
This commit is contained in:
commit
b5579a68cd
@ -34,11 +34,13 @@ Namespace Jobs.FinalizeDocument
|
|||||||
|
|
||||||
Try
|
Try
|
||||||
Using oSourceStream As New MemoryStream(pSourceBuffer)
|
Using oSourceStream As New MemoryStream(pSourceBuffer)
|
||||||
|
' Open PDF
|
||||||
oResult = Manager.InitFromStream(oSourceStream)
|
oResult = Manager.InitFromStream(oSourceStream)
|
||||||
If oResult <> GdPictureStatus.OK Then
|
If oResult <> GdPictureStatus.OK Then
|
||||||
Throw New BurnAnnotationException($"Could not open document for burning: [{oResult}]")
|
Throw New BurnAnnotationException($"Could not open document for burning: [{oResult}]")
|
||||||
End If
|
End If
|
||||||
|
|
||||||
|
' Add annotation to PDF
|
||||||
For Each oJSON In pInstantJSONList
|
For Each oJSON In pInstantJSONList
|
||||||
If AddInstantJSONAnnotationToPDF(oJSON) = False Then
|
If AddInstantJSONAnnotationToPDF(oJSON) = False Then
|
||||||
Logger.Warn($"Error in AddInstantJSONAnnotationToPDF - oJson: ")
|
Logger.Warn($"Error in AddInstantJSONAnnotationToPDF - oJson: ")
|
||||||
@ -51,6 +53,7 @@ Namespace Jobs.FinalizeDocument
|
|||||||
Throw New BurnAnnotationException($"Could not burn annotations to file: [{oResult}]")
|
Throw New BurnAnnotationException($"Could not burn annotations to file: [{oResult}]")
|
||||||
End If
|
End If
|
||||||
|
|
||||||
|
'Save PDF
|
||||||
Using oNewStream As New MemoryStream()
|
Using oNewStream As New MemoryStream()
|
||||||
oResult = Manager.SaveDocumentToPDF(oNewStream)
|
oResult = Manager.SaveDocumentToPDF(oNewStream)
|
||||||
If oResult <> GdPictureStatus.OK Then
|
If oResult <> GdPictureStatus.OK Then
|
||||||
|
|||||||
@ -7,5 +7,10 @@ Public Class Config
|
|||||||
Public Property Debug As Boolean = False
|
Public Property Debug As Boolean = False
|
||||||
Public Property IntervalInMin As Integer = 1
|
Public Property IntervalInMin As Integer = 1
|
||||||
|
|
||||||
Public Property IgnoredLabels As List(Of String) = New List(Of String) From {"Date", "Datum", "ZIP", "PLZ", "Place", "Ort"}
|
Public Property IgnoredLabels As List(Of String) = New List(Of String) From {
|
||||||
|
"Date", "Datum",
|
||||||
|
"ZIP", "PLZ",
|
||||||
|
"Place", "Ort",
|
||||||
|
"Position", "Stellung"
|
||||||
|
}
|
||||||
End Class
|
End Class
|
||||||
|
|||||||
@ -15,7 +15,7 @@ Public Class frmFinalizePDF
|
|||||||
Private Manager As AnnotationManager
|
Private Manager As AnnotationManager
|
||||||
Private PDFBurner As FinalizeDocument.PDFBurner
|
Private PDFBurner As FinalizeDocument.PDFBurner
|
||||||
Private pGDPictureLicenseKey As String = "kG1Qf9PwmqgR8aDmIW2zI_ebj48RzqAJegRxcystEmkbTGQqfkNBdFOXIb6C_A00Ra8zZkrHdfjqzOPXK7kgkF2YDhvrqKfqh4WDug2vOt0qO31IommzkANSuLjZ4zmraoubyEVd25rE3veQ2h_j7tGIoH_LyIHmy24GaXsxdG0yCzIBMdiLbMMMDwcPY-809KeZ83Grv76OVhFvcbBWyYc251vou1N-kGg5_ZlHDgfWoY85gTLRxafjD3KS_i9ARW4BMiy36y8n7UP2jN8kGRnW_04ubpFtfjJqvtsrP_J9D0x7bqV8xtVtT5JI6dpKsVTiMgDCrIcoFSo5gCC1fw9oUopX4TDCkBQttO4-WHBlOeq9dG5Yb0otonVmJKaQA2tP6sMR-lZDs3ql_WI9t91yPWgpssrJUxSHDd27_LMTH_owJIqkF3NOJd9mYQuAv22oNKFYbH8e41pVKb8cT33Y9CgcQ_sy6YDA5PTuIRi67mjKge_nD9rd0IN213Ir9M_EFWqg9e4haWzIdHXQUo0md70kVhPX4UIH_BKJnxEEnFfoFRNMh77bB0N4jkcBEHPl-ghOERv8dOztf4vCnNpzzWvcLD2cqWIm6THy8XGGq9h4hp8aEreRleSMwv9QQAC7mjLwhQ1rBYkpUHlpTjhTLnMwHknl6HH0Z6zzmsgkRKVyfquv94Pd7QbQfZrRka0ss_48pf9p8hAywEn81Q=="
|
Private pGDPictureLicenseKey As String = "kG1Qf9PwmqgR8aDmIW2zI_ebj48RzqAJegRxcystEmkbTGQqfkNBdFOXIb6C_A00Ra8zZkrHdfjqzOPXK7kgkF2YDhvrqKfqh4WDug2vOt0qO31IommzkANSuLjZ4zmraoubyEVd25rE3veQ2h_j7tGIoH_LyIHmy24GaXsxdG0yCzIBMdiLbMMMDwcPY-809KeZ83Grv76OVhFvcbBWyYc251vou1N-kGg5_ZlHDgfWoY85gTLRxafjD3KS_i9ARW4BMiy36y8n7UP2jN8kGRnW_04ubpFtfjJqvtsrP_J9D0x7bqV8xtVtT5JI6dpKsVTiMgDCrIcoFSo5gCC1fw9oUopX4TDCkBQttO4-WHBlOeq9dG5Yb0otonVmJKaQA2tP6sMR-lZDs3ql_WI9t91yPWgpssrJUxSHDd27_LMTH_owJIqkF3NOJd9mYQuAv22oNKFYbH8e41pVKb8cT33Y9CgcQ_sy6YDA5PTuIRi67mjKge_nD9rd0IN213Ir9M_EFWqg9e4haWzIdHXQUo0md70kVhPX4UIH_BKJnxEEnFfoFRNMh77bB0N4jkcBEHPl-ghOERv8dOztf4vCnNpzzWvcLD2cqWIm6THy8XGGq9h4hp8aEreRleSMwv9QQAC7mjLwhQ1rBYkpUHlpTjhTLnMwHknl6HH0Z6zzmsgkRKVyfquv94Pd7QbQfZrRka0ss_48pf9p8hAywEn81Q=="
|
||||||
Private ReadOnly _ignoredLabels As New List(Of String) From {"Date", "Datum", "ZIP", "PLZ", "Place", "Ort"}
|
Private ReadOnly _ignoredLabels As New List(Of String) From {"Date", "Datum", "ZIP", "PLZ", "Place", "Ort", "Position", "Stellung"}
|
||||||
|
|
||||||
Private Sub frmFinalizePDF_Load(sender As Object, e As EventArgs) Handles MyBase.Load
|
Private Sub frmFinalizePDF_Load(sender As Object, e As EventArgs) Handles MyBase.Load
|
||||||
LogConfig = New LogConfig(LogConfig.PathType.CustomPath, Application.StartupPath)
|
LogConfig = New LogConfig(LogConfig.PathType.CustomPath, Application.StartupPath)
|
||||||
@ -48,20 +48,33 @@ Public Class frmFinalizePDF
|
|||||||
|
|
||||||
End Function
|
End Function
|
||||||
|
|
||||||
|
Private Function ReadEnvelope(ByVal pEnvID As Integer) As Byte()
|
||||||
|
Dim strSql As String = "Select [BYTE_DATA] from [TBSIG_ENVELOPE_DOCUMENT] WHERE ENVELOPE_ID = " & pEnvID
|
||||||
|
Dim obyteDB = Database.GetScalarValue(strSql)
|
||||||
|
If Not IsDBNull(obyteDB) Then
|
||||||
|
Dim fileData As Byte() = DirectCast(Database.GetScalarValue(strSql), Byte())
|
||||||
|
If fileData IsNot Nothing Then
|
||||||
|
Return fileData
|
||||||
|
End If
|
||||||
|
End If
|
||||||
|
|
||||||
|
Throw New InvalidOperationException($"Byte data is null. Envelope ID: {pEnvID}")
|
||||||
|
|
||||||
|
End Function
|
||||||
|
|
||||||
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
|
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
|
||||||
Try
|
Try
|
||||||
|
|
||||||
Dim oDocumentPath = LoadEnvelopeDocument()
|
|
||||||
Dim oFileInfo = New FileInfo(oDocumentPath)
|
|
||||||
Dim oTable = LoadAnnotationDataForEnvelope()
|
Dim oTable = LoadAnnotationDataForEnvelope()
|
||||||
Dim oJsonList = oTable.Rows.
|
Dim oJsonList = oTable.Rows.
|
||||||
Cast(Of DataRow).
|
Cast(Of DataRow).
|
||||||
Select(Function(r As DataRow) r.Item("VALUE").ToString()).
|
Select(Function(r As DataRow) r.Item("VALUE").ToString()).
|
||||||
ToList()
|
ToList()
|
||||||
|
|
||||||
Dim oBuffer As Byte() = File.ReadAllBytes(oDocumentPath)
|
Dim oBuffer As Byte() = ReadEnvelope(CInt(txtEnvelope.Text))
|
||||||
Dim oNewBuffer = PDFBurner.BurnInstantJSONAnnotationsToPDF(oBuffer, oJsonList)
|
Dim oNewBuffer = PDFBurner.BurnInstantJSONAnnotationsToPDF(oBuffer, oJsonList)
|
||||||
Dim oNewPath = Path.Combine(oFileInfo.Directory.FullName, $"{oFileInfo.Name}.burned.pdf")
|
Dim desktopPath As String = Environment.GetFolderPath(Environment.SpecialFolder.Desktop)
|
||||||
|
Dim oNewPath = Path.Combine(desktopPath, $"E{txtEnvelope.Text}R{txtReceiver.Text}.burned.pdf")
|
||||||
|
|
||||||
File.WriteAllBytes(oNewPath, oNewBuffer)
|
File.WriteAllBytes(oNewPath, oNewBuffer)
|
||||||
Catch ex As Exception
|
Catch ex As Exception
|
||||||
|
|||||||
23
EnvelopeGenerator.Web/Controllers/ConfigController.cs
Normal file
23
EnvelopeGenerator.Web/Controllers/ConfigController.cs
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
using EnvelopeGenerator.Web.Models;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.Extensions.Options;
|
||||||
|
|
||||||
|
namespace EnvelopeGenerator.Web.Controllers;
|
||||||
|
|
||||||
|
[Route("api/[controller]")]
|
||||||
|
[ApiController]
|
||||||
|
public class ConfigController : ControllerBase
|
||||||
|
{
|
||||||
|
private readonly AnnotationParams _annotParams;
|
||||||
|
|
||||||
|
public ConfigController(IOptionsMonitor<AnnotationParams> annotationParamsOptions)
|
||||||
|
{
|
||||||
|
_annotParams = annotationParamsOptions.CurrentValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpGet("Annotations")]
|
||||||
|
public IActionResult GetAnnotationParams()
|
||||||
|
{
|
||||||
|
return Ok(_annotParams.AnnotationDictionary);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,58 +1,82 @@
|
|||||||
namespace EnvelopeGenerator.Web.Models;
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
public record Annotation(
|
namespace EnvelopeGenerator.Web.Models;
|
||||||
string Id,
|
|
||||||
string? HorBoundAnnotId = null, string? VerBoundAnnotId = null)
|
public record Annotation
|
||||||
{
|
{
|
||||||
#region Layout
|
public required string Name { get; init; }
|
||||||
internal double _marginX = default;
|
|
||||||
|
|
||||||
internal double _marginY = default;
|
#region Bound Annotation
|
||||||
|
[JsonIgnore]
|
||||||
|
public string? HorBoundAnnotName { get; init; }
|
||||||
|
|
||||||
internal double _width = default;
|
[JsonIgnore]
|
||||||
|
public string? VerBoundAnnotName { get; init; }
|
||||||
internal double _height = default;
|
|
||||||
|
|
||||||
public double MarginX
|
|
||||||
{
|
|
||||||
get => _marginX;
|
|
||||||
init => _marginX = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public double MarginY
|
|
||||||
{
|
|
||||||
get => _marginY;
|
|
||||||
init => _marginY = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public double Width
|
|
||||||
{
|
|
||||||
get => _width;
|
|
||||||
init => _width = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public double Height
|
|
||||||
{
|
|
||||||
get => _height;
|
|
||||||
init => _height = value;
|
|
||||||
}
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Pos
|
#region Layout
|
||||||
public double PosX => MarginX + (HorBoundAnnot?.HorBoundary ?? 0);
|
[JsonIgnore]
|
||||||
|
public double? MarginLeft { get; set; }
|
||||||
|
|
||||||
public double PosY => MarginY + (VerBoundAnnot?.VerBoundary ?? 0);
|
[JsonIgnore]
|
||||||
|
public double MarginLeftRatio { get; init; } = 1;
|
||||||
|
|
||||||
|
[JsonIgnore]
|
||||||
|
public double? MarginTop { get; set; }
|
||||||
|
|
||||||
|
[JsonIgnore]
|
||||||
|
public double MarginTopRatio { get; init; } = 1;
|
||||||
|
|
||||||
|
public double? Width { get; set; }
|
||||||
|
|
||||||
|
[JsonIgnore]
|
||||||
|
public double WidthRatio { get; init; } = 1;
|
||||||
|
|
||||||
|
public double? Height { get; set; }
|
||||||
|
|
||||||
|
[JsonIgnore]
|
||||||
|
public double HeightRatio { get; init; } = 1;
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Position
|
||||||
|
public double Left => (MarginLeft ?? 0) + (HorBoundAnnot?.HorBoundary ?? 0);
|
||||||
|
|
||||||
|
public double Top => (MarginTop ?? 0) + (VerBoundAnnot?.VerBoundary ?? 0);
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Boundary
|
#region Boundary
|
||||||
public double HorBoundary => MarginX + Width;
|
[JsonIgnore]
|
||||||
|
public double HorBoundary => Left + (Width ?? 0);
|
||||||
|
|
||||||
public double VerBoundary => MarginY + Height;
|
[JsonIgnore]
|
||||||
|
public double VerBoundary => Top + (Height ?? 0);
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region BoundAnnot
|
#region BoundAnnot
|
||||||
public Annot? HorBoundAnnot { get; set; }
|
[JsonIgnore]
|
||||||
|
public Annotation? HorBoundAnnot { get; set; }
|
||||||
|
|
||||||
public Annot? VerBoundAnnot { get; set; }
|
[JsonIgnore]
|
||||||
|
public Annotation? VerBoundAnnot { get; set; }
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
[JsonIgnore]
|
||||||
|
internal Annotation Default
|
||||||
|
{
|
||||||
|
set
|
||||||
|
{
|
||||||
|
// To set null value, annotation must have null (0) value but null must has non-null value
|
||||||
|
if (MarginLeft == null && value.MarginLeft != null)
|
||||||
|
MarginLeft = value.MarginLeft * MarginLeftRatio;
|
||||||
|
|
||||||
|
if (MarginTop == null && value.MarginTop != null)
|
||||||
|
MarginTop = value.MarginTop * MarginTopRatio;
|
||||||
|
|
||||||
|
if (Width == null && value.Width != null)
|
||||||
|
Width = value.Width * WidthRatio;
|
||||||
|
|
||||||
|
if (Height == null && value.Height != null)
|
||||||
|
Height = value.Height * HeightRatio;
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
57
EnvelopeGenerator.Web/Models/AnnotationParams.cs
Normal file
57
EnvelopeGenerator.Web/Models/AnnotationParams.cs
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace EnvelopeGenerator.Web.Models;
|
||||||
|
|
||||||
|
public class AnnotationParams
|
||||||
|
{
|
||||||
|
[JsonIgnore]
|
||||||
|
public Annotation? DefaultAnnotation { get; init; }
|
||||||
|
|
||||||
|
private readonly IEnumerable<Annotation> _annots = new List<Annotation>();
|
||||||
|
|
||||||
|
public Annotation this[string name] => _annots.First(a => a.Name == name);
|
||||||
|
|
||||||
|
public bool TryGet(string name, out Annotation annotation)
|
||||||
|
{
|
||||||
|
#pragma warning disable CS8601 // Possible null reference assignment.
|
||||||
|
annotation = _annots.FirstOrDefault(a => a.Name == name);
|
||||||
|
#pragma warning restore CS8601 // Possible null reference assignment.
|
||||||
|
return annotation is not null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public required IEnumerable<Annotation> Annotations
|
||||||
|
{
|
||||||
|
get => _annots;
|
||||||
|
init
|
||||||
|
{
|
||||||
|
_annots = value;
|
||||||
|
|
||||||
|
if (DefaultAnnotation is not null)
|
||||||
|
foreach (var annot in _annots)
|
||||||
|
annot.Default = DefaultAnnotation;
|
||||||
|
|
||||||
|
foreach (var annot in _annots)
|
||||||
|
{
|
||||||
|
#region set bound annotations
|
||||||
|
// horizontal
|
||||||
|
if (annot.HorBoundAnnotName is string horBoundAnnotName)
|
||||||
|
if (TryGet(horBoundAnnotName, out var horBoundAnnot))
|
||||||
|
annot.HorBoundAnnot = horBoundAnnot;
|
||||||
|
else
|
||||||
|
throw new InvalidOperationException($"{horBoundAnnotName} added as bound anotation. However, it is not defined.");
|
||||||
|
|
||||||
|
// vertical
|
||||||
|
if (annot.VerBoundAnnotName is string verBoundAnnotName)
|
||||||
|
if (TryGet(verBoundAnnotName, out var verBoundAnnot))
|
||||||
|
annot.VerBoundAnnot = verBoundAnnot;
|
||||||
|
else
|
||||||
|
throw new InvalidOperationException($"{verBoundAnnotName} added as bound anotation. However, it is not defined.");
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
|
||||||
|
AnnotationDictionary = _annots.ToDictionary(a => a.Name.ToLower(), a => a);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Dictionary<string, Annotation> AnnotationDictionary { get; private init; } = new();
|
||||||
|
}
|
||||||
@ -163,6 +163,8 @@ try
|
|||||||
|
|
||||||
builder.ConfigureBySection<CustomImages>();
|
builder.ConfigureBySection<CustomImages>();
|
||||||
|
|
||||||
|
builder.ConfigureBySection<AnnotationParams>();
|
||||||
|
|
||||||
var app = builder.Build();
|
var app = builder.Build();
|
||||||
|
|
||||||
// Configure the HTTP request pipeline.
|
// Configure the HTTP request pipeline.
|
||||||
|
|||||||
@ -149,5 +149,60 @@
|
|||||||
"EnvelopeReceiverReadOnly": [ "TBSIG_ENVELOPE_RECEIVER_READ_ONLY_UPD" ],
|
"EnvelopeReceiverReadOnly": [ "TBSIG_ENVELOPE_RECEIVER_READ_ONLY_UPD" ],
|
||||||
"Receiver": []
|
"Receiver": []
|
||||||
},
|
},
|
||||||
"MainPageTitle": null
|
"MainPageTitle": null,
|
||||||
|
"AnnotationParams": {
|
||||||
|
"DefaultAnnotation": {
|
||||||
|
"Width": 1,
|
||||||
|
"Height": 0.5,
|
||||||
|
"MarginTop": 1
|
||||||
|
},
|
||||||
|
"Annotations": [
|
||||||
|
{
|
||||||
|
"Name": "Signature",
|
||||||
|
"MarginTop": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Name": "PositionLabel",
|
||||||
|
"VerBoundAnnotName": "Signature",
|
||||||
|
"WidthRatio": 1.2,
|
||||||
|
"HeightRatio": 0.5,
|
||||||
|
"MarginTopRatio": 0.22
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Name": "Position",
|
||||||
|
"VerBoundAnnotName": "PositionLabel",
|
||||||
|
"WidthRatio": 1.2,
|
||||||
|
"HeightRatio": 0.5,
|
||||||
|
"MarginTopRatio": -0.05
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Name": "CityLabel",
|
||||||
|
"VerBoundAnnotName": "Position",
|
||||||
|
"WidthRatio": 1.2,
|
||||||
|
"HeightRatio": 0.5,
|
||||||
|
"MarginTopRatio": 0.05
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Name": "City",
|
||||||
|
"VerBoundAnnotName": "CityLabel",
|
||||||
|
"WidthRatio": 1.2,
|
||||||
|
"HeightRatio": 0.5,
|
||||||
|
"MarginTopRatio": -0.05
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Name": "DateLabel",
|
||||||
|
"VerBoundAnnotName": "City",
|
||||||
|
"WidthRatio": 1.55,
|
||||||
|
"HeightRatio": 0.5,
|
||||||
|
"MarginTopRatio": 0.05
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Name": "Date",
|
||||||
|
"VerBoundAnnotName": "DateLabel",
|
||||||
|
"WidthRatio": 1.55,
|
||||||
|
"HeightRatio": 0.5,
|
||||||
|
"MarginTopRatio": -0.1
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,47 +1,20 @@
|
|||||||
class Annotation {
|
|
||||||
static async createAnnotations(document, instance) {
|
async function createAnnotations(document, instance) {
|
||||||
const signatures = []
|
const signatures = [];
|
||||||
|
|
||||||
for (var element of document.elements) {
|
for(var element of document.elements) {
|
||||||
const [annotation, formField, annotation_date, formFieldDate, annotation_city, formFieldCity, annotation_date_label, formFieldDateLabel, annotation_city_label, formFieldCityLabel] = await Annotation.createSignature(element)
|
const annotParams = await getAnnotationParams(element.left, element.top);
|
||||||
signatures.push(annotation)
|
|
||||||
signatures.push(formField)
|
|
||||||
signatures.push(annotation_date)
|
|
||||||
signatures.push(formFieldDate)
|
|
||||||
signatures.push(annotation_city)
|
|
||||||
signatures.push(formFieldCity)
|
|
||||||
|
|
||||||
signatures.push(annotation_date_label)
|
|
||||||
signatures.push(formFieldDateLabel)
|
|
||||||
|
|
||||||
signatures.push(annotation_city_label)
|
|
||||||
signatures.push(formFieldCityLabel)
|
|
||||||
}
|
|
||||||
|
|
||||||
await instance.create(signatures)
|
|
||||||
}
|
|
||||||
|
|
||||||
static async createSignature(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
|
const page = element.page - 1
|
||||||
|
|
||||||
//signatures
|
//signatures
|
||||||
|
const id = PSPDFKit.generateInstantId()
|
||||||
const annotation = new PSPDFKit.Annotations.WidgetAnnotation({
|
const annotation = new PSPDFKit.Annotations.WidgetAnnotation({
|
||||||
id: id,
|
id: id,
|
||||||
pageIndex: page,
|
pageIndex: page,
|
||||||
formFieldName: id,
|
formFieldName: id,
|
||||||
backgroundColor: PSPDFKit.Color.YELLOW,
|
backgroundColor: PSPDFKit.Color.YELLOW,
|
||||||
blendMode: 'multiply',
|
blendMode: 'multiply',
|
||||||
boundingBox: new PSPDFKit.Geometry.Rect({
|
boundingBox: new PSPDFKit.Geometry.Rect(annotParams.signature),
|
||||||
width,
|
|
||||||
height,
|
|
||||||
top,
|
|
||||||
left,
|
|
||||||
}),
|
|
||||||
})
|
})
|
||||||
|
|
||||||
const formField = new PSPDFKit.FormFields.SignatureFormField({
|
const formField = new PSPDFKit.FormFields.SignatureFormField({
|
||||||
@ -49,10 +22,44 @@
|
|||||||
annotationIds: PSPDFKit.Immutable.List([annotation.id]),
|
annotationIds: PSPDFKit.Immutable.List([annotation.id]),
|
||||||
})
|
})
|
||||||
|
|
||||||
/**
|
//position
|
||||||
* Date, post code and place text form part
|
const id_position = PSPDFKit.generateInstantId()
|
||||||
*/
|
const annotation_position = new PSPDFKit.Annotations.WidgetAnnotation({
|
||||||
const date_place_top_shift = 9.5;
|
id: id_position,
|
||||||
|
pageIndex: page,
|
||||||
|
formFieldName: id_position,
|
||||||
|
backgroundColor: PSPDFKit.Color.DarkBlue,
|
||||||
|
blendMode: 'multiply',
|
||||||
|
boundingBox: new PSPDFKit.Geometry.Rect(annotParams.position),
|
||||||
|
fontSize: 8
|
||||||
|
})
|
||||||
|
|
||||||
|
const formFieldPosition = new PSPDFKit.FormFields.TextFormField({
|
||||||
|
name: id_position,
|
||||||
|
annotationIds: PSPDFKit.Immutable.List([annotation_position.id]),
|
||||||
|
value: "",
|
||||||
|
readOnly: false
|
||||||
|
})
|
||||||
|
|
||||||
|
//city
|
||||||
|
const id_city = PSPDFKit.generateInstantId()
|
||||||
|
const annotation_city = new PSPDFKit.Annotations.WidgetAnnotation({
|
||||||
|
id: id_city,
|
||||||
|
pageIndex: page,
|
||||||
|
formFieldName: id_city,
|
||||||
|
backgroundColor: PSPDFKit.Color.DarkBlue,
|
||||||
|
blendMode: 'multiply',
|
||||||
|
boundingBox: new PSPDFKit.Geometry.Rect(annotParams.city),
|
||||||
|
fontSize: 8
|
||||||
|
})
|
||||||
|
|
||||||
|
const formFieldCity = new PSPDFKit.FormFields.TextFormField({
|
||||||
|
name: id_city,
|
||||||
|
annotationIds: PSPDFKit.Immutable.List([annotation_city.id]),
|
||||||
|
value: "",
|
||||||
|
readOnly: false
|
||||||
|
})
|
||||||
|
|
||||||
//date
|
//date
|
||||||
const id_date = PSPDFKit.generateInstantId()
|
const id_date = PSPDFKit.generateInstantId()
|
||||||
const annotation_date = new PSPDFKit.Annotations.WidgetAnnotation({
|
const annotation_date = new PSPDFKit.Annotations.WidgetAnnotation({
|
||||||
@ -61,12 +68,7 @@
|
|||||||
formFieldName: id_date,
|
formFieldName: id_date,
|
||||||
backgroundColor: PSPDFKit.Color.DarkBlue,
|
backgroundColor: PSPDFKit.Color.DarkBlue,
|
||||||
blendMode: 'multiply',
|
blendMode: 'multiply',
|
||||||
boundingBox: new PSPDFKit.Geometry.Rect({
|
boundingBox: new PSPDFKit.Geometry.Rect(annotParams.date),
|
||||||
width: width * 1.55,
|
|
||||||
height: height / 2,
|
|
||||||
top: top + height + 25 + date_place_top_shift + (height),
|
|
||||||
left: left
|
|
||||||
}),
|
|
||||||
fontSize: 8,
|
fontSize: 8,
|
||||||
backgroundColor: PSPDFKit.Color.TRANSPARENT,
|
backgroundColor: PSPDFKit.Color.TRANSPARENT,
|
||||||
fontColor: PSPDFKit.Color.Black,
|
fontColor: PSPDFKit.Color.Black,
|
||||||
@ -81,30 +83,6 @@
|
|||||||
readOnly: true
|
readOnly: true
|
||||||
})
|
})
|
||||||
|
|
||||||
//city
|
|
||||||
const id_city = PSPDFKit.generateInstantId()
|
|
||||||
const annotation_city = new PSPDFKit.Annotations.WidgetAnnotation({
|
|
||||||
id: id_city,
|
|
||||||
pageIndex: page,
|
|
||||||
formFieldName: id_city,
|
|
||||||
backgroundColor: PSPDFKit.Color.DarkBlue,
|
|
||||||
blendMode: 'multiply',
|
|
||||||
boundingBox: new PSPDFKit.Geometry.Rect({
|
|
||||||
width: width * 1.2,
|
|
||||||
height: height / 2,
|
|
||||||
top: top + height + 23 + date_place_top_shift + 2,
|
|
||||||
left: left,
|
|
||||||
}),
|
|
||||||
fontSize: 8
|
|
||||||
})
|
|
||||||
|
|
||||||
const formFieldCity = new PSPDFKit.FormFields.TextFormField({
|
|
||||||
name: id_city,
|
|
||||||
annotationIds: PSPDFKit.Immutable.List([annotation_city.id]),
|
|
||||||
value: "",
|
|
||||||
readOnly: false
|
|
||||||
})
|
|
||||||
|
|
||||||
this.markFieldAsRequired(formFieldCity);
|
this.markFieldAsRequired(formFieldCity);
|
||||||
|
|
||||||
this.markFieldAsCity(formFieldCity);
|
this.markFieldAsCity(formFieldCity);
|
||||||
@ -112,7 +90,6 @@
|
|||||||
/**
|
/**
|
||||||
* Date, post code and place label part
|
* Date, post code and place label part
|
||||||
*/
|
*/
|
||||||
const label_top_shift = -15
|
|
||||||
|
|
||||||
//date label
|
//date label
|
||||||
const id_date_label = PSPDFKit.generateInstantId()
|
const id_date_label = PSPDFKit.generateInstantId()
|
||||||
@ -121,12 +98,7 @@
|
|||||||
pageIndex: page,
|
pageIndex: page,
|
||||||
formFieldName: id_date_label,
|
formFieldName: id_date_label,
|
||||||
blendMode: 'multiply',
|
blendMode: 'multiply',
|
||||||
boundingBox: new PSPDFKit.Geometry.Rect({
|
boundingBox: new PSPDFKit.Geometry.Rect(annotParams.datelabel),
|
||||||
width: width * 0.75,
|
|
||||||
height: height / 2,
|
|
||||||
top: top + height + 23 + label_top_shift + date_place_top_shift + (height) + 4,
|
|
||||||
left: left
|
|
||||||
}),
|
|
||||||
fontSize: 8,
|
fontSize: 8,
|
||||||
backgroundColor: PSPDFKit.Color.TRANSPARENT,
|
backgroundColor: PSPDFKit.Color.TRANSPARENT,
|
||||||
fontColor: PSPDFKit.Color.Black,
|
fontColor: PSPDFKit.Color.Black,
|
||||||
@ -148,12 +120,7 @@
|
|||||||
pageIndex: page,
|
pageIndex: page,
|
||||||
formFieldName: id_city_label,
|
formFieldName: id_city_label,
|
||||||
blendMode: 'multiply',
|
blendMode: 'multiply',
|
||||||
boundingBox: new PSPDFKit.Geometry.Rect({
|
boundingBox: new PSPDFKit.Geometry.Rect(annotParams.citylabel),
|
||||||
width: width * 1.2,
|
|
||||||
height: height / 2,
|
|
||||||
top: top + height + 25 + label_top_shift + date_place_top_shift,
|
|
||||||
left: left
|
|
||||||
}),
|
|
||||||
fontSize: 8,
|
fontSize: 8,
|
||||||
backgroundColor: PSPDFKit.Color.TRANSPARENT,
|
backgroundColor: PSPDFKit.Color.TRANSPARENT,
|
||||||
fontColor: PSPDFKit.Color.Black,
|
fontColor: PSPDFKit.Color.Black,
|
||||||
@ -167,167 +134,169 @@
|
|||||||
readOnly: true
|
readOnly: true
|
||||||
})
|
})
|
||||||
|
|
||||||
return [annotation, formField, annotation_date, formFieldDate, annotation_city, formFieldCity, annotation_date_label, formFieldDateLabel, annotation_city_label, formFieldCityLabel]
|
//position label
|
||||||
}
|
const id_position_label = PSPDFKit.generateInstantId()
|
||||||
|
const annotation_position_label = new PSPDFKit.Annotations.WidgetAnnotation({
|
||||||
static createTextBox(element) {
|
id: id_position_label,
|
||||||
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,
|
pageIndex: page,
|
||||||
formFieldName: id,
|
formFieldName: id_position_label,
|
||||||
backgroundColor: PSPDFKit.Color.YELLOW,
|
|
||||||
blendMode: 'multiply',
|
blendMode: 'multiply',
|
||||||
boundingBox: new PSPDFKit.Geometry.Rect({
|
boundingBox: new PSPDFKit.Geometry.Rect(annotParams.positionlabel),
|
||||||
width,
|
fontSize: 8,
|
||||||
height,
|
backgroundColor: PSPDFKit.Color.TRANSPARENT,
|
||||||
top,
|
fontColor: PSPDFKit.Color.Black,
|
||||||
left,
|
isBold: true,
|
||||||
}),
|
|
||||||
})
|
})
|
||||||
|
|
||||||
const formField = new PSPDFKit.FormFields.SignatureFormField({
|
const formFieldPositionLabel = new PSPDFKit.FormFields.TextFormField({
|
||||||
name: id,
|
name: id_position_label,
|
||||||
annotationIds: PSPDFKit.Immutable.List([annotation.id]),
|
annotationIds: PSPDFKit.Immutable.List([annotation_position_label.id]),
|
||||||
|
value: "Position",
|
||||||
|
readOnly: true
|
||||||
})
|
})
|
||||||
|
|
||||||
return [annotation, formField]
|
signatures.push(annotation)
|
||||||
|
signatures.push(formField)
|
||||||
|
signatures.push(annotation_date)
|
||||||
|
signatures.push(formFieldDate)
|
||||||
|
signatures.push(annotation_city)
|
||||||
|
signatures.push(formFieldCity)
|
||||||
|
signatures.push(annotation_position)
|
||||||
|
signatures.push(formFieldPosition)
|
||||||
|
|
||||||
|
signatures.push(annotation_date_label)
|
||||||
|
signatures.push(formFieldDateLabel)
|
||||||
|
|
||||||
|
signatures.push(annotation_city_label)
|
||||||
|
signatures.push(formFieldCityLabel)
|
||||||
|
|
||||||
|
signatures.push(annotation_position_label)
|
||||||
|
signatures.push(formFieldPositionLabel)
|
||||||
}
|
}
|
||||||
|
|
||||||
static async getAnnotations(instance) {
|
await instance.create(signatures);
|
||||||
const array = await Promise.all(
|
}
|
||||||
Array.from({ length: instance.totalPageCount }).map((_, pageIndex) =>
|
|
||||||
instance.getAnnotations(pageIndex)
|
async function 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), [])
|
)
|
||||||
)
|
|
||||||
}
|
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
|
async function deleteAnnotations(instance) {
|
||||||
return await instance.delete(pageAnnotations)
|
const allAnnotations = await getAnnotations(instance)
|
||||||
}
|
const pageAnnotations = allAnnotations.filter(isSignature)
|
||||||
|
//deleting all Annotations
|
||||||
static async validateAnnotations(instance) {
|
return await instance.delete(pageAnnotations)
|
||||||
const allAnnotations = await Annotation.getAnnotations(instance)
|
}
|
||||||
const pageAnnotations = allAnnotations
|
|
||||||
.map((annotation) => {
|
async function validateAnnotations(instance) {
|
||||||
return annotation
|
const allAnnotations = await getAnnotations(instance)
|
||||||
})
|
const pageAnnotations = allAnnotations
|
||||||
|
.map((annotation) => {
|
||||||
return true
|
return annotation
|
||||||
}
|
})
|
||||||
|
|
||||||
static isSignature(annotation) {
|
return true
|
||||||
return !!annotation.isSignature || annotation.description == 'FRAME'
|
}
|
||||||
}
|
|
||||||
|
function isSignature(annotation) {
|
||||||
static createImageAnnotation(boundingBox, pageIndex, imageAttachmentId) {
|
return !!annotation.isSignature || annotation.description == 'FRAME'
|
||||||
const frameAnnotation = new PSPDFKit.Annotations.ImageAnnotation({
|
}
|
||||||
pageIndex: pageIndex,
|
|
||||||
isSignature: false,
|
function createImageAnnotation(boundingBox, pageIndex, imageAttachmentId) {
|
||||||
readOnly: true,
|
const frameAnnotation = new PSPDFKit.Annotations.ImageAnnotation({
|
||||||
locked: true,
|
pageIndex: pageIndex,
|
||||||
lockedContents: true,
|
isSignature: false,
|
||||||
contentType: 'image/png',
|
readOnly: true,
|
||||||
imageAttachmentId,
|
locked: true,
|
||||||
description: 'FRAME',
|
lockedContents: true,
|
||||||
boundingBox: boundingBox,
|
contentType: 'image/png',
|
||||||
})
|
imageAttachmentId,
|
||||||
return frameAnnotation
|
description: 'FRAME',
|
||||||
}
|
boundingBox: boundingBox,
|
||||||
|
})
|
||||||
static async createAnnotationFrameBlob(receiverName, receiverSignature, timestamp, width, height) {
|
return frameAnnotation
|
||||||
Comp.SignatureProgress.SignedCount += 1;
|
}
|
||||||
const canvas = document.createElement('canvas')
|
|
||||||
const scale = 4
|
async function createAnnotationFrameBlob(receiverName, receiverSignature, timestamp, width, height) {
|
||||||
const fontSize = 10
|
Comp.SignatureProgress.SignedCount += 1;
|
||||||
|
const canvas = document.createElement('canvas')
|
||||||
canvas.width = width * scale
|
const scale = 4
|
||||||
canvas.height = height * scale
|
const fontSize = 10
|
||||||
|
|
||||||
const ctx = canvas.getContext('2d')
|
canvas.width = width * scale
|
||||||
// This supposedly makes the lines and text less blurry
|
canvas.height = height * scale
|
||||||
// See: https://stackoverflow.com/questions/8696631/canvas-drawings-like-lines-are-blurry
|
|
||||||
ctx.translate(0.5, 0.5)
|
const ctx = canvas.getContext('2d')
|
||||||
|
// This supposedly makes the lines and text less blurry
|
||||||
// This also should make the lines and text less blurry
|
// See: https://stackoverflow.com/questions/8696631/canvas-drawings-like-lines-are-blurry
|
||||||
ctx.textRendering = "geometricPrecision"
|
ctx.translate(0.5, 0.5)
|
||||||
|
|
||||||
const date = timestamp
|
// This also should make the lines and text less blurry
|
||||||
const dateString = date.toLocaleString('de-DE')
|
ctx.textRendering = "geometricPrecision"
|
||||||
|
|
||||||
const signatureLength = 100 * scale
|
const date = timestamp
|
||||||
const signatureString = receiverSignature.substring(0, 15) + "…"
|
const dateString = date.toLocaleString('de-DE')
|
||||||
|
|
||||||
ctx.beginPath()
|
const signatureLength = 100 * scale
|
||||||
|
const signatureString = receiverSignature.substring(0, 15) + "…"
|
||||||
ctx.moveTo(30 * scale, 10 * scale)
|
|
||||||
ctx.lineTo(signatureLength, 10 * scale)
|
ctx.beginPath()
|
||||||
|
|
||||||
ctx.moveTo(30 * scale, 10 * scale)
|
ctx.moveTo(30 * scale, 10 * scale)
|
||||||
ctx.arcTo(10 * scale, 10 * scale, 10 * scale, 30 * scale, 20 * scale)
|
ctx.lineTo(signatureLength, 10 * scale)
|
||||||
|
|
||||||
ctx.moveTo(10 * scale, 30 * scale)
|
ctx.moveTo(30 * scale, 10 * scale)
|
||||||
ctx.arcTo(10 * scale, 50 * scale, 30 * scale, 50 * scale, 20 * scale)
|
ctx.arcTo(10 * scale, 10 * scale, 10 * scale, 30 * scale, 20 * scale)
|
||||||
|
|
||||||
ctx.moveTo(30 * scale, 50 * scale)
|
ctx.moveTo(10 * scale, 30 * scale)
|
||||||
ctx.lineTo(signatureLength, 50 * scale)
|
ctx.arcTo(10 * scale, 50 * scale, 30 * scale, 50 * scale, 20 * scale)
|
||||||
|
|
||||||
ctx.strokeStyle = 'darkblue'
|
ctx.moveTo(30 * scale, 50 * scale)
|
||||||
ctx.stroke()
|
ctx.lineTo(signatureLength, 50 * scale)
|
||||||
|
|
||||||
ctx.fillStyle = 'black'
|
ctx.strokeStyle = 'darkblue'
|
||||||
ctx.font = `${fontSize * scale}px sans-serif`
|
ctx.stroke()
|
||||||
ctx.fillText('Signed by', 15 * scale, 10 * scale)
|
|
||||||
ctx.fillText(receiverName, 15 * scale, 60 * scale)
|
ctx.fillStyle = 'black'
|
||||||
ctx.fillText(signatureString, 15 * scale, 70 * scale)
|
ctx.font = `${fontSize * scale}px sans-serif`
|
||||||
|
ctx.fillText('Signed by', 15 * scale, 10 * scale)
|
||||||
return new Promise((resolve) => {
|
ctx.fillText(receiverName, 15 * scale, 60 * scale)
|
||||||
canvas.toBlob((blob) => {
|
ctx.fillText(signatureString, 15 * scale, 70 * scale)
|
||||||
const url = URL.createObjectURL(blob)
|
|
||||||
resolve(url)
|
return new Promise((resolve) => {
|
||||||
})
|
canvas.toBlob((blob) => {
|
||||||
})
|
const url = URL.createObjectURL(blob)
|
||||||
}
|
resolve(url)
|
||||||
|
})
|
||||||
static inchToPoint(inch) {
|
})
|
||||||
return inch * 72
|
}
|
||||||
}
|
|
||||||
|
//required
|
||||||
//required
|
requiredFieldNames = new Array()
|
||||||
static #requiredFieldNames = new Array()
|
|
||||||
|
function markFieldAsRequired(formField) {
|
||||||
static markFieldAsRequired(formField) {
|
requiredFieldNames.push(formField.name)
|
||||||
this.#requiredFieldNames.push(formField.name)
|
}
|
||||||
}
|
|
||||||
|
function isFieldRequired(formField) {
|
||||||
static isFieldRequired(formField) {
|
return requiredFieldNames.includes(formField.name)
|
||||||
return this.#requiredFieldNames.includes(formField.name)
|
}
|
||||||
}
|
|
||||||
|
//city
|
||||||
//city
|
cityFieldNames = new Array()
|
||||||
static #cityFieldNames = new Array()
|
|
||||||
|
function markFieldAsCity(formField) {
|
||||||
static markFieldAsCity(formField) {
|
cityFieldNames.push(formField.name)
|
||||||
this.#cityFieldNames.push(formField.name)
|
}
|
||||||
}
|
|
||||||
|
function isCityField(formField) {
|
||||||
static isCityField(formField) {
|
return cityFieldNames.includes(formField.name)
|
||||||
return this.#cityFieldNames.includes(formField.name)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@ -70,7 +70,7 @@ class App {
|
|||||||
// Load annotations into PSPDFKit
|
// Load annotations into PSPDFKit
|
||||||
try {
|
try {
|
||||||
this.signatureCount = this.currentDocument.elements.length
|
this.signatureCount = this.currentDocument.elements.length
|
||||||
await Annotation.createAnnotations(this.currentDocument, this.Instance)
|
await createAnnotations(this.currentDocument, this.Instance)
|
||||||
|
|
||||||
const openResponse = await this.Network.openDocument(this.envelopeKey)
|
const openResponse = await this.Network.openDocument(this.envelopeKey)
|
||||||
|
|
||||||
@ -109,7 +109,7 @@ class App {
|
|||||||
const height = 75
|
const height = 75
|
||||||
const timestamp = new Date()
|
const timestamp = new Date()
|
||||||
|
|
||||||
const imageUrl = await Annotation.createAnnotationFrameBlob(
|
const imageUrl = await createAnnotationFrameBlob(
|
||||||
this.envelopeReceiver.name,
|
this.envelopeReceiver.name,
|
||||||
this.currentReceiver.signature,
|
this.currentReceiver.signature,
|
||||||
timestamp,
|
timestamp,
|
||||||
@ -121,7 +121,7 @@ class App {
|
|||||||
const blob = await request.blob()
|
const blob = await request.blob()
|
||||||
const imageAttachmentId = await this.Instance.createAttachment(blob)
|
const imageAttachmentId = await this.Instance.createAttachment(blob)
|
||||||
|
|
||||||
const frameAnnotation = Annotation.createImageAnnotation(
|
const frameAnnotation = createImageAnnotation(
|
||||||
new PSPDFKit.Geometry.Rect({
|
new PSPDFKit.Geometry.Rect({
|
||||||
left: left,
|
left: left,
|
||||||
top: top,
|
top: top,
|
||||||
@ -222,7 +222,7 @@ class App {
|
|||||||
const iFormFieldValues = await iJSON.formFieldValues;
|
const iFormFieldValues = await iJSON.formFieldValues;
|
||||||
|
|
||||||
//check required
|
//check required
|
||||||
const iReqFields = iFormFieldValues.filter(f => Annotation.isFieldRequired(f))
|
const iReqFields = iFormFieldValues.filter(f => isFieldRequired(f))
|
||||||
const hasEmptyReq = iReqFields.some(f => (f.value === undefined || f.value === null || f.value === ""))
|
const hasEmptyReq = iReqFields.some(f => (f.value === undefined || f.value === null || f.value === ""))
|
||||||
|
|
||||||
if (hasEmptyReq) {
|
if (hasEmptyReq) {
|
||||||
@ -236,7 +236,7 @@ class App {
|
|||||||
|
|
||||||
//check city
|
//check city
|
||||||
const city_regex = new RegExp("^[a-zA-Z\\u0080-\\u024F]+(?:([\\ \\-\\']|(\\.\\ ))[a-zA-Z\\u0080-\\u024F]+)*$")
|
const city_regex = new RegExp("^[a-zA-Z\\u0080-\\u024F]+(?:([\\ \\-\\']|(\\.\\ ))[a-zA-Z\\u0080-\\u024F]+)*$")
|
||||||
const iCityFields = iFormFieldValues.filter(f => Annotation.isCityField(f))
|
const iCityFields = iFormFieldValues.filter(f => isCityField(f))
|
||||||
for (var f of iCityFields)
|
for (var f of iCityFields)
|
||||||
if (!IS_MOBILE_DEVICE && !city_regex.test(f.value)) {
|
if (!IS_MOBILE_DEVICE && !city_regex.test(f.value)) {
|
||||||
Swal.fire({
|
Swal.fire({
|
||||||
@ -322,7 +322,7 @@ class App {
|
|||||||
|
|
||||||
|
|
||||||
async validateAnnotations(totalSignatures) {
|
async validateAnnotations(totalSignatures) {
|
||||||
const annotations = await Annotation.getAnnotations(this.Instance)
|
const annotations = await getAnnotations(this.Instance)
|
||||||
const filtered = annotations
|
const filtered = annotations
|
||||||
.map(a => a.toJS())
|
.map(a => a.toJS())
|
||||||
.filter(a => a.isSignature)
|
.filter(a => a.isSignature)
|
||||||
@ -343,7 +343,7 @@ class App {
|
|||||||
})
|
})
|
||||||
|
|
||||||
if (result.isConfirmed) {
|
if (result.isConfirmed) {
|
||||||
const result = await Annotation.deleteAnnotations(this.Instance)
|
const result = await deleteAnnotations(this.Instance)
|
||||||
}
|
}
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
|||||||
4
EnvelopeGenerator.Web/wwwroot/js/app.min.js
vendored
4
EnvelopeGenerator.Web/wwwroot/js/app.min.js
vendored
@ -1,3 +1,3 @@
|
|||||||
const ActionType={Created:0,Saved:1,Sent:2,EmailSent:3,Delivered:4,Seen:5,Signed:6,Rejected:7};class App{constructor(n,t,i,r,u,f){this.container=f??`#${this.constructor.name.toLowerCase()}`;this.envelopeKey=n;this.Network=new Network;this.Instance=null;this.currentDocument=null;this.currentReceiver=null;this.signatureCount=0;this.envelopeReceiver=t;this.documentBytes=i;this.licenseKey=r;this.locale=u}async init(){this.currentDocument=this.envelopeReceiver.envelope.documents[0];this.currentReceiver=this.envelopeReceiver.receiver;const n=this.documentBytes;if(n.fatal||n.error)return Swal.fire({title:"Fehler",text:"Dokument konnte nicht geladen werden!",icon:"error"});const t=this.documentBytes;this.Instance=await UI.loadPSPDFKit(t,this.container,this.licenseKey,this.locale);UI.addToolbarItems(this.Instance,this.handleClick.bind(this));this.Instance.addEventListener("annotations.load",this.handleAnnotationsLoad.bind(this));this.Instance.addEventListener("annotations.change",this.handleAnnotationsChange.bind(this));this.Instance.addEventListener("annotations.create",this.handleAnnotationsCreate.bind(this));this.Instance.addEventListener("annotations.willChange",()=>{Comp.ActPanel.Toggle()});try{this.signatureCount=this.currentDocument.elements.length;await Annotation.createAnnotations(this.currentDocument,this.Instance);const n=await this.Network.openDocument(this.envelopeKey);if(n.fatal||n.error)return Swal.fire({title:"Fehler",text:"Umschlag konnte nicht geöffnet werden!",icon:"error"})}catch(i){}[...document.getElementsByClassName("btn_refresh")].forEach(n=>n.addEventListener("click",()=>this.handleClick("RESET")));[...document.getElementsByClassName("btn_complete")].forEach(n=>n.addEventListener("click",()=>this.handleClick("FINISH")));[...document.getElementsByClassName("btn_reject")].forEach(n=>n.addEventListener("click",()=>this.handleClick("REJECT")))}handleAnnotationsLoad(n){n.toJS()}handleAnnotationsChange(){}async handleAnnotationsCreate(n){const t=n.toJS()[0],i=!!t.formFieldName,r=!!t.isSignature;if(i===!1&&r===!0){const r=t.boundingBox.left-20,u=t.boundingBox.top-20,n=150,i=75,f=new Date,e=await Annotation.createAnnotationFrameBlob(this.envelopeReceiver.name,this.currentReceiver.signature,f,n,i),o=await fetch(e),s=await o.blob(),h=await this.Instance.createAttachment(s),c=Annotation.createImageAnnotation(new PSPDFKit.Geometry.Rect({left:r,top:u,width:n,height:i}),t.pageIndex,h);this.Instance.create(c)}}async handleClick(n){let t=!1;switch(n){case"RESET":t=await this.handleReset(null);Comp.SignatureProgress.SignedCount=0;t.isConfirmed&&Swal.fire({title:"Erfolg",text:"Dokument wurde zurückgesetzt",icon:"info"});break;case"FINISH":t=await this.handleFinish(null);t==!0&&(window.location.href=`/EnvelopeKey/${this.envelopeKey}/Success`);break;case"REJECT":Swal.fire({title:localized.rejection,html:`<div class="text-start fs-6 p-0 m-0">${localized.rejectionReasonQ}</div>`,icon:"question",input:"text",inputAttributes:{autocapitalize:"off"},showCancelButton:!0,confirmButtonColor:"#3085d6",cancelButtonColor:"#d33",confirmButtonText:localized.complete,cancelButtonText:localized.back,showLoaderOnConfirm:!0,preConfirm:async n=>{try{return await rejectEnvelope(n)}catch(t){Swal.showValidationMessage(`
|
const ActionType={Created:0,Saved:1,Sent:2,EmailSent:3,Delivered:4,Seen:5,Signed:6,Rejected:7};class App{constructor(n,t,i,r,u,f){this.container=f??`#${this.constructor.name.toLowerCase()}`;this.envelopeKey=n;this.Network=new Network;this.Instance=null;this.currentDocument=null;this.currentReceiver=null;this.signatureCount=0;this.envelopeReceiver=t;this.documentBytes=i;this.licenseKey=r;this.locale=u}async init(){this.currentDocument=this.envelopeReceiver.envelope.documents[0];this.currentReceiver=this.envelopeReceiver.receiver;const n=this.documentBytes;if(n.fatal||n.error)return Swal.fire({title:"Fehler",text:"Dokument konnte nicht geladen werden!",icon:"error"});const t=this.documentBytes;this.Instance=await UI.loadPSPDFKit(t,this.container,this.licenseKey,this.locale);UI.addToolbarItems(this.Instance,this.handleClick.bind(this));this.Instance.addEventListener("annotations.load",this.handleAnnotationsLoad.bind(this));this.Instance.addEventListener("annotations.change",this.handleAnnotationsChange.bind(this));this.Instance.addEventListener("annotations.create",this.handleAnnotationsCreate.bind(this));this.Instance.addEventListener("annotations.willChange",()=>{Comp.ActPanel.Toggle()});try{this.signatureCount=this.currentDocument.elements.length;await createAnnotations(this.currentDocument,this.Instance);const n=await this.Network.openDocument(this.envelopeKey);if(n.fatal||n.error)return Swal.fire({title:"Fehler",text:"Umschlag konnte nicht geöffnet werden!",icon:"error"})}catch(i){}[...document.getElementsByClassName("btn_refresh")].forEach(n=>n.addEventListener("click",()=>this.handleClick("RESET")));[...document.getElementsByClassName("btn_complete")].forEach(n=>n.addEventListener("click",()=>this.handleClick("FINISH")));[...document.getElementsByClassName("btn_reject")].forEach(n=>n.addEventListener("click",()=>this.handleClick("REJECT")))}handleAnnotationsLoad(n){n.toJS()}handleAnnotationsChange(){}async handleAnnotationsCreate(n){const t=n.toJS()[0],i=!!t.formFieldName,r=!!t.isSignature;if(i===!1&&r===!0){const r=t.boundingBox.left-20,u=t.boundingBox.top-20,n=150,i=75,f=new Date,e=await createAnnotationFrameBlob(this.envelopeReceiver.name,this.currentReceiver.signature,f,n,i),o=await fetch(e),s=await o.blob(),h=await this.Instance.createAttachment(s),c=createImageAnnotation(new PSPDFKit.Geometry.Rect({left:r,top:u,width:n,height:i}),t.pageIndex,h);this.Instance.create(c)}}async handleClick(n){let t=!1;switch(n){case"RESET":t=await this.handleReset(null);Comp.SignatureProgress.SignedCount=0;t.isConfirmed&&Swal.fire({title:"Erfolg",text:"Dokument wurde zurückgesetzt",icon:"info"});break;case"FINISH":t=await this.handleFinish(null);t==!0&&(window.location.href=`/EnvelopeKey/${this.envelopeKey}/Success`);break;case"REJECT":Swal.fire({title:localized.rejection,html:`<div class="text-start fs-6 p-0 m-0">${localized.rejectionReasonQ}</div>`,icon:"question",input:"text",inputAttributes:{autocapitalize:"off"},showCancelButton:!0,confirmButtonColor:"#3085d6",cancelButtonColor:"#d33",confirmButtonText:localized.complete,cancelButtonText:localized.back,showLoaderOnConfirm:!0,preConfirm:async n=>{try{return await rejectEnvelope(n)}catch(t){Swal.showValidationMessage(`
|
||||||
Request failed: ${t}
|
Request failed: ${t}
|
||||||
`)}},allowOutsideClick:()=>!Swal.isLoading()}).then(n=>{if(n.isConfirmed){const t=n.value;t.ok?redirRejected():Swal.showValidationMessage(`Request failed: ${t.message}`)}});break;case"COPY_URL":const n=window.location.href.replace(/\/readonly/gi,"");navigator.clipboard.writeText(n).then(function(){bsNotify("Kopiert",{alert_type:"success",delay:4,icon_name:"check_circle"})}).catch(function(){bsNotify("Unerwarteter Fehler",{alert_type:"danger",delay:4,icon_name:"error"})});break;case"SHARE":Comp.ShareBackdrop.show();break;case"LOGOUT":await logout()}}async handleFinish(){const n=await this.Instance.exportInstantJSON(),t=await n.formFieldValues,r=t.filter(n=>Annotation.isFieldRequired(n)),u=r.some(n=>n.value===undefined||n.value===null||n.value==="");if(u)return Swal.fire({title:"Warnung",text:"Bitte füllen Sie alle Standortinformationen vollständig aus!",icon:"warning"}),!1;const f=new RegExp("^[a-zA-Z\\u0080-\\u024F]+(?:([\\ \\-\\']|(\\.\\ ))[a-zA-Z\\u0080-\\u024F]+)*$"),e=t.filter(n=>Annotation.isCityField(n));for(var i of e)if(!IS_MOBILE_DEVICE&&!f.test(i.value))return Swal.fire({title:"Warnung",text:`Bitte überprüfen Sie die eingegebene Ortsangabe "${i.value}" auf korrekte Formatierung. Beispiele für richtige Formate sind: München, Île-de-France, Sauðárkrókur, San Francisco, St. Catharines usw.`,icon:"warning"}),!1;const o=await this.validateAnnotations(this.signatureCount);return o===!1?(Swal.fire({title:"Warnung",text:"Es wurden nicht alle Signaturfelder ausgefüllt!",icon:"warning"}),!1):Swal.fire({title:localized.confirmation,html:`<div class="text-start fs-6 p-0 m-0">${localized.sigAgree}</div>`,icon:"question",showCancelButton:!0,confirmButtonColor:"#3085d6",cancelButtonColor:"#d33",confirmButtonText:localized.finalize,cancelButtonText:localized.back}).then(async t=>{if(t.isConfirmed){try{await this.Instance.save()}catch(i){return Swal.fire({title:"Fehler",text:"Umschlag konnte nicht signiert werden!",icon:"error"}),!1}try{const i=await n,t=await this.Network.postEnvelope(this.envelopeKey,this.currentDocument.id,i);return t.fatal?(Swal.fire({title:"Fehler",text:"Umschlag konnte nicht signiert werden!",icon:"error"}),!1):t.error?(Swal.fire({title:"Warnung",text:"Umschlag ist nicht mehr verfügbar.",icon:"warning"}),!1):!0}catch(i){return!1}}else return!1})}async validateAnnotations(n){const t=await Annotation.getAnnotations(this.Instance),i=t.map(n=>n.toJS()).filter(n=>n.isSignature);return n>i.length?!1:!0}async handleReset(){const n=await Swal.fire({title:"Sind sie sicher?",text:"Wollen Sie das Dokument und alle erstellten Signaturen zurücksetzen?",icon:"question",showCancelButton:!0});if(n.isConfirmed){const n=await Annotation.deleteAnnotations(this.Instance)}return n}}
|
`)}},allowOutsideClick:()=>!Swal.isLoading()}).then(n=>{if(n.isConfirmed){const t=n.value;t.ok?redirRejected():Swal.showValidationMessage(`Request failed: ${t.message}`)}});break;case"COPY_URL":const n=window.location.href.replace(/\/readonly/gi,"");navigator.clipboard.writeText(n).then(function(){bsNotify("Kopiert",{alert_type:"success",delay:4,icon_name:"check_circle"})}).catch(function(){bsNotify("Unerwarteter Fehler",{alert_type:"danger",delay:4,icon_name:"error"})});break;case"SHARE":Comp.ShareBackdrop.show();break;case"LOGOUT":await logout()}}async handleFinish(){const n=await this.Instance.exportInstantJSON(),t=await n.formFieldValues,r=t.filter(n=>isFieldRequired(n)),u=r.some(n=>n.value===undefined||n.value===null||n.value==="");if(u)return Swal.fire({title:"Warnung",text:"Bitte füllen Sie alle Standortinformationen vollständig aus!",icon:"warning"}),!1;const f=new RegExp("^[a-zA-Z\\u0080-\\u024F]+(?:([\\ \\-\\']|(\\.\\ ))[a-zA-Z\\u0080-\\u024F]+)*$"),e=t.filter(n=>isCityField(n));for(var i of e)if(!IS_MOBILE_DEVICE&&!f.test(i.value))return Swal.fire({title:"Warnung",text:`Bitte überprüfen Sie die eingegebene Ortsangabe "${i.value}" auf korrekte Formatierung. Beispiele für richtige Formate sind: München, Île-de-France, Sauðárkrókur, San Francisco, St. Catharines usw.`,icon:"warning"}),!1;const o=await this.validateAnnotations(this.signatureCount);return o===!1?(Swal.fire({title:"Warnung",text:"Es wurden nicht alle Signaturfelder ausgefüllt!",icon:"warning"}),!1):Swal.fire({title:localized.confirmation,html:`<div class="text-start fs-6 p-0 m-0">${localized.sigAgree}</div>`,icon:"question",showCancelButton:!0,confirmButtonColor:"#3085d6",cancelButtonColor:"#d33",confirmButtonText:localized.finalize,cancelButtonText:localized.back}).then(async t=>{if(t.isConfirmed){try{await this.Instance.save()}catch(i){return Swal.fire({title:"Fehler",text:"Umschlag konnte nicht signiert werden!",icon:"error"}),!1}try{const i=await n,t=await this.Network.postEnvelope(this.envelopeKey,this.currentDocument.id,i);return t.fatal?(Swal.fire({title:"Fehler",text:"Umschlag konnte nicht signiert werden!",icon:"error"}),!1):t.error?(Swal.fire({title:"Warnung",text:"Umschlag ist nicht mehr verfügbar.",icon:"warning"}),!1):!0}catch(i){return!1}}else return!1})}async validateAnnotations(n){const t=await getAnnotations(this.Instance),i=t.map(n=>n.toJS()).filter(n=>n.isSignature);return n>i.length?!1:!0}async handleReset(){const n=await Swal.fire({title:"Sind sie sicher?",text:"Wollen Sie das Dokument und alle erstellten Signaturen zurücksetzen?",icon:"question",showCancelButton:!0});if(n.isConfirmed){const n=await deleteAnnotations(this.Instance)}return n}}
|
||||||
@ -69,7 +69,7 @@
|
|||||||
* Creates a GET HTTP request to `url`
|
* Creates a GET HTTP request to `url`
|
||||||
* @param {any} url
|
* @param {any} url
|
||||||
*/
|
*/
|
||||||
getRequest(url, body) {
|
getRequest(url) {
|
||||||
const token = this.getCSRFToken()
|
const token = this.getCSRFToken()
|
||||||
const options = {
|
const options = {
|
||||||
credentials: 'include',
|
credentials: 'include',
|
||||||
@ -79,10 +79,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (body !== undefined) {
|
|
||||||
options.body = JSON.stringify(body);
|
|
||||||
}
|
|
||||||
|
|
||||||
return fetch(url, options)
|
return fetch(url, options)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -207,3 +203,23 @@ async function logout() {
|
|||||||
window.location.href = "/";
|
window.location.href = "/";
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getAnnotationParams(leftInInch = 0, topInInch = 0, inchToPointFactor = 72) {
|
||||||
|
return fetch(`${window.location.origin}/api/Config/Annotations`, {
|
||||||
|
credentials: 'include',
|
||||||
|
method: 'GET'
|
||||||
|
})
|
||||||
|
.then(res => res.json())
|
||||||
|
.then(annotParams => {
|
||||||
|
for(var key in annotParams){
|
||||||
|
var annot = annotParams[key];
|
||||||
|
annot.width *= inchToPointFactor;
|
||||||
|
annot.height *= inchToPointFactor;
|
||||||
|
annot.left += leftInInch;
|
||||||
|
annot.left *= inchToPointFactor;
|
||||||
|
annot.top += topInInch;
|
||||||
|
annot.top *= inchToPointFactor;
|
||||||
|
}
|
||||||
|
return annotParams;
|
||||||
|
});
|
||||||
|
}
|
||||||
@ -1 +1 @@
|
|||||||
async function setLangAsync(n,t){document.getElementById("selectedFlag").className="fi "+t+" me-2";await fetch(`/lang/${n}`,{method:"POST",headers:{"Content-Type":"application/json"}})}async function setLanguage(n){const t=await fetch("/lang",{method:"GET",headers:{"Content-Type":"application/json"}}).then(n=>n.json()).then(t=>t.includes(n)).catch(()=>!1);if(t)return await fetch(`/lang/${n}`,{method:"POST",headers:{"Content-Type":"application/json"}}).then(n=>{if(n.redirected)window.location.href=n.url;else if(!n.ok)return Promise.reject("Failed to set language")})}async function logout(){return await fetch(`/auth/logout`,{method:"POST",headers:{"Content-Type":"application/json"}}).then(n=>{n.ok&&(window.location.href="/")})}class Network{async getEnvelope(n){return this.getRequest(`/api/envelope/${n}`).then(this.wrapJsonResponse.bind(this))}async postEnvelope(n,t,i){return this.postRequest(`/api/envelope/${n}?index=${t}`,i).then(this.wrapJsonResponse.bind(this))}async getDocument(n,t){return this.getRequest(`/api/document/${n}?index=${t}`).then(this.wrapBinaryResponse.bind(this))}async openDocument(n){return this.postRequest(`/api/document/${n}`,{}).then(this.wrapJsonResponse.bind(this))}withCSRFToken(n){const t=getCSRFToken;let i=n.headers;return n.headers={...i,...t},n}getCSRFToken(){const n=document.getElementsByName("__RequestVerificationToken")[0].value;return{"X-XSRF-TOKEN":n}}getRequest(n,t){const r=this.getCSRFToken(),i={credentials:"include",method:"GET",headers:{...r}};return t!==undefined&&(i.body=JSON.stringify(t)),fetch(n,i)}postRequest(n,t){const i=this.getCSRFToken(),r={credentials:"include",method:"POST",headers:{...i,"Content-Type":"application/json; charset=utf-8"},body:JSON.stringify(t)};return fetch(n,r)}async wrapJsonResponse(n){return await this.wrapResponse(n,async n=>await n.json())}async wrapBinaryResponse(n){return await this.wrapResponse(n,async n=>await n.arrayBuffer())}async wrapResponse(n,t){let i;if(n.status===200){const r=await t(n);i=new WrappedResponse(r,null)}else if(n.status===403){const t=await n.json();i=new WrappedResponse(null,t)}else i=new WrappedResponse(null,null);return i}}class WrappedResponse{constructor(n,t){this.data=n;this.error=t;this.fatal=n===null&&t===null}}
|
async function setLangAsync(n,t){document.getElementById("selectedFlag").className="fi "+t+" me-2";await fetch(`/lang/${n}`,{method:"POST",headers:{"Content-Type":"application/json"}})}async function setLanguage(n){const t=await fetch("/lang",{method:"GET",headers:{"Content-Type":"application/json"}}).then(n=>n.json()).then(t=>t.includes(n)).catch(()=>!1);if(t)return await fetch(`/lang/${n}`,{method:"POST",headers:{"Content-Type":"application/json"}}).then(n=>{if(n.redirected)window.location.href=n.url;else if(!n.ok)return Promise.reject("Failed to set language")})}async function logout(){return await fetch(`/auth/logout`,{method:"POST",headers:{"Content-Type":"application/json"}}).then(n=>{n.ok&&(window.location.href="/")})}function getAnnotationParams(n=0,t=0,i=72){return fetch(`${window.location.origin}/api/Config/Annotations`,{credentials:"include",method:"GET"}).then(n=>n.json()).then(r=>{var f,u;for(f in r)u=r[f],u.width*=i,u.height*=i,u.left+=n,u.left*=i,u.top+=t,u.top*=i;return r})}class Network{async getEnvelope(n){return this.getRequest(`/api/envelope/${n}`).then(this.wrapJsonResponse.bind(this))}async postEnvelope(n,t,i){return this.postRequest(`/api/envelope/${n}?index=${t}`,i).then(this.wrapJsonResponse.bind(this))}async getDocument(n,t){return this.getRequest(`/api/document/${n}?index=${t}`).then(this.wrapBinaryResponse.bind(this))}async openDocument(n){return this.postRequest(`/api/document/${n}`,{}).then(this.wrapJsonResponse.bind(this))}withCSRFToken(n){const t=getCSRFToken;let i=n.headers;return n.headers={...i,...t},n}getCSRFToken(){const n=document.getElementsByName("__RequestVerificationToken")[0].value;return{"X-XSRF-TOKEN":n}}getRequest(n){const t=this.getCSRFToken(),i={credentials:"include",method:"GET",headers:{...t}};return fetch(n,i)}postRequest(n,t){const i=this.getCSRFToken(),r={credentials:"include",method:"POST",headers:{...i,"Content-Type":"application/json; charset=utf-8"},body:JSON.stringify(t)};return fetch(n,r)}async wrapJsonResponse(n){return await this.wrapResponse(n,async n=>await n.json())}async wrapBinaryResponse(n){return await this.wrapResponse(n,async n=>await n.arrayBuffer())}async wrapResponse(n,t){let i;if(n.status===200){const r=await t(n);i=new WrappedResponse(r,null)}else if(n.status===403){const t=await n.json();i=new WrappedResponse(null,t)}else i=new WrappedResponse(null,null);return i}}class WrappedResponse{constructor(n,t){this.data=n;this.error=t;this.fatal=n===null&&t===null}}
|
||||||
Loading…
x
Reference in New Issue
Block a user