From da3c7bc0c2061099d5a42c51eece566db0e279aa Mon Sep 17 00:00:00 2001 From: Developer 02 Date: Mon, 17 Mar 2025 15:47:38 +0100 Subject: [PATCH 01/32] feat(annotation.js): Datum und Ort wurden vertauscht, um die Lesbarkeit zu verbessern. --- .../wwwroot/js/annotation.js | 51 ++++++++++--------- 1 file changed, 26 insertions(+), 25 deletions(-) diff --git a/EnvelopeGenerator.Web/wwwroot/js/annotation.js b/EnvelopeGenerator.Web/wwwroot/js/annotation.js index 82faac8b..95e04969 100644 --- a/EnvelopeGenerator.Web/wwwroot/js/annotation.js +++ b/EnvelopeGenerator.Web/wwwroot/js/annotation.js @@ -53,6 +53,31 @@ * Date, post code and place text form part */ const date_place_top_shift = 9.5; + + //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 + date_place_top_shift + 25, + left: left, + }), + fontSize: 8 + }) + + const formFieldCity = new PSPDFKit.FormFields.TextFormField({ + name: id_city, + annotationIds: PSPDFKit.Immutable.List([annotation_city.id]), + value: "", + readOnly: false + }) + //date const id_date = PSPDFKit.generateInstantId() const annotation_date = new PSPDFKit.Annotations.WidgetAnnotation({ @@ -64,7 +89,7 @@ boundingBox: new PSPDFKit.Geometry.Rect({ width: width * 1.55, height: height / 2, - top: top + height + 25 + date_place_top_shift + (height), + top: top + 2 * height + date_place_top_shift + 23, left: left }), fontSize: 8, @@ -81,30 +106,6 @@ 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.markFieldAsCity(formFieldCity); From df019a724337cd29a59fed5de7b7cd06de0ebd24 Mon Sep 17 00:00:00 2001 From: Developer 02 Date: Thu, 20 Mar 2025 09:22:36 +0100 Subject: [PATCH 02/32] =?UTF-8?q?feat(AnnotationParams):=20Erstellt,=20um?= =?UTF-8?q?=20Annotationen=20=C3=BCber=20Appsettings=20zu=20konfigurieren.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- EnvelopeGenerator.Web/Models/Annotation.cs | 8 +++----- EnvelopeGenerator.Web/Models/AnnotationParams.cs | 6 ++++++ EnvelopeGenerator.Web/Program.cs | 2 ++ EnvelopeGenerator.Web/appsettings.json | 7 ++++++- 4 files changed, 17 insertions(+), 6 deletions(-) create mode 100644 EnvelopeGenerator.Web/Models/AnnotationParams.cs diff --git a/EnvelopeGenerator.Web/Models/Annotation.cs b/EnvelopeGenerator.Web/Models/Annotation.cs index 85bd0ef0..c730939f 100644 --- a/EnvelopeGenerator.Web/Models/Annotation.cs +++ b/EnvelopeGenerator.Web/Models/Annotation.cs @@ -1,8 +1,6 @@ namespace EnvelopeGenerator.Web.Models; -public record Annotation( - string Id, - string? HorBoundAnnotId = null, string? VerBoundAnnotId = null) +public record Annotation(string? HorBoundAnnotId = null, string? VerBoundAnnotId = null) { #region Layout internal double _marginX = default; @@ -51,8 +49,8 @@ public record Annotation( #endregion #region BoundAnnot - public Annot? HorBoundAnnot { get; set; } + public Annotation? HorBoundAnnot { get; set; } - public Annot? VerBoundAnnot { get; set; } + public Annotation? VerBoundAnnot { get; set; } #endregion }; \ No newline at end of file diff --git a/EnvelopeGenerator.Web/Models/AnnotationParams.cs b/EnvelopeGenerator.Web/Models/AnnotationParams.cs new file mode 100644 index 00000000..864cef88 --- /dev/null +++ b/EnvelopeGenerator.Web/Models/AnnotationParams.cs @@ -0,0 +1,6 @@ +namespace EnvelopeGenerator.Web.Models; + +public class AnnotationParams +{ + public required Dictionary Annotations { get; init; } +} diff --git a/EnvelopeGenerator.Web/Program.cs b/EnvelopeGenerator.Web/Program.cs index 9c61127c..a9545764 100644 --- a/EnvelopeGenerator.Web/Program.cs +++ b/EnvelopeGenerator.Web/Program.cs @@ -163,6 +163,8 @@ try builder.ConfigureBySection(); + builder.ConfigureBySection(); + var app = builder.Build(); // Configure the HTTP request pipeline. diff --git a/EnvelopeGenerator.Web/appsettings.json b/EnvelopeGenerator.Web/appsettings.json index 59f07e6a..994141a1 100644 --- a/EnvelopeGenerator.Web/appsettings.json +++ b/EnvelopeGenerator.Web/appsettings.json @@ -149,5 +149,10 @@ "EnvelopeReceiverReadOnly": [ "TBSIG_ENVELOPE_RECEIVER_READ_ONLY_UPD" ], "Receiver": [] }, - "MainPageTitle": null + "MainPageTitle": null, + "AnnotationParams": { + "Annotations": { + + } + } } From cbd71aa2b9ae89223025ad36f3f5eae5643db4fd Mon Sep 17 00:00:00 2001 From: Developer 02 Date: Thu, 20 Mar 2025 09:41:51 +0100 Subject: [PATCH 03/32] =?UTF-8?q?feat(AnnotationParams):=20Logik=20zur=20I?= =?UTF-8?q?nitialisierung=20von=20gebundenen=20Annotationen=20hinzugef?= =?UTF-8?q?=C3=BCgt=20Annots.init?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- EnvelopeGenerator.Web/Models/Annotation.cs | 2 +- .../Models/AnnotationParams.cs | 27 ++++++++++++++++++- 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/EnvelopeGenerator.Web/Models/Annotation.cs b/EnvelopeGenerator.Web/Models/Annotation.cs index c730939f..58262e7b 100644 --- a/EnvelopeGenerator.Web/Models/Annotation.cs +++ b/EnvelopeGenerator.Web/Models/Annotation.cs @@ -1,6 +1,6 @@ namespace EnvelopeGenerator.Web.Models; -public record Annotation(string? HorBoundAnnotId = null, string? VerBoundAnnotId = null) +public record Annotation(string? HorBoundAnnotName = null, string? VerBoundAnnotName = null) { #region Layout internal double _marginX = default; diff --git a/EnvelopeGenerator.Web/Models/AnnotationParams.cs b/EnvelopeGenerator.Web/Models/AnnotationParams.cs index 864cef88..9df111f3 100644 --- a/EnvelopeGenerator.Web/Models/AnnotationParams.cs +++ b/EnvelopeGenerator.Web/Models/AnnotationParams.cs @@ -2,5 +2,30 @@ public class AnnotationParams { - public required Dictionary Annotations { get; init; } + private readonly Dictionary _annots = new(); + + public required Dictionary Annots + { + get => _annots; + init + { + // set bound annotations + foreach (var name in _annots.Keys) + { + // horizontal + if (_annots[name].HorBoundAnnotName is string horBoundAnnotName) + if (_annots.TryGetValue(horBoundAnnotName, out var horBoundAnnot)) + _annots[name].HorBoundAnnot = horBoundAnnot; + else + throw new InvalidOperationException($"{horBoundAnnotName} added as bound anotation. However, it is not defined."); + + // vertical + if (_annots[name].VerBoundAnnotName is string verBoundAnnotName) + if (_annots.TryGetValue(verBoundAnnotName, out var verBoundAnnot)) + _annots[name].VerBoundAnnot = verBoundAnnot; + else + throw new InvalidOperationException($"{verBoundAnnotName} added as bound anotation. However, it is not defined."); + } + } + } } From 8a6a11c1bc5887484bda94b95dc8e9506bbd2084 Mon Sep 17 00:00:00 2001 From: Developer 02 Date: Thu, 20 Mar 2025 10:23:33 +0100 Subject: [PATCH 04/32] feat(AnnotationParams): Aktualisiert, um Standardwerte in Annots.init zu setzen. --- EnvelopeGenerator.Web/Models/Annotation.cs | 8 +++++- .../Models/AnnotationParams.cs | 25 ++++++++++++++++--- EnvelopeGenerator.Web/appsettings.json | 8 ++++++ 3 files changed, 36 insertions(+), 5 deletions(-) diff --git a/EnvelopeGenerator.Web/Models/Annotation.cs b/EnvelopeGenerator.Web/Models/Annotation.cs index 58262e7b..4032fca4 100644 --- a/EnvelopeGenerator.Web/Models/Annotation.cs +++ b/EnvelopeGenerator.Web/Models/Annotation.cs @@ -1,7 +1,13 @@ namespace EnvelopeGenerator.Web.Models; -public record Annotation(string? HorBoundAnnotName = null, string? VerBoundAnnotName = null) +public class Annotation { + #region Bound Annotation + public string? HorBoundAnnotName { get; init; } + + public string? VerBoundAnnotName { get; init; } + #endregion + #region Layout internal double _marginX = default; diff --git a/EnvelopeGenerator.Web/Models/AnnotationParams.cs b/EnvelopeGenerator.Web/Models/AnnotationParams.cs index 9df111f3..4886a67a 100644 --- a/EnvelopeGenerator.Web/Models/AnnotationParams.cs +++ b/EnvelopeGenerator.Web/Models/AnnotationParams.cs @@ -1,6 +1,6 @@ namespace EnvelopeGenerator.Web.Models; -public class AnnotationParams +public class AnnotationParams: Annotation { private readonly Dictionary _annots = new(); @@ -9,15 +9,31 @@ public class AnnotationParams get => _annots; init { - // set bound annotations + _annots = value; + foreach (var name in _annots.Keys) { + #region set default values + if (_annots[name]._marginX == default) + _annots[name]._marginX = MarginX; + + if (_annots[name]._marginY == default) + _annots[name]._marginY = MarginY; + + if (_annots[name]._width == default) + _annots[name]._width = Width; + + if (_annots[name]._height == default) + _annots[name]._height = Height; + #endregion + + #region set bound annotations // horizontal if (_annots[name].HorBoundAnnotName is string horBoundAnnotName) if (_annots.TryGetValue(horBoundAnnotName, out var horBoundAnnot)) _annots[name].HorBoundAnnot = horBoundAnnot; - else - throw new InvalidOperationException($"{horBoundAnnotName} added as bound anotation. However, it is not defined."); + else + throw new InvalidOperationException($"{horBoundAnnotName} added as bound anotation. However, it is not defined."); // vertical if (_annots[name].VerBoundAnnotName is string verBoundAnnotName) @@ -25,6 +41,7 @@ public class AnnotationParams _annots[name].VerBoundAnnot = verBoundAnnot; else throw new InvalidOperationException($"{verBoundAnnotName} added as bound anotation. However, it is not defined."); + #endregion } } } diff --git a/EnvelopeGenerator.Web/appsettings.json b/EnvelopeGenerator.Web/appsettings.json index 994141a1..3bf5e281 100644 --- a/EnvelopeGenerator.Web/appsettings.json +++ b/EnvelopeGenerator.Web/appsettings.json @@ -152,7 +152,15 @@ "MainPageTitle": null, "AnnotationParams": { "Annotations": { + "Signature": { + }, + "City": { + + }, + "Date": { + + } } } } From b6563d71b06a1c06525de80fb8b7a69261c95b70 Mon Sep 17 00:00:00 2001 From: Developer 02 Date: Thu, 20 Mar 2025 10:27:53 +0100 Subject: [PATCH 05/32] feat(Annotation): marginX in left und marginY in top umbenannt. --- EnvelopeGenerator.Web/Models/Annotation.cs | 24 +++++++++---------- .../Models/AnnotationParams.cs | 8 +++---- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/EnvelopeGenerator.Web/Models/Annotation.cs b/EnvelopeGenerator.Web/Models/Annotation.cs index 4032fca4..6c200a80 100644 --- a/EnvelopeGenerator.Web/Models/Annotation.cs +++ b/EnvelopeGenerator.Web/Models/Annotation.cs @@ -9,24 +9,24 @@ public class Annotation #endregion #region Layout - internal double _marginX = default; + internal double _left = default; - internal double _marginY = default; + internal double _top = default; internal double _width = default; internal double _height = default; - public double MarginX + public double Left { - get => _marginX; - init => _marginX = value; + get => _left; + init => _left = value; } - public double MarginY + public double Top { - get => _marginY; - init => _marginY = value; + get => _top; + init => _top = value; } public double Width @@ -43,15 +43,15 @@ public class Annotation #endregion #region Pos - public double PosX => MarginX + (HorBoundAnnot?.HorBoundary ?? 0); + public double PosX => Left + (HorBoundAnnot?.HorBoundary ?? 0); - public double PosY => MarginY + (VerBoundAnnot?.VerBoundary ?? 0); + public double PosY => Top + (VerBoundAnnot?.VerBoundary ?? 0); #endregion #region Boundary - public double HorBoundary => MarginX + Width; + public double HorBoundary => Left + Width; - public double VerBoundary => MarginY + Height; + public double VerBoundary => Top + Height; #endregion #region BoundAnnot diff --git a/EnvelopeGenerator.Web/Models/AnnotationParams.cs b/EnvelopeGenerator.Web/Models/AnnotationParams.cs index 4886a67a..f46486ac 100644 --- a/EnvelopeGenerator.Web/Models/AnnotationParams.cs +++ b/EnvelopeGenerator.Web/Models/AnnotationParams.cs @@ -14,11 +14,11 @@ public class AnnotationParams: Annotation foreach (var name in _annots.Keys) { #region set default values - if (_annots[name]._marginX == default) - _annots[name]._marginX = MarginX; + if (_annots[name]._left == default) + _annots[name]._left = Left; - if (_annots[name]._marginY == default) - _annots[name]._marginY = MarginY; + if (_annots[name]._top == default) + _annots[name]._top = Top; if (_annots[name]._width == default) _annots[name]._width = Width; From d5b4ea46d30f5d849202af7bff2eb5f6e8891832 Mon Sep 17 00:00:00 2001 From: Developer 02 Date: Thu, 20 Mar 2025 11:39:40 +0100 Subject: [PATCH 06/32] =?UTF-8?q?feat(DefaultAnnotation):=20Hinzuf=C3=BCge?= =?UTF-8?q?n=20der=20M=C3=B6glichkeit,=20eine=20Annotation=20mit=20zentral?= =?UTF-8?q?en=20Standardwerten=20zu=20konfigurieren.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Models/AnnotationParams.cs | 24 ++++++++++++------- EnvelopeGenerator.Web/appsettings.json | 3 +++ 2 files changed, 18 insertions(+), 9 deletions(-) diff --git a/EnvelopeGenerator.Web/Models/AnnotationParams.cs b/EnvelopeGenerator.Web/Models/AnnotationParams.cs index f46486ac..2f6d6995 100644 --- a/EnvelopeGenerator.Web/Models/AnnotationParams.cs +++ b/EnvelopeGenerator.Web/Models/AnnotationParams.cs @@ -1,7 +1,9 @@ namespace EnvelopeGenerator.Web.Models; -public class AnnotationParams: Annotation +public class AnnotationParams { + private Annotation? DefaultAnnotation { get; init; } + private readonly Dictionary _annots = new(); public required Dictionary Annots @@ -14,17 +16,21 @@ public class AnnotationParams: Annotation foreach (var name in _annots.Keys) { #region set default values - if (_annots[name]._left == default) - _annots[name]._left = Left; + if(DefaultAnnotation is not null) + { + // To set default value, annotation must have default (0) value but default must has non-default value + if (_annots[name]._left == default && DefaultAnnotation.Left != default) + _annots[name]._left = DefaultAnnotation.Left; - if (_annots[name]._top == default) - _annots[name]._top = Top; + if (_annots[name]._top == default && DefaultAnnotation.Top != default) + _annots[name]._top = DefaultAnnotation.Top; - if (_annots[name]._width == default) - _annots[name]._width = Width; + if (_annots[name]._width == default && DefaultAnnotation.Width != default) + _annots[name]._width = DefaultAnnotation.Width; - if (_annots[name]._height == default) - _annots[name]._height = Height; + if (_annots[name]._height == default && DefaultAnnotation.Height != default) + _annots[name]._height = DefaultAnnotation.Height; + } #endregion #region set bound annotations diff --git a/EnvelopeGenerator.Web/appsettings.json b/EnvelopeGenerator.Web/appsettings.json index 3bf5e281..68165506 100644 --- a/EnvelopeGenerator.Web/appsettings.json +++ b/EnvelopeGenerator.Web/appsettings.json @@ -151,6 +151,9 @@ }, "MainPageTitle": null, "AnnotationParams": { + "DefaultAnnotation": { + + }, "Annotations": { "Signature": { From 353f7698f4e20ec69d4b1cf727c865b27764b1a6 Mon Sep 17 00:00:00 2001 From: Developer 02 Date: Thu, 20 Mar 2025 11:50:59 +0100 Subject: [PATCH 07/32] =?UTF-8?q?feat(ConfigController):=20Erstellt,=20um?= =?UTF-8?q?=20Webanwendungen=20=C3=BCber=20den=20Server=20zu=20konfigurier?= =?UTF-8?q?en.=20=20-=20GetAnnotationParams=20Endpunkt=20hinzuf=C3=BCgen,?= =?UTF-8?q?=20um=20Annotationsdaten=20zu=20senden?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Controllers/ConfigController.cs | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 EnvelopeGenerator.Web/Controllers/ConfigController.cs diff --git a/EnvelopeGenerator.Web/Controllers/ConfigController.cs b/EnvelopeGenerator.Web/Controllers/ConfigController.cs new file mode 100644 index 00000000..2c3330fd --- /dev/null +++ b/EnvelopeGenerator.Web/Controllers/ConfigController.cs @@ -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(IOptions annotationParamsOptions) + { + _annotParams = annotationParamsOptions.Value; + } + + [HttpGet("Annotations")] + public IActionResult GetAnnotationParams() + { + return Ok(_annotParams); + } +} From 43db4e275b430dbb9f915c5714d223632725544d Mon Sep 17 00:00:00 2001 From: Developer 02 Date: Thu, 20 Mar 2025 12:46:57 +0100 Subject: [PATCH 08/32] =?UTF-8?q?fix(Annotation):=20JsonIgnore-Attribut=20?= =?UTF-8?q?zu=20HorBoundAnnot=20und=20VerBoundAnnot=20hinzuf=C3=BCgen?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- EnvelopeGenerator.Web/Models/Annotation.cs | 6 +++++- EnvelopeGenerator.Web/Models/AnnotationParams.cs | 4 ++-- EnvelopeGenerator.Web/appsettings.json | 8 ++++---- 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/EnvelopeGenerator.Web/Models/Annotation.cs b/EnvelopeGenerator.Web/Models/Annotation.cs index 6c200a80..e3c21f28 100644 --- a/EnvelopeGenerator.Web/Models/Annotation.cs +++ b/EnvelopeGenerator.Web/Models/Annotation.cs @@ -1,4 +1,6 @@ -namespace EnvelopeGenerator.Web.Models; +using System.Text.Json.Serialization; + +namespace EnvelopeGenerator.Web.Models; public class Annotation { @@ -55,8 +57,10 @@ public class Annotation #endregion #region BoundAnnot + [JsonIgnore] public Annotation? HorBoundAnnot { get; set; } + [JsonIgnore] public Annotation? VerBoundAnnot { get; set; } #endregion }; \ No newline at end of file diff --git a/EnvelopeGenerator.Web/Models/AnnotationParams.cs b/EnvelopeGenerator.Web/Models/AnnotationParams.cs index 2f6d6995..011858cb 100644 --- a/EnvelopeGenerator.Web/Models/AnnotationParams.cs +++ b/EnvelopeGenerator.Web/Models/AnnotationParams.cs @@ -2,11 +2,11 @@ public class AnnotationParams { - private Annotation? DefaultAnnotation { get; init; } + public Annotation? DefaultAnnotation { get; init; } private readonly Dictionary _annots = new(); - public required Dictionary Annots + public required Dictionary Annotations { get => _annots; init diff --git a/EnvelopeGenerator.Web/appsettings.json b/EnvelopeGenerator.Web/appsettings.json index 68165506..aec7c0d7 100644 --- a/EnvelopeGenerator.Web/appsettings.json +++ b/EnvelopeGenerator.Web/appsettings.json @@ -152,17 +152,17 @@ "MainPageTitle": null, "AnnotationParams": { "DefaultAnnotation": { - + "Width": 1, + "Height": 0.5 }, "Annotations": { "Signature": { - }, "City": { - + "VerBoundAnnotName": "Signature" }, "Date": { - + "VerBoundAnnotName": "City" } } } From 093e64de8182cb753beaf034dbde6791a25c18ec Mon Sep 17 00:00:00 2001 From: Developer 02 Date: Thu, 20 Mar 2025 14:27:58 +0100 Subject: [PATCH 09/32] =?UTF-8?q?feat(Annotation):=20Hinzuf=C3=BCgen=20der?= =?UTF-8?q?=20Eigenschaft=20Name?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- EnvelopeGenerator.Web/Models/Annotation.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/EnvelopeGenerator.Web/Models/Annotation.cs b/EnvelopeGenerator.Web/Models/Annotation.cs index e3c21f28..cb08d806 100644 --- a/EnvelopeGenerator.Web/Models/Annotation.cs +++ b/EnvelopeGenerator.Web/Models/Annotation.cs @@ -2,8 +2,10 @@ namespace EnvelopeGenerator.Web.Models; -public class Annotation +public record Annotation { + public required string Name { get; init; } + #region Bound Annotation public string? HorBoundAnnotName { get; init; } From 78b5e3f5ccb5b06669239db9cd412cfe7d339321 Mon Sep 17 00:00:00 2001 From: Developer 02 Date: Thu, 20 Mar 2025 14:44:57 +0100 Subject: [PATCH 10/32] =?UTF-8?q?feat(Annotations):=20Konvertiere=20=5Fann?= =?UTF-8?q?ots=20von=20Dictionary=20zu=20IEnumerable.=20=20-=20Zugeh=C3=B6?= =?UTF-8?q?rige=20Index-=20und=20TryGet-Methoden=20hinzugef=C3=BCgt.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Models/AnnotationParams.cs | 52 ++++++++++++------- EnvelopeGenerator.Web/appsettings.json | 13 +++-- 2 files changed, 42 insertions(+), 23 deletions(-) diff --git a/EnvelopeGenerator.Web/Models/AnnotationParams.cs b/EnvelopeGenerator.Web/Models/AnnotationParams.cs index 011858cb..d52126f7 100644 --- a/EnvelopeGenerator.Web/Models/AnnotationParams.cs +++ b/EnvelopeGenerator.Web/Models/AnnotationParams.cs @@ -1,50 +1,66 @@ -namespace EnvelopeGenerator.Web.Models; +using System.Text.Json.Serialization; + +namespace EnvelopeGenerator.Web.Models; public class AnnotationParams { + [JsonIgnore] public Annotation? DefaultAnnotation { get; init; } - private readonly Dictionary _annots = new(); + private readonly IEnumerable _annots = new List(); + + 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; + } + + [JsonIgnore] + public IEnumerable Names => _annots.Select(annot => annot.Name); - public required Dictionary Annotations + public required IEnumerable Annotations { get => _annots; init { _annots = value; - foreach (var name in _annots.Keys) + foreach (var name in Names) { #region set default values if(DefaultAnnotation is not null) { // To set default value, annotation must have default (0) value but default must has non-default value - if (_annots[name]._left == default && DefaultAnnotation.Left != default) - _annots[name]._left = DefaultAnnotation.Left; + if (this[name]._left == default && DefaultAnnotation.Left != default) + this[name]._left = DefaultAnnotation.Left; - if (_annots[name]._top == default && DefaultAnnotation.Top != default) - _annots[name]._top = DefaultAnnotation.Top; + if (this[name]._top == default && DefaultAnnotation.Top != default) + this[name]._top = DefaultAnnotation.Top; - if (_annots[name]._width == default && DefaultAnnotation.Width != default) - _annots[name]._width = DefaultAnnotation.Width; + if (this[name]._width == default && DefaultAnnotation.Width != default) + this[name]._width = DefaultAnnotation.Width; - if (_annots[name]._height == default && DefaultAnnotation.Height != default) - _annots[name]._height = DefaultAnnotation.Height; + if (this[name]._height == default && DefaultAnnotation.Height != default) + this[name]._height = DefaultAnnotation.Height; } #endregion #region set bound annotations // horizontal - if (_annots[name].HorBoundAnnotName is string horBoundAnnotName) - if (_annots.TryGetValue(horBoundAnnotName, out var horBoundAnnot)) - _annots[name].HorBoundAnnot = horBoundAnnot; + if (this[name].HorBoundAnnotName is string horBoundAnnotName) + if (TryGet(horBoundAnnotName, out var horBoundAnnot)) + this[name].HorBoundAnnot = horBoundAnnot; else throw new InvalidOperationException($"{horBoundAnnotName} added as bound anotation. However, it is not defined."); // vertical - if (_annots[name].VerBoundAnnotName is string verBoundAnnotName) - if (_annots.TryGetValue(verBoundAnnotName, out var verBoundAnnot)) - _annots[name].VerBoundAnnot = verBoundAnnot; + if (this[name].VerBoundAnnotName is string verBoundAnnotName) + if (TryGet(verBoundAnnotName, out var verBoundAnnot)) + this[name].VerBoundAnnot = verBoundAnnot; else throw new InvalidOperationException($"{verBoundAnnotName} added as bound anotation. However, it is not defined."); #endregion diff --git a/EnvelopeGenerator.Web/appsettings.json b/EnvelopeGenerator.Web/appsettings.json index aec7c0d7..3574a25b 100644 --- a/EnvelopeGenerator.Web/appsettings.json +++ b/EnvelopeGenerator.Web/appsettings.json @@ -155,15 +155,18 @@ "Width": 1, "Height": 0.5 }, - "Annotations": { - "Signature": { + "Annotations": [ + { + "Name": "Signature" }, - "City": { + { + "Name": "City", "VerBoundAnnotName": "Signature" }, - "Date": { + { + "Name": "Date", "VerBoundAnnotName": "City" } - } + ] } } From 14be46d3d685dbd3958a8fe64d1535bed29088d8 Mon Sep 17 00:00:00 2001 From: Developer 02 Date: Thu, 20 Mar 2025 14:56:36 +0100 Subject: [PATCH 11/32] =?UTF-8?q?refactor(Annotation):=20Umbenennen=20von?= =?UTF-8?q?=20left=20in=20marginLeft,=20top=20in=20marginTop,=20posX=20in?= =?UTF-8?q?=20Left=20und=20posY=20in=20top=20f=C3=BCr=20eine=20CSS-=C3=A4h?= =?UTF-8?q?nlichere=20Benennung?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- EnvelopeGenerator.Web/Models/Annotation.cs | 28 +++++++++---------- .../Models/AnnotationParams.cs | 8 +++--- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/EnvelopeGenerator.Web/Models/Annotation.cs b/EnvelopeGenerator.Web/Models/Annotation.cs index cb08d806..e909eddf 100644 --- a/EnvelopeGenerator.Web/Models/Annotation.cs +++ b/EnvelopeGenerator.Web/Models/Annotation.cs @@ -13,24 +13,24 @@ public record Annotation #endregion #region Layout - internal double _left = default; + internal double _marginLeft = default; - internal double _top = default; + internal double _marginTop = default; internal double _width = default; internal double _height = default; - - public double Left + + public double MarginLeft { - get => _left; - init => _left = value; + get => _marginLeft; + init => _marginLeft = value; } - public double Top + public double MarginTop { - get => _top; - init => _top = value; + get => _marginTop; + init => _marginTop = value; } public double Width @@ -46,16 +46,16 @@ public record Annotation } #endregion - #region Pos - public double PosX => Left + (HorBoundAnnot?.HorBoundary ?? 0); + #region Position + public double Left => MarginLeft + (HorBoundAnnot?.HorBoundary ?? 0); - public double PosY => Top + (VerBoundAnnot?.VerBoundary ?? 0); + public double Top => MarginTop + (VerBoundAnnot?.VerBoundary ?? 0); #endregion #region Boundary - public double HorBoundary => Left + Width; + public double HorBoundary => MarginLeft + Width; - public double VerBoundary => Top + Height; + public double VerBoundary => MarginTop + Height; #endregion #region BoundAnnot diff --git a/EnvelopeGenerator.Web/Models/AnnotationParams.cs b/EnvelopeGenerator.Web/Models/AnnotationParams.cs index d52126f7..0a81004b 100644 --- a/EnvelopeGenerator.Web/Models/AnnotationParams.cs +++ b/EnvelopeGenerator.Web/Models/AnnotationParams.cs @@ -35,11 +35,11 @@ public class AnnotationParams if(DefaultAnnotation is not null) { // To set default value, annotation must have default (0) value but default must has non-default value - if (this[name]._left == default && DefaultAnnotation.Left != default) - this[name]._left = DefaultAnnotation.Left; + if (this[name]._marginLeft == default && DefaultAnnotation.MarginLeft != default) + this[name]._marginLeft = DefaultAnnotation.MarginLeft; - if (this[name]._top == default && DefaultAnnotation.Top != default) - this[name]._top = DefaultAnnotation.Top; + if (this[name]._marginTop == default && DefaultAnnotation.MarginTop != default) + this[name]._marginTop = DefaultAnnotation.MarginTop; if (this[name]._width == default && DefaultAnnotation.Width != default) this[name]._width = DefaultAnnotation.Width; From db84abf0e7713bb249b3277f55075286d0f5b34b Mon Sep 17 00:00:00 2001 From: Developer 02 Date: Thu, 20 Mar 2025 14:58:41 +0100 Subject: [PATCH 12/32] =?UTF-8?q?feat(Anmerkung):=20JsonIgnore-Attribut=20?= =?UTF-8?q?f=C3=BCr=20nicht-clientbezogene=20Entit=C3=A4ten=20hinzugef?= =?UTF-8?q?=C3=BCgt?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- EnvelopeGenerator.Web/Models/Annotation.cs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/EnvelopeGenerator.Web/Models/Annotation.cs b/EnvelopeGenerator.Web/Models/Annotation.cs index e909eddf..b4774cb1 100644 --- a/EnvelopeGenerator.Web/Models/Annotation.cs +++ b/EnvelopeGenerator.Web/Models/Annotation.cs @@ -7,8 +7,10 @@ public record Annotation public required string Name { get; init; } #region Bound Annotation + [JsonIgnore] public string? HorBoundAnnotName { get; init; } + [JsonIgnore] public string? VerBoundAnnotName { get; init; } #endregion @@ -20,13 +22,15 @@ public record Annotation internal double _width = default; internal double _height = default; - + + [JsonIgnore] public double MarginLeft { get => _marginLeft; init => _marginLeft = value; } + [JsonIgnore] public double MarginTop { get => _marginTop; @@ -53,8 +57,10 @@ public record Annotation #endregion #region Boundary + [JsonIgnore] public double HorBoundary => MarginLeft + Width; + [JsonIgnore] public double VerBoundary => MarginTop + Height; #endregion From 0b87a3746a4f3cb8e276f7d727eb0e61113998a5 Mon Sep 17 00:00:00 2001 From: Developer 02 Date: Thu, 20 Mar 2025 15:52:21 +0100 Subject: [PATCH 13/32] =?UTF-8?q?fix(Annotation):=20Aktualisiert,=20um=20M?= =?UTF-8?q?arginLeft=20und=20Top=20bei=20der=20Berechnung=20von=20HorBound?= =?UTF-8?q?ary=20und=20VerBoundary=20zu=20ber=C3=BCcksichtigen?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- EnvelopeGenerator.Web/Models/Annotation.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/EnvelopeGenerator.Web/Models/Annotation.cs b/EnvelopeGenerator.Web/Models/Annotation.cs index b4774cb1..215ef046 100644 --- a/EnvelopeGenerator.Web/Models/Annotation.cs +++ b/EnvelopeGenerator.Web/Models/Annotation.cs @@ -58,10 +58,10 @@ public record Annotation #region Boundary [JsonIgnore] - public double HorBoundary => MarginLeft + Width; + public double HorBoundary => Left + Width; [JsonIgnore] - public double VerBoundary => MarginTop + Height; + public double VerBoundary => Top + Height; #endregion #region BoundAnnot From 036e1f68a88ca6222c8b71f7a90d07d711bb6a71 Mon Sep 17 00:00:00 2001 From: Developer 02 Date: Thu, 20 Mar 2025 16:48:42 +0100 Subject: [PATCH 14/32] =?UTF-8?q?refactor(Annotation):=20Default.set=20hin?= =?UTF-8?q?zugef=C3=BCgt,=20um=20Standardwerte=20zu=20setzen?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- EnvelopeGenerator.Web/Models/Annotation.cs | 20 +++++++++++++++++ .../Models/AnnotationParams.cs | 22 ++++--------------- 2 files changed, 24 insertions(+), 18 deletions(-) diff --git a/EnvelopeGenerator.Web/Models/Annotation.cs b/EnvelopeGenerator.Web/Models/Annotation.cs index 215ef046..448365ed 100644 --- a/EnvelopeGenerator.Web/Models/Annotation.cs +++ b/EnvelopeGenerator.Web/Models/Annotation.cs @@ -71,4 +71,24 @@ public record Annotation [JsonIgnore] public Annotation? VerBoundAnnot { get; set; } #endregion + + [JsonIgnore] + internal Annotation Default + { + set + { + // To set default value, annotation must have default (0) value but default must has non-default value + if (_marginLeft == default && value.MarginLeft != default) + _marginLeft = value.MarginLeft; + + if (_marginTop == default && value.MarginTop != default) + _marginTop = value.MarginTop; + + if (_width == default && value.Width != default) + _width = value.Width; + + if (_height == default && value.Height != default) + _height = value.Height; + } + } }; \ No newline at end of file diff --git a/EnvelopeGenerator.Web/Models/AnnotationParams.cs b/EnvelopeGenerator.Web/Models/AnnotationParams.cs index 0a81004b..68997f6e 100644 --- a/EnvelopeGenerator.Web/Models/AnnotationParams.cs +++ b/EnvelopeGenerator.Web/Models/AnnotationParams.cs @@ -29,26 +29,12 @@ public class AnnotationParams { _annots = value; + if (DefaultAnnotation is not null) + foreach (var annot in _annots) + annot.Default = DefaultAnnotation; + foreach (var name in Names) { - #region set default values - if(DefaultAnnotation is not null) - { - // To set default value, annotation must have default (0) value but default must has non-default value - if (this[name]._marginLeft == default && DefaultAnnotation.MarginLeft != default) - this[name]._marginLeft = DefaultAnnotation.MarginLeft; - - if (this[name]._marginTop == default && DefaultAnnotation.MarginTop != default) - this[name]._marginTop = DefaultAnnotation.MarginTop; - - if (this[name]._width == default && DefaultAnnotation.Width != default) - this[name]._width = DefaultAnnotation.Width; - - if (this[name]._height == default && DefaultAnnotation.Height != default) - this[name]._height = DefaultAnnotation.Height; - } - #endregion - #region set bound annotations // horizontal if (this[name].HorBoundAnnotName is string horBoundAnnotName) From 210ce072f8e855b20d025151afea69702cc32c58 Mon Sep 17 00:00:00 2001 From: Developer 02 Date: Thu, 20 Mar 2025 17:01:13 +0100 Subject: [PATCH 15/32] refactor(AnnotationParams): vereinfacht --- EnvelopeGenerator.Web/Models/AnnotationParams.cs | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/EnvelopeGenerator.Web/Models/AnnotationParams.cs b/EnvelopeGenerator.Web/Models/AnnotationParams.cs index 68997f6e..70410e17 100644 --- a/EnvelopeGenerator.Web/Models/AnnotationParams.cs +++ b/EnvelopeGenerator.Web/Models/AnnotationParams.cs @@ -19,9 +19,6 @@ public class AnnotationParams return annotation is not null; } - [JsonIgnore] - public IEnumerable Names => _annots.Select(annot => annot.Name); - public required IEnumerable Annotations { get => _annots; @@ -33,20 +30,20 @@ public class AnnotationParams foreach (var annot in _annots) annot.Default = DefaultAnnotation; - foreach (var name in Names) + foreach (var annot in _annots) { #region set bound annotations // horizontal - if (this[name].HorBoundAnnotName is string horBoundAnnotName) + if (annot.HorBoundAnnotName is string horBoundAnnotName) if (TryGet(horBoundAnnotName, out var horBoundAnnot)) - this[name].HorBoundAnnot = horBoundAnnot; + annot.HorBoundAnnot = horBoundAnnot; else throw new InvalidOperationException($"{horBoundAnnotName} added as bound anotation. However, it is not defined."); // vertical - if (this[name].VerBoundAnnotName is string verBoundAnnotName) + if (annot.VerBoundAnnotName is string verBoundAnnotName) if (TryGet(verBoundAnnotName, out var verBoundAnnot)) - this[name].VerBoundAnnot = verBoundAnnot; + annot.VerBoundAnnot = verBoundAnnot; else throw new InvalidOperationException($"{verBoundAnnotName} added as bound anotation. However, it is not defined."); #endregion From eb024acfa7eebd0814625e98af710fcef60c7ee7 Mon Sep 17 00:00:00 2001 From: Developer 02 Date: Thu, 20 Mar 2025 17:16:42 +0100 Subject: [PATCH 16/32] =?UTF-8?q?featAnnotation):=20Hinzuf=C3=BCgen=20von?= =?UTF-8?q?=20Verh=C3=A4ltnisanteilen,=20um=20die=20Konfiguration=20=C3=BC?= =?UTF-8?q?ber=20das=20Verh=C3=A4ltnis=20zu=20erm=C3=B6glichen?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- EnvelopeGenerator.Web/Models/Annotation.cs | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/EnvelopeGenerator.Web/Models/Annotation.cs b/EnvelopeGenerator.Web/Models/Annotation.cs index 448365ed..fd54b68f 100644 --- a/EnvelopeGenerator.Web/Models/Annotation.cs +++ b/EnvelopeGenerator.Web/Models/Annotation.cs @@ -30,6 +30,9 @@ public record Annotation init => _marginLeft = value; } + [JsonIgnore] + public double MarginLeftRatio { get; init; } = 1; + [JsonIgnore] public double MarginTop { @@ -37,17 +40,26 @@ public record Annotation init => _marginTop = value; } + [JsonIgnore] + public double MarginTopRatio { get; init; } = 1; + public double Width { get => _width; init => _width = value; } + [JsonIgnore] + public double WidthRatio { get; init; } = 1; + public double Height { get => _height; init => _height = value; } + + [JsonIgnore] + public double HeightRatio { get; init; } = 1; #endregion #region Position @@ -79,16 +91,16 @@ public record Annotation { // To set default value, annotation must have default (0) value but default must has non-default value if (_marginLeft == default && value.MarginLeft != default) - _marginLeft = value.MarginLeft; + _marginLeft = value.MarginLeft * MarginLeftRatio; if (_marginTop == default && value.MarginTop != default) - _marginTop = value.MarginTop; + _marginTop = value.MarginTop * MarginTopRatio; if (_width == default && value.Width != default) - _width = value.Width; + _width = value.Width * WidthRatio; if (_height == default && value.Height != default) - _height = value.Height; + _height = value.Height * HeightRatio; } } }; \ No newline at end of file From 80e1e7dcf306d241d4c7f618d14fa1f97fcc4417 Mon Sep 17 00:00:00 2001 From: Developer 02 Date: Fri, 21 Mar 2025 12:01:42 +0100 Subject: [PATCH 17/32] =?UTF-8?q?feat(ClientCoefficient):=20Erstellt,=20um?= =?UTF-8?q?=20die=20Dimensionen=20f=C3=BCr=20den=20Kunden=20bis=20zu=20ein?= =?UTF-8?q?em=20gewissen=20Grad=20zu=20erh=C3=B6hen?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- EnvelopeGenerator.Web/Models/Annotation.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/EnvelopeGenerator.Web/Models/Annotation.cs b/EnvelopeGenerator.Web/Models/Annotation.cs index fd54b68f..fef3cb10 100644 --- a/EnvelopeGenerator.Web/Models/Annotation.cs +++ b/EnvelopeGenerator.Web/Models/Annotation.cs @@ -101,6 +101,11 @@ public record Annotation if (_height == default && value.Height != default) _height = value.Height * HeightRatio; + + ClientCoefficient = value.ClientCoefficient; } } + + [JsonIgnore] + public double ClientCoefficient { get; set; } = 1; }; \ No newline at end of file From 91f1296e9b3ef7a9b956c039809f7c6f33b4e5a7 Mon Sep 17 00:00:00 2001 From: Developer 02 Date: Fri, 21 Mar 2025 12:29:39 +0100 Subject: [PATCH 18/32] =?UTF-8?q?Revert=20"feat(ClientCoefficient):=20Erst?= =?UTF-8?q?ellt,=20um=20die=20Dimensionen=20f=C3=BCr=20den=20Kunden=20bis?= =?UTF-8?q?=20zu=20einem=20gewissen=20Grad=20zu=20erh=C3=B6hen"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 80e1e7dcf306d241d4c7f618d14fa1f97fcc4417. --- EnvelopeGenerator.Web/Models/Annotation.cs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/EnvelopeGenerator.Web/Models/Annotation.cs b/EnvelopeGenerator.Web/Models/Annotation.cs index fef3cb10..fd54b68f 100644 --- a/EnvelopeGenerator.Web/Models/Annotation.cs +++ b/EnvelopeGenerator.Web/Models/Annotation.cs @@ -101,11 +101,6 @@ public record Annotation if (_height == default && value.Height != default) _height = value.Height * HeightRatio; - - ClientCoefficient = value.ClientCoefficient; } } - - [JsonIgnore] - public double ClientCoefficient { get; set; } = 1; }; \ No newline at end of file From 2d7c0a292bf924d59e45c50f5066c19f434e803e Mon Sep 17 00:00:00 2001 From: Developer 02 Date: Fri, 21 Mar 2025 13:11:54 +0100 Subject: [PATCH 19/32] feat(appsettings): Konfigurierte AnnotationParams --- EnvelopeGenerator.Web/appsettings.json | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/EnvelopeGenerator.Web/appsettings.json b/EnvelopeGenerator.Web/appsettings.json index 3574a25b..d62f2cc0 100644 --- a/EnvelopeGenerator.Web/appsettings.json +++ b/EnvelopeGenerator.Web/appsettings.json @@ -161,11 +161,17 @@ }, { "Name": "City", - "VerBoundAnnotName": "Signature" + "VerBoundAnnotName": "Signature", + "WidthRatio": 1.2, + "HeightRatio": 0.5, + "MarginTopRatio": 0.48 }, { "Name": "Date", - "VerBoundAnnotName": "City" + "VerBoundAnnotName": "City", + "WidthRatio": 1.55, + "HeightRatio": 0.5, + "MarginTopRatio": 0.45 } ] } From a7b980bd2896c328db44dcdda579372fac7290ec Mon Sep 17 00:00:00 2001 From: Developer 02 Date: Fri, 21 Mar 2025 14:13:49 +0100 Subject: [PATCH 20/32] refactor(Annotation): Aktualisiert, um null anstelle von Standard zu verwenden --- EnvelopeGenerator.Web/Models/Annotation.cs | 58 +++++++--------------- EnvelopeGenerator.Web/appsettings.json | 6 ++- 2 files changed, 21 insertions(+), 43 deletions(-) diff --git a/EnvelopeGenerator.Web/Models/Annotation.cs b/EnvelopeGenerator.Web/Models/Annotation.cs index fd54b68f..6db0265a 100644 --- a/EnvelopeGenerator.Web/Models/Annotation.cs +++ b/EnvelopeGenerator.Web/Models/Annotation.cs @@ -15,65 +15,41 @@ public record Annotation #endregion #region Layout - internal double _marginLeft = default; - - internal double _marginTop = default; - - internal double _width = default; - - internal double _height = default; - [JsonIgnore] - public double MarginLeft - { - get => _marginLeft; - init => _marginLeft = value; - } + public double? MarginLeft { get; set; } [JsonIgnore] public double MarginLeftRatio { get; init; } = 1; [JsonIgnore] - public double MarginTop - { - get => _marginTop; - init => _marginTop = value; - } + public double? MarginTop { get; set; } [JsonIgnore] public double MarginTopRatio { get; init; } = 1; - public double Width - { - get => _width; - init => _width = value; - } + public double? Width { get; set; } [JsonIgnore] public double WidthRatio { get; init; } = 1; - public double Height - { - get => _height; - init => _height = value; - } + public double? Height { get; set; } [JsonIgnore] public double HeightRatio { get; init; } = 1; #endregion #region Position - public double Left => MarginLeft + (HorBoundAnnot?.HorBoundary ?? 0); + public double Left => (MarginLeft ?? 0) + (HorBoundAnnot?.HorBoundary ?? 0); - public double Top => MarginTop + (VerBoundAnnot?.VerBoundary ?? 0); + public double Top => (MarginTop ?? 0) + (VerBoundAnnot?.VerBoundary ?? 0); #endregion #region Boundary [JsonIgnore] - public double HorBoundary => Left + Width; + public double HorBoundary => Left + (Width ?? 0); [JsonIgnore] - public double VerBoundary => Top + Height; + public double VerBoundary => Top + (Height ?? 0); #endregion #region BoundAnnot @@ -89,18 +65,18 @@ public record Annotation { set { - // To set default value, annotation must have default (0) value but default must has non-default value - if (_marginLeft == default && value.MarginLeft != default) - _marginLeft = value.MarginLeft * MarginLeftRatio; + // 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 == default && value.MarginTop != default) - _marginTop = value.MarginTop * MarginTopRatio; + if (MarginTop == null && value.MarginTop != null) + MarginTop = value.MarginTop * MarginTopRatio; - if (_width == default && value.Width != default) - _width = value.Width * WidthRatio; + if (Width == null && value.Width != null) + Width = value.Width * WidthRatio; - if (_height == default && value.Height != default) - _height = value.Height * HeightRatio; + if (Height == null && value.Height != null) + Height = value.Height * HeightRatio; } } }; \ No newline at end of file diff --git a/EnvelopeGenerator.Web/appsettings.json b/EnvelopeGenerator.Web/appsettings.json index d62f2cc0..c9db9ee2 100644 --- a/EnvelopeGenerator.Web/appsettings.json +++ b/EnvelopeGenerator.Web/appsettings.json @@ -153,11 +153,13 @@ "AnnotationParams": { "DefaultAnnotation": { "Width": 1, - "Height": 0.5 + "Height": 0.5, + "MarginTop": 1 }, "Annotations": [ { - "Name": "Signature" + "Name": "Signature", + "MarginTop": 0 }, { "Name": "City", From 2dfe508552a906cccf1594820a00f2cc888ce1a6 Mon Sep 17 00:00:00 2001 From: Developer 02 Date: Fri, 21 Mar 2025 15:39:24 +0100 Subject: [PATCH 21/32] =?UTF-8?q?feat(network.js):=20Methode=20zum=20Abruf?= =?UTF-8?q?en=20von=20Anmerkungsparametern=20hinzugef=C3=BCgt?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- EnvelopeGenerator.Web/wwwroot/js/network.js | 14 +++++++++----- EnvelopeGenerator.Web/wwwroot/js/network.min.js | 2 +- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/EnvelopeGenerator.Web/wwwroot/js/network.js b/EnvelopeGenerator.Web/wwwroot/js/network.js index ab10e929..913196c2 100644 --- a/EnvelopeGenerator.Web/wwwroot/js/network.js +++ b/EnvelopeGenerator.Web/wwwroot/js/network.js @@ -69,7 +69,7 @@ * Creates a GET HTTP request to `url` * @param {any} url */ - getRequest(url, body) { + getRequest(url) { const token = this.getCSRFToken() const options = { credentials: 'include', @@ -79,10 +79,6 @@ } } - if (body !== undefined) { - options.body = JSON.stringify(body); - } - return fetch(url, options) } @@ -206,4 +202,12 @@ async function logout() { if (res.ok) window.location.href = "/"; }); +} + +async function getAnnotationParams() { + return fetch(`${window.location.origin}/api/Config/Annotations`, { + credentials: 'include', + method: 'GET' + }) + .then(res => res.json()); } \ No newline at end of file diff --git a/EnvelopeGenerator.Web/wwwroot/js/network.min.js b/EnvelopeGenerator.Web/wwwroot/js/network.min.js index 6666c294..2e9b60fc 100644 --- a/EnvelopeGenerator.Web/wwwroot/js/network.min.js +++ b/EnvelopeGenerator.Web/wwwroot/js/network.min.js @@ -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}} \ No newline at end of file +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="/")})}async function getAnnotationParams(){return fetch(`${window.location.origin}/api/Config/Annotations`,{credentials:"include",method:"GET"}).then(n=>n.json())}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}} \ No newline at end of file From eef6bf27f15a4841460b1bce0fa8641f4cd4472d Mon Sep 17 00:00:00 2001 From: Developer 02 Date: Fri, 21 Mar 2025 16:14:31 +0100 Subject: [PATCH 22/32] =?UTF-8?q?feat(ConfigController):=20GetAnnotationPa?= =?UTF-8?q?rams=20aktualisiert,=20um=20W=C3=B6rterbuch=20zu=20senden?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- EnvelopeGenerator.Web/Controllers/ConfigController.cs | 5 +++-- EnvelopeGenerator.Web/wwwroot/js/network.js | 2 +- EnvelopeGenerator.Web/wwwroot/js/network.min.js | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/EnvelopeGenerator.Web/Controllers/ConfigController.cs b/EnvelopeGenerator.Web/Controllers/ConfigController.cs index 2c3330fd..3f322a85 100644 --- a/EnvelopeGenerator.Web/Controllers/ConfigController.cs +++ b/EnvelopeGenerator.Web/Controllers/ConfigController.cs @@ -1,4 +1,5 @@ -using EnvelopeGenerator.Web.Models; +using AngleSharp.Common; +using EnvelopeGenerator.Web.Models; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Options; @@ -18,6 +19,6 @@ public class ConfigController : ControllerBase [HttpGet("Annotations")] public IActionResult GetAnnotationParams() { - return Ok(_annotParams); + return Ok(_annotParams.Annotations.ToDictionary(a => a.Name.ToLower(), a => a)); } } diff --git a/EnvelopeGenerator.Web/wwwroot/js/network.js b/EnvelopeGenerator.Web/wwwroot/js/network.js index 913196c2..1b97a488 100644 --- a/EnvelopeGenerator.Web/wwwroot/js/network.js +++ b/EnvelopeGenerator.Web/wwwroot/js/network.js @@ -204,7 +204,7 @@ async function logout() { }); } -async function getAnnotationParams() { +function getAnnotationParams() { return fetch(`${window.location.origin}/api/Config/Annotations`, { credentials: 'include', method: 'GET' diff --git a/EnvelopeGenerator.Web/wwwroot/js/network.min.js b/EnvelopeGenerator.Web/wwwroot/js/network.min.js index 2e9b60fc..02721bc2 100644 --- a/EnvelopeGenerator.Web/wwwroot/js/network.min.js +++ b/EnvelopeGenerator.Web/wwwroot/js/network.min.js @@ -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="/")})}async function getAnnotationParams(){return fetch(`${window.location.origin}/api/Config/Annotations`,{credentials:"include",method:"GET"}).then(n=>n.json())}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}} \ No newline at end of file +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(){return fetch(`${window.location.origin}/api/Config/Annotations`,{credentials:"include",method:"GET"}).then(n=>n.json())}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}} \ No newline at end of file From 9ae1efb94692c4049d14e96f51c511e3e4f10a88 Mon Sep 17 00:00:00 2001 From: Developer 02 Date: Mon, 24 Mar 2025 10:24:35 +0100 Subject: [PATCH 23/32] =?UTF-8?q?refactor(network):=20Die=20Methode=20getA?= =?UTF-8?q?nnotationParams=20wurde=20aktualisiert,=20um=20die=20Anmerkung?= =?UTF-8?q?=20=C3=BCbersetzen=20und=20das=20Verh=C3=A4ltnis=20ihrer=20Gr?= =?UTF-8?q?=C3=B6=C3=9Fe=20=C3=A4ndern=20zu=20k=C3=B6nnen.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- EnvelopeGenerator.Web/wwwroot/js/annotation.js | 16 ++++++---------- EnvelopeGenerator.Web/wwwroot/js/network.js | 14 ++++++++++++-- EnvelopeGenerator.Web/wwwroot/js/network.min.js | 2 +- 3 files changed, 19 insertions(+), 13 deletions(-) diff --git a/EnvelopeGenerator.Web/wwwroot/js/annotation.js b/EnvelopeGenerator.Web/wwwroot/js/annotation.js index 95e04969..26108087 100644 --- a/EnvelopeGenerator.Web/wwwroot/js/annotation.js +++ b/EnvelopeGenerator.Web/wwwroot/js/annotation.js @@ -22,11 +22,12 @@ } static async createSignature(element) { + const annotParams = await getAnnotationParams(element.left, element.top); 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 width = annotParams.signature.width; + const height = annotParams.signature.height; + const top = annotParams.signature.top; + const left = annotParams.signature.left; const page = element.page - 1 //signatures @@ -36,12 +37,7 @@ formFieldName: id, backgroundColor: PSPDFKit.Color.YELLOW, blendMode: 'multiply', - boundingBox: new PSPDFKit.Geometry.Rect({ - width, - height, - top, - left, - }), + boundingBox: new PSPDFKit.Geometry.Rect(annotParams.signature), }) const formField = new PSPDFKit.FormFields.SignatureFormField({ diff --git a/EnvelopeGenerator.Web/wwwroot/js/network.js b/EnvelopeGenerator.Web/wwwroot/js/network.js index 1b97a488..1238afa7 100644 --- a/EnvelopeGenerator.Web/wwwroot/js/network.js +++ b/EnvelopeGenerator.Web/wwwroot/js/network.js @@ -204,10 +204,20 @@ async function logout() { }); } -function getAnnotationParams() { +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(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.width / 2; + annot.top = (topInInch + annot.top) * inchToPointFactor - annot.height / 2; + } + return annotParams; + }); } \ No newline at end of file diff --git a/EnvelopeGenerator.Web/wwwroot/js/network.min.js b/EnvelopeGenerator.Web/wwwroot/js/network.min.js index 02721bc2..874bcee0 100644 --- a/EnvelopeGenerator.Web/wwwroot/js/network.min.js +++ b/EnvelopeGenerator.Web/wwwroot/js/network.min.js @@ -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="/")})}function getAnnotationParams(){return fetch(`${window.location.origin}/api/Config/Annotations`,{credentials:"include",method:"GET"}).then(n=>n.json())}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}} \ No newline at end of file +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.width/2,u.top=(t+u.top)*i-u.height/2;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}} \ No newline at end of file From e9cb49c6a7b4cbb30faa7deacd7214294e337b94 Mon Sep 17 00:00:00 2001 From: Developer 02 Date: Mon, 24 Mar 2025 12:48:28 +0100 Subject: [PATCH 24/32] feat(annotation.js): Konfigurierte Beschriftungen --- .../Controllers/ConfigController.cs | 4 +-- EnvelopeGenerator.Web/appsettings.json | 22 ++++++++++++--- .../wwwroot/js/annotation.js | 28 +++---------------- EnvelopeGenerator.Web/wwwroot/js/network.js | 6 ++-- .../wwwroot/js/network.min.js | 2 +- 5 files changed, 29 insertions(+), 33 deletions(-) diff --git a/EnvelopeGenerator.Web/Controllers/ConfigController.cs b/EnvelopeGenerator.Web/Controllers/ConfigController.cs index 3f322a85..b381b15d 100644 --- a/EnvelopeGenerator.Web/Controllers/ConfigController.cs +++ b/EnvelopeGenerator.Web/Controllers/ConfigController.cs @@ -11,9 +11,9 @@ public class ConfigController : ControllerBase { private readonly AnnotationParams _annotParams; - public ConfigController(IOptions annotationParamsOptions) + public ConfigController(IOptionsMonitor annotationParamsOptions) { - _annotParams = annotationParamsOptions.Value; + _annotParams = annotationParamsOptions.CurrentValue; } [HttpGet("Annotations")] diff --git a/EnvelopeGenerator.Web/appsettings.json b/EnvelopeGenerator.Web/appsettings.json index c9db9ee2..8b74e5b9 100644 --- a/EnvelopeGenerator.Web/appsettings.json +++ b/EnvelopeGenerator.Web/appsettings.json @@ -162,18 +162,32 @@ "MarginTop": 0 }, { - "Name": "City", + "Name": "CityLabel", "VerBoundAnnotName": "Signature", "WidthRatio": 1.2, "HeightRatio": 0.5, - "MarginTopRatio": 0.48 + "MarginTopRatio": 0.25 }, { - "Name": "Date", + "Name": "City", + "VerBoundAnnotName": "CityLabel", + "WidthRatio": 1.2, + "HeightRatio": 0.5, + "MarginTopRatio": 0 + }, + { + "Name": "DateLabel", "VerBoundAnnotName": "City", "WidthRatio": 1.55, "HeightRatio": 0.5, - "MarginTopRatio": 0.45 + "MarginTopRatio": 0.10 + }, + { + "Name": "Date", + "VerBoundAnnotName": "DateLabel", + "WidthRatio": 1.55, + "HeightRatio": 0.5, + "MarginTopRatio": 0 } ] } diff --git a/EnvelopeGenerator.Web/wwwroot/js/annotation.js b/EnvelopeGenerator.Web/wwwroot/js/annotation.js index 26108087..b809eda5 100644 --- a/EnvelopeGenerator.Web/wwwroot/js/annotation.js +++ b/EnvelopeGenerator.Web/wwwroot/js/annotation.js @@ -58,12 +58,7 @@ formFieldName: id_city, backgroundColor: PSPDFKit.Color.DarkBlue, blendMode: 'multiply', - boundingBox: new PSPDFKit.Geometry.Rect({ - width: width * 1.2, - height: height / 2, - top: top + height + date_place_top_shift + 25, - left: left, - }), + boundingBox: new PSPDFKit.Geometry.Rect(annotParams.city), fontSize: 8 }) @@ -82,12 +77,7 @@ formFieldName: id_date, backgroundColor: PSPDFKit.Color.DarkBlue, blendMode: 'multiply', - boundingBox: new PSPDFKit.Geometry.Rect({ - width: width * 1.55, - height: height / 2, - top: top + 2 * height + date_place_top_shift + 23, - left: left - }), + boundingBox: new PSPDFKit.Geometry.Rect(annotParams.date), fontSize: 8, backgroundColor: PSPDFKit.Color.TRANSPARENT, fontColor: PSPDFKit.Color.Black, @@ -118,12 +108,7 @@ pageIndex: page, formFieldName: id_date_label, blendMode: 'multiply', - boundingBox: new PSPDFKit.Geometry.Rect({ - width: width * 0.75, - height: height / 2, - top: top + height + 23 + label_top_shift + date_place_top_shift + (height) + 4, - left: left - }), + boundingBox: new PSPDFKit.Geometry.Rect(annotParams.datelabel), fontSize: 8, backgroundColor: PSPDFKit.Color.TRANSPARENT, fontColor: PSPDFKit.Color.Black, @@ -145,12 +130,7 @@ pageIndex: page, formFieldName: id_city_label, blendMode: 'multiply', - boundingBox: new PSPDFKit.Geometry.Rect({ - width: width * 1.2, - height: height / 2, - top: top + height + 25 + label_top_shift + date_place_top_shift, - left: left - }), + boundingBox: new PSPDFKit.Geometry.Rect(annotParams.citylabel), fontSize: 8, backgroundColor: PSPDFKit.Color.TRANSPARENT, fontColor: PSPDFKit.Color.Black, diff --git a/EnvelopeGenerator.Web/wwwroot/js/network.js b/EnvelopeGenerator.Web/wwwroot/js/network.js index 1238afa7..3f8ad38e 100644 --- a/EnvelopeGenerator.Web/wwwroot/js/network.js +++ b/EnvelopeGenerator.Web/wwwroot/js/network.js @@ -215,8 +215,10 @@ function getAnnotationParams(leftInInch = 0, topInInch = 0, inchToPointFactor = var annot = annotParams[key]; annot.width *= inchToPointFactor; annot.height *= inchToPointFactor; - annot.left = (leftInInch + annot.left) * inchToPointFactor - annot.width / 2; - annot.top = (topInInch + annot.top) * inchToPointFactor - annot.height / 2; + annot.left += leftInInch; + annot.left *= inchToPointFactor; + annot.top += topInInch; + annot.top *= inchToPointFactor; } return annotParams; }); diff --git a/EnvelopeGenerator.Web/wwwroot/js/network.min.js b/EnvelopeGenerator.Web/wwwroot/js/network.min.js index 874bcee0..f3dc9e20 100644 --- a/EnvelopeGenerator.Web/wwwroot/js/network.min.js +++ b/EnvelopeGenerator.Web/wwwroot/js/network.min.js @@ -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="/")})}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.width/2,u.top=(t+u.top)*i-u.height/2;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}} \ No newline at end of file +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}} \ No newline at end of file From 0f855158c3a5ed7223c7910a6a39ea4f694abac6 Mon Sep 17 00:00:00 2001 From: Developer 02 Date: Mon, 24 Mar 2025 13:19:59 +0100 Subject: [PATCH 25/32] =?UTF-8?q?fix(annotation.js):=20Unn=C3=B6tige=20Var?= =?UTF-8?q?iablen=20entfernen.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- EnvelopeGenerator.Web/wwwroot/js/annotation.js | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/EnvelopeGenerator.Web/wwwroot/js/annotation.js b/EnvelopeGenerator.Web/wwwroot/js/annotation.js index b809eda5..1cf0010a 100644 --- a/EnvelopeGenerator.Web/wwwroot/js/annotation.js +++ b/EnvelopeGenerator.Web/wwwroot/js/annotation.js @@ -23,14 +23,10 @@ static async createSignature(element) { const annotParams = await getAnnotationParams(element.left, element.top); - const id = PSPDFKit.generateInstantId() - const width = annotParams.signature.width; - const height = annotParams.signature.height; - const top = annotParams.signature.top; - const left = annotParams.signature.left; const page = element.page - 1 //signatures + const id = PSPDFKit.generateInstantId() const annotation = new PSPDFKit.Annotations.WidgetAnnotation({ id: id, pageIndex: page, From c45e6875d0323e841a6090017132d85d7c6d8cd6 Mon Sep 17 00:00:00 2001 From: Developer 02 Date: Tue, 25 Mar 2025 17:13:51 +0100 Subject: [PATCH 26/32] =?UTF-8?q?feat(postion):=20Hinzuf=C3=BCgen=20und=20?= =?UTF-8?q?Konfigurieren=20von=20Positions-=20und=20Positionsbeschriftungs?= =?UTF-8?q?annotationen.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- EnvelopeGenerator.Web/appsettings.json | 16 +++++- .../wwwroot/js/annotation.js | 53 ++++++++++++++++--- 2 files changed, 61 insertions(+), 8 deletions(-) diff --git a/EnvelopeGenerator.Web/appsettings.json b/EnvelopeGenerator.Web/appsettings.json index 8b74e5b9..97b99aac 100644 --- a/EnvelopeGenerator.Web/appsettings.json +++ b/EnvelopeGenerator.Web/appsettings.json @@ -162,12 +162,26 @@ "MarginTop": 0 }, { - "Name": "CityLabel", + "Name": "PositionLabel", "VerBoundAnnotName": "Signature", "WidthRatio": 1.2, "HeightRatio": 0.5, "MarginTopRatio": 0.25 }, + { + "Name": "Position", + "VerBoundAnnotName": "PositionLabel", + "WidthRatio": 1.2, + "HeightRatio": 0.5, + "MarginTopRatio": 0 + }, + { + "Name": "CityLabel", + "VerBoundAnnotName": "Position", + "WidthRatio": 1.2, + "HeightRatio": 0.5, + "MarginTopRatio": 0.10 + }, { "Name": "City", "VerBoundAnnotName": "CityLabel", diff --git a/EnvelopeGenerator.Web/wwwroot/js/annotation.js b/EnvelopeGenerator.Web/wwwroot/js/annotation.js index 1cf0010a..793c00f6 100644 --- a/EnvelopeGenerator.Web/wwwroot/js/annotation.js +++ b/EnvelopeGenerator.Web/wwwroot/js/annotation.js @@ -3,19 +3,24 @@ const signatures = [] 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 [annotation, formField, annotation_date, formFieldDate, annotation_city, formFieldCity, annotation_position, formFieldPosition, annotation_date_label, formFieldDateLabel, annotation_city_label, formFieldCityLabel, annotation_position_label, formFieldPositionLabel] = await Annotation.createSignature(element) 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) } await instance.create(signatures) @@ -41,10 +46,24 @@ annotationIds: PSPDFKit.Immutable.List([annotation.id]), }) - /** - * Date, post code and place text form part - */ - const date_place_top_shift = 9.5; + //position + const id_position = PSPDFKit.generateInstantId() + const annotation_position = new PSPDFKit.Annotations.WidgetAnnotation({ + 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() @@ -95,7 +114,6 @@ /** * Date, post code and place label part */ - const label_top_shift = -15 //date label const id_date_label = PSPDFKit.generateInstantId() @@ -140,7 +158,28 @@ 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({ + id: id_position_label, + pageIndex: page, + formFieldName: id_position_label, + blendMode: 'multiply', + boundingBox: new PSPDFKit.Geometry.Rect(annotParams.positionlabel), + fontSize: 8, + backgroundColor: PSPDFKit.Color.TRANSPARENT, + fontColor: PSPDFKit.Color.Black, + isBold: true, + }) + + const formFieldPositionLabel = new PSPDFKit.FormFields.TextFormField({ + name: id_position_label, + annotationIds: PSPDFKit.Immutable.List([annotation_position_label.id]), + value: "Position", + readOnly: true + }) + + return [annotation, formField, annotation_date, formFieldDate, annotation_city, formFieldCity, annotation_position, formFieldPosition, annotation_date_label, formFieldDateLabel, annotation_city_label, formFieldCityLabel, annotation_position_label, formFieldPositionLabel] } static createTextBox(element) { From fb0022bd2c7591ac3128b3ed5863f3439ba1c181 Mon Sep 17 00:00:00 2001 From: Developer 02 Date: Wed, 26 Mar 2025 10:15:05 +0100 Subject: [PATCH 27/32] fix(annotation): Die klassenbasierte Struktur wurde entfernt und die Methode createSignature in die Methode createAnnotations integriert. --- .../wwwroot/js/annotation.js | 307 ++++++++---------- EnvelopeGenerator.Web/wwwroot/js/app.js | 14 +- EnvelopeGenerator.Web/wwwroot/js/app.min.js | 4 +- 3 files changed, 141 insertions(+), 184 deletions(-) diff --git a/EnvelopeGenerator.Web/wwwroot/js/annotation.js b/EnvelopeGenerator.Web/wwwroot/js/annotation.js index 793c00f6..628583d9 100644 --- a/EnvelopeGenerator.Web/wwwroot/js/annotation.js +++ b/EnvelopeGenerator.Web/wwwroot/js/annotation.js @@ -1,32 +1,8 @@ -class Annotation { - static async createAnnotations(document, instance) { - const signatures = [] - - for (var element of document.elements) { - const [annotation, formField, annotation_date, formFieldDate, annotation_city, formFieldCity, annotation_position, formFieldPosition, annotation_date_label, formFieldDateLabel, annotation_city_label, formFieldCityLabel, annotation_position_label, formFieldPositionLabel] = await Annotation.createSignature(element) - 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) - } - - await instance.create(signatures) - } + +async function createAnnotations(document, instance) { + const signatures = []; - static async createSignature(element) { + for(var element of document.elements) { const annotParams = await getAnnotationParams(element.left, element.top); const page = element.page - 1 @@ -179,167 +155,148 @@ readOnly: true }) - return [annotation, formField, annotation_date, formFieldDate, annotation_city, formFieldCity, annotation_position, formFieldPosition, annotation_date_label, formFieldDateLabel, annotation_city_label, formFieldCityLabel, annotation_position_label, formFieldPositionLabel] - } - - static createTextBox(element) { - const id = PSPDFKit.generateInstantId() - const width = Annotation.inchToPoint(element.width) - const height = Annotation.inchToPoint(element.height) - const top = Annotation.inchToPoint(element.top) - height / 2 - const left = Annotation.inchToPoint(element.left) - width / 2 - const page = element.page - 1 - - //shift - top += height + 10 + 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) - const annotation = new PSPDFKit.Annotations.WidgetAnnotation({ - id: id, - pageIndex: page, - formFieldName: id, - backgroundColor: PSPDFKit.Color.YELLOW, - blendMode: 'multiply', - boundingBox: new PSPDFKit.Geometry.Rect({ - width, - height, - top, - left, - }), - }) + signatures.push(annotation_date_label) + signatures.push(formFieldDateLabel) - const formField = new PSPDFKit.FormFields.SignatureFormField({ - name: id, - annotationIds: PSPDFKit.Immutable.List([annotation.id]), - }) + signatures.push(annotation_city_label) + signatures.push(formFieldCityLabel) - return [annotation, formField] + signatures.push(annotation_position_label) + signatures.push(formFieldPositionLabel) } - static async getAnnotations(instance) { - const array = await Promise.all( - Array.from({ length: instance.totalPageCount }).map((_, pageIndex) => - instance.getAnnotations(pageIndex) - ) - ) + await instance.create(signatures); +} - return array.flatMap((annotations) => - annotations.reduce((acc, annotation) => acc.concat(annotation), []) +async function getAnnotations(instance) { + const array = await Promise.all( + Array.from({ length: instance.totalPageCount }).map((_, pageIndex) => + instance.getAnnotations(pageIndex) ) - } - - static async deleteAnnotations(instance) { - const allAnnotations = await Annotation.getAnnotations(instance) - const pageAnnotations = allAnnotations.filter(Annotation.isSignature) - //deleting all Annotations - return await instance.delete(pageAnnotations) - } - - static async validateAnnotations(instance) { - const allAnnotations = await Annotation.getAnnotations(instance) - const pageAnnotations = allAnnotations - .map((annotation) => { - return annotation - }) - - return true - } - - static isSignature(annotation) { - return !!annotation.isSignature || annotation.description == 'FRAME' - } - - static createImageAnnotation(boundingBox, pageIndex, imageAttachmentId) { - const frameAnnotation = new PSPDFKit.Annotations.ImageAnnotation({ - pageIndex: pageIndex, - isSignature: false, - readOnly: true, - locked: true, - lockedContents: true, - contentType: 'image/png', - imageAttachmentId, - description: 'FRAME', - boundingBox: boundingBox, + ) + + return array.flatMap((annotations) => + annotations.reduce((acc, annotation) => acc.concat(annotation), []) + ) +} + +async function deleteAnnotations(instance) { + const allAnnotations = await getAnnotations(instance) + const pageAnnotations = allAnnotations.filter(isSignature) + //deleting all Annotations + return await instance.delete(pageAnnotations) +} + +async function validateAnnotations(instance) { + const allAnnotations = await getAnnotations(instance) + const pageAnnotations = allAnnotations + .map((annotation) => { + return annotation }) - return frameAnnotation - } - - static async createAnnotationFrameBlob(receiverName, receiverSignature, timestamp, width, height) { - Comp.SignatureProgress.SignedCount += 1; - const canvas = document.createElement('canvas') - const scale = 4 - const fontSize = 10 - - canvas.width = width * scale - canvas.height = height * scale - - const ctx = canvas.getContext('2d') - // This supposedly makes the lines and text less blurry - // See: https://stackoverflow.com/questions/8696631/canvas-drawings-like-lines-are-blurry - ctx.translate(0.5, 0.5) - - // This also should make the lines and text less blurry - ctx.textRendering = "geometricPrecision" - - const date = timestamp - const dateString = date.toLocaleString('de-DE') - - const signatureLength = 100 * scale - const signatureString = receiverSignature.substring(0, 15) + "…" - - ctx.beginPath() - - ctx.moveTo(30 * scale, 10 * scale) - ctx.lineTo(signatureLength, 10 * scale) - ctx.moveTo(30 * scale, 10 * scale) - ctx.arcTo(10 * scale, 10 * scale, 10 * scale, 30 * scale, 20 * scale) - - ctx.moveTo(10 * scale, 30 * scale) - ctx.arcTo(10 * scale, 50 * scale, 30 * scale, 50 * scale, 20 * scale) - - ctx.moveTo(30 * scale, 50 * scale) - ctx.lineTo(signatureLength, 50 * scale) - - ctx.strokeStyle = 'darkblue' - ctx.stroke() - - ctx.fillStyle = 'black' - ctx.font = `${fontSize * scale}px sans-serif` - ctx.fillText('Signed by', 15 * scale, 10 * scale) - ctx.fillText(receiverName, 15 * scale, 60 * scale) - ctx.fillText(signatureString, 15 * scale, 70 * scale) - - return new Promise((resolve) => { - canvas.toBlob((blob) => { - const url = URL.createObjectURL(blob) - resolve(url) - }) + return true +} + +function isSignature(annotation) { + return !!annotation.isSignature || annotation.description == 'FRAME' +} + +function createImageAnnotation(boundingBox, pageIndex, imageAttachmentId) { + const frameAnnotation = new PSPDFKit.Annotations.ImageAnnotation({ + pageIndex: pageIndex, + isSignature: false, + readOnly: true, + locked: true, + lockedContents: true, + contentType: 'image/png', + imageAttachmentId, + description: 'FRAME', + boundingBox: boundingBox, + }) + return frameAnnotation +} + +async function createAnnotationFrameBlob(receiverName, receiverSignature, timestamp, width, height) { + Comp.SignatureProgress.SignedCount += 1; + const canvas = document.createElement('canvas') + const scale = 4 + const fontSize = 10 + + canvas.width = width * scale + canvas.height = height * scale + + const ctx = canvas.getContext('2d') + // This supposedly makes the lines and text less blurry + // See: https://stackoverflow.com/questions/8696631/canvas-drawings-like-lines-are-blurry + ctx.translate(0.5, 0.5) + + // This also should make the lines and text less blurry + ctx.textRendering = "geometricPrecision" + + const date = timestamp + const dateString = date.toLocaleString('de-DE') + + const signatureLength = 100 * scale + const signatureString = receiverSignature.substring(0, 15) + "…" + + ctx.beginPath() + + ctx.moveTo(30 * scale, 10 * scale) + ctx.lineTo(signatureLength, 10 * scale) + + ctx.moveTo(30 * scale, 10 * scale) + ctx.arcTo(10 * scale, 10 * scale, 10 * scale, 30 * scale, 20 * scale) + + ctx.moveTo(10 * scale, 30 * scale) + ctx.arcTo(10 * scale, 50 * scale, 30 * scale, 50 * scale, 20 * scale) + + ctx.moveTo(30 * scale, 50 * scale) + ctx.lineTo(signatureLength, 50 * scale) + + ctx.strokeStyle = 'darkblue' + ctx.stroke() + + ctx.fillStyle = 'black' + ctx.font = `${fontSize * scale}px sans-serif` + ctx.fillText('Signed by', 15 * scale, 10 * scale) + ctx.fillText(receiverName, 15 * scale, 60 * scale) + ctx.fillText(signatureString, 15 * scale, 70 * scale) + + return new Promise((resolve) => { + canvas.toBlob((blob) => { + const url = URL.createObjectURL(blob) + resolve(url) }) - } + }) +} - static inchToPoint(inch) { - return inch * 72 - } - - //required - static #requiredFieldNames = new Array() +//required +requiredFieldNames = new Array() - static markFieldAsRequired(formField) { - this.#requiredFieldNames.push(formField.name) - } +function markFieldAsRequired(formField) { + requiredFieldNames.push(formField.name) +} - static isFieldRequired(formField) { - return this.#requiredFieldNames.includes(formField.name) - } +function isFieldRequired(formField) { + return requiredFieldNames.includes(formField.name) +} - //city - static #cityFieldNames = new Array() +//city +cityFieldNames = new Array() - static markFieldAsCity(formField) { - this.#cityFieldNames.push(formField.name) - } +function markFieldAsCity(formField) { + cityFieldNames.push(formField.name) +} - static isCityField(formField) { - return this.#cityFieldNames.includes(formField.name) - } +function isCityField(formField) { + return cityFieldNames.includes(formField.name) } \ No newline at end of file diff --git a/EnvelopeGenerator.Web/wwwroot/js/app.js b/EnvelopeGenerator.Web/wwwroot/js/app.js index 883f171f..93e21526 100644 --- a/EnvelopeGenerator.Web/wwwroot/js/app.js +++ b/EnvelopeGenerator.Web/wwwroot/js/app.js @@ -70,7 +70,7 @@ class App { // Load annotations into PSPDFKit try { 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) @@ -109,7 +109,7 @@ class App { const height = 75 const timestamp = new Date() - const imageUrl = await Annotation.createAnnotationFrameBlob( + const imageUrl = await createAnnotationFrameBlob( this.envelopeReceiver.name, this.currentReceiver.signature, timestamp, @@ -121,7 +121,7 @@ class App { const blob = await request.blob() const imageAttachmentId = await this.Instance.createAttachment(blob) - const frameAnnotation = Annotation.createImageAnnotation( + const frameAnnotation = createImageAnnotation( new PSPDFKit.Geometry.Rect({ left: left, top: top, @@ -222,7 +222,7 @@ class App { const iFormFieldValues = await iJSON.formFieldValues; //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 === "")) if (hasEmptyReq) { @@ -236,7 +236,7 @@ class App { //check city 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) if (!IS_MOBILE_DEVICE && !city_regex.test(f.value)) { Swal.fire({ @@ -322,7 +322,7 @@ class App { async validateAnnotations(totalSignatures) { - const annotations = await Annotation.getAnnotations(this.Instance) + const annotations = await getAnnotations(this.Instance) const filtered = annotations .map(a => a.toJS()) .filter(a => a.isSignature) @@ -343,7 +343,7 @@ class App { }) if (result.isConfirmed) { - const result = await Annotation.deleteAnnotations(this.Instance) + const result = await deleteAnnotations(this.Instance) } return result diff --git a/EnvelopeGenerator.Web/wwwroot/js/app.min.js b/EnvelopeGenerator.Web/wwwroot/js/app.min.js index ba32108f..b2e22c52 100644 --- a/EnvelopeGenerator.Web/wwwroot/js/app.min.js +++ b/EnvelopeGenerator.Web/wwwroot/js/app.min.js @@ -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:`
${localized.rejectionReasonQ}
`,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:`
${localized.rejectionReasonQ}
`,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} - `)}},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:`
${localized.sigAgree}
`,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}} \ No newline at end of file + `)}},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:`
${localized.sigAgree}
`,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}} \ No newline at end of file From db5a2a86403e1d29734db2e41bfa90bc9bcea14b Mon Sep 17 00:00:00 2001 From: Developer 02 Date: Wed, 26 Mar 2025 10:42:34 +0100 Subject: [PATCH 28/32] =?UTF-8?q?feat(AnnotationParams):=20Hinzuf=C3=BCgen?= =?UTF-8?q?=20der=20Eigenschaft=20AnnotationDictionary,=20um=20Anmerkungen?= =?UTF-8?q?=20in=20Form=20eines=20W=C3=B6rterbuchs=20zu=20speichern.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- EnvelopeGenerator.Web/Controllers/ConfigController.cs | 5 ++--- EnvelopeGenerator.Web/Models/AnnotationParams.cs | 4 ++++ 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/EnvelopeGenerator.Web/Controllers/ConfigController.cs b/EnvelopeGenerator.Web/Controllers/ConfigController.cs index b381b15d..edf4859f 100644 --- a/EnvelopeGenerator.Web/Controllers/ConfigController.cs +++ b/EnvelopeGenerator.Web/Controllers/ConfigController.cs @@ -1,5 +1,4 @@ -using AngleSharp.Common; -using EnvelopeGenerator.Web.Models; +using EnvelopeGenerator.Web.Models; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Options; @@ -19,6 +18,6 @@ public class ConfigController : ControllerBase [HttpGet("Annotations")] public IActionResult GetAnnotationParams() { - return Ok(_annotParams.Annotations.ToDictionary(a => a.Name.ToLower(), a => a)); + return Ok(_annotParams.AnnotationDictionary); } } diff --git a/EnvelopeGenerator.Web/Models/AnnotationParams.cs b/EnvelopeGenerator.Web/Models/AnnotationParams.cs index 70410e17..052968e1 100644 --- a/EnvelopeGenerator.Web/Models/AnnotationParams.cs +++ b/EnvelopeGenerator.Web/Models/AnnotationParams.cs @@ -48,6 +48,10 @@ public class AnnotationParams 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 AnnotationDictionary { get; private init; } = new(); } From 88c2721ba5bc24f4c27f0f7b558ad2321c708c7f Mon Sep 17 00:00:00 2001 From: Developer 02 Date: Wed, 26 Mar 2025 10:55:46 +0100 Subject: [PATCH 29/32] =?UTF-8?q?refactor(appsettings):=20bearbeitete=20Gr?= =?UTF-8?q?=C3=B6=C3=9Fenparameter=20der=20annotations?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- EnvelopeGenerator.Web/appsettings.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/EnvelopeGenerator.Web/appsettings.json b/EnvelopeGenerator.Web/appsettings.json index 97b99aac..136c48a8 100644 --- a/EnvelopeGenerator.Web/appsettings.json +++ b/EnvelopeGenerator.Web/appsettings.json @@ -166,42 +166,42 @@ "VerBoundAnnotName": "Signature", "WidthRatio": 1.2, "HeightRatio": 0.5, - "MarginTopRatio": 0.25 + "MarginTopRatio": 0.22 }, { "Name": "Position", "VerBoundAnnotName": "PositionLabel", "WidthRatio": 1.2, "HeightRatio": 0.5, - "MarginTopRatio": 0 + "MarginTopRatio": -0.05 }, { "Name": "CityLabel", "VerBoundAnnotName": "Position", "WidthRatio": 1.2, "HeightRatio": 0.5, - "MarginTopRatio": 0.10 + "MarginTopRatio": 0.05 }, { "Name": "City", "VerBoundAnnotName": "CityLabel", "WidthRatio": 1.2, "HeightRatio": 0.5, - "MarginTopRatio": 0 + "MarginTopRatio": -0.05 }, { "Name": "DateLabel", "VerBoundAnnotName": "City", "WidthRatio": 1.55, "HeightRatio": 0.5, - "MarginTopRatio": 0.10 + "MarginTopRatio": 0.05 }, { "Name": "Date", "VerBoundAnnotName": "DateLabel", "WidthRatio": 1.55, "HeightRatio": 0.5, - "MarginTopRatio": 0 + "MarginTopRatio": -0.1 } ] } From 6083eea496ebfebeef07907e68cd46093db3b43b Mon Sep 17 00:00:00 2001 From: Developer 02 Date: Wed, 26 Mar 2025 13:55:24 +0100 Subject: [PATCH 30/32] refactor(frmFinalizePDF): Aktualisiert, um die Datei aus der DB zu lesen --- EnvelopeGenerator.Test/frmFinalizePDF.vb | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/EnvelopeGenerator.Test/frmFinalizePDF.vb b/EnvelopeGenerator.Test/frmFinalizePDF.vb index 300f6513..e9240913 100644 --- a/EnvelopeGenerator.Test/frmFinalizePDF.vb +++ b/EnvelopeGenerator.Test/frmFinalizePDF.vb @@ -48,20 +48,33 @@ Public Class frmFinalizePDF 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 Try - Dim oDocumentPath = LoadEnvelopeDocument() - Dim oFileInfo = New FileInfo(oDocumentPath) Dim oTable = LoadAnnotationDataForEnvelope() Dim oJsonList = oTable.Rows. Cast(Of DataRow). Select(Function(r As DataRow) r.Item("VALUE").ToString()). ToList() - Dim oBuffer As Byte() = File.ReadAllBytes(oDocumentPath) + Dim oBuffer As Byte() = ReadEnvelope(CInt(txtEnvelope.Text)) 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) Catch ex As Exception From 88777e0c27b2c87e87fbc12de72a7f9c4e330993 Mon Sep 17 00:00:00 2001 From: Developer 02 Date: Thu, 27 Mar 2025 14:01:33 +0100 Subject: [PATCH 31/32] refactor(Config): Standardliste IgnoredLabels aktualisieren --- .../Jobs/FinalizeDocument/PDFBurner.vb | 3 +++ EnvelopeGenerator.Service/Config.vb | 7 ++++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/EnvelopeGenerator.Common/Jobs/FinalizeDocument/PDFBurner.vb b/EnvelopeGenerator.Common/Jobs/FinalizeDocument/PDFBurner.vb index d1254b60..c7010dc1 100644 --- a/EnvelopeGenerator.Common/Jobs/FinalizeDocument/PDFBurner.vb +++ b/EnvelopeGenerator.Common/Jobs/FinalizeDocument/PDFBurner.vb @@ -34,11 +34,13 @@ Namespace Jobs.FinalizeDocument Try Using oSourceStream As New MemoryStream(pSourceBuffer) + ' Open PDF oResult = Manager.InitFromStream(oSourceStream) If oResult <> GdPictureStatus.OK Then Throw New BurnAnnotationException($"Could not open document for burning: [{oResult}]") End If + ' Add annotation to PDF For Each oJSON In pInstantJSONList If AddInstantJSONAnnotationToPDF(oJSON) = False Then Logger.Warn($"Error in AddInstantJSONAnnotationToPDF - oJson: ") @@ -51,6 +53,7 @@ Namespace Jobs.FinalizeDocument Throw New BurnAnnotationException($"Could not burn annotations to file: [{oResult}]") End If + 'Save PDF Using oNewStream As New MemoryStream() oResult = Manager.SaveDocumentToPDF(oNewStream) If oResult <> GdPictureStatus.OK Then diff --git a/EnvelopeGenerator.Service/Config.vb b/EnvelopeGenerator.Service/Config.vb index 28118a25..2e04fd0a 100644 --- a/EnvelopeGenerator.Service/Config.vb +++ b/EnvelopeGenerator.Service/Config.vb @@ -7,5 +7,10 @@ Public Class Config Public Property Debug As Boolean = False 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 From 891436ceeffa9ba0520100cb50aed9c2765c3bcc Mon Sep 17 00:00:00 2001 From: Developer 02 Date: Thu, 27 Mar 2025 16:19:57 +0100 Subject: [PATCH 32/32] =?UTF-8?q?refactor(frmFinalizePDF):=20=5FignoredLab?= =?UTF-8?q?els=20=E2=80=9EPosition=E2=80=9C,=20=E2=80=9EStellung=E2=80=9C?= =?UTF-8?q?=20hinzuf=C3=BCgen?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- EnvelopeGenerator.Test/frmFinalizePDF.vb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/EnvelopeGenerator.Test/frmFinalizePDF.vb b/EnvelopeGenerator.Test/frmFinalizePDF.vb index e9240913..e6512651 100644 --- a/EnvelopeGenerator.Test/frmFinalizePDF.vb +++ b/EnvelopeGenerator.Test/frmFinalizePDF.vb @@ -15,7 +15,7 @@ Public Class frmFinalizePDF Private Manager As AnnotationManager 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 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 LogConfig = New LogConfig(LogConfig.PathType.CustomPath, Application.StartupPath)