Add envelope settings step to wizard
Introduced a new step (step 2) in the `CreateEnvelopeWizardPopup` for configuring envelope settings, including security, reminders, and expiration options. - Added fields for certification type, final email options, 2FA, access codes, and reminder settings. - Updated step titles, descriptions, and total steps from 4 to 5. - Implemented validation logic for the new settings step. - Added methods to handle changes in settings fields and apply defaults. - Updated `CreateEnvelopeWizardResult` and `CreateEnvelopeBootstrapPayload` to include new fields. - Modified `SenderEditorPage` and `SenderPage` to handle new settings. - Styled the new step with updated CSS for grids, groups, and toggles. - Refactored state reset logic to initialize new fields.
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
@using EnvelopeGenerator.Application.Common.Dto
|
||||
@using EnvelopeGenerator.Application.Common.Dto.Receiver
|
||||
@using EnvelopeGenerator.Application.Resources
|
||||
@using EnvelopeGenerator.Domain.Constants
|
||||
@using EnvelopeGenerator.Domain.Resources
|
||||
@using EnvelopeGenerator.Server.Client.Components.Sender.ReceiverSuggestionFilter
|
||||
@using EnvelopeGenerator.Server.Client.Services
|
||||
@@ -106,6 +107,93 @@
|
||||
</div>
|
||||
}
|
||||
else if (_currentStep == 2)
|
||||
{
|
||||
<div class="sender-create-wizard__settings-grid">
|
||||
<div class="sender-create-wizard__settings-group">
|
||||
<div class="sender-create-wizard__settings-title">
|
||||
@L("SenderEditor_EnvelopeSettings", "Envelope-Einstellungen")
|
||||
</div>
|
||||
|
||||
<div class="sender-create-wizard__form-grid">
|
||||
<div class="sender-create-wizard__field">
|
||||
<label class="sender-create-wizard__label">@L("CertificationType", "Zertifizierung")</label>
|
||||
<select @bind="_certificationType" class="sender-create-wizard__select">
|
||||
<option value="1">@L("AdvancedElectronicSignature", "Advanced Electronic Signature")</option>
|
||||
<option value="2">@L("ElectronicSignature", "Electronic Signature")</option>
|
||||
<option value="3">@L("QualifiedSignature", "Qualified Signature")</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="sender-create-wizard__field">
|
||||
<label class="sender-create-wizard__label">@L("FinalEmailToCreator", "Finale E-Mail an Ersteller")</label>
|
||||
<select @bind="_finalEmailToCreator" class="sender-create-wizard__select">
|
||||
<option value="0">@L("No", "Nein")</option>
|
||||
<option value="1">@L("Yes", "Ja")</option>
|
||||
<option value="2">@L("YesWithAttachment", "Ja, mit Anhang")</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="sender-create-wizard__field">
|
||||
<label class="sender-create-wizard__label">@L("FinalEmailToReceivers", "Finale E-Mail an Empfänger")</label>
|
||||
<select @bind="_finalEmailToReceivers" class="sender-create-wizard__select">
|
||||
<option value="0">@L("No", "Nein")</option>
|
||||
<option value="1">@L("Yes", "Ja")</option>
|
||||
<option value="2">@L("YesWithAttachment", "Ja, mit Anhang")</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="sender-create-wizard__field sender-create-wizard__field--full">
|
||||
<div class="sender-create-wizard__settings-toggles">
|
||||
<label class="sender-create-wizard__settings-toggle">
|
||||
<input type="checkbox" checked="@_tfaEnabled" @onchange="OnTfaChanged" />
|
||||
@L("TFAEnabled", "2FA aktiviert")
|
||||
</label>
|
||||
<label class="sender-create-wizard__settings-toggle">
|
||||
<input type="checkbox" checked="@_useAccessCode" @onchange="OnUseAccessCodeChanged" disabled="@_tfaEnabled" />
|
||||
@L("UseAccessCode", "Zugriffscode verwenden")
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="sender-create-wizard__settings-group">
|
||||
<div class="sender-create-wizard__settings-title">
|
||||
@L("SendReminderEmails", "Erinnerungs-E-Mails senden")
|
||||
</div>
|
||||
|
||||
<div class="sender-create-wizard__form-grid">
|
||||
<div class="sender-create-wizard__field sender-create-wizard__field--full">
|
||||
<label class="sender-create-wizard__settings-toggle">
|
||||
<input type="checkbox" checked="@_sendReminderEmails" @onchange="OnSendReminderEmailsChanged" />
|
||||
@L("SendReminderEmails", "Erinnerungs-E-Mails senden")
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="sender-create-wizard__field">
|
||||
<label class="sender-create-wizard__label">@L("FirstReminderDays", "Erste Erinnerung (Tage)")</label>
|
||||
<InputNumber @bind-Value="_firstReminderDays" class="form-control form-control-sm" disabled="@(!_sendReminderEmails)" />
|
||||
</div>
|
||||
|
||||
<div class="sender-create-wizard__field">
|
||||
<label class="sender-create-wizard__label">@L("ReminderIntervalDays", "Erinnerungsintervall (Tage)")</label>
|
||||
<InputNumber @bind-Value="_reminderIntervalDays" class="form-control form-control-sm" disabled="@(!_sendReminderEmails)" />
|
||||
</div>
|
||||
|
||||
<div class="sender-create-wizard__field">
|
||||
<label class="sender-create-wizard__label">@L("ExpiresWhenDays", "Läuft ab nach (Tage)")</label>
|
||||
<InputNumber @bind-Value="_expiresWhenDays" class="form-control form-control-sm" />
|
||||
</div>
|
||||
|
||||
<div class="sender-create-wizard__field">
|
||||
<label class="sender-create-wizard__label">@L("ExpiresWarningWhenDays", "Ablaufwarnung (Tage)")</label>
|
||||
<InputNumber @bind-Value="_expiresWarningWhenDays" class="form-control form-control-sm" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
else if (_currentStep == 3)
|
||||
{
|
||||
<div class="sender-create-wizard__suggestions">
|
||||
<div class="sender-create-wizard__suggestions-title">@L("SenderWizard_RecentReceivers", "Zuletzt verwendete Empfänger")</div>
|
||||
@@ -320,7 +408,7 @@
|
||||
[Parameter]
|
||||
public IReadOnlyList<EnvelopeTypeDto> EnvelopeTypes { get; set; } = [];
|
||||
|
||||
private const int TotalSteps = 4;
|
||||
private const int TotalSteps = 5;
|
||||
private static readonly System.ComponentModel.DataAnnotations.EmailAddressAttribute EmailValidator = new();
|
||||
|
||||
private bool _isVisible;
|
||||
@@ -331,6 +419,16 @@
|
||||
private int? _selectedEnvelopeTypeId;
|
||||
private string _message = string.Empty;
|
||||
private string _language = "de-DE";
|
||||
private bool _useAccessCode;
|
||||
private bool _tfaEnabled;
|
||||
private int _certificationType = (int)CertificationType.AdvancedElectronicSignature;
|
||||
private int _finalEmailToCreator = (int)FinalEmailType.No;
|
||||
private int _finalEmailToReceivers = (int)FinalEmailType.No;
|
||||
private bool _sendReminderEmails;
|
||||
private int _firstReminderDays;
|
||||
private int _reminderIntervalDays;
|
||||
private int _expiresWhenDays;
|
||||
private int _expiresWarningWhenDays;
|
||||
|
||||
private string _receiverName = string.Empty;
|
||||
private string _receiverEmail = string.Empty;
|
||||
@@ -372,8 +470,9 @@
|
||||
{
|
||||
0 => L("SenderWizard_Step_Basics", "Grunddaten"),
|
||||
1 => L("SenderWizard_Step_Message", "Nachricht und Optionen"),
|
||||
2 => L("SenderWizard_Step_Receivers", "Empfänger"),
|
||||
3 => L("SenderWizard_Step_Document", "Dokument"),
|
||||
2 => L("SenderEditor_EnvelopeSettings", "Envelope-Einstellungen"),
|
||||
3 => L("SenderWizard_Step_Receivers", "Empfänger"),
|
||||
4 => L("SenderWizard_Step_Document", "Dokument"),
|
||||
_ => L("SenderWizard_Step_Basics", "Grunddaten")
|
||||
};
|
||||
|
||||
@@ -381,8 +480,9 @@
|
||||
{
|
||||
0 => L("SenderWizard_Step_Basics_Desc", "Starten Sie mit den Pflichtangaben für den Umschlag."),
|
||||
1 => L("SenderWizard_Step_Message_Desc", "Fügen Sie optionale Nachricht und Einstellungen hinzu."),
|
||||
2 => L("SenderWizard_Step_Receivers_Desc", "Definieren Sie die Empfänger für den Signaturprozess."),
|
||||
3 => L("SenderWizard_Step_Document_Desc", "Laden Sie das Dokument hoch und platzieren Sie Signaturfelder."),
|
||||
2 => L("SenderWizard_Step_Settings_Desc", "Konfigurieren Sie Sicherheits-, Erinnerungs- und Ablaufoptionen."),
|
||||
3 => L("SenderWizard_Step_Receivers_Desc", "Definieren Sie die Empfänger für den Signaturprozess."),
|
||||
4 => L("SenderWizard_Step_Document_Desc", "Laden Sie das Dokument hoch und platzieren Sie Signaturfelder."),
|
||||
_ => L("SenderWizard_Step_Basics_Desc", "Starten Sie mit den Pflichtangaben für den Umschlag.")
|
||||
};
|
||||
|
||||
@@ -391,7 +491,7 @@
|
||||
_isVisible = Visible;
|
||||
|
||||
if (_selectedEnvelopeTypeId is null && EnvelopeTypes.Count > 0)
|
||||
_selectedEnvelopeTypeId = GetDefaultEnvelopeTypeId();
|
||||
ApplyDefaultEnvelopeType();
|
||||
|
||||
if (Visible && !_previousVisible)
|
||||
ResetWizardState();
|
||||
@@ -434,6 +534,10 @@
|
||||
if (int.TryParse(raw, out var id) && id > 0)
|
||||
{
|
||||
_selectedEnvelopeTypeId = id;
|
||||
var selectedType = EnvelopeTypes.FirstOrDefault(x => x.Id == id);
|
||||
if (selectedType is not null)
|
||||
ApplyEnvelopeTypeDefaults(selectedType);
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
@@ -600,7 +704,7 @@
|
||||
{
|
||||
_currentStep++;
|
||||
|
||||
if (_currentStep == 2)
|
||||
if (_currentStep == 3)
|
||||
await EnsureRecentSuggestionsLoadedAsync();
|
||||
}
|
||||
}
|
||||
@@ -655,6 +759,16 @@
|
||||
Message: _message.Trim(),
|
||||
EnvelopeTypeId: _selectedEnvelopeTypeId,
|
||||
Language: string.IsNullOrWhiteSpace(_language) ? "de-DE" : _language,
|
||||
UseAccessCode: _useAccessCode,
|
||||
TFAEnabled: _tfaEnabled,
|
||||
CertificationType: _certificationType,
|
||||
FinalEmailToCreator: _finalEmailToCreator,
|
||||
FinalEmailToReceivers: _finalEmailToReceivers,
|
||||
SendReminderEmails: _sendReminderEmails,
|
||||
FirstReminderDays: _firstReminderDays,
|
||||
ReminderIntervalDays: _reminderIntervalDays,
|
||||
ExpiresWhenDays: _expiresWhenDays,
|
||||
ExpiresWarningWhenDays: _expiresWarningWhenDays,
|
||||
Receivers: _receivers.ToList(),
|
||||
DocumentBytes: _documentBytes,
|
||||
DocumentFileName: _documentFileName);
|
||||
@@ -687,7 +801,7 @@
|
||||
if (_currentStep == 1)
|
||||
return;
|
||||
|
||||
if (_currentStep == 2 && (!string.IsNullOrWhiteSpace(_receiverName) || !string.IsNullOrWhiteSpace(_receiverEmail)))
|
||||
if (_currentStep == 3 && (!string.IsNullOrWhiteSpace(_receiverName) || !string.IsNullOrWhiteSpace(_receiverEmail)))
|
||||
{
|
||||
await AddReceiver();
|
||||
return;
|
||||
@@ -771,6 +885,17 @@
|
||||
}
|
||||
|
||||
if (_currentStep == 2)
|
||||
{
|
||||
if (!ValidateSettings(out var settingsError))
|
||||
{
|
||||
_validationMessage = settingsError;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if (_currentStep == 3)
|
||||
{
|
||||
if (_receivers.Count == 0)
|
||||
{
|
||||
@@ -781,7 +906,7 @@
|
||||
return true;
|
||||
}
|
||||
|
||||
if (_currentStep == 3)
|
||||
if (_currentStep == 4)
|
||||
{
|
||||
if (_documentBytes is null || _documentBytes.Length == 0)
|
||||
{
|
||||
@@ -854,15 +979,151 @@
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
private void OnTfaChanged(ChangeEventArgs args)
|
||||
{
|
||||
_validationMessage = null;
|
||||
_tfaEnabled = ParseCheckboxValue(args);
|
||||
if (_tfaEnabled)
|
||||
_useAccessCode = true;
|
||||
}
|
||||
|
||||
private void OnUseAccessCodeChanged(ChangeEventArgs args)
|
||||
{
|
||||
_validationMessage = null;
|
||||
|
||||
if (_tfaEnabled)
|
||||
{
|
||||
_useAccessCode = true;
|
||||
return;
|
||||
}
|
||||
|
||||
_useAccessCode = ParseCheckboxValue(args);
|
||||
}
|
||||
|
||||
private void OnSendReminderEmailsChanged(ChangeEventArgs args)
|
||||
{
|
||||
_validationMessage = null;
|
||||
_sendReminderEmails = ParseCheckboxValue(args);
|
||||
}
|
||||
|
||||
private static bool ParseCheckboxValue(ChangeEventArgs args)
|
||||
{
|
||||
if (args.Value is bool boolValue)
|
||||
return boolValue;
|
||||
|
||||
return bool.TryParse(args.Value?.ToString(), out var parsed) && parsed;
|
||||
}
|
||||
|
||||
private void ApplyEnvelopeTypeDefaults(EnvelopeTypeDto envelopeType)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(envelopeType.Language))
|
||||
_language = envelopeType.Language;
|
||||
|
||||
if (envelopeType.UseAccessCode.HasValue)
|
||||
_useAccessCode = envelopeType.UseAccessCode.Value;
|
||||
|
||||
if (_tfaEnabled)
|
||||
_useAccessCode = true;
|
||||
|
||||
if (envelopeType.CertificationType.HasValue)
|
||||
_certificationType = envelopeType.CertificationType.Value;
|
||||
|
||||
if (envelopeType.FinalEmailToCreator.HasValue)
|
||||
_finalEmailToCreator = envelopeType.FinalEmailToCreator.Value;
|
||||
|
||||
if (envelopeType.FinalEmailToReceivers.HasValue)
|
||||
_finalEmailToReceivers = envelopeType.FinalEmailToReceivers.Value;
|
||||
|
||||
if (envelopeType.SendReminderEmails.HasValue)
|
||||
_sendReminderEmails = envelopeType.SendReminderEmails.Value;
|
||||
|
||||
if (envelopeType.FirstReminderDays.HasValue)
|
||||
_firstReminderDays = envelopeType.FirstReminderDays.Value;
|
||||
|
||||
if (envelopeType.ReminderIntervalDays.HasValue)
|
||||
_reminderIntervalDays = envelopeType.ReminderIntervalDays.Value;
|
||||
|
||||
if (envelopeType.ExpiresDays.HasValue)
|
||||
_expiresWhenDays = envelopeType.ExpiresDays.Value;
|
||||
|
||||
if (envelopeType.ExpiresWarningDays.HasValue)
|
||||
_expiresWarningWhenDays = envelopeType.ExpiresWarningDays.Value;
|
||||
|
||||
NormalizeSettings();
|
||||
}
|
||||
|
||||
private void NormalizeSettings()
|
||||
{
|
||||
_language = string.IsNullOrWhiteSpace(_language) ? "de-DE" : _language.Trim();
|
||||
|
||||
if (_tfaEnabled)
|
||||
_useAccessCode = true;
|
||||
|
||||
_firstReminderDays = Math.Max(0, _firstReminderDays);
|
||||
_reminderIntervalDays = Math.Max(0, _reminderIntervalDays);
|
||||
_expiresWhenDays = Math.Max(0, _expiresWhenDays);
|
||||
_expiresWarningWhenDays = Math.Max(0, _expiresWarningWhenDays);
|
||||
|
||||
if (_expiresWhenDays > 0 && _expiresWarningWhenDays > _expiresWhenDays)
|
||||
_expiresWarningWhenDays = _expiresWhenDays;
|
||||
}
|
||||
|
||||
private bool ValidateSettings(out string? message)
|
||||
{
|
||||
NormalizeSettings();
|
||||
|
||||
if (_sendReminderEmails && _reminderIntervalDays <= 0)
|
||||
{
|
||||
message = L("SenderEditor_Validation_ReminderInterval", "Bitte geben Sie ein Erinnerungsintervall groesser als 0 Tage ein.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (_sendReminderEmails && _firstReminderDays < 0)
|
||||
{
|
||||
message = L("SenderEditor_Validation_FirstReminder", "Bitte geben Sie gueltige Tage fuer die erste Erinnerung ein.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (_expiresWhenDays > 0 && _expiresWarningWhenDays > _expiresWhenDays)
|
||||
{
|
||||
message = L("SenderEditor_Validation_ExpiryWarning", "Die Ablaufwarnung darf nicht nach dem Ablaufdatum liegen.");
|
||||
return false;
|
||||
}
|
||||
|
||||
message = null;
|
||||
return true;
|
||||
}
|
||||
|
||||
private void ApplyDefaultEnvelopeType()
|
||||
{
|
||||
_selectedEnvelopeTypeId = GetDefaultEnvelopeTypeId();
|
||||
if (!_selectedEnvelopeTypeId.HasValue)
|
||||
return;
|
||||
|
||||
var selectedType = EnvelopeTypes.FirstOrDefault(x => x.Id == _selectedEnvelopeTypeId.Value);
|
||||
if (selectedType is not null)
|
||||
ApplyEnvelopeTypeDefaults(selectedType);
|
||||
}
|
||||
|
||||
private void ResetWizardState()
|
||||
{
|
||||
_currentStep = 0;
|
||||
_validationMessage = null;
|
||||
|
||||
_title = string.Empty;
|
||||
_selectedEnvelopeTypeId = GetDefaultEnvelopeTypeId();
|
||||
_selectedEnvelopeTypeId = null;
|
||||
_message = string.Empty;
|
||||
_language = "de-DE";
|
||||
_useAccessCode = false;
|
||||
_tfaEnabled = false;
|
||||
_certificationType = (int)CertificationType.AdvancedElectronicSignature;
|
||||
_finalEmailToCreator = (int)FinalEmailType.No;
|
||||
_finalEmailToReceivers = (int)FinalEmailType.No;
|
||||
_sendReminderEmails = false;
|
||||
_firstReminderDays = 0;
|
||||
_reminderIntervalDays = 0;
|
||||
_expiresWhenDays = 0;
|
||||
_expiresWarningWhenDays = 0;
|
||||
|
||||
_receiverName = string.Empty;
|
||||
_receiverEmail = string.Empty;
|
||||
@@ -877,6 +1138,8 @@
|
||||
_documentSizeText = string.Empty;
|
||||
_documentPreviewPageCount = 0;
|
||||
_documentPreviewPages = [];
|
||||
|
||||
ApplyDefaultEnvelopeType();
|
||||
}
|
||||
|
||||
private int? GetDefaultEnvelopeTypeId()
|
||||
|
||||
@@ -5,6 +5,16 @@ public sealed record CreateEnvelopeWizardResult(
|
||||
string Message,
|
||||
int? EnvelopeTypeId,
|
||||
string Language,
|
||||
bool UseAccessCode,
|
||||
bool TFAEnabled,
|
||||
int CertificationType,
|
||||
int FinalEmailToCreator,
|
||||
int FinalEmailToReceivers,
|
||||
bool SendReminderEmails,
|
||||
int FirstReminderDays,
|
||||
int ReminderIntervalDays,
|
||||
int ExpiresWhenDays,
|
||||
int ExpiresWarningWhenDays,
|
||||
IReadOnlyList<CreateEnvelopeWizardReceiver> Receivers,
|
||||
byte[]? DocumentBytes,
|
||||
string? DocumentFileName);
|
||||
|
||||
Reference in New Issue
Block a user