< Summary

Information
Class: Chronicis.Client.Components.Settings.DataManagementSection
Assembly: Chronicis.Client
File(s): /home/runner/work/chronicis/chronicis/src/Chronicis.Client/Components/Settings/DataManagementSection.razor
Line coverage
100%
Covered lines: 6
Uncovered lines: 0
Coverable lines: 6
Total lines: 160
Line coverage: 100%
Branch coverage
100%
Covered branches: 12
Total branches: 12
Branch coverage: 100%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
BuildRenderTree(...)100%1212100%
.ctor()100%11100%
DismissExportAlert(...)100%11100%

File(s)

/home/runner/work/chronicis/chronicis/src/Chronicis.Client/Components/Settings/DataManagementSection.razor

#LineLine coverage
 1@using Chronicis.Shared.DTOs
 2
 3<!-- Export Section -->
 4<div class="mb-6">
 5    <MudText Typo="Typo.subtitle2" Color="Color.Primary" Class="mb-2" Style="font-weight: 600;">
 6        Export World Data
 7    </MudText>
 8    <MudText Typo="Typo.body2" Class="mud-text-secondary mb-4">
 9        Download all articles, sessions, and notes from a world as a zip archive
 10        containing organized Markdown files. Great for backups or migrating to other tools.
 11    </MudText>
 12
 1813    @if (_isLoadingWorlds)
 14    {
 15        <MudProgressLinear Indeterminate="true" Color="Color.Primary" Class="mb-3" />
 16    }
 1717    else if (_worlds is not { Count: > 0 })
 18    {
 19        <MudAlert Severity="Severity.Info" Dense="true" Variant="Variant.Outlined">
 20            You don't have any worlds to export yet. Create a world first!
 21        </MudAlert>
 22    }
 23    else
 24    {
 25        <div class="d-flex flex-column flex-sm-row gap-3 align-start">
 26            <MudSelect T="WorldDto"
 27                       @bind-Value="_selectedWorld"
 28                       Label="Select World"
 29                       Variant="Variant.Outlined"
 30                       AnchorOrigin="Origin.BottomCenter"
 31                       Dense="true"
 32                       Style="min-width: 280px;">
 33                @foreach (var world in _worlds!)
 34                {
 35                    <MudSelectItem Value="@world">@world.Name</MudSelectItem>
 36                }
 37            </MudSelect>
 38
 39            <MudButton Variant="Variant.Filled"
 40                       Color="Color.Primary"
 41                       StartIcon="@Icons.Material.Filled.Download"
 42                       OnClick="ExportWorld"
 43                       Disabled="@(_selectedWorld == null || _isExporting)">
 44                @if (_isExporting)
 45                {
 46                    <MudProgressCircular Size="Size.Small" Indeterminate="true" Class="mr-2" />
 47                    <span>Exporting...</span>
 48                }
 49                else
 50                {
 51                    <span>Export to Markdown</span>
 52                }
 53            </MudButton>
 54        </div>
 55
 1356        @if (_exportSuccess.HasValue)
 57        {
 58            <MudAlert Severity="@(_exportSuccess.Value ? Severity.Success : Severity.Error)"
 59                      Class="mt-4"
 60                      Dense="true"
 61                      Variant="Variant.Outlined"
 62                      ShowCloseIcon="true"
 63                      CloseIconClicked="DismissExportAlert">
 64                @if (_exportSuccess.Value)
 65                {
 66                    <span>Export complete! Your download should begin automatically.</span>
 67                }
 68                else
 69                {
 70                    <span>Export failed. Please try again or contact support if the problem persists.</span>
 71                }
 72            </MudAlert>
 73        }
 74    }
 75</div>
 76
 77<MudDivider Class="my-5" />
 78
 79<!-- Import Section (Placeholder) -->
 80<div>
 81    <MudText Typo="Typo.subtitle2" Color="Color.Primary" Class="mb-2" Style="font-weight: 600;">
 82        Import Data
 83    </MudText>
 84    <MudText Typo="Typo.body2" Class="mud-text-secondary mb-4">
 85        Import content from other tools or restore from a backup.
 86    </MudText>
 87
 88    <MudAlert Severity="Severity.Info" Dense="true" Variant="Variant.Outlined" Icon="@Icons.Material.Filled.Construction
 89        Import functionality is coming soon! We're working on support for importing from
 90        Markdown files, Notion exports, and other popular campaign management tools.
 91    </MudAlert>
 92</div>
 93
 94@code {
 95    [Inject] private IWorldApiService WorldApi { get; set; } = default!;
 96    [Inject] private IExportApiService ExportApi { get; set; } = default!;
 97    [Inject] private ISnackbar Snackbar { get; set; } = default!;
 98
 99    private List<WorldDto>? _worlds;
 100    private WorldDto? _selectedWorld;
 9101    private bool _isLoadingWorlds = true;
 102    private bool _isExporting = false;
 103    private bool? _exportSuccess = null;
 104
 105    protected override async Task OnInitializedAsync()
 106    {
 107        _isLoadingWorlds = true;
 108        try
 109        {
 110            _worlds = await WorldApi.GetWorldsAsync();
 111            if (_worlds?.Any() == true)
 112            {
 113                _selectedWorld = _worlds.First();
 114            }
 115        }
 116        finally
 117        {
 118            _isLoadingWorlds = false;
 119        }
 120    }
 121
 122    private async Task ExportWorld()
 123    {
 124        if (_selectedWorld == null) return;
 125
 126        _isExporting = true;
 127        _exportSuccess = null;
 128        StateHasChanged();
 129
 130        try
 131        {
 132            var success = await ExportApi.ExportWorldToMarkdownAsync(_selectedWorld.Id, _selectedWorld.Name);
 133            _exportSuccess = success;
 134
 135            if (success)
 136            {
 137                Snackbar.Add($"Export of '{_selectedWorld.Name}' completed!", Severity.Success);
 138            }
 139            else
 140            {
 141                Snackbar.Add("Export failed. Please try again.", Severity.Error);
 142            }
 143        }
 144        catch (Exception ex)
 145        {
 146            _exportSuccess = false;
 147            Snackbar.Add($"Export error: {ex.Message}", Severity.Error);
 148        }
 149        finally
 150        {
 151            _isExporting = false;
 152            StateHasChanged();
 153        }
 154    }
 155
 156    private void DismissExportAlert(MudAlert? _)
 157    {
 1158        _exportSuccess = null;
 1159    }
 160}