Compare commits

...

8 Commits

Author SHA1 Message Date
Developer 02
425645a610 feat: neue Klasse für Desktop-Schaltflächen mit dem Namen 'btn-desktop' erstellt
- CSS hinzugefügt, um die Klasse btn-desktop auszublenden, wenn die Breite weniger als 1024px beträgt.
2024-10-14 17:41:51 +02:00
Developer 02
24e6ffc5ef feat: CSS mit Bootstrap für mobil beschreibbare Toolbar-Elemente anordnen 2024-10-14 17:24:49 +02:00
Developer 02
1dd9ce6bbc feat: Aktivieren Sie die Schaltfläche für die mobile Ablehnung.
- Ereignis hinzugefügt.
 - In die Mitte der Schaltflächenleiste verschoben
2024-10-14 17:06:01 +02:00
Developer 02
e528fa6409 feat: getMobileItems umbenennen in getMobileWritableItems 2024-10-14 16:05:27 +02:00
Developer 02
6440dd09d1 feat: Erstellung der konstanten Variablen DEVICE_TYPE und IS_DESKTOP.
- Aufteilung der benutzerdefinierten Symbolleistenelemente in writableItems und mobileItems
 - beide werden abhängig von der jeweiligen Bedingung hinzugefügt
2024-10-14 15:44:21 +02:00
Developer 02
869493bd97 feat: Globale Konstante isReadOnly-Wert erstellt.
- Constraint für ReadOnly-Schaltfläche mit isReadOnly-Wert hinzugefügt
2024-10-14 14:02:02 +02:00
Developer 02
1cb9042736 feat(ui.js): Freigabe-Schaltfläche als Symbolleisten-Schaltfläche hinzugefügt.
- Share-Button auf der linken Seite der Kopfzeile entfernt
2024-10-14 11:27:41 +02:00
Developer 02
c9410a1e2e feat(ReadOnlyController): Try-Catch zur 'CreateAsync'-Methode hinzugefügt.
- Unnötige Testmethoden wurden aus dem Controller entfernt.
2024-10-14 09:38:16 +02:00
11 changed files with 280 additions and 191 deletions

View File

@@ -28,79 +28,75 @@ namespace EnvelopeGenerator.Web.Controllers
_histService = histService;
}
[HttpGet]
[Authorize]
public async Task<IActionResult> GetAllAsync()
{
var res = await _erroService.ReadAllAsync();
return Ok(res);
}
[HttpPost]
[Authorize]
public async Task<IActionResult> CreateAsync([FromBody] EnvelopeReceiverReadOnlyCreateDto createDto)
{
//set AddedWho
var authReceiverMail = this.GetAuthReceiverMail();
if (authReceiverMail is null)
try
{
_logger.LogError("Email clam is not found in envelope-receiver-read-only creation process. Create DTO is:\n {dto}", JsonConvert.SerializeObject(createDto));
return Unauthorized();
}
var envelopeId = this.GetAuthEnvelopeId();
if (envelopeId is null)
{
_logger.LogError("Envelope Id clam is not found in envelope-receiver-read-only creation process. Create DTO is:\n {dto}", JsonConvert.SerializeObject(createDto));
return Unauthorized();
}
createDto.AddedWho = authReceiverMail;
createDto.EnvelopeId = envelopeId;
// create entity
var creation_res = await _erroService.CreateAsync(createDto: createDto);
if (creation_res.IsFailed)
{
_logger.LogNotice(creation_res);
return StatusCode(StatusCodes.Status500InternalServerError);
}
//read new entity
var read_res = await _erroService.ReadByIdAsync(creation_res.Data);
if (read_res.IsFailed)
{
_logger.LogNotice(creation_res);
return StatusCode(StatusCodes.Status500InternalServerError);
}
var new_erro = read_res.Data;
//send email two receiver
return await _mailService.SendAsync(new_erro).ThenAsync<int, IActionResult>(SuccessAsync: async res =>
{
//TODO: implement multi-threading to history process (Task)
//TODO: remove casting after change the id type
var hist_res = await _histService.RecordAsync((int) createDto.EnvelopeId, createDto.AddedWho, Common.Constants.EnvelopeStatus.EnvelopeShared);
if (hist_res.IsFailed)
//set AddedWho
var authReceiverMail = this.GetAuthReceiverMail();
if (authReceiverMail is null)
{
_logger.LogError("Although the envelope was sent as read-only, the EnvelopeShared hisotry could not be saved. Create DTO:\n{createDto}", JsonConvert.SerializeObject(createDto));
_logger.LogNotice(hist_res.Notices);
_logger.LogError("Email clam is not found in envelope-receiver-read-only creation process. Create DTO is:\n {dto}", JsonConvert.SerializeObject(createDto));
return Unauthorized();
}
return Ok();
},
Fail: (msg, ntc) =>
{
_logger.LogNotice(ntc);
return StatusCode(StatusCodes.Status500InternalServerError);
});
}
var envelopeId = this.GetAuthEnvelopeId();
if (envelopeId is null)
{
_logger.LogError("Envelope Id clam is not found in envelope-receiver-read-only creation process. Create DTO is:\n {dto}", JsonConvert.SerializeObject(createDto));
return Unauthorized();
}
[HttpGet("key/{readOnlyId}")]
public IActionResult CreateLink(long readOnlyId) => Ok(
Request.Headers["Origin"].ToString() + "/EnvelopeKey/" + readOnlyId.EncodeEnvelopeReceiverId());
createDto.AddedWho = authReceiverMail;
createDto.EnvelopeId = envelopeId;
// create entity
var creation_res = await _erroService.CreateAsync(createDto: createDto);
if (creation_res.IsFailed)
{
_logger.LogNotice(creation_res);
return StatusCode(StatusCodes.Status500InternalServerError);
}
//read new entity
var read_res = await _erroService.ReadByIdAsync(creation_res.Data);
if (read_res.IsFailed)
{
_logger.LogNotice(creation_res);
return StatusCode(StatusCodes.Status500InternalServerError);
}
var new_erro = read_res.Data;
//send email two receiver
return await _mailService.SendAsync(new_erro).ThenAsync<int, IActionResult>(SuccessAsync: async res =>
{
//TODO: implement multi-threading to history process (Task)
//TODO: remove casting after change the id type
var hist_res = await _histService.RecordAsync((int)createDto.EnvelopeId, createDto.AddedWho, Common.Constants.EnvelopeStatus.EnvelopeShared);
if (hist_res.IsFailed)
{
_logger.LogError("Although the envelope was sent as read-only, the EnvelopeShared hisotry could not be saved. Create DTO:\n{createDto}", JsonConvert.SerializeObject(createDto));
_logger.LogNotice(hist_res.Notices);
}
return Ok();
},
Fail: (msg, ntc) =>
{
_logger.LogNotice(ntc);
return StatusCode(StatusCodes.Status500InternalServerError);
});
}
catch(Exception ex)
{
_logger.LogError(ex, "{Message}", ex.Message);
return StatusCode(StatusCodes.Status500InternalServerError);
}
}
}
}

View File

@@ -31,20 +31,20 @@
@if (!isReadOnly)
{
<div id="flex-action-panel" class="btn-group btn_group position-fixed bottom-0 end-0 d-flex align-items-center" role="group" aria-label="Basic mixed styles example">
<button class="btn_complete btn btn-primary" type="button">
<button class="btn_complete btn btn-primary btn-desktop" type="button">
<svg class="icon" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewBox="0 0 20 16">
<path d="m10.036 8.278 9.258-7.79A1.979 1.979 0 0 0 18 0H2A1.987 1.987 0 0 0 .641.541l9.395 7.737Z" />
<path d="M11.241 9.817c-.36.275-.801.425-1.255.427-.428 0-.845-.138-1.187-.395L0 2.6V14a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2V2.5l-8.759 7.317Z" />
</svg>
<span>@_localizer[WebKey.Complete]</span>
</button>
<button class="btn_reject btn btn-danger" type="button">
<button class="btn_reject btn btn-danger btn-desktop" type="button">
<svg width="25px" height="25px" viewBox="43.5 43.5 512 512" version="1.1" fill="currentColor" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<path class="st0" d="M263.24,43.5c-117.36,0-212.5,95.14-212.5,212.5s95.14,212.5,212.5,212.5s212.5-95.14,212.5-212.5 S380.6,43.5,263.24,43.5z M367.83,298.36c17.18,17.18,17.18,45.04,0,62.23v0c-17.18,17.18-45.04,17.18-62.23,0l-42.36-42.36 l-42.36,42.36c-17.18,17.18-45.04,17.18-62.23,0v0c-17.18-17.18-17.18-45.04,0-62.23L201.01,256l-42.36-42.36 c-17.18-17.18-17.18-45.04,0-62.23v0c17.18-17.18,45.04-17.18,62.23,0l42.36,42.36l42.36-42.36c17.18-17.18,45.04-17.18,62.23,0v0 c17.18,17.18,17.18,45.04,0,62.23L325.46,256L367.83,298.36z" />
</svg>
<span>@_localizer[WebKey.Reject]</span>
</button>
<button class="btn_refresh btn btn-secondary" type="button">
<button class="btn_refresh btn btn-secondary btn-desktop" type="button">
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor" class="bi bi-arrow-counterclockwise" viewBox="0 0 16 16">
<path fill-rule="evenodd" d="M8 3a5 5 0 1 1-4.546 2.914.5.5 0 0 0-.908-.417A6 6 0 1 0 8 2v1z" />
<path d="M8 4.466V.534a.25.25 0 0 0-.41-.192L5.23 2.308a.25.25 0 0 0 0 .384l2.36 1.966A.25.25 0 0 0 8 4.466z" />
@@ -57,19 +57,11 @@
<div class="dd-card-preview">
<h6 class="uppercase">Digital Data</h6>
<h2>signFlow</h2>
@if (!isReadOnly)
@if (isReadOnly)
{
<button type="button" data-bs-toggle="modal" data-bs-target="#staticBackdrop">
<button type="button" id="btn-copy">
<span class="material-symbols-outlined">
share
</span>
</button>
}
else
{
<button type="button" data-bs-toggle="modal" id="btn-copy" data-bs-target="#staticBackdrop">
<span class="material-symbols-outlined">
content_copy
content_copy
</span>
</button>
}
@@ -116,11 +108,11 @@
</div>
@if (!isReadOnly)
{
<div class="modal fade" id="staticBackdrop" data-bs-backdrop="static" data-bs-keyboard="false" tabindex="-1" aria-labelledby="staticBackdropLabel" aria-hidden="true">
<div class="modal fade" id="shareBackdrop" data-bs-backdrop="static" data-bs-keyboard="false" tabindex="-1" aria-labelledby="shareBackdropLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<small class="modal-title text-body-secondary" id="staticBackdropLabel">Geben Sie hier den Empfänger ein, mit welchem Sie das Dokument teilen wollen:</small>
<small class="modal-title text-body-secondary" id="shareBackdropLabel">Geben Sie hier den Empfänger ein, mit welchem Sie das Dokument teilen wollen:</small>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">

View File

@@ -3,9 +3,13 @@
@using Newtonsoft.Json.Serialization
@{
var nonce = _accessor.HttpContext?.Items["csp-nonce"] as string;
var isReadOnly = false;
if (ViewData["IsReadOnly"] is bool isReadOnly_bool)
isReadOnly = isReadOnly_bool;
}
<!DOCTYPE html>
<html lang="en">
<html lang="de">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no" />
@@ -27,10 +31,19 @@
font-variation-settings: 'FILL' 0, 'wght' 400, 'GRAD' 0, 'opsz' 24
}
</style>
<script nonce="@nonce">
@if (ViewData["EnvelopeKey"] is string envelopeKey)
{
<script nonce="@nonce">const ENV_KEY = "@envelopeKey.TrySanitize(_sanitizer)"</script>
@: const ENV_KEY = "@envelopeKey.TrySanitize(_sanitizer)"
}
const IS_READONLY = @isReadOnly.ToString().ToLower();
const DEVICE_TYPE = window.innerWidth <= 768 ? 'mobile' : window.innerWidth <= 1024 ? 'tablet' : 'desktop';
const IS_DESKTOP = DEVICE_TYPE == 'desktop'
</script>
<script src="~/lib/jquery/dist/jquery.min.js"></script>
<script src="~/lib/popper/dist/umd/popper.min.js"></script>
<script src="~/lib/bootstrap/dist/js/bootstrap.min.js"></script>

View File

@@ -31,39 +31,90 @@
}
.button-finish {
transition: background-color linear 300ms;
background-color: #059669; /* emerald-600 */
color: white;
border-left: none;
color: #fff;
background-color: #0d6efd;
border-color: #0d6efd;
}
.button-finish:hover, .button-finish:focus, .button-finish:active {
background-color: #10b981; /* emerald-500 */
color: white;
.button-finish:hover {
color: #fff;
background-color: #0b5ed7;
border-color: #0a58ca;
}
.button-finish:focus {
box-shadow: 0 0 0 0.25rem rgba(49, 132, 253, 0.5);
}
.button-finish:active {
color: #fff;
background-color: #0a58ca;
border-color: #0a53be;
box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
}
.button-finish:disabled {
color: #fff;
background-color: #0d6efd;
border-color: #0d6efd;
}
.button-reject {
transition: background-color linear 300ms;
background-color: #d97706; /* amber-600 */
color: white;
border-left: none;
color: #fff;
background-color: #dc3545;
border-color: #dc3545;
}
.button-reject:hover, .button-reject:focus, .button-reject:active {
background-color: #f59e0b; /* amber-500 */
color: white;
.button-reject:hover {
color: #fff;
background-color: #bb2d3b;
border-color: #b02a37;
}
.button-reject:focus {
box-shadow: 0 0 0 0.25rem rgba(225, 83, 97, 0.5);
}
.button-reject:active {
color: #fff;
background-color: #b02a37;
border-color: #a52834;
box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
}
.button-reject:disabled {
color: #fff;
background-color: #dc3545;
border-color: #dc3545;
}
.button-reset {
transition: background-color linear 300ms;
background-color: #2563eb; /* blue-600 */
color: white;
border-left: none;
color: #fff;
background-color: #6c757d;
border-color: #6c757d;
}
.button-reset:hover, .button-reset:focus, .button-reset:active {
background-color: #3b82f6; /* blue-500 */
color: white;
.button-reset:hover {
color: #fff;
background-color: #5c636a;
border-color: #565e64;
}
.button-reset:focus {
box-shadow: 0 0 0 0.25rem rgba(130, 138, 145, 0.5);
}
.button-reset:active {
color: #fff;
background-color: #565e64;
border-color: #51585e;
box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
}
.button-reset:disabled {
color: #fff;
background-color: #6c757d;
border-color: #6c757d;
}
body {
@@ -498,6 +549,12 @@ footer#page-footer {
}
}
@media (max-width: 1024px) {
#flex-action-panel, .btn-desktop {
display: none;
}
}
@media (max-height: 600px) {
.collapse {
height: 4rem;

File diff suppressed because one or more lines are too long

View File

@@ -48,7 +48,7 @@ class App {
// Load PSPDFKit
this.Instance = await UI.loadPSPDFKit(arrayBuffer, this.container, this.licenseKey, this.locale)
UI.configurePSPDFKit(this.Instance, this.handleClick.bind(this))
UI.addToolbarItems(this.Instance, this.handleClick.bind(this))
this.Instance.addEventListener(
'annotations.load',
@@ -87,6 +87,7 @@ class App {
//add click events of external buttons
[...document.getElementsByClassName('btn_refresh')].forEach(btn => btn.addEventListener('click', _ => this.handleClick('RESET')));
[...document.getElementsByClassName('btn_complete')].forEach(btn => btn.addEventListener('click', _ => this.handleClick('FINISH')));
[...document.getElementsByClassName('btn_reject')].forEach(btn => btn.addEventListener('click', _ => this.handleClick('REJECT')));
}
handleAnnotationsLoad(loadedAnnotations) {
@@ -163,19 +164,59 @@ class App {
break
case 'REJECT':
alert('Dokument abgelent!')
Swal.fire({
title: localized.rejection,
html: `<div class="text-start fs-6 p-0 m-0">${localized.rejectionReasonQ}</div>`,
icon: "question",
input: "text",
inputAttributes: {
autocapitalize: "off"
},
showCancelButton: true,
confirmButtonColor: "#3085d6",
cancelButtonColor: "#d33",
confirmButtonText: localized.complete,
cancelButtonText: localized.back,
showLoaderOnConfirm: true,
preConfirm: async (reason) => {
try {
var res = await rejectEnvelope(reason);
return res;
} catch (error) {
Swal.showValidationMessage(`
Request failed: ${error}
`);
}
},
allowOutsideClick: () => !Swal.isLoading()
}).then((result) => {
if (!result.isConfirmed)
return;
const res = result.value;
if (res.ok) {
redirRejected()
}
else
Swal.showValidationMessage(`Request failed: ${res.message}`);
});
break;
case 'SHARE':
// Show the modal
Comp.ShareBackdrop.show();
break;
}
}
async handleFinish(event) {
const iJSON = await this.Instance.exportInstantJSON()
const iFormFieldValues = await iJSON.formFieldValues;
//check required
const iReqFields = iFormFieldValues.filter(f => Annotation.isFieldRequired(f))
const hasEmptyReq = iReqFields.some(f => (f.value === undefined || f.value === null || f.value === ""))
if (hasEmptyReq){
if (hasEmptyReq) {
Swal.fire({
title: 'Warnung',
text: 'Bitte füllen Sie alle Standortinformationen vollständig aus!',
@@ -187,8 +228,8 @@ 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))
for(var f of iCityFields)
if(!city_regex.test(f.value)){
for (var f of iCityFields)
if (!city_regex.test(f.value)) {
Swal.fire({
title: 'Warnung',
text: `Bitte überprüfen Sie die eingegebene Ortsangabe "${f.value}" auf korrekte Formatierung. Beispiele für richtige Formate sind: München, Île-de-France, Sauðárkrókur, San Francisco, St. Catharines usw.`,

View File

@@ -1 +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.configurePSPDFKit(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")))}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":alert("Dokument abgelent!")}}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(!f.test(i.value))return Swal.fire({title:"Warnung",text:`Bitte überprüfen Sie die eingegebene Ortsangabe "${i.value}" auf korrekte Formatierung. Beispiele für richtige Formate sind: München, Île-de-France, Sauðárkrókur, San Francisco, St. Catharines usw.`,icon:"warning"}),!1;const o=await this.validateAnnotations(this.signatureCount);return o===!1?(Swal.fire({title:"Warnung",text:"Es wurden nicht alle Signaturfelder ausgefüllt!",icon:"warning"}),!1):Swal.fire({title:localized.confirmation,html:`<div class="text-start fs-6 p-0 m-0">${localized.sigAgree}</div>`,icon:"question",showCancelButton:!0,confirmButtonColor:"#3085d6",cancelButtonColor:"#d33",confirmButtonText:localized.finalize,cancelButtonText:localized.back}).then(async t=>{if(t.isConfirmed){try{await this.Instance.save()}catch(i){return Swal.fire({title:"Fehler",text:"Umschlag konnte nicht signiert werden!",icon:"error"}),!1}try{const i=await n,t=await this.Network.postEnvelope(this.envelopeKey,this.currentDocument.id,i);return t.fatal?(Swal.fire({title:"Fehler",text:"Umschlag konnte nicht signiert werden!",icon:"error"}),!1):t.error?(Swal.fire({title:"Warnung",text:"Umschlag ist nicht mehr verfügbar.",icon:"warning"}),!1):!0}catch(i){return!1}}else return!1})}async validateAnnotations(n){const t=await Annotation.getAnnotations(this.Instance),i=t.map(n=>n.toJS()).filter(n=>n.isSignature);return n>i.length?!1:!0}async handleReset(){const n=await Swal.fire({title:"Sind sie sicher?",text:"Wollen Sie das Dokument und alle erstellten Signaturen zurücksetzen?",icon:"question",showCancelButton:!0});if(n.isConfirmed){const n=await Annotation.deleteAnnotations(this.Instance)}return n}}
const ActionType={Created:0,Saved:1,Sent:2,EmailSent:3,Delivered:4,Seen:5,Signed:6,Rejected:7};class App{constructor(n,t,i,r,u,f){this.container=f??`#${this.constructor.name.toLowerCase()}`;this.envelopeKey=n;this.Network=new Network;this.Instance=null;this.currentDocument=null;this.currentReceiver=null;this.signatureCount=0;this.envelopeReceiver=t;this.documentBytes=i;this.licenseKey=r;this.locale=u}async init(){this.currentDocument=this.envelopeReceiver.envelope.documents[0];this.currentReceiver=this.envelopeReceiver.receiver;const n=this.documentBytes;if(n.fatal||n.error)return Swal.fire({title:"Fehler",text:"Dokument konnte nicht geladen werden!",icon:"error"});const t=this.documentBytes;this.Instance=await UI.loadPSPDFKit(t,this.container,this.licenseKey,this.locale);UI.addToolbarItems(this.Instance,this.handleClick.bind(this));this.Instance.addEventListener("annotations.load",this.handleAnnotationsLoad.bind(this));this.Instance.addEventListener("annotations.change",this.handleAnnotationsChange.bind(this));this.Instance.addEventListener("annotations.create",this.handleAnnotationsCreate.bind(this));this.Instance.addEventListener("annotations.willChange",()=>{Comp.ActPanel.Toggle()});try{this.signatureCount=this.currentDocument.elements.length;await Annotation.createAnnotations(this.currentDocument,this.Instance);const n=await this.Network.openDocument(this.envelopeKey);if(n.fatal||n.error)return Swal.fire({title:"Fehler",text:"Umschlag konnte nicht geöffnet werden!",icon:"error"})}catch(i){}[...document.getElementsByClassName("btn_refresh")].forEach(n=>n.addEventListener("click",()=>this.handleClick("RESET")));[...document.getElementsByClassName("btn_complete")].forEach(n=>n.addEventListener("click",()=>this.handleClick("FINISH")));[...document.getElementsByClassName("btn_reject")].forEach(n=>n.addEventListener("click",()=>this.handleClick("REJECT")))}handleAnnotationsLoad(n){n.toJS()}handleAnnotationsChange(){}async handleAnnotationsCreate(n){const t=n.toJS()[0],i=!!t.formFieldName,r=!!t.isSignature;if(i===!1&&r===!0){const r=t.boundingBox.left-20,u=t.boundingBox.top-20,n=150,i=75,f=new Date,e=await Annotation.createAnnotationFrameBlob(this.envelopeReceiver.name,this.currentReceiver.signature,f,n,i),o=await fetch(e),s=await o.blob(),h=await this.Instance.createAttachment(s),c=Annotation.createImageAnnotation(new PSPDFKit.Geometry.Rect({left:r,top:u,width:n,height:i}),t.pageIndex,h);this.Instance.create(c)}}async handleClick(n){let t=!1;switch(n){case"RESET":t=await this.handleReset(null);Comp.SignatureProgress.SignedCount=0;t.isConfirmed&&Swal.fire({title:"Erfolg",text:"Dokument wurde zurückgesetzt",icon:"info"});break;case"FINISH":t=await this.handleFinish(null);t==!0&&(window.location.href=`/EnvelopeKey/${this.envelopeKey}/Success`);break;case"REJECT":Swal.fire({title:localized.rejection,html:`<div class="text-start fs-6 p-0 m-0">${localized.rejectionReasonQ}</div>`,icon:"question",input:"text",inputAttributes:{autocapitalize:"off"},showCancelButton:!0,confirmButtonColor:"#3085d6",cancelButtonColor:"#d33",confirmButtonText:localized.complete,cancelButtonText:localized.back,showLoaderOnConfirm:!0,preConfirm:async n=>{try{return await rejectEnvelope(n)}catch(t){Swal.showValidationMessage(`
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"SHARE":Comp.ShareBackdrop.show()}}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(!f.test(i.value))return Swal.fire({title:"Warnung",text:`Bitte überprüfen Sie die eingegebene Ortsangabe "${i.value}" auf korrekte Formatierung. Beispiele für richtige Formate sind: München, Île-de-France, Sauðárkrókur, San Francisco, St. Catharines usw.`,icon:"warning"}),!1;const o=await this.validateAnnotations(this.signatureCount);return o===!1?(Swal.fire({title:"Warnung",text:"Es wurden nicht alle Signaturfelder ausgefüllt!",icon:"warning"}),!1):Swal.fire({title:localized.confirmation,html:`<div class="text-start fs-6 p-0 m-0">${localized.sigAgree}</div>`,icon:"question",showCancelButton:!0,confirmButtonColor:"#3085d6",cancelButtonColor:"#d33",confirmButtonText:localized.finalize,cancelButtonText:localized.back}).then(async t=>{if(t.isConfirmed){try{await this.Instance.save()}catch(i){return Swal.fire({title:"Fehler",text:"Umschlag konnte nicht signiert werden!",icon:"error"}),!1}try{const i=await n,t=await this.Network.postEnvelope(this.envelopeKey,this.currentDocument.id,i);return t.fatal?(Swal.fire({title:"Fehler",text:"Umschlag konnte nicht signiert werden!",icon:"error"}),!1):t.error?(Swal.fire({title:"Warnung",text:"Umschlag ist nicht mehr verfügbar.",icon:"warning"}),!1):!0}catch(i){return!1}}else return!1})}async validateAnnotations(n){const t=await Annotation.getAnnotations(this.Instance),i=t.map(n=>n.toJS()).filter(n=>n.isSignature);return n>i.length?!1:!0}async handleReset(){const n=await Swal.fire({title:"Sind sie sicher?",text:"Wollen Sie das Dokument und alle erstellten Signaturen zurücksetzen?",icon:"question",showCancelButton:!0});if(n.isConfirmed){const n=await Annotation.deleteAnnotations(this.Instance)}return n}}

View File

@@ -1,40 +1,3 @@
$('.btn_reject').click(_ =>
Swal.fire({
title: localized.rejection,
html: `<div class="text-start fs-6 p-0 m-0">${localized.rejectionReasonQ}</div>`,
icon: "question",
input: "text",
inputAttributes: {
autocapitalize: "off"
},
showCancelButton: true,
confirmButtonColor: "#3085d6",
cancelButtonColor: "#d33",
confirmButtonText: localized.complete,
cancelButtonText: localized.back,
showLoaderOnConfirm: true,
preConfirm: async (reason) => {
try {
var res = await rejectEnvelope(reason);
return res;
} catch (error) {
Swal.showValidationMessage(`
Request failed: ${error}
`);
}
},
allowOutsideClick: () => !Swal.isLoading()
}).then((result) => {
if (!result.isConfirmed)
return;
const res = result.value;
if (res.ok) {
redirRejected()
}
else
Swal.showValidationMessage(`Request failed: ${res.message}`);
}));
document.querySelectorAll('.email-input').forEach(input => {
input.addEventListener('input', function () {
if (/^\S+@\S+\.\S+$/.test(this.value)) {
@@ -110,4 +73,10 @@ class Comp {
return this.__SignedCountBar;
}
}
static __ShareBackdrop;
static get ShareBackdrop() {
Comp.__ShareBackdrop ??= new bootstrap.Modal(document.getElementById('shareBackdrop'));
return this.__ShareBackdrop;
}
}

View File

@@ -1,3 +1 @@
$(".btn_reject").click(()=>Swal.fire({title:localized.rejection,html:`<div class="text-start fs-6 p-0 m-0">${localized.rejectionReasonQ}</div>`,icon:"question",input:"text",inputAttributes:{autocapitalize:"off"},showCancelButton:!0,confirmButtonColor:"#3085d6",cancelButtonColor:"#d33",confirmButtonText:localized.complete,cancelButtonText:localized.back,showLoaderOnConfirm:!0,preConfirm:async n=>{try{return await rejectEnvelope(n)}catch(t){Swal.showValidationMessage(`
Request failed: ${t}
`)}},allowOutsideClick:()=>!Swal.isLoading()}).then(n=>{if(n.isConfirmed){const t=n.value;t.ok?redirRejected():Swal.showValidationMessage(`Request failed: ${t.message}`)}}));document.querySelectorAll(".email-input").forEach(n=>{n.addEventListener("input",function(){/^\S+@\S+\.\S+$/.test(this.value)?this.classList.remove("is-invalid"):this.classList.add("is-invalid")})});const bsNotify=(n,t)=>alertify.notify(`<div class="alert ${t.alert_type?"alert-"+t.alert_type:""}" role="alert"><span class="material-symbols-outlined">${t?.icon_name??""}</span><p>${n}</p></div>`,"custom",t?.delay??5);class Comp{static ActPanel=class{static __Root;static get Root(){Comp.ActPanel.__Root??=document.getElementById("flex-action-panel");return Comp.ActPanel.__Root}static get Elements(){return[...Comp.ActPanel.Root.children]}static get IsHided(){return Comp.ActPanel.Root.style.display=="none"}static set Display(n){Comp.ActPanel.Root.style.display=n;Comp.ActPanel.Elements.forEach(t=>t.style.display=n)}static Toggle(){Comp.ActPanel.Display=Comp.ActPanel.IsHided?"":"none"}};static SignatureProgress=class{static __SignatureCount;static get SignatureCount(){this.__SignatureCount=parseInt(document.getElementById("signature-count").innerText);return this.__SignatureCount}static __SignedCountSpan;static get SignedCountSpan(){this.__SignedCountSpan??=document.getElementById("signed-count");return Comp.SignatureProgress.__SignedCountSpan}static __signedCount=0;static get SignedCount(){return this.__signedCount}static set SignedCount(n){this.__signedCount=n;const t=(n/this.SignatureCount)*100;this.SignedCountBar.style.setProperty("--progress-width",t+"%");this.SignedCountSpan.innerText=n.toString()}static __SignedCountBar;static get SignedCountBar(){this.__SignedCountBar??=document.getElementById("signed-count-bar");return this.__SignedCountBar}};}
document.querySelectorAll(".email-input").forEach(n=>{n.addEventListener("input",function(){/^\S+@\S+\.\S+$/.test(this.value)?this.classList.remove("is-invalid"):this.classList.add("is-invalid")})});const bsNotify=(n,t)=>alertify.notify(`<div class="alert ${t.alert_type?"alert-"+t.alert_type:""}" role="alert"><span class="material-symbols-outlined">${t?.icon_name??""}</span><p>${n}</p></div>`,"custom",t?.delay??5);class Comp{static ActPanel=class{static __Root;static get Root(){Comp.ActPanel.__Root??=document.getElementById("flex-action-panel");return Comp.ActPanel.__Root}static get Elements(){return[...Comp.ActPanel.Root.children]}static get IsHided(){return Comp.ActPanel.Root.style.display=="none"}static set Display(n){Comp.ActPanel.Root.style.display=n;Comp.ActPanel.Elements.forEach(t=>t.style.display=n)}static Toggle(){Comp.ActPanel.Display=Comp.ActPanel.IsHided?"":"none"}};static SignatureProgress=class{static __SignatureCount;static get SignatureCount(){this.__SignatureCount=parseInt(document.getElementById("signature-count").innerText);return this.__SignatureCount}static __SignedCountSpan;static get SignedCountSpan(){this.__SignedCountSpan??=document.getElementById("signed-count");return Comp.SignatureProgress.__SignedCountSpan}static __signedCount=0;static get SignedCount(){return this.__signedCount}static set SignedCount(n){this.__signedCount=n;const t=(n/this.SignatureCount)*100;this.SignedCountBar.style.setProperty("--progress-width",t+"%");this.SignedCountSpan.innerText=n.toString()}static __SignedCountBar;static get SignedCountBar(){this.__SignedCountBar??=document.getElementById("signed-count-bar");return this.__SignedCountBar}};static __ShareBackdrop;static get ShareBackdrop(){return Comp.__ShareBackdrop??=new bootstrap.Modal(document.getElementById("shareBackdrop")),this.__ShareBackdrop}}

View File

@@ -10,6 +10,7 @@
'zoom-mode',
'spacer',
'search',
'export-pdf'
]
// Load the PSPDFKit UI by setting a target element as the container to render in
@@ -49,9 +50,15 @@
return UI.Instance;
}
static configurePSPDFKit(instance, handler) {
const toolbarItems = UI.getToolbarItems(instance, handler)
toolbarItems.push({type: "export-pdf"})
static addToolbarItems(instance, handler) {
var toolbarItems = instance.toolbarItems.filter((item) => UI.allowedToolbarItems.includes(item.type));
if (!IS_READONLY)
toolbarItems = toolbarItems.concat(UI.getWritableItems(handler));
if (!IS_DESKTOP && !IS_READONLY)
toolbarItems = toolbarItems.concat(UI.getMobileWritableItems(handler));
instance.setToolbarItems(toolbarItems)
}
@@ -60,12 +67,6 @@
return null
}
static getToolbarItems(instance, handler) {
const customItems = UI.getCustomItems(handler)
const defaultItems = UI.getDefaultItems(instance.toolbarItems)
return defaultItems.concat(customItems)
}
static createElementFromHTML(html) {
const el = document.createElement('div')
el.innerHTML = html.trim()
@@ -73,21 +74,36 @@
return el.firstChild
}
static getCustomItems = function (callback) {
return []
static getWritableItems = function (callback) {
return [
{
type: 'custom',
id: 'button-reset',
className: 'button-reset',
title: 'Zurücksetzen',
id: 'button-share',
className: 'button-share',
title: 'Teilen',
onPress() {
callback('RESET')
callback('SHARE')
},
icon: `<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor" class="bi bi-arrow-counterclockwise" viewBox="0 0 16 16">
<path fill-rule="evenodd" d="M8 3a5 5 0 1 1-4.546 2.914.5.5 0 0 0-.908-.417A6 6 0 1 0 8 2v1z"/>
<path d="M8 4.466V.534a.25.25 0 0 0-.41-.192L5.23 2.308a.25.25 0 0 0 0 .384l2.36 1.966A.25.25 0 0 0 8 4.466z"/>
</svg>`,
icon: `<svg width="30" height="30" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M20 13V17.5C20 20.5577 16 20.5 12 20.5C8 20.5 4 20.5577 4 17.5V13M12 3L12 15M12 3L16 7M12 3L8 7" stroke="#000000" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
</svg>`,
}
];
}
static getMobileWritableItems = function (callback) {
return [
{
type: 'custom',
id: 'button-finish',
className: 'button-finish',
onPress() {
callback('FINISH')
},
icon: `<svg class="icon" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewBox="-4 -4 26 26">
<path d="m10.036 8.278 9.258-7.79A1.979 1.979 0 0 0 18 0H2A1.987 1.987 0 0 0 .641.541l9.395 7.737Z" />
<path d="M11.241 9.817c-.36.275-.801.425-1.255.427-.428 0-.845-.138-1.187-.395L0 2.6V14a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2V2.5l-8.759 7.317Z" />
</svg>`
},
{
type: 'custom',
@@ -97,24 +113,24 @@
onPress() {
callback('REJECT')
},
icon: `<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor" class="bi bi-hand-thumbs-down" viewBox="0 0 16 16">
<path d="M8.864 15.674c-.956.24-1.843-.484-1.908-1.42-.072-1.05-.23-2.015-.428-2.59-.125-.36-.479-1.012-1.04-1.638-.557-.624-1.282-1.179-2.131-1.41C2.685 8.432 2 7.85 2 7V3c0-.845.682-1.464 1.448-1.546 1.07-.113 1.564-.415 2.068-.723l.048-.029c.272-.166.578-.349.97-.484C6.931.08 7.395 0 8 0h3.5c.937 0 1.599.478 1.934 1.064.164.287.254.607.254.913 0 .152-.023.312-.077.464.201.262.38.577.488.9.11.33.172.762.004 1.15.069.13.12.268.159.403.077.27.113.567.113.856 0 .289-.036.586-.113.856-.035.12-.08.244-.138.363.394.571.418 1.2.234 1.733-.206.592-.682 1.1-1.2 1.272-.847.283-1.803.276-2.516.211a9.877 9.877 0 0 1-.443-.05 9.364 9.364 0 0 1-.062 4.51c-.138.508-.55.848-1.012.964zM11.5 1H8c-.51 0-.863.068-1.14.163-.281.097-.506.229-.776.393l-.04.025c-.555.338-1.198.73-2.49.868-.333.035-.554.29-.554.55V7c0 .255.226.543.62.65 1.095.3 1.977.997 2.614 1.709.635.71 1.064 1.475 1.238 1.977.243.7.407 1.768.482 2.85.025.362.36.595.667.518l.262-.065c.16-.04.258-.144.288-.255a8.34 8.34 0 0 0-.145-4.726.5.5 0 0 1 .595-.643h.003l.014.004.058.013a8.912 8.912 0 0 0 1.036.157c.663.06 1.457.054 2.11-.163.175-.059.45-.301.57-.651.107-.308.087-.67-.266-1.021L12.793 7l.353-.354c.043-.042.105-.14.154-.315.048-.167.075-.37.075-.581 0-.211-.027-.414-.075-.581-.05-.174-.111-.273-.154-.315l-.353-.354.353-.354c.047-.047.109-.176.005-.488a2.224 2.224 0 0 0-.505-.804l-.353-.354.353-.354c.006-.005.041-.05.041-.17a.866.866 0 0 0-.121-.415C12.4 1.272 12.063 1 11.5 1"/>
</svg>`,
icon: `<svg width="25px" height="25px" viewBox="43.5 43.5 512 512" version="1.1" fill="currentColor" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<path class="st0" d="M263.24,43.5c-117.36,0-212.5,95.14-212.5,212.5s95.14,212.5,212.5,212.5s212.5-95.14,212.5-212.5 S380.6,43.5,263.24,43.5z M367.83,298.36c17.18,17.18,17.18,45.04,0,62.23v0c-17.18,17.18-45.04,17.18-62.23,0l-42.36-42.36 l-42.36,42.36c-17.18,17.18-45.04,17.18-62.23,0v0c-17.18-17.18-17.18-45.04,0-62.23L201.01,256l-42.36-42.36 c-17.18-17.18-17.18-45.04,0-62.23v0c17.18-17.18,45.04-17.18,62.23,0l42.36,42.36l42.36-42.36c17.18-17.18,45.04-17.18,62.23,0v0 c17.18,17.18,17.18,45.04,0,62.23L325.46,256L367.83,298.36z" />
</svg>`,
},
{
type: 'custom',
id: 'button-finish',
className: 'button-finish',
title: 'Abschließen',
id: 'button-reset',
className: 'button-reset',
title: 'Zurücksetzen',
onPress() {
callback('FINISH')
callback('RESET')
},
},
]
}
static getDefaultItems(items) {
return items.filter((item) => UI.allowedToolbarItems.includes(item.type))
icon: `<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor" class="bi bi-arrow-counterclockwise" viewBox="-1 -1 16 16">
<path fill-rule="evenodd" d="M8 3a5 5 0 1 1-4.546 2.914.5.5 0 0 0-.908-.417A6 6 0 1 0 8 2v1z"/>
<path d="M8 4.466V.534a.25.25 0 0 0-.41-.192L5.23 2.308a.25.25 0 0 0 0 .384l2.36 1.966A.25.25 0 0 0 8 4.466z"/>
</svg>`,
}
];
}
static getPresets() {

View File

@@ -1,7 +1,12 @@
class UI{static allowedToolbarItems=["sidebar-thumbnails","sidebar-document-ouline","sidebar-bookmarks","pager","pan","zoom-out","zoom-in","zoom-mode","spacer","search",];static Instance
static loadPSPDFKit(n,t,i,r){return UI.Instance=PSPDFKit.load({inlineWorkers:!1,locale:r,licenseKey:i,styleSheets:["/css/site.css"],container:t,document:n,annotationPresets:UI.getPresets(),electronicSignatures:{creationModes:["DRAW","TYPE","IMAGE"]},initialViewState:new PSPDFKit.ViewState({sidebarMode:PSPDFKit.SidebarMode.THUMBNAILS}),isEditableAnnotation:function(n){return n.isSignature||n.description=="FRAME"?!1:!0},customRenderers:{Annotation:UI.annotationRenderer}}),UI.Instance}static configurePSPDFKit(n,t){const i=UI.getToolbarItems(n,t);i.push({type:"export-pdf"});n.setToolbarItems(i)}static annotationRenderer(){return null}static getToolbarItems(n,t){const i=UI.getCustomItems(t),r=UI.getDefaultItems(n.toolbarItems);return r.concat(i)}static createElementFromHTML(n){const t=document.createElement("div");return t.innerHTML=n.trim(),t.firstChild}static getCustomItems=function(n){return[];return[{type:"custom",id:"button-reset",className:"button-reset",title:"Zurücksetzen",onPress(){n("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">
<path fill-rule="evenodd" d="M8 3a5 5 0 1 1-4.546 2.914.5.5 0 0 0-.908-.417A6 6 0 1 0 8 2v1z"/>
<path d="M8 4.466V.534a.25.25 0 0 0-.41-.192L5.23 2.308a.25.25 0 0 0 0 .384l2.36 1.966A.25.25 0 0 0 8 4.466z"/>
</svg>`},{type:"custom",id:"button-reject",className:"button-reject",title:"Ablehnen",onPress(){n("REJECT")},icon:`<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor" class="bi bi-hand-thumbs-down" viewBox="0 0 16 16">
<path d="M8.864 15.674c-.956.24-1.843-.484-1.908-1.42-.072-1.05-.23-2.015-.428-2.59-.125-.36-.479-1.012-1.04-1.638-.557-.624-1.282-1.179-2.131-1.41C2.685 8.432 2 7.85 2 7V3c0-.845.682-1.464 1.448-1.546 1.07-.113 1.564-.415 2.068-.723l.048-.029c.272-.166.578-.349.97-.484C6.931.08 7.395 0 8 0h3.5c.937 0 1.599.478 1.934 1.064.164.287.254.607.254.913 0 .152-.023.312-.077.464.201.262.38.577.488.9.11.33.172.762.004 1.15.069.13.12.268.159.403.077.27.113.567.113.856 0 .289-.036.586-.113.856-.035.12-.08.244-.138.363.394.571.418 1.2.234 1.733-.206.592-.682 1.1-1.2 1.272-.847.283-1.803.276-2.516.211a9.877 9.877 0 0 1-.443-.05 9.364 9.364 0 0 1-.062 4.51c-.138.508-.55.848-1.012.964zM11.5 1H8c-.51 0-.863.068-1.14.163-.281.097-.506.229-.776.393l-.04.025c-.555.338-1.198.73-2.49.868-.333.035-.554.29-.554.55V7c0 .255.226.543.62.65 1.095.3 1.977.997 2.614 1.709.635.71 1.064 1.475 1.238 1.977.243.7.407 1.768.482 2.85.025.362.36.595.667.518l.262-.065c.16-.04.258-.144.288-.255a8.34 8.34 0 0 0-.145-4.726.5.5 0 0 1 .595-.643h.003l.014.004.058.013a8.912 8.912 0 0 0 1.036.157c.663.06 1.457.054 2.11-.163.175-.059.45-.301.57-.651.107-.308.087-.67-.266-1.021L12.793 7l.353-.354c.043-.042.105-.14.154-.315.048-.167.075-.37.075-.581 0-.211-.027-.414-.075-.581-.05-.174-.111-.273-.154-.315l-.353-.354.353-.354c.047-.047.109-.176.005-.488a2.224 2.224 0 0 0-.505-.804l-.353-.354.353-.354c.006-.005.041-.05.041-.17a.866.866 0 0 0-.121-.415C12.4 1.272 12.063 1 11.5 1"/>
</svg>`},{type:"custom",id:"button-finish",className:"button-finish",title:"Abschließen",onPress(){n("FINISH")}},]};static getDefaultItems(n){return n.filter(n=>UI.allowedToolbarItems.includes(n.type))}static getPresets(){const n=PSPDFKit.defaultAnnotationPresets;return n.ink={lineWidth:10},n.widget={readOnly:!0},n}}
class UI{static allowedToolbarItems=["sidebar-thumbnails","sidebar-document-ouline","sidebar-bookmarks","pager","pan","zoom-out","zoom-in","zoom-mode","spacer","search","export-pdf"];static Instance
static loadPSPDFKit(n,t,i,r){return UI.Instance=PSPDFKit.load({inlineWorkers:!1,locale:r,licenseKey:i,styleSheets:["/css/site.css"],container:t,document:n,annotationPresets:UI.getPresets(),electronicSignatures:{creationModes:["DRAW","TYPE","IMAGE"]},initialViewState:new PSPDFKit.ViewState({sidebarMode:PSPDFKit.SidebarMode.THUMBNAILS}),isEditableAnnotation:function(n){return n.isSignature||n.description=="FRAME"?!1:!0},customRenderers:{Annotation:UI.annotationRenderer}}),UI.Instance}static addToolbarItems(n,t){var i=n.toolbarItems.filter(n=>UI.allowedToolbarItems.includes(n.type));IS_READONLY||(i=i.concat(UI.getWritableItems(t)));IS_DESKTOP||IS_READONLY||(i=i.concat(UI.getMobileWritableItems(t)));n.setToolbarItems(i)}static annotationRenderer(){return null}static createElementFromHTML(n){const t=document.createElement("div");return t.innerHTML=n.trim(),t.firstChild}static getWritableItems=function(n){return[{type:"custom",id:"button-share",className:"button-share",title:"Teilen",onPress(){n("SHARE")},icon:`<svg width="30" height="30" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M20 13V17.5C20 20.5577 16 20.5 12 20.5C8 20.5 4 20.5577 4 17.5V13M12 3L12 15M12 3L16 7M12 3L8 7" stroke="#000000" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
</svg>`}]};static getMobileWritableItems=function(n){return[{type:"custom",id:"button-finish",className:"button-finish",onPress(){n("FINISH")},icon:`<svg class="icon" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewBox="-4 -4 26 26">
<path d="m10.036 8.278 9.258-7.79A1.979 1.979 0 0 0 18 0H2A1.987 1.987 0 0 0 .641.541l9.395 7.737Z" />
<path d="M11.241 9.817c-.36.275-.801.425-1.255.427-.428 0-.845-.138-1.187-.395L0 2.6V14a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2V2.5l-8.759 7.317Z" />
</svg>`},{type:"custom",id:"button-reject",className:"button-reject",title:"Ablehnen",onPress(){n("REJECT")},icon:`<svg width="25px" height="25px" viewBox="43.5 43.5 512 512" version="1.1" fill="currentColor" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<path class="st0" d="M263.24,43.5c-117.36,0-212.5,95.14-212.5,212.5s95.14,212.5,212.5,212.5s212.5-95.14,212.5-212.5 S380.6,43.5,263.24,43.5z M367.83,298.36c17.18,17.18,17.18,45.04,0,62.23v0c-17.18,17.18-45.04,17.18-62.23,0l-42.36-42.36 l-42.36,42.36c-17.18,17.18-45.04,17.18-62.23,0v0c-17.18-17.18-17.18-45.04,0-62.23L201.01,256l-42.36-42.36 c-17.18-17.18-17.18-45.04,0-62.23v0c17.18-17.18,45.04-17.18,62.23,0l42.36,42.36l42.36-42.36c17.18-17.18,45.04-17.18,62.23,0v0 c17.18,17.18,17.18,45.04,0,62.23L325.46,256L367.83,298.36z" />
</svg>`},{type:"custom",id:"button-reset",className:"button-reset",title:"Zurücksetzen",onPress(){n("RESET")},icon:`<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor" class="bi bi-arrow-counterclockwise" viewBox="-1 -1 16 16">
<path fill-rule="evenodd" d="M8 3a5 5 0 1 1-4.546 2.914.5.5 0 0 0-.908-.417A6 6 0 1 0 8 2v1z"/>
<path d="M8 4.466V.534a.25.25 0 0 0-.41-.192L5.23 2.308a.25.25 0 0 0 0 .384l2.36 1.966A.25.25 0 0 0 8 4.466z"/>
</svg>`}]};static getPresets(){const n=PSPDFKit.defaultAnnotationPresets;return n.ink={lineWidth:10},n.widget={readOnly:!0},n}}