Skip to content

Commit

Permalink
More loading states and UI updates
Browse files Browse the repository at this point in the history
  • Loading branch information
dennisreimann committed Aug 22, 2023
1 parent ca08084 commit 1571455
Show file tree
Hide file tree
Showing 8 changed files with 132 additions and 122 deletions.
8 changes: 4 additions & 4 deletions BTCPayApp.UI/Constants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -114,8 +114,8 @@ public static class Brand
PrimaryContrastText = Colors.White,
Secondary = Colors.White,
SecondaryContrastText = Colors.Primary500,
Tertiary = Colors.White,
TertiaryContrastText = Colors.Light500,
Tertiary = Colors.Light500,
TertiaryContrastText = Colors.White,
Info = Colors.Blue500,
InfoContrastText = Colors.White,
Success = Colors.Green500,
Expand Down Expand Up @@ -156,8 +156,8 @@ public static class Brand
PrimaryContrastText = Colors.White,
Secondary = Colors.White,
SecondaryContrastText = Colors.Primary500,
Tertiary = Colors.White,
TertiaryContrastText = Colors.Dark500,
Tertiary = Colors.Dark500,
TertiaryContrastText = Colors.Black,
Info = Colors.Blue500,
InfoContrastText = Colors.White,
Success = Colors.Green500,
Expand Down
3 changes: 2 additions & 1 deletion BTCPayApp.UI/Features/RootState.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ public enum LoadingHandles
UiState,
PairConfig,
WalletConfig,
TransactionState
TransactionState,
LightningState
}

public RootState() : this(new HashSet<LoadingHandles>(), null, null, null, LightningNodeState.NotConfigured, false, false)
Expand Down
2 changes: 2 additions & 0 deletions BTCPayApp.UI/Pages/WalletSetupPage.razor
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,14 @@
var xpub = mKey.Derive(kp).Neuter().ToString(Network.Main);
if (obj is { UseExisting: false, SetStore: true })
{
Dispatcher.Dispatch(new RootState.LoadingAction(RootState.LoadingHandles.WalletConfig, true));
await BTCPayConnection.Client.UpdateStoreOnChainPaymentMethod(config.PairingResult.StoreId, "BTC", new UpdateOnChainPaymentMethodRequest
{
Enabled = true,
DerivationScheme = xpub,
AccountKeyPath = new RootedKeyPath(mKey, kp)
});
Dispatcher.Dispatch(new RootState.LoadingAction(RootState.LoadingHandles.WalletConfig, false));
}
Dispatcher.Dispatch(new RootState.WalletConfigLoadedAction(new WalletConfig
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,35 +7,49 @@

@if (ConfiguredWallet is not null)
{
@if (IsConfiguredWalletHot)
{
<MudText>Your BTCPay Server store already has an onchain hot wallet configured. Would you like to:</MudText>
}
else
{
<MudText>Your BTCPay Server store already has an onchain watch-only wallet configured. Would you like to:</MudText>
}
<MudAlert Severity="Severity.Warning" Class="mb-4">
@if (IsConfiguredWalletHot)
{
<MudText>Your BTCPay Server store already has an onchain hot wallet configured.</MudText>
}
else
{
<MudText>Your BTCPay Server store already has an onchain watch-only wallet configured.</MudText>
}
</MudAlert>
}

<ValidationEditContext Model="this" @ref="_validationEditContext" Validate="Validate" OnValidSubmit="OnSubmit">
<MudRadioGroup Label="Wallet Creation Options" @bind-SelectedOption="@SelectedOption" For="() => SelectedOption">
<MudRadioGroup Label="Wallet Creation Options" Class="mb-4" @bind-SelectedOption="@SelectedOption" For="() => SelectedOption">
@foreach (var option in Options)
{
<MudRadio T="string" Option="@option.Key">@option.Value</MudRadio>
<div>
<MudRadio T="string" Option="@option.Key" Class="align-start">
<div class="d-flex flex-wrap gap-3 pt-3">
<MudText>@option.Value.Item1</MudText>
@if (option.Value.Item2)
{
<MudChip Variant="Variant.Text" Color="Color.Warning" Size="Size.Small" Class="ma-0">Your existing wallet will be overwritten!</MudChip>
}
</div>
</MudRadio>
</div>
}
</MudRadioGroup>
@if (IsMnemonicRequired)
{
<MudTextField
@bind-Value="Mnemonic"
HelperText="Mnemonic Seed"
Variant="Variant.Filled"
Variant="Variant.Outlined"
AdornmentIcon="@Icons.Material.Filled.Refresh"
Adornment="Adornment.End"
OnAdornmentClick="GenerateSeed"
For="() => Mnemonic"/>
}
<MudButton ButtonType="ButtonType.Submit">Continue</MudButton>
<MudButton ButtonType="ButtonType.Submit" Variant="Variant.Filled" Color="Color.Primary" Disabled="_validationEditContext.Invalid" Class="mt-3">
Continue
</MudButton>
</ValidationEditContext>

@code {
Expand All @@ -50,25 +64,25 @@
get { return new[] {"use-configured-wallet", "create-wallet", "create-wallet-separate"}.Contains(SelectedOption); }
}

private Dictionary<string, string> Options
private Dictionary<string, (string, bool)> Options
{
get
{
var result = new Dictionary<string, string>();
var warningPrefix = "";
var result = new Dictionary<string, (string, bool)>();
var hasWarning = false;
if (ConfiguredWallet is not null)
{
if (IsConfiguredWalletHot)
{
result.Add("use-configured-hot-wallet", "Import the configured hot wallet");
result.Add("use-configured-hot-wallet", ("Import the configured hot wallet", false));
}

result.Add("use-configured-wallet", "Import the configured wallet but store the keys on app");
warningPrefix = "⚠️ Your BTCPay Server store wallet will be overwritten! ⚠️ ";
result.Add("use-configured-wallet", ("Import the configured wallet but store the keys on app", false));
hasWarning = true;
}

result.Add("create-wallet", $"Create a new wallet to use on BTCPay Server and store the keys on app {warningPrefix}");
result.Add("create-wallet-separate", "Create a new wallet to be used only on app");
result.Add("create-wallet", ("Create a new wallet to use on BTCPay Server and store the keys on app", hasWarning));
result.Add("create-wallet-separate", ("Create a new wallet to be used only on app", false));
return result;
}
}
Expand Down
14 changes: 5 additions & 9 deletions BTCPayApp.UI/Shared/Configuration/PairBTCPayServer.razor
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
@using BTCPayApp.CommonServer
@using BTCPayApp.Core
@using System.Net.Http.Json
@using BTCPayApp.UI.Features
@inject IDispatcher Dispatcher
@inject IState<RootState> State

@if (Result is null)
{
Expand All @@ -12,10 +15,6 @@
<MudItem>
<MudButton ButtonType="ButtonType.Submit" Variant="Variant.Filled" Color="Color.Primary" Disabled="_validationEditContext.Invalid">
Submit
@if (Loading)
{
<MudProgressCircular Color="Color.Inherit" Size="Size.Small" Indeterminate="true"/>
}
</MudButton>
</MudItem>
</MudGrid>
Expand Down Expand Up @@ -45,7 +44,6 @@ else if (Result.StoreId is null)
}
}

private bool Loading { get; set; }
private ValidationEditContext _validationEditContext { get; set; }
private PairSuccessResult? Result { get; set; }

Expand All @@ -63,9 +61,8 @@ else if (Result.StoreId is null)
{
try
{
Loading = true;

var client = HttpClientFactory.CreateClient();
Dispatcher.Dispatch(new RootState.LoadingAction(RootState.LoadingHandles.PairConfig, true));
var response = await client.GetAsync(PairingUrl);
response.EnsureSuccessStatusCode();
Result = await response.Content.ReadFromJsonAsync<PairSuccessResult>();
Expand All @@ -89,7 +86,7 @@ else if (Result.StoreId is null)
}
finally
{
Loading = false;
Dispatcher.Dispatch(new RootState.LoadingAction(RootState.LoadingHandles.PairConfig, false));
}
}

Expand All @@ -99,5 +96,4 @@ else if (Result.StoreId is null)
{
throw new NotImplementedException();
}

}
125 changes: 76 additions & 49 deletions BTCPayApp.UI/Shared/Dashboard.razor
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
@using Microsoft.AspNetCore.SignalR.Client
@using BTCPayApp.UI.Features
@using BTCPayApp.UI.Pages
@using BTCPayApp.Core
@inherits Fluxor.Blazor.Web.Components.FluxorComponent

<MudText Typo="Typo.h5" Class="mb-4">Dashboard</MudText>
Expand All @@ -28,10 +29,10 @@ else if (State.Value.PairConfig is not null)
}
else
{
<MudAlert Severity="Severity.Error">
<div class="d-flex align-center justify-space-between gap-3">
<MudAlert Severity="Severity.Warning">
<div class="d-flex flex-wrap align-center justify-space-between gap-3">
No BTCPay Server paired.
<MudButton Href="@Routes.Pair" Variant="Variant.Text" Color="Color.Error" Size="Size.Small">
<MudButton Href="@Routes.Pair" Variant="Variant.Filled" Color="Color.Primary" Size="Size.Small">
Configure connection
</MudButton>
</div>
Expand All @@ -48,65 +49,73 @@ else if (State.Value.WalletConfig is not null)
}
else
{
<MudAlert Severity="Severity.Error">
<div class="d-flex align-center justify-space-between gap-3">
<MudAlert Severity="Severity.Warning">
<div class="d-flex flex-wrap align-center justify-space-between gap-3">
Your wallet is not configured.
<MudButton Href="@Routes.WalletSetup" Variant="Variant.Text" Color="Color.Error" Size="Size.Small">
<MudButton Href="@Routes.WalletSetup" Variant="Variant.Filled" Color="Color.Primary" Size="Size.Small">
Set up a wallet
</MudButton>
</div>
</MudAlert>
}

<MudAlert Severity="Severity.Normal">Lightning Node: @State.Value.LightningNodeState</MudAlert>
@if (State.Value.Loading.Contains(RootState.LoadingHandles.LightningState))
{
<MudAlert Severity="Severity.Info">Lightning node loading.</MudAlert>
}
else
{
<MudAlert Severity="@LightningSeverity">Your Lightning node is @LightningStatus</MudAlert>
}

<MudPaper >
@if (State.Value.Loading.Contains(RootState.LoadingHandles.TransactionState))
@if (State.Value.Loading.Contains(RootState.LoadingHandles.TransactionState))
{
<MudAlert Severity="Severity.Info">Transactions loading.</MudAlert>
}
else
{
<MudText Typo="Typo.h6" Class="mt-8" GutterBottom="true">Transactions</MudText>
@if (OnChainTransactionsState.Value.Error is not false)
{
<MudProgressCircular Color="Color.Default" Indeterminate="true"/>
<MudAlert Severity="Severity.Warning">
<div class="d-flex flex-wrap align-center justify-space-between gap-3">
There was an error loading your transactions.
<MudButton Variant="Variant.Filled" Color="Color.Primary" Size="Size.Small" OnClick="() => Dispatcher.Dispatch(new OnChainTransactionsState.LoadTransactionsAction())">
Retry
</MudButton>
</div>
</MudAlert>
}
else
else if (OnChainTransactionsState.Value.AllTransactions?.Any() is true)
{
@if (OnChainTransactionsState.Value.Error is not false)
{
<MudAlert Severity="Severity.Error">
<div class="d-flex align-center justify-space-between gap-3">
There was an error loading your transactions.
<MudButton Variant="Variant.Text" Color="Color.Error" Size="Size.Small" OnClick="() => Dispatcher.Dispatch(new OnChainTransactionsState.LoadTransactionsAction())">
Retry
</MudButton>
</div>
</MudAlert>
}

@if (OnChainTransactionsState.Value.AllTransactions is not null)
{
<MudList>
@foreach (var tx in OnChainTransactionsState.Value.AllTransactions)
{
<MudListItem>
<MudListItemText>
<div class="d-flex align-center justify-space-between gap-3">
<div>
<MudText Typo="Typo.body2" Class="mb-1">@tx.Value.Id</MudText>
<MudText Typo="Typo.caption" Class="mb-1">@tx.Value.Timestamp</MudText>
</div>
<div>
<MudText Typo="Typo.body2" Class="mb-1">@tx.Value.Balance</MudText>
<MudText Typo="Typo.caption" Class="mb-1">@tx.Value.Status</MudText>
</div>
<MudList>
@foreach (var tx in OnChainTransactionsState.Value.AllTransactions)
{
<MudListItem>
<MudListItemText>
<div class="d-flex align-center justify-space-between gap-3">
<div>
<MudText Typo="Typo.body2" Class="mb-1">@tx.Value.Id</MudText>
<MudText Typo="Typo.caption" Class="mb-1">@tx.Value.Timestamp</MudText>
</div>
</MudListItemText>
</MudListItem>
}
</MudList>
<MudButton Variant="Variant.Text" Color="Color.Default" Size="Size.Small" OnClick="() => Dispatcher.Dispatch(new OnChainTransactionsState.LoadTransactionsAction())">
Refresh
</MudButton>
}
<div>
<MudText Typo="Typo.body2" Class="mb-1">@tx.Value.Balance</MudText>
<MudText Typo="Typo.caption" Class="mb-1">@tx.Value.Status</MudText>
</div>
</div>
</MudListItemText>
</MudListItem>
}
</MudList>
<MudButton Variant="Variant.Filled" Color="Color.Default" Size="Size.Small" OnClick="() => Dispatcher.Dispatch(new OnChainTransactionsState.LoadTransactionsAction())">
Refresh
</MudButton>
}
</MudPaper>

else
{
<MudText GutterBottom="true" Color="Color.Tertiary">There are no transactions, yet.</MudText>
}
}
@code {
private string ConnectionStatus => State.Value.BTCPayServerConnectionState?.ToString().ToLowerInvariant() ?? "not connected";

Expand All @@ -118,6 +127,24 @@ else
_ => Severity.Warning
};

private string LightningStatus => State.Value.LightningNodeState switch {

LightningNodeState.NotConfigured => "not configured",
LightningNodeState.WaitingForBackend => "waiting for the backend",
LightningNodeState.ShuttingDown => "shutting down",
LightningNodeState.Error => "in error state",
_ => State.Value.LightningNodeState.ToString().ToLowerInvariant()
};

private Severity LightningSeverity => State.Value.LightningNodeState switch {
LightningNodeState.Bootstrapping => Severity.Info,
LightningNodeState.Starting => Severity.Info,
LightningNodeState.WaitingForBackend => Severity.Info,
LightningNodeState.Connected => Severity.Success,
LightningNodeState.Error => Severity.Error,
_ => Severity.Warning
};

protected override Task OnAfterRenderAsync(bool firstRender)
{
if (!firstRender) return base.OnAfterRenderAsync(firstRender);
Expand Down
Loading

0 comments on commit 1571455

Please sign in to comment.