03-11-23
This commit is contained in:
@@ -9,7 +9,7 @@ namespace EnvelopeGenerator.Web.Controllers
|
||||
{
|
||||
internal DatabaseService database;
|
||||
internal LogConfig logConfig;
|
||||
internal Logger logger;
|
||||
public Logger logger;
|
||||
|
||||
public BaseController(DatabaseService database, LoggingService logging)
|
||||
{
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
using DigitalData.Modules.Logging;
|
||||
using EnvelopeGenerator.Common;
|
||||
using EnvelopeGenerator.Common;
|
||||
using EnvelopeGenerator.Web.Services;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using static EnvelopeGenerator.Web.Constants;
|
||||
|
||||
namespace EnvelopeGenerator.Web.Controllers
|
||||
{
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
using EnvelopeGenerator.Web.Services;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using static EnvelopeGenerator.Common.Constants;
|
||||
using System;
|
||||
using static System.Collections.Specialized.BitVector32;
|
||||
|
||||
namespace EnvelopeGenerator.Web.Controllers
|
||||
{
|
||||
|
||||
@@ -6,21 +6,19 @@ using System.Diagnostics;
|
||||
|
||||
namespace EnvelopeGenerator.Web.Controllers
|
||||
{
|
||||
public class HomeController : Controller
|
||||
public class HomeController : BaseController
|
||||
{
|
||||
private readonly EnvelopeService _envelopeService;
|
||||
private readonly ILogger<HomeController> _logger;
|
||||
|
||||
public HomeController(ILogger<HomeController> logger, EnvelopeService envelopeService)
|
||||
public HomeController(DatabaseService database, LoggingService logging, EnvelopeService envelopeService): base(database, logging)
|
||||
{
|
||||
_envelopeService = envelopeService;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
[Route("/")]
|
||||
public IActionResult Index()
|
||||
{
|
||||
{
|
||||
var receiverId = 1;
|
||||
List<Envelope> envelopes = _envelopeService.LoadEnvelopes(receiverId);
|
||||
|
||||
@@ -29,13 +27,23 @@ namespace EnvelopeGenerator.Web.Controllers
|
||||
|
||||
[HttpGet]
|
||||
[Route("/EnvelopeKey/{EnvelopeReceiverId}")]
|
||||
public IActionResult Show()
|
||||
public IActionResult ShowEnvelope()
|
||||
{
|
||||
ViewData["EnvelopeKey"] = HttpContext.Request.RouteValues["EnvelopeReceiverId"];
|
||||
|
||||
return View();
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
[Route("/EnvelopeKey/{EnvelopeReceiverId}/Success")]
|
||||
public IActionResult EnvelopeSigned()
|
||||
{
|
||||
ViewData["EnvelopeKey"] = HttpContext.Request.RouteValues["EnvelopeReceiverId"];
|
||||
|
||||
return View();
|
||||
}
|
||||
|
||||
|
||||
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
|
||||
public IActionResult Error()
|
||||
{
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
@@ -12,21 +12,22 @@
|
||||
<PackageReference Include="System.Drawing.Common" Version="7.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\EnvelopeGenerator.Common\EnvelopeGenerator.Common.vbproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Reference Include="DigitalData.Modules.Base">
|
||||
<HintPath>..\DDModules\Base\bin\Debug\DigitalData.Modules.Base.dll</HintPath>
|
||||
<HintPath>..\..\DDModules\Base\bin\Debug\DigitalData.Modules.Base.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="DigitalData.Modules.Config">
|
||||
<HintPath>..\DDModules\Config\bin\Debug\DigitalData.Modules.Config.dll</HintPath>
|
||||
<HintPath>..\..\DDModules\Config\bin\Debug\DigitalData.Modules.Config.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="DigitalData.Modules.Database">
|
||||
<HintPath>..\DDModules\Database\bin\Debug\DigitalData.Modules.Database.dll</HintPath>
|
||||
<HintPath>..\..\DDModules\Database\bin\Debug\DigitalData.Modules.Database.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="DigitalData.Modules.Logging">
|
||||
<HintPath>..\DDModules\Logging\bin\Debug\DigitalData.Modules.Logging.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="EnvelopeGenerator.Common">
|
||||
<HintPath>..\EnvelopeGenerator\EnvelopeGenerator.Common\bin\Debug\EnvelopeGenerator.Common.dll</HintPath>
|
||||
<HintPath>..\..\DDModules\Logging\bin\Debug\DigitalData.Modules.Logging.dll</HintPath>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
21
EnvelopeGenerator.Web/Views/Home/EnvelopeSigned.cshtml
Normal file
21
EnvelopeGenerator.Web/Views/Home/EnvelopeSigned.cshtml
Normal file
@@ -0,0 +1,21 @@
|
||||
@{
|
||||
ViewData["Title"] = "Privacy Policy";
|
||||
}
|
||||
|
||||
<div id="page-success" class="container p-5">
|
||||
<header class="text-center">
|
||||
<div class="icon bg-success text-light">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="72" height="72" fill="currentColor" class="bi bi-check2-circle" viewBox="0 0 16 16">
|
||||
<path d="M2.5 8a5.5 5.5 0 0 1 8.25-4.764.5.5 0 0 0 .5-.866A6.5 6.5 0 1 0 14.5 8a.5.5 0 0 0-1 0 5.5 5.5 0 1 1-11 0z" />
|
||||
<path d="M15.354 3.354a.5.5 0 0 0-.708-.708L8 9.293 5.354 6.646a.5.5 0 1 0-.708.708l3 3a.5.5 0 0 0 .708 0l7-7z" />
|
||||
</svg>
|
||||
</div>
|
||||
<h1>Umschlag erfolgreich signiert!</h1>
|
||||
</header>
|
||||
|
||||
<section class="text-center">
|
||||
<p>Sie haben das Dokument erfolgreich signiert. Im Anschluss erhalten Sie eine schriftliche Bestätigung.</p>
|
||||
</section>
|
||||
|
||||
|
||||
</div>
|
||||
@@ -11,8 +11,27 @@
|
||||
}
|
||||
}
|
||||
|
||||
@foreach (Envelope envelope in @Model)
|
||||
{
|
||||
<li><a href="/EnvelopeKey/@encodeEnvelopeKey(envelope)">@envelope.Title</a></li>
|
||||
}
|
||||
<div class="container">
|
||||
<section>
|
||||
<ul>
|
||||
@foreach (Envelope envelope in @Model)
|
||||
{
|
||||
<li><a href="/EnvelopeKey/@encodeEnvelopeKey(envelope)">@envelope.Title</a></li>
|
||||
}
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<a href="#" id="url" target="_blank">Show image</a>
|
||||
<img src="#" id="img" />
|
||||
</section>
|
||||
|
||||
<script>
|
||||
document.addEventListener("DOMContentLoaded", function() {
|
||||
const anno = new Annotation()
|
||||
anno.createAnnotationFrameBlob("Deine Mudda", 200, 80).then(url => document.getElementById("img").src = url)
|
||||
})
|
||||
</script>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
Colors taken from:
|
||||
https://tailwindcss.com/docs/customizing-colors#default-color-palette
|
||||
*/
|
||||
|
||||
.button-finish {
|
||||
transition: background-color linear 300ms;
|
||||
background-color: #059669;
|
||||
color: white;
|
||||
border-left: none;
|
||||
}
|
||||
|
||||
.button-finish:hover, .button-finish:focus, .button-finish:active {
|
||||
background-color: #10b981;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.button-reset {
|
||||
transition: background-color linear 300ms;
|
||||
background-color: #2563eb;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.button-reset:hover, .button-reset:focus, .button-reset:active {
|
||||
background-color: #3b82f6;
|
||||
color: white;
|
||||
}
|
||||
|
||||
#page-success header .icon {
|
||||
display: inline-block;
|
||||
border-radius: 100px;
|
||||
padding: 15px;
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
@@ -20,7 +20,7 @@
|
||||
))
|
||||
).flatMap((annotations) =>
|
||||
annotations.reduce((acc, annotation) => acc.concat(annotation), [])
|
||||
).filter((annotation) => !!annotation.isSignature);
|
||||
).filter((annotation) => !!annotation.isSignature || annotation.description == "FRAME");
|
||||
//deleting all Annotations
|
||||
return await instance.delete(pageAnnotations);
|
||||
}
|
||||
@@ -50,9 +50,9 @@
|
||||
const annotation = this.createSignatureAnnotation(id, width, height, top, left, page)
|
||||
console.log(annotation)
|
||||
|
||||
const formField = new SignatureFormField({
|
||||
const formField = new PSPDFKit.FormFields.SignatureFormField({
|
||||
name: id,
|
||||
annotationIds: List([annotation.id])
|
||||
annotationIds: PSPDFKit.Immutable.List([annotation.id])
|
||||
})
|
||||
console.log(formField)
|
||||
|
||||
@@ -64,12 +64,54 @@
|
||||
id: id,
|
||||
pageIndex: pageIndex,
|
||||
formFieldName: id,
|
||||
boundingBox: new Rect({ width, height, top, left })
|
||||
boundingBox: new PSPDFKit.Geometry.Rect({ width, height, top, left })
|
||||
})
|
||||
|
||||
return annotation
|
||||
}
|
||||
|
||||
async createAnnotationFrameBlob(receiverName, width, height) {
|
||||
const canvas = document.createElement("canvas");
|
||||
canvas.width = width;
|
||||
canvas.height = height;
|
||||
|
||||
const ctx = canvas.getContext("2d");
|
||||
|
||||
const date = new Date();
|
||||
const dateString = date.toLocaleDateString("de-DE");
|
||||
|
||||
const signatureLength = 100;
|
||||
|
||||
ctx.beginPath();
|
||||
|
||||
ctx.moveTo(30, 10);
|
||||
ctx.lineTo(signatureLength, 10);
|
||||
|
||||
ctx.moveTo(30, 10);
|
||||
ctx.arcTo(10, 10, 10, 30, 20);
|
||||
|
||||
ctx.moveTo(10, 30);
|
||||
ctx.arcTo(10, 50, 30, 50, 20);
|
||||
|
||||
ctx.moveTo(30, 50);
|
||||
ctx.lineTo(signatureLength, 50);
|
||||
|
||||
ctx.strokeStyle = "darkblue";
|
||||
ctx.stroke();
|
||||
|
||||
ctx.fillStyle = "black";
|
||||
ctx.font = "10px serif";
|
||||
ctx.fillText("Signed by", 30, 10)
|
||||
ctx.fillText(receiverName + ", " + dateString, 15, 60)
|
||||
|
||||
return new Promise(resolve => {
|
||||
canvas.toBlob((blob) => {
|
||||
const url = URL.createObjectURL(blob);
|
||||
resolve(url)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
inchToPoint(inch) {
|
||||
return inch * 72;
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ class App {
|
||||
|
||||
this.Instance = null;
|
||||
this.currentDocument = null;
|
||||
this.currentReceiver = null;
|
||||
}
|
||||
|
||||
// This function will be called in the ShowEnvelope.razor page
|
||||
@@ -32,6 +33,9 @@ class App {
|
||||
console.debug("Loading envelope from database..")
|
||||
const envelopeObject = await this.Network.getEnvelope(this.envelopeKey);
|
||||
this.currentDocument = envelopeObject.envelope.documents[0];
|
||||
this.currentReceiver = envelopeObject.receiver;
|
||||
|
||||
console.log(envelopeObject)
|
||||
|
||||
// Load the document from the filestore
|
||||
console.debug("Loading document from filestore")
|
||||
@@ -47,13 +51,85 @@ class App {
|
||||
this.Instance = await this.UI.loadPSPDFKit(arrayBuffer, this.container)
|
||||
this.UI.configurePSPDFKit(this.Instance, this.handleClick.bind(this))
|
||||
|
||||
this.Instance.addEventListener("annotations.load", this.handleAnnotationsLoad)
|
||||
this.Instance.addEventListener("annotations.change", this.handleAnnotationsChange)
|
||||
this.Instance.addEventListener("annotations.create", this.handleAnnotationsCreate.bind(this))
|
||||
|
||||
// Load annotations into PSPDFKit
|
||||
console.debug("Loading annotations..")
|
||||
const annotations = this.Annotation.createAnnotations(this.currentDocument)
|
||||
const createdAnnotations = await this.Instance.create(annotations)
|
||||
|
||||
const description = "Umschlag wurde geöffnet"
|
||||
await this.Network.postHistory(this.envelopeKey, ActionType.Seen, description);
|
||||
try {
|
||||
const annotations = this.Annotation.createAnnotations(this.currentDocument)
|
||||
const createdAnnotations = await this.Instance.create(annotations)
|
||||
|
||||
const description = "Umschlag wurde geöffnet"
|
||||
await this.Network.postHistory(this.envelopeKey, ActionType.Seen, description);
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
handleAnnotationsLoad(loadedAnnotations) {
|
||||
console.log("annotations loaded", loadedAnnotations.toJS());
|
||||
}
|
||||
|
||||
handleAnnotationsChange() {}
|
||||
|
||||
async handleAnnotationsCreate(createdAnnotations) {
|
||||
console.log("annotations created");
|
||||
|
||||
console.log(createdAnnotations.toJS())
|
||||
|
||||
const annotation = createdAnnotations.toJS()[0];
|
||||
const isFormField = !!annotation.formFieldName;
|
||||
const isSignature = !!annotation.isSignature;
|
||||
|
||||
console.log("form field", isFormField, "signature", isSignature)
|
||||
|
||||
//if (!isSignature) {
|
||||
// return;
|
||||
//}
|
||||
|
||||
//if (!(isFormField && isSignature)) {
|
||||
// return;
|
||||
//}
|
||||
|
||||
if (isFormField === false && isSignature === true) {
|
||||
|
||||
|
||||
const left = annotation.boundingBox.left - 25;
|
||||
const top = annotation.boundingBox.top - 25;
|
||||
const width = 150;
|
||||
const height = 75;
|
||||
|
||||
console.log(annotation.boundingBox)
|
||||
|
||||
const imageUrl = await this.Annotation.createAnnotationFrameBlob(this.currentReceiver.name, width, height);
|
||||
|
||||
const request = await fetch(imageUrl);
|
||||
const blob = await request.blob();
|
||||
const imageAttachmentId = await this.Instance.createAttachment(blob);
|
||||
const frameAnnotation = new PSPDFKit.Annotations.ImageAnnotation({
|
||||
pageIndex: annotation.pageIndex,
|
||||
isSignature: false,
|
||||
readOnly: true,
|
||||
locked: true,
|
||||
lockedContents: true,
|
||||
contentType: 'image/png',
|
||||
imageAttachmentId,
|
||||
description: 'FRAME',
|
||||
boundingBox: new PSPDFKit.Geometry.Rect({
|
||||
left: left,
|
||||
top: top,
|
||||
width: width,
|
||||
height: height,
|
||||
}),
|
||||
});
|
||||
|
||||
this.Instance.create(frameAnnotation);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
async handleClick(eventType) {
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
// and a arraybuffer which represents the document that should be displayed.
|
||||
loadPSPDFKit(arrayBuffer, container) {
|
||||
return PSPDFKit.load({
|
||||
styleSheets: ['/css/site.css'],
|
||||
container: container,
|
||||
document: arrayBuffer,
|
||||
autoSaveMode: "DISABLED",
|
||||
@@ -26,24 +27,20 @@
|
||||
isEditableAnnotation: function (annotation) {
|
||||
// Check if the annotation is a signature
|
||||
// This will allow new signatures, but not allow edits.
|
||||
return !annotation.isSignature;
|
||||
console.log(annotation.isSignature, annotation.description)
|
||||
|
||||
if (annotation.isSignature || annotation.description == "FRAME") {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
//return !annotation.isSignature;
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
configurePSPDFKit(instance, handler) {
|
||||
instance.addEventListener("annotations.load", (loadedAnnotations) => {
|
||||
console.log("annotations loaded", loadedAnnotations.toJS());
|
||||
})
|
||||
|
||||
instance.addEventListener("annotations.change", () => {
|
||||
console.log("annotations changed")
|
||||
})
|
||||
|
||||
instance.addEventListener("annotations.create", async (createdAnnotations) => {
|
||||
console.log("annotations created");
|
||||
})
|
||||
|
||||
const toolbarItems = this.getToolbarItems(instance, handler)
|
||||
instance.setToolbarItems(toolbarItems)
|
||||
|
||||
@@ -56,14 +53,22 @@
|
||||
return defaultItems.concat(customItems)
|
||||
}
|
||||
|
||||
createElementFromHTML(html) {
|
||||
const el = document.createElement('div')
|
||||
el.innerHTML = html.trim()
|
||||
|
||||
return el.firstChild
|
||||
}
|
||||
|
||||
getCustomItems = function (callback) {
|
||||
const customItems = [
|
||||
return [
|
||||
{
|
||||
type: "custom",
|
||||
id: "button-reset",
|
||||
className: "button-reset",
|
||||
title: "Zurücksetzen",
|
||||
onPress() {
|
||||
console.log("RESET")
|
||||
callback("RESET")
|
||||
},
|
||||
icon: `<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor" class="bi bi-arrow-counterclockwise" viewBox="0 0 16 16">
|
||||
@@ -77,15 +82,11 @@
|
||||
className: "button-finish",
|
||||
title: "Abschließen",
|
||||
onPress() {
|
||||
console.log("FINISH")
|
||||
callback("FINISH")
|
||||
},
|
||||
icon: `<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor" class="bi bi-check2-circle" viewBox="0 0 16 16">
|
||||
<path d="M2.5 8a5.5 5.5 0 0 1 8.25-4.764.5.5 0 0 0 .5-.866A6.5 6.5 0 1 0 14.5 8a.5.5 0 0 0-1 0 5.5 5.5 0 1 1-11 0z"/>
|
||||
<path d="M15.354 3.354a.5.5 0 0 0-.708-.708L8 9.293 5.354 6.646a.5.5 0 1 0-.708.708l3 3a.5.5 0 0 0 .708 0l7-7z" />
|
||||
</svg>`
|
||||
}
|
||||
}
|
||||
]
|
||||
return customItems
|
||||
}
|
||||
|
||||
getDefaultItems(items) {
|
||||
|
||||
Reference in New Issue
Block a user