Compare commits
15 Commits
a6ddc72df3
...
1bf1c37296
| Author | SHA1 | Date | |
|---|---|---|---|
| 1bf1c37296 | |||
| ea6f3e61be | |||
| 0c446bba56 | |||
| e74c777687 | |||
| d678111f25 | |||
| 469e335fc3 | |||
| 8d9dbbea19 | |||
| d1088798e5 | |||
| b4353cd9ff | |||
| 0ea7386cb6 | |||
| 161ec6491d | |||
| 6d254281f8 | |||
| 5dc32a02a9 | |||
| ba468c3f99 | |||
| bca0b09cf4 |
@@ -62,25 +62,16 @@ public class DocumentController(IMediator mediator, IAuthorizationService authSe
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
/// Gets the document for the specified envelope key.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="envelopeKey"></param>
|
/// <param name="envelopeKey"></param>
|
||||||
/// <param name="cancel"></param>
|
/// <param name="cancel"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
|
[Authorize(Policy = AuthPolicy.Receiver)]
|
||||||
[HttpGet("{envelopeKey}")]
|
[HttpGet("{envelopeKey}")]
|
||||||
public async Task<IActionResult> GetDocumentOfReceiver(string envelopeKey, CancellationToken cancel)
|
public async Task<IActionResult> GetDocumentOfReceiver(string envelopeKey, CancellationToken cancel)
|
||||||
{
|
{
|
||||||
var envelopeIdStr = User.FindFirst(EnvelopeClaimNames.EnvelopeId)?.Value;
|
int envelopeId = User.GetEnvelopeIdOfReceiver();
|
||||||
|
|
||||||
if (!int.TryParse(envelopeIdStr, out int envelopeId))
|
|
||||||
{
|
|
||||||
logger.LogError(
|
|
||||||
"Inner service error: Failed to parse Envelope ID from claims. Claim '{ClaimName}' had an invalid or missing value: '{ClaimValue}'.",
|
|
||||||
EnvelopeClaimNames.EnvelopeId,
|
|
||||||
envelopeIdStr ?? "null");
|
|
||||||
|
|
||||||
return StatusCode(StatusCodes.Status500InternalServerError, "Inner service error: Invalid envelope claim.");
|
|
||||||
}
|
|
||||||
|
|
||||||
var senderDoc = await mediator.Send(new ReadDocumentQuery() { EnvelopeId = envelopeId }, cancel);
|
var senderDoc = await mediator.Send(new ReadDocumentQuery() { EnvelopeId = envelopeId }, cancel);
|
||||||
|
|
||||||
|
|||||||
@@ -10,9 +10,9 @@
|
|||||||
<Authors>Digital Data GmbH</Authors>
|
<Authors>Digital Data GmbH</Authors>
|
||||||
<Company>Digital Data GmbH</Company>
|
<Company>Digital Data GmbH</Company>
|
||||||
<Product>EnvelopeGenerator.GeneratorAPI</Product>
|
<Product>EnvelopeGenerator.GeneratorAPI</Product>
|
||||||
<Version>1.3.0</Version>
|
<Version>1.3.1</Version>
|
||||||
<FileVersion>1.3.0</FileVersion>
|
<FileVersion>1.3.1</FileVersion>
|
||||||
<AssemblyVersion>1.3.0</AssemblyVersion>
|
<AssemblyVersion>1.3.1</AssemblyVersion>
|
||||||
<PackageOutputPath>Copyright © 2025 Digital Data GmbH. All rights reserved.</PackageOutputPath>
|
<PackageOutputPath>Copyright © 2025 Digital Data GmbH. All rights reserved.</PackageOutputPath>
|
||||||
<DocumentationFile>bin\$(Configuration)\$(TargetFramework)\$(AssemblyName).xml</DocumentationFile>
|
<DocumentationFile>bin\$(Configuration)\$(TargetFramework)\$(AssemblyName).xml</DocumentationFile>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|||||||
@@ -11,6 +11,10 @@ namespace EnvelopeGenerator.API.Extensions;
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public static class ReceiverClaimExtensions
|
public static class ReceiverClaimExtensions
|
||||||
{
|
{
|
||||||
|
private static readonly string[] EnvelopeIdClaimTypes = [EnvelopeClaimTypes.Id, "envelope_id", "EnvelopeId"];
|
||||||
|
private static readonly string[] EnvelopeUuidClaimTypes = [ClaimTypes.NameIdentifier, "envelope_uuid", "EnvelopeUuid"];
|
||||||
|
private static readonly string[] ReceiverSignatureClaimTypes = [ClaimTypes.Hash, "receiver_sig", "ReceiverSignature"];
|
||||||
|
|
||||||
private static string GetRequiredClaimOfReceiver(this ClaimsPrincipal user, string claimType)
|
private static string GetRequiredClaimOfReceiver(this ClaimsPrincipal user, string claimType)
|
||||||
{
|
{
|
||||||
var value = user.FindFirstValue(claimType);
|
var value = user.FindFirstValue(claimType);
|
||||||
@@ -27,15 +31,32 @@ public static class ReceiverClaimExtensions
|
|||||||
throw new InvalidOperationException(message);
|
throw new InvalidOperationException(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static string GetRequiredClaimOfReceiver(this ClaimsPrincipal user, params string[] claimTypes)
|
||||||
|
{
|
||||||
|
foreach (var claimType in claimTypes.Where(t => !string.IsNullOrWhiteSpace(t)).Distinct())
|
||||||
|
{
|
||||||
|
var value = user.FindFirstValue(claimType);
|
||||||
|
if (!string.IsNullOrWhiteSpace(value))
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
var identity = user.Identity;
|
||||||
|
var principalName = identity?.Name ?? "(anonymous)";
|
||||||
|
var authType = identity?.AuthenticationType ?? "(none)";
|
||||||
|
var availableClaims = string.Join(", ", user.Claims.Select(c => $"{c.Type}={c.Value}"));
|
||||||
|
var message = $"Required claim(s) '{string.Join("', '", claimTypes)}' are missing for user '{principalName}' (auth: {authType}). Available claims: [{availableClaims}].";
|
||||||
|
throw new InvalidOperationException(message);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the authenticated envelope UUID from the claims.
|
/// Gets the authenticated envelope UUID from the claims.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static string GetEnvelopeUuidOfReceiver(this ClaimsPrincipal user) => user.GetRequiredClaimOfReceiver(ClaimTypes.NameIdentifier);
|
public static string GetEnvelopeUuidOfReceiver(this ClaimsPrincipal user) => user.GetRequiredClaimOfReceiver(EnvelopeUuidClaimTypes);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the authenticated receiver signature from the claims.
|
/// Gets the authenticated receiver signature from the claims.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static string GetReceiverSignatureOfReceiver(this ClaimsPrincipal user) => user.GetRequiredClaimOfReceiver(ClaimTypes.Hash);
|
public static string GetReceiverSignatureOfReceiver(this ClaimsPrincipal user) => user.GetRequiredClaimOfReceiver(ReceiverSignatureClaimTypes);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the authenticated receiver display name from the claims.
|
/// Gets the authenticated receiver display name from the claims.
|
||||||
@@ -57,7 +78,7 @@ public static class ReceiverClaimExtensions
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public static int GetEnvelopeIdOfReceiver(this ClaimsPrincipal user)
|
public static int GetEnvelopeIdOfReceiver(this ClaimsPrincipal user)
|
||||||
{
|
{
|
||||||
var envIdStr = user.GetRequiredClaimOfReceiver(EnvelopeClaimTypes.Id);
|
var envIdStr = user.GetRequiredClaimOfReceiver(EnvelopeIdClaimTypes);
|
||||||
if (!int.TryParse(envIdStr, out var envId))
|
if (!int.TryParse(envIdStr, out var envId))
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException($"Claim '{EnvelopeClaimTypes.Id}' is not a valid integer.");
|
throw new InvalidOperationException($"Claim '{EnvelopeClaimTypes.Id}' is not a valid integer.");
|
||||||
|
|||||||
@@ -329,15 +329,7 @@ try
|
|||||||
app.MapControllers();
|
app.MapControllers();
|
||||||
|
|
||||||
// Catch-all YARP proxy — only forward requests that are not swagger/scalar/openapi paths.
|
// Catch-all YARP proxy — only forward requests that are not swagger/scalar/openapi paths.
|
||||||
app.MapWhen(
|
app.MapReverseProxy();
|
||||||
ctx =>
|
|
||||||
{
|
|
||||||
var path = ctx.Request.Path.Value ?? string.Empty;
|
|
||||||
return !path.StartsWith("/swagger", StringComparison.OrdinalIgnoreCase) &&
|
|
||||||
!path.StartsWith("/scalar", StringComparison.OrdinalIgnoreCase) &&
|
|
||||||
!path.StartsWith("/openapi", StringComparison.OrdinalIgnoreCase);
|
|
||||||
},
|
|
||||||
branch => branch.UseRouting().UseEndpoints(e => e.MapReverseProxy()));
|
|
||||||
|
|
||||||
app.Run();
|
app.Run();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,20 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!--
|
||||||
|
https://go.microsoft.com/fwlink/?LinkID=208121.
|
||||||
|
-->
|
||||||
|
<Project>
|
||||||
|
<PropertyGroup>
|
||||||
|
<WebPublishMethod>Package</WebPublishMethod>
|
||||||
|
<LastUsedBuildConfiguration>Release</LastUsedBuildConfiguration>
|
||||||
|
<LastUsedPlatform>Any CPU</LastUsedPlatform>
|
||||||
|
<SiteUrlToLaunchAfterPublish />
|
||||||
|
<LaunchSiteAfterPublish>true</LaunchSiteAfterPublish>
|
||||||
|
<ExcludeApp_Data>false</ExcludeApp_Data>
|
||||||
|
<ProjectGuid>5e0e17c0-ff5a-4246-bf87-1add85376a27</ProjectGuid>
|
||||||
|
<DesktopBuildPackageLocation>M:\App&Service\0 DD - Smart UP\signFLOW\API\net8\$(Version)\EnvelopeGenerator.API.zip</DesktopBuildPackageLocation>
|
||||||
|
<PackageAsSingleFile>true</PackageAsSingleFile>
|
||||||
|
<DeployIisAppPath>EnvelopeGenerator</DeployIisAppPath>
|
||||||
|
<_TargetId>IISWebDeployPackage</_TargetId>
|
||||||
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
|
</PropertyGroup>
|
||||||
|
</Project>
|
||||||
@@ -1,10 +1,21 @@
|
|||||||
{
|
{
|
||||||
"Logging": {
|
"Logging": {
|
||||||
"LogLevel": {
|
"LogLevel": {
|
||||||
"Default": "Information",
|
"Default": "Information",
|
||||||
"Microsoft.AspNetCore": "Warning"
|
"Microsoft.AspNetCore": "Warning"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"ReverseProxy": {
|
||||||
|
"Clusters": {
|
||||||
|
"receiver-ui": {
|
||||||
|
"Destinations": {
|
||||||
|
"primary": {
|
||||||
|
"Address": "https://localhost:52936"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"AuthClientParams": {
|
"AuthClientParams": {
|
||||||
"Url": "http://172.24.12.39:9090/auth-hub",
|
"Url": "http://172.24.12.39:9090/auth-hub",
|
||||||
"PublicKeys": [
|
"PublicKeys": [
|
||||||
|
|||||||
@@ -29,9 +29,12 @@
|
|||||||
"ClusterId": "receiver-ui",
|
"ClusterId": "receiver-ui",
|
||||||
"Order": 100,
|
"Order": 100,
|
||||||
"Match": {
|
"Match": {
|
||||||
"Path": "/envelope/{**catch-all}",
|
"Path": "/envelope/{EnvelopeKey}",
|
||||||
"Methods": [ "GET", "HEAD" ]
|
"Methods": [ "GET", "HEAD" ]
|
||||||
}
|
},
|
||||||
|
"Transforms": [
|
||||||
|
{ "PathSet": "/index.html" }
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"receiver-ui-static-assets": {
|
"receiver-ui-static-assets": {
|
||||||
"ClusterId": "receiver-ui",
|
"ClusterId": "receiver-ui",
|
||||||
|
|||||||
@@ -14,11 +14,11 @@
|
|||||||
<PackageIcon>Assets\icon.ico</PackageIcon>
|
<PackageIcon>Assets\icon.ico</PackageIcon>
|
||||||
<PackageTags>digital data envelope generator web</PackageTags>
|
<PackageTags>digital data envelope generator web</PackageTags>
|
||||||
<Description>EnvelopeGenerator.ReceiverUI is a Blazor WebAssembly application developed to manage signing processes. It uses Entity Framework Core (EF Core) for database operations. The user interface for signing processes is developed with Razor View Engine (.cshtml files) and JavaScript under wwwroot, integrated with PSPDFKit. This integration allows users to view and sign documents seamlessly.</Description>
|
<Description>EnvelopeGenerator.ReceiverUI is a Blazor WebAssembly application developed to manage signing processes. It uses Entity Framework Core (EF Core) for database operations. The user interface for signing processes is developed with Razor View Engine (.cshtml files) and JavaScript under wwwroot, integrated with PSPDFKit. This integration allows users to view and sign documents seamlessly.</Description>
|
||||||
<Version>1.2.0</Version>
|
<Version>1.3.0</Version>
|
||||||
<!-- NuGet package version -->
|
<!-- NuGet package version -->
|
||||||
<AssemblyVersion>1.2.0.0</AssemblyVersion>
|
<AssemblyVersion>1.3.0.0</AssemblyVersion>
|
||||||
<!-- Assembly version for API compatibility -->
|
<!-- Assembly version for API compatibility -->
|
||||||
<FileVersion>1.2.0.0</FileVersion>
|
<FileVersion>1.3.0.0</FileVersion>
|
||||||
<!-- Windows file version -->
|
<!-- Windows file version -->
|
||||||
<Copyright>Copyright © 2026 Digital Data GmbH. All rights reserved.</Copyright>
|
<Copyright>Copyright © 2026 Digital Data GmbH. All rights reserved.</Copyright>
|
||||||
|
|
||||||
@@ -29,6 +29,7 @@
|
|||||||
<PackageReference Include="DevExpress.Blazor.Reporting.Viewer" Version="25.2.3" />
|
<PackageReference Include="DevExpress.Blazor.Reporting.Viewer" Version="25.2.3" />
|
||||||
<PackageReference Include="DevExpress.Drawing.Skia" Version="25.2.3" />
|
<PackageReference Include="DevExpress.Drawing.Skia" Version="25.2.3" />
|
||||||
<PackageReference Include="HarfBuzzSharp.NativeAssets.WebAssembly" Version="8.3.1.2" />
|
<PackageReference Include="HarfBuzzSharp.NativeAssets.WebAssembly" Version="8.3.1.2" />
|
||||||
|
<PackageReference Include="itext" Version="8.0.5" />
|
||||||
<PackageReference Include="SkiaSharp.NativeAssets.WebAssembly" Version="3.119.1" />
|
<PackageReference Include="SkiaSharp.NativeAssets.WebAssembly" Version="3.119.1" />
|
||||||
<PackageReference Include="SkiaSharp.Views.Blazor" Version="3.119.1" />
|
<PackageReference Include="SkiaSharp.Views.Blazor" Version="3.119.1" />
|
||||||
<NativeFileReference Include="$(HarfBuzzSharpStaticLibraryPath)\2.0.23\*.a" />
|
<NativeFileReference Include="$(HarfBuzzSharpStaticLibraryPath)\2.0.23\*.a" />
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
@page "/"
|
@page "/"
|
||||||
|
@inject IJSRuntime JS
|
||||||
|
|
||||||
<link href="_content/DevExpress.Blazor.Themes/blazing-berry.bs5.min.css" rel="stylesheet" />
|
<link href="_content/DevExpress.Blazor.Themes/blazing-berry.bs5.min.css" rel="stylesheet" />
|
||||||
|
|
||||||
@@ -18,12 +19,10 @@
|
|||||||
|
|
||||||
<div class="home-content">
|
<div class="home-content">
|
||||||
<div class="home-card card shadow border-0">
|
<div class="home-card card shadow border-0">
|
||||||
<div class="card-body p-4 p-md-5 text-center">
|
<div class="card-body p-4 p-md-5">
|
||||||
|
|
||||||
<p class="text-muted mb-4" style="font-size: 0.92rem; line-height: 1.7;">
|
<p class="text-muted mb-4" style="font-size: 0.92rem; line-height: 1.7; text-align: justify; text-align-last: left; min-height: calc(0.92rem * 1.7 * 9);">
|
||||||
Das digitale Unterschriftenportal ist eine Plattform, die entwickelt wurde, um Ihre Dokumente sicher zu unterschreiben und zu verwalten.
|
<span id="home-description"></span>
|
||||||
Mit seiner benutzerfreundlichen Oberfläche können Sie Ihre Dokumente schnell hochladen, die Unterschriftsprozesse verfolgen und Ihre digitalen Unterschriftenanwendungen einfach durchführen.
|
|
||||||
Dieses Portal beschleunigt Ihren Arbeitsablauf mit rechtlich gültigen Unterschriften und erhöht gleichzeitig die Sicherheit Ihrer Dokumente.
|
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<div class="mt-4 pt-3 border-top">
|
<div class="mt-4 pt-3 border-top">
|
||||||
@@ -57,4 +56,16 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
|
private const string HomePageDescription =
|
||||||
|
"Das digitale Unterschriftenportal ist eine Plattform, die entwickelt wurde, um Ihre Dokumente sicher zu unterschreiben und zu verwalten. " +
|
||||||
|
"Mit seiner benutzerfreundlichen Oberfläche können Sie Ihre Dokumente schnell hochladen, die Unterschriftsprozesse verfolgen und Ihre digitalen Unterschriftenanwendungen einfach durchführen. " +
|
||||||
|
"Dieses Portal beschleunigt Ihren Arbeitsablauf mit rechtlich gültigen Unterschriften und erhöht gleichzeitig die Sicherheit Ihrer Dokumente.";
|
||||||
|
|
||||||
|
protected override async Task OnAfterRenderAsync(bool firstRender)
|
||||||
|
{
|
||||||
|
if (firstRender)
|
||||||
|
{
|
||||||
|
await JS.InvokeVoidAsync("receiverSignature.startTyped", "home-description", HomePageDescription, 15);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -654,30 +654,22 @@ Shown="OnPopupShownAsync">
|
|||||||
var imageBytes = Convert.FromBase64String(signatureDataUrl[(signatureDataUrl.IndexOf(',') + 1)..]);
|
var imageBytes = Convert.FromBase64String(signatureDataUrl[(signatureDataUrl.IndexOf(',') + 1)..]);
|
||||||
using var imageStream = new MemoryStream(imageBytes);
|
using var imageStream = new MemoryStream(imageBytes);
|
||||||
var imageSource = new ImageSource(DXImage.FromStream(imageStream));
|
var imageSource = new ImageSource(DXImage.FromStream(imageStream));
|
||||||
var bottomMargin = report.Bands.OfType<BottomMarginBand>().FirstOrDefault();
|
|
||||||
|
|
||||||
if (bottomMargin is null) {
|
var detail = report.Bands.OfType<DevExpress.XtraReports.UI.DetailBand>().FirstOrDefault();
|
||||||
bottomMargin = new BottomMarginBand();
|
if (detail is null) return;
|
||||||
report.Bands.Add(bottomMargin);
|
|
||||||
}
|
|
||||||
|
|
||||||
var annotId = annotation?.Id.ToString() ?? "0";
|
var annotId = annotation?.Id.ToString() ?? "0";
|
||||||
RemoveExistingSignatureById(bottomMargin, annotId);
|
RemoveExistingSignatureById(detail, annotId);
|
||||||
|
|
||||||
const float sigWidth = 230F;
|
const float sigWidth = 230F;
|
||||||
const float sigImgHeight = 70F;
|
const float sigImgHeight = 70F;
|
||||||
const float infoHeight = 48.75F;
|
const float infoHeight = 48.75F;
|
||||||
const float innerGap = 5F;
|
const float innerGap = 5F;
|
||||||
const float bottomPad = 6F;
|
|
||||||
const float defaultTopPad = 8F;
|
|
||||||
const float maxBandHeight = 210F;
|
|
||||||
|
|
||||||
float sigX = (float)(annotation?.X ?? 390.0);
|
float sigX = (float)(annotation?.X ?? 390.0);
|
||||||
float requiredHeight = defaultTopPad + sigImgHeight + innerGap + infoHeight + bottomPad;
|
float imageY = (float)(annotation?.Y ?? 900.0);
|
||||||
bottomMargin.HeightF = Math.Min(maxBandHeight, Math.Max(bottomMargin.HeightF, requiredHeight));
|
|
||||||
float topPad = Math.Max(0F, bottomMargin.HeightF - bottomPad - infoHeight - innerGap - sigImgHeight);
|
|
||||||
float imageY = topPad;
|
|
||||||
float labelY = imageY + sigImgHeight + innerGap;
|
float labelY = imageY + sigImgHeight + innerGap;
|
||||||
|
int targetPage = annotation?.Page ?? 1;
|
||||||
|
|
||||||
var signatureInformation = string.IsNullOrWhiteSpace(signerPosition)
|
var signatureInformation = string.IsNullOrWhiteSpace(signerPosition)
|
||||||
? $"{signerFullName}\n{signaturePlace}, {DateTime.Now:d}"
|
? $"{signerFullName}\n{signaturePlace}, {DateTime.Now:d}"
|
||||||
@@ -690,7 +682,7 @@ Shown="OnPopupShownAsync">
|
|||||||
Sizing = ImageSizeMode.ZoomImage,
|
Sizing = ImageSizeMode.ZoomImage,
|
||||||
Borders = BorderSide.Bottom,
|
Borders = BorderSide.Bottom,
|
||||||
BorderColor = System.Drawing.Color.FromArgb(73, 80, 87),
|
BorderColor = System.Drawing.Color.FromArgb(73, 80, 87),
|
||||||
BackColor = Color.FromArgb(219, 219, 219),
|
BackColor = Color.FromArgb(219, 219, 219)
|
||||||
};
|
};
|
||||||
|
|
||||||
var signatureLabel = new XRLabel {
|
var signatureLabel = new XRLabel {
|
||||||
@@ -704,16 +696,29 @@ Shown="OnPopupShownAsync">
|
|||||||
BackColor = Color.FromArgb(219, 219, 219)
|
BackColor = Color.FromArgb(219, 219, 219)
|
||||||
};
|
};
|
||||||
|
|
||||||
bottomMargin.Controls.AddRange(new XRControl[] { signature, signatureLabel });
|
// Show each control only on the target page using an independent print counter
|
||||||
|
int sigPrintCount = 0;
|
||||||
|
signature.BeforePrint += (_, e) => {
|
||||||
|
sigPrintCount++;
|
||||||
|
e.Cancel = sigPrintCount != targetPage;
|
||||||
|
};
|
||||||
|
|
||||||
|
int lblPrintCount = 0;
|
||||||
|
signatureLabel.BeforePrint += (_, e) => {
|
||||||
|
lblPrintCount++;
|
||||||
|
e.Cancel = lblPrintCount != targetPage;
|
||||||
|
};
|
||||||
|
|
||||||
|
detail.Controls.AddRange(new XRControl[] { signature, signatureLabel });
|
||||||
}
|
}
|
||||||
|
|
||||||
static void RemoveExistingSignatureById(BottomMarginBand bottomMargin, string annotId) {
|
static void RemoveExistingSignatureById(DevExpress.XtraReports.UI.DetailBand detail, string annotId) {
|
||||||
var controls = bottomMargin.Controls
|
var controls = detail.Controls
|
||||||
.Cast<XRControl>()
|
.Cast<XRControl>()
|
||||||
.Where(c => c.Name == $"receiverSignatureImage_{annotId}" || c.Name == $"receiverSignatureLabel_{annotId}")
|
.Where(c => c.Name == $"receiverSignatureImage_{annotId}" || c.Name == $"receiverSignatureLabel_{annotId}")
|
||||||
.ToArray();
|
.ToArray();
|
||||||
foreach (var c in controls)
|
foreach (var c in controls)
|
||||||
bottomMargin.Controls.Remove(c);
|
detail.Controls.Remove(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose() {
|
public void Dispose() {
|
||||||
|
|||||||
41
EnvelopeGenerator.ReceiverUI/wwwroot/css/privacy-policy.css
Normal file
41
EnvelopeGenerator.ReceiverUI/wwwroot/css/privacy-policy.css
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
body {
|
||||||
|
font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
|
||||||
|
line-height: 1.6;
|
||||||
|
margin: 1.25rem;
|
||||||
|
background-color: #f4f4f4;
|
||||||
|
}
|
||||||
|
|
||||||
|
header {
|
||||||
|
text-align: center;
|
||||||
|
margin: 0rem 10rem 3rem 10rem;
|
||||||
|
box-shadow: 0 .25rem .5rem rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
color: #0056b3;
|
||||||
|
}
|
||||||
|
|
||||||
|
section {
|
||||||
|
background-color: white;
|
||||||
|
padding: 1.25rem;
|
||||||
|
border-radius: 0.5rem;
|
||||||
|
box-shadow: 0 .25rem .5rem rgba(0, 0, 0, 0.1);
|
||||||
|
margin: 0rem 10rem 3rem 10rem
|
||||||
|
}
|
||||||
|
|
||||||
|
ul {
|
||||||
|
list-style: disc inside;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: #0056b3;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
a:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
1
EnvelopeGenerator.ReceiverUI/wwwroot/css/privacy-policy.min.css
vendored
Normal file
1
EnvelopeGenerator.ReceiverUI/wwwroot/css/privacy-policy.min.css
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
body{font-family:system-ui,-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Oxygen,Ubuntu,Cantarell,'Open Sans','Helvetica Neue',sans-serif;line-height:1.6;margin:1.25rem;background-color:#f4f4f4}header{text-align:center;margin:0 10rem 3rem 10rem;box-shadow:0 .25rem .5rem rgba(0,0,0,.1)}h1{color:#333}h2{color:#0056b3}section{background-color:#fff;padding:1.25rem;border-radius:.5rem;box-shadow:0 .25rem .5rem rgba(0,0,0,.1);margin:0 10rem 3rem 10rem}ul{list-style:disc inside}a{color:#0056b3;text-decoration:none}a:hover{text-decoration:underline}
|
||||||
@@ -5,7 +5,7 @@
|
|||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<title>Datenschutzinformation für das Fernsignatursystem: signFLOW</title>
|
<title>Datenschutzinformation für das Fernsignatursystem: signFLOW</title>
|
||||||
<link rel="stylesheet" href="css/privacy-policy.min.css">
|
<link rel="stylesheet" href="../css/privacy-policy.min.css">
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
|
|||||||
@@ -3,13 +3,13 @@
|
|||||||
"id": 1,
|
"id": 1,
|
||||||
"page": 1,
|
"page": 1,
|
||||||
"x": 390.0,
|
"x": 390.0,
|
||||||
"y": 980.0
|
"y": 380.0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": 2,
|
"id": 2,
|
||||||
"page": 2,
|
"page": 2,
|
||||||
"x": 390.0,
|
"x": 390.0,
|
||||||
"y": 980.0
|
"y": 680.0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": 3,
|
"id": 3,
|
||||||
|
|||||||
@@ -65,6 +65,7 @@
|
|||||||
<a class="dismiss">X</a>
|
<a class="dismiss">X</a>
|
||||||
</div>
|
</div>
|
||||||
<script src="_content/DevExpress.Blazor.Resources/js/preload-script.js"></script>
|
<script src="_content/DevExpress.Blazor.Resources/js/preload-script.js"></script>
|
||||||
|
<script src="js/typed.umd.js"></script>
|
||||||
<script src="js/receiver-signature.js?v=9"></script>
|
<script src="js/receiver-signature.js?v=9"></script>
|
||||||
<script src="_framework/blazor.webassembly.js"></script>
|
<script src="_framework/blazor.webassembly.js"></script>
|
||||||
</body>
|
</body>
|
||||||
|
|||||||
@@ -315,12 +315,22 @@ window.receiverSignature = (() => {
|
|||||||
state.hasSignature = true;
|
state.hasSignature = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function startTyped(elementId, text, typeSpeed) {
|
||||||
|
if (typeof Typed === 'undefined') return;
|
||||||
|
new Typed('#' + elementId, {
|
||||||
|
strings: [text],
|
||||||
|
typeSpeed: typeSpeed || 15,
|
||||||
|
showCursor: false
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function getDataUrl(id) { const c = document.getElementById(id); const s = pads.get(id); return (c && s && s.hasSignature) ? c.toDataURL('image/png') : null; }
|
function getDataUrl(id) { const c = document.getElementById(id); const s = pads.get(id); return (c && s && s.hasSignature) ? c.toDataURL('image/png') : null; }
|
||||||
function getTypedDataUrl(id) { const c = document.getElementById(id); const s = typedSignatures.get(id); return (c && s && s.hasSignature) ? c.toDataURL('image/png') : null; }
|
function getTypedDataUrl(id) { const c = document.getElementById(id); const s = typedSignatures.get(id); return (c && s && s.hasSignature) ? c.toDataURL('image/png') : null; }
|
||||||
function getImageDataUrl(id) { const c = document.getElementById(id); const s = imageSignatures.get(id); return (c && s && s.hasSignature) ? c.toDataURL('image/png') : null; }
|
function getImageDataUrl(id) { const c = document.getElementById(id); const s = imageSignatures.get(id); return (c && s && s.hasSignature) ? c.toDataURL('image/png') : null; }
|
||||||
|
|
||||||
// ?? Public API ??????????????????????????????????????????????????????????
|
// ?? Public API ??????????????????????????????????????????????????????????
|
||||||
return {
|
return {
|
||||||
|
startTyped: startTyped,
|
||||||
installAnnotationCheckboxes: installAnnotationCheckboxes,
|
installAnnotationCheckboxes: installAnnotationCheckboxes,
|
||||||
debugDumpViewerDom: debugDumpViewerDom,
|
debugDumpViewerDom: debugDumpViewerDom,
|
||||||
initialize: initialize,
|
initialize: initialize,
|
||||||
|
|||||||
3
EnvelopeGenerator.ReceiverUI/wwwroot/js/typed.umd.js
Normal file
3
EnvelopeGenerator.ReceiverUI/wwwroot/js/typed.umd.js
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
!function(t,s){"object"==typeof exports&&"undefined"!=typeof module?module.exports=s():"function"==typeof define&&define.amd?define(s):(t||self).Typed=s()}(this,function(){function t(){return t=Object.assign?Object.assign.bind():function(t){for(var s=1;s<arguments.length;s++){var e=arguments[s];for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&(t[n]=e[n])}return t},t.apply(this,arguments)}var s={strings:["These are the default values...","You know what you should do?","Use your own!","Have a great day!"],stringsElement:null,typeSpeed:0,startDelay:0,backSpeed:0,smartBackspace:!0,shuffle:!1,backDelay:700,fadeOut:!1,fadeOutClass:"typed-fade-out",fadeOutDelay:500,loop:!1,loopCount:Infinity,showCursor:!0,cursorChar:"|",autoInsertCss:!0,attr:null,bindInputFocusEvents:!1,contentType:"html",onBegin:function(t){},onComplete:function(t){},preStringTyped:function(t,s){},onStringTyped:function(t,s){},onLastStringBackspaced:function(t){},onTypingPaused:function(t,s){},onTypingResumed:function(t,s){},onReset:function(t){},onStop:function(t,s){},onStart:function(t,s){},onDestroy:function(t){}},e=new(/*#__PURE__*/function(){function e(){}var n=e.prototype;return n.load=function(e,n,i){if(e.el="string"==typeof i?document.querySelector(i):i,e.options=t({},s,n),e.isInput="input"===e.el.tagName.toLowerCase(),e.attr=e.options.attr,e.bindInputFocusEvents=e.options.bindInputFocusEvents,e.showCursor=!e.isInput&&e.options.showCursor,e.cursorChar=e.options.cursorChar,e.cursorBlinking=!0,e.elContent=e.attr?e.el.getAttribute(e.attr):e.el.textContent,e.contentType=e.options.contentType,e.typeSpeed=e.options.typeSpeed,e.startDelay=e.options.startDelay,e.backSpeed=e.options.backSpeed,e.smartBackspace=e.options.smartBackspace,e.backDelay=e.options.backDelay,e.fadeOut=e.options.fadeOut,e.fadeOutClass=e.options.fadeOutClass,e.fadeOutDelay=e.options.fadeOutDelay,e.isPaused=!1,e.strings=e.options.strings.map(function(t){return t.trim()}),e.stringsElement="string"==typeof e.options.stringsElement?document.querySelector(e.options.stringsElement):e.options.stringsElement,e.stringsElement){e.strings=[],e.stringsElement.style.cssText="clip: rect(0 0 0 0);clip-path:inset(50%);height:1px;overflow:hidden;position:absolute;white-space:nowrap;width:1px;";var r=Array.prototype.slice.apply(e.stringsElement.children),o=r.length;if(o)for(var a=0;a<o;a+=1)e.strings.push(r[a].innerHTML.trim())}for(var u in e.strPos=0,e.currentElContent=this.getCurrentElContent(e),e.currentElContent&&e.currentElContent.length>0&&(e.strPos=e.currentElContent.length-1,e.strings.unshift(e.currentElContent)),e.sequence=[],e.strings)e.sequence[u]=u;e.arrayPos=0,e.stopNum=0,e.loop=e.options.loop,e.loopCount=e.options.loopCount,e.curLoop=0,e.shuffle=e.options.shuffle,e.pause={status:!1,typewrite:!0,curString:"",curStrPos:0},e.typingComplete=!1,e.autoInsertCss=e.options.autoInsertCss,e.autoInsertCss&&(this.appendCursorAnimationCss(e),this.appendFadeOutAnimationCss(e))},n.getCurrentElContent=function(t){return t.attr?t.el.getAttribute(t.attr):t.isInput?t.el.value:"html"===t.contentType?t.el.innerHTML:t.el.textContent},n.appendCursorAnimationCss=function(t){var s="data-typed-js-cursor-css";if(t.showCursor&&!document.querySelector("["+s+"]")){var e=document.createElement("style");e.setAttribute(s,"true"),e.innerHTML="\n .typed-cursor{\n opacity: 1;\n }\n .typed-cursor.typed-cursor--blink{\n animation: typedjsBlink 0.7s infinite;\n -webkit-animation: typedjsBlink 0.7s infinite;\n animation: typedjsBlink 0.7s infinite;\n }\n @keyframes typedjsBlink{\n 50% { opacity: 0.0; }\n }\n @-webkit-keyframes typedjsBlink{\n 0% { opacity: 1; }\n 50% { opacity: 0.0; }\n 100% { opacity: 1; }\n }\n ",document.body.appendChild(e)}},n.appendFadeOutAnimationCss=function(t){var s="data-typed-fadeout-js-css";if(t.fadeOut&&!document.querySelector("["+s+"]")){var e=document.createElement("style");e.setAttribute(s,"true"),e.innerHTML="\n .typed-fade-out{\n opacity: 0;\n transition: opacity .25s;\n }\n .typed-cursor.typed-cursor--blink.typed-fade-out{\n -webkit-animation: 0;\n animation: 0;\n }\n ",document.body.appendChild(e)}},e}()),n=new(/*#__PURE__*/function(){function t(){}var s=t.prototype;return s.typeHtmlChars=function(t,s,e){if("html"!==e.contentType)return s;var n=t.substring(s).charAt(0);if("<"===n||"&"===n){var i;for(i="<"===n?">":";";t.substring(s+1).charAt(0)!==i&&!(1+ ++s>t.length););s++}return s},s.backSpaceHtmlChars=function(t,s,e){if("html"!==e.contentType)return s;var n=t.substring(s).charAt(0);if(">"===n||";"===n){var i;for(i=">"===n?"<":"&";t.substring(s-1).charAt(0)!==i&&!(--s<0););s--}return s},t}());/*#__PURE__*/
|
||||||
|
return function(){function t(t,s){e.load(this,s,t),this.begin()}var s=t.prototype;return s.toggle=function(){this.pause.status?this.start():this.stop()},s.stop=function(){this.typingComplete||this.pause.status||(this.toggleBlinking(!0),this.pause.status=!0,this.options.onStop(this.arrayPos,this))},s.start=function(){this.typingComplete||this.pause.status&&(this.pause.status=!1,this.pause.typewrite?this.typewrite(this.pause.curString,this.pause.curStrPos):this.backspace(this.pause.curString,this.pause.curStrPos),this.options.onStart(this.arrayPos,this))},s.destroy=function(){this.reset(!1),this.options.onDestroy(this)},s.reset=function(t){void 0===t&&(t=!0),clearInterval(this.timeout),this.replaceText(""),this.cursor&&this.cursor.parentNode&&(this.cursor.parentNode.removeChild(this.cursor),this.cursor=null),this.strPos=0,this.arrayPos=0,this.curLoop=0,t&&(this.insertCursor(),this.options.onReset(this),this.begin())},s.begin=function(){var t=this;this.options.onBegin(this),this.typingComplete=!1,this.shuffleStringsIfNeeded(this),this.insertCursor(),this.bindInputFocusEvents&&this.bindFocusEvents(),this.timeout=setTimeout(function(){0===t.strPos?t.typewrite(t.strings[t.sequence[t.arrayPos]],t.strPos):t.backspace(t.strings[t.sequence[t.arrayPos]],t.strPos)},this.startDelay)},s.typewrite=function(t,s){var e=this;this.fadeOut&&this.el.classList.contains(this.fadeOutClass)&&(this.el.classList.remove(this.fadeOutClass),this.cursor&&this.cursor.classList.remove(this.fadeOutClass));var i=this.humanizer(this.typeSpeed),r=1;!0!==this.pause.status?this.timeout=setTimeout(function(){s=n.typeHtmlChars(t,s,e);var i=0,o=t.substring(s);if("^"===o.charAt(0)&&/^\^\d+/.test(o)){var a=1;a+=(o=/\d+/.exec(o)[0]).length,i=parseInt(o),e.temporaryPause=!0,e.options.onTypingPaused(e.arrayPos,e),t=t.substring(0,s)+t.substring(s+a),e.toggleBlinking(!0)}if("`"===o.charAt(0)){for(;"`"!==t.substring(s+r).charAt(0)&&(r++,!(s+r>t.length)););var u=t.substring(0,s),p=t.substring(u.length+1,s+r),c=t.substring(s+r+1);t=u+p+c,r--}e.timeout=setTimeout(function(){e.toggleBlinking(!1),s>=t.length?e.doneTyping(t,s):e.keepTyping(t,s,r),e.temporaryPause&&(e.temporaryPause=!1,e.options.onTypingResumed(e.arrayPos,e))},i)},i):this.setPauseStatus(t,s,!0)},s.keepTyping=function(t,s,e){0===s&&(this.toggleBlinking(!1),this.options.preStringTyped(this.arrayPos,this));var n=t.substring(0,s+=e);this.replaceText(n),this.typewrite(t,s)},s.doneTyping=function(t,s){var e=this;this.options.onStringTyped(this.arrayPos,this),this.toggleBlinking(!0),this.arrayPos===this.strings.length-1&&(this.complete(),!1===this.loop||this.curLoop===this.loopCount)||(this.timeout=setTimeout(function(){e.backspace(t,s)},this.backDelay))},s.backspace=function(t,s){var e=this;if(!0!==this.pause.status){if(this.fadeOut)return this.initFadeOut();this.toggleBlinking(!1);var i=this.humanizer(this.backSpeed);this.timeout=setTimeout(function(){s=n.backSpaceHtmlChars(t,s,e);var i=t.substring(0,s);if(e.replaceText(i),e.smartBackspace){var r=e.strings[e.arrayPos+1];e.stopNum=r&&i===r.substring(0,s)?s:0}s>e.stopNum?(s--,e.backspace(t,s)):s<=e.stopNum&&(e.arrayPos++,e.arrayPos===e.strings.length?(e.arrayPos=0,e.options.onLastStringBackspaced(),e.shuffleStringsIfNeeded(),e.begin()):e.typewrite(e.strings[e.sequence[e.arrayPos]],s))},i)}else this.setPauseStatus(t,s,!1)},s.complete=function(){this.options.onComplete(this),this.loop?this.curLoop++:this.typingComplete=!0},s.setPauseStatus=function(t,s,e){this.pause.typewrite=e,this.pause.curString=t,this.pause.curStrPos=s},s.toggleBlinking=function(t){this.cursor&&(this.pause.status||this.cursorBlinking!==t&&(this.cursorBlinking=t,t?this.cursor.classList.add("typed-cursor--blink"):this.cursor.classList.remove("typed-cursor--blink")))},s.humanizer=function(t){return Math.round(Math.random()*t/2)+t},s.shuffleStringsIfNeeded=function(){this.shuffle&&(this.sequence=this.sequence.sort(function(){return Math.random()-.5}))},s.initFadeOut=function(){var t=this;return this.el.className+=" "+this.fadeOutClass,this.cursor&&(this.cursor.className+=" "+this.fadeOutClass),setTimeout(function(){t.arrayPos++,t.replaceText(""),t.strings.length>t.arrayPos?t.typewrite(t.strings[t.sequence[t.arrayPos]],0):(t.typewrite(t.strings[0],0),t.arrayPos=0)},this.fadeOutDelay)},s.replaceText=function(t){this.attr?this.el.setAttribute(this.attr,t):this.isInput?this.el.value=t:"html"===this.contentType?this.el.innerHTML=t:this.el.textContent=t},s.bindFocusEvents=function(){var t=this;this.isInput&&(this.el.addEventListener("focus",function(s){t.stop()}),this.el.addEventListener("blur",function(s){t.el.value&&0!==t.el.value.length||t.start()}))},s.insertCursor=function(){this.showCursor&&(this.cursor||(this.cursor=document.createElement("span"),this.cursor.className="typed-cursor",this.cursor.setAttribute("aria-hidden",!0),this.cursor.innerHTML=this.cursorChar,this.el.parentNode&&this.el.parentNode.insertBefore(this.cursor,this.el.nextSibling)))},t}()});
|
||||||
|
//# sourceMappingURL=typed.umd.js.map
|
||||||
@@ -20,6 +20,9 @@ EndProject
|
|||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "core", "core", "{9943209E-1744-4944-B1BA-4F87FC1A0EEB}"
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "core", "core", "{9943209E-1744-4944-B1BA-4F87FC1A0EEB}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{134D4164-B291-4E19-99B9-E4FA3AFAB62C}"
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{134D4164-B291-4E19-99B9-E4FA3AFAB62C}"
|
||||||
|
ProjectSection(SolutionItems) = preProject
|
||||||
|
COPILOT_CONTEXT_EN.md = COPILOT_CONTEXT_EN.md
|
||||||
|
EndProjectSection
|
||||||
EndProject
|
EndProject
|
||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{0CBC2432-A561-4440-89BC-671B66A24146}"
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{0CBC2432-A561-4440-89BC-671B66A24146}"
|
||||||
EndProject
|
EndProject
|
||||||
|
|||||||
Reference in New Issue
Block a user