Add export feature UI to EnvelopeSenderPage (placeholder)
Introduced a new export feature to the EnvelopeSenderPage, including a dropdown for selecting export formats (XLSX, CSV, PDF) and a checkbox to export only selected rows. Added a placeholder export button ("Exportieren") that is currently disabled, with export logic to be implemented in a future phase.
Added private fields `_selectedExportFormat` and `_exportSelectedRowsOnly` to manage the export state. Implemented `IsExportDisabled()` to control button availability and a placeholder method `ExportSelectedFormatPlaceholderAsync()`.
Updated `sender-page.css` to style the export feature, including the export button, dropdown, and checkbox. Added theme-specific styles for "purple" and "blazing-dark" themes. Adjusted toolbar element order to position the export group before the logout button.
This commit is contained in:
@@ -104,6 +104,31 @@
|
|||||||
Vorschau
|
Vorschau
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
|
<div class="sender-export-group" title="Export der aktuellen Tabellenansicht">
|
||||||
|
<label class="sender-export-label" for="sender-export-format">Format</label>
|
||||||
|
<select id="sender-export-format" class="sender-export-format" @bind="_selectedExportFormat" aria-label="Exportformat auswählen">
|
||||||
|
<option value="xlsx">XLSX</option>
|
||||||
|
<option value="csv">CSV</option>
|
||||||
|
<option value="pdf">PDF</option>
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<label class="sender-export-selected">
|
||||||
|
<input type="checkbox" @bind="_exportSelectedRowsOnly" />
|
||||||
|
<span>Nur ausgewählte</span>
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<button class="sender-btn sender-btn--export"
|
||||||
|
@onclick="ExportSelectedFormatPlaceholderAsync"
|
||||||
|
disabled="@IsExportDisabled()"
|
||||||
|
title="Export wird in Phase 2 aktiviert">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" viewBox="0 0 16 16">
|
||||||
|
<path d="M.5 9.9a.5.5 0 0 1 .5.5V13a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1v-2.6a.5.5 0 0 1 1 0V13a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2v-2.6a.5.5 0 0 1 .5-.5z" />
|
||||||
|
<path d="M5.354 6.146a.5.5 0 0 1 .707 0L7.5 7.586V.5a.5.5 0 0 1 1 0v7.086l1.439-1.44a.5.5 0 0 1 .707.708l-2.293 2.293a.5.5 0 0 1-.707 0L5.354 6.854a.5.5 0 0 1 0-.708z" />
|
||||||
|
</svg>
|
||||||
|
Exportieren
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
<button class="sender-btn sender-btn--logout" @onclick="LogoutAsync" disabled="@_isLoggingOut" title="Abmelden">
|
<button class="sender-btn sender-btn--logout" @onclick="LogoutAsync" disabled="@_isLoggingOut" title="Abmelden">
|
||||||
@if (_isLoggingOut)
|
@if (_isLoggingOut)
|
||||||
{
|
{
|
||||||
@@ -514,6 +539,10 @@
|
|||||||
private byte[]? _previewPdfBytes = null;
|
private byte[]? _previewPdfBytes = null;
|
||||||
private string? _previewErrorMessage = null;
|
private string? _previewErrorMessage = null;
|
||||||
|
|
||||||
|
// Phase 6e (step 1): UI state only. Export logic is added in step 2.
|
||||||
|
private string _selectedExportFormat = "xlsx";
|
||||||
|
private bool _exportSelectedRowsOnly = false;
|
||||||
|
|
||||||
// Stable keys used to store/restore each grid's layout in UserPreferences.GridLayouts
|
// Stable keys used to store/restore each grid's layout in UserPreferences.GridLayouts
|
||||||
private const string GridKeyActive = "sender.active-envelopes";
|
private const string GridKeyActive = "sender.active-envelopes";
|
||||||
private const string GridKeyCompleted = "sender.completed-envelopes";
|
private const string GridKeyCompleted = "sender.completed-envelopes";
|
||||||
@@ -572,6 +601,19 @@
|
|||||||
await LoadEnvelopesAsync();
|
await LoadEnvelopesAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool IsExportDisabled()
|
||||||
|
{
|
||||||
|
if (_isLoading)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return _exportSelectedRowsOnly && _selectedEnvelope is null;
|
||||||
|
}
|
||||||
|
|
||||||
|
Task ExportSelectedFormatPlaceholderAsync()
|
||||||
|
{
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
void CreateEnvelope()
|
void CreateEnvelope()
|
||||||
{
|
{
|
||||||
Navigation.NavigateTo("/sender/editor");
|
Navigation.NavigateTo("/sender/editor");
|
||||||
|
|||||||
@@ -136,6 +136,59 @@
|
|||||||
min-width: 38px;
|
min-width: 38px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.sender-btn--export {
|
||||||
|
padding-inline: 0.875rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sender-export-group {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.45rem;
|
||||||
|
padding: 0.35rem 0.5rem;
|
||||||
|
border: 1px solid rgba(126, 34, 206, 0.18);
|
||||||
|
border-radius: 10px;
|
||||||
|
background: rgba(126, 34, 206, 0.04);
|
||||||
|
}
|
||||||
|
|
||||||
|
.sender-export-label {
|
||||||
|
font-size: 0.72rem;
|
||||||
|
font-weight: 700;
|
||||||
|
color: #4b5563;
|
||||||
|
letter-spacing: 0.01em;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sender-export-format {
|
||||||
|
height: 32px;
|
||||||
|
min-width: 84px;
|
||||||
|
padding: 0 0.5rem;
|
||||||
|
border: 1px solid rgba(126, 34, 206, 0.25);
|
||||||
|
border-radius: 8px;
|
||||||
|
background: #fff;
|
||||||
|
color: #1e293b;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
font-weight: 600;
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sender-export-format:focus {
|
||||||
|
border-color: rgba(126, 34, 206, 0.55);
|
||||||
|
box-shadow: 0 0 0 2px rgba(126, 34, 206, 0.12);
|
||||||
|
}
|
||||||
|
|
||||||
|
.sender-export-selected {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.35rem;
|
||||||
|
font-size: 0.74rem;
|
||||||
|
color: #4b5563;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sender-export-selected input[type="checkbox"] {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
.sender-content {
|
.sender-content {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
min-height: 0;
|
min-height: 0;
|
||||||
@@ -314,6 +367,14 @@
|
|||||||
justify-content: flex-start;
|
justify-content: flex-start;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.sender-export-group {
|
||||||
|
order: 98;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sender-btn--logout {
|
||||||
|
order: 99;
|
||||||
|
}
|
||||||
|
|
||||||
.sender-title {
|
.sender-title {
|
||||||
font-size: 1.125rem;
|
font-size: 1.125rem;
|
||||||
}
|
}
|
||||||
@@ -373,6 +434,20 @@
|
|||||||
box-shadow: 0 4px 12px rgba(147, 51, 234, 0.22);
|
box-shadow: 0 4px 12px rgba(147, 51, 234, 0.22);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[data-sf-theme="purple"] .sender-export-group {
|
||||||
|
border-color: rgba(147, 51, 234, 0.28);
|
||||||
|
background: rgba(147, 51, 234, 0.08);
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-sf-theme="purple"] .sender-export-format {
|
||||||
|
border-color: rgba(147, 51, 234, 0.36);
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-sf-theme="purple"] .sender-export-format:focus {
|
||||||
|
border-color: rgba(147, 51, 234, 0.6);
|
||||||
|
box-shadow: 0 0 0 2px rgba(147, 51, 234, 0.14);
|
||||||
|
}
|
||||||
|
|
||||||
[data-sf-theme="purple"] .sender-tabs {
|
[data-sf-theme="purple"] .sender-tabs {
|
||||||
border-bottom-color: rgba(147, 51, 234, 0.12);
|
border-bottom-color: rgba(147, 51, 234, 0.12);
|
||||||
}
|
}
|
||||||
@@ -445,6 +520,27 @@
|
|||||||
border-color: transparent;
|
border-color: transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[data-sf-theme="blazing-dark"] .sender-export-group {
|
||||||
|
border-color: rgba(129, 140, 248, 0.26);
|
||||||
|
background: rgba(99, 102, 241, 0.08);
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-sf-theme="blazing-dark"] .sender-export-label,
|
||||||
|
[data-sf-theme="blazing-dark"] .sender-export-selected {
|
||||||
|
color: rgba(255, 255, 255, 0.72);
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-sf-theme="blazing-dark"] .sender-export-format {
|
||||||
|
background: rgba(255, 255, 255, 0.08);
|
||||||
|
color: rgba(255, 255, 255, 0.9);
|
||||||
|
border-color: rgba(129, 140, 248, 0.35);
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-sf-theme="blazing-dark"] .sender-export-format:focus {
|
||||||
|
border-color: rgba(129, 140, 248, 0.58);
|
||||||
|
box-shadow: 0 0 0 2px rgba(129, 140, 248, 0.16);
|
||||||
|
}
|
||||||
|
|
||||||
[data-sf-theme="blazing-dark"] .sender-grid-container {
|
[data-sf-theme="blazing-dark"] .sender-grid-container {
|
||||||
background: rgba(15, 20, 40, 0.95);
|
background: rgba(15, 20, 40, 0.95);
|
||||||
box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.5), 0 0 0 1px rgba(255, 255, 255, 0.06);
|
box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.5), 0 0 0 1px rgba(255, 255, 255, 0.06);
|
||||||
|
|||||||
Reference in New Issue
Block a user