Skip to content

Commit

Permalink
Merge pull request #110 from modersohn/feature/AccountsOverviewPage
Browse files Browse the repository at this point in the history
Added account overview page
  • Loading branch information
fudgebucket27 authored Apr 18, 2022
2 parents be6cb5a + 1954a18 commit 8a6274b
Show file tree
Hide file tree
Showing 3 changed files with 213 additions and 0 deletions.
128 changes: 128 additions & 0 deletions Lexplorer/Pages/AccountsOverview.razor
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
@using Lexplorer.Helpers;
@using Lexplorer.Components;
@using System.Diagnostics;
@inject Lexplorer.Services.LoopringGraphQLService LoopringGraphQLService;
@inject NavigationManager NavigationManager;
@inject IAppCache AppCache;
@page "/account";

<PageTitle>The Lexplorer - Accounts</PageTitle>

<MudTable Dense="true" Striped="true" Bordered="true" Items="@accounts" Hover="true" Loading=@isLoading>
<ToolBarContent>
<MudText Typo="Typo.h6">Latest accounts</MudText>
<MudSpacer />
<MudIconButton Icon="@Icons.Filled.FirstPage" Disabled=@(gotoPage == 1) OnClick="@(() => gotoPage = 1)" />
<MudIconButton Icon="@Icons.Filled.NavigateBefore" Disabled=@(gotoPage == 1) OnClick="@(() => gotoPage -= 1)" />
<MudNumericField HideSpinButtons="true" @bind-Value="gotoPage" Label="Page" Variant="Variant.Outlined" Min="1" Margin="Margin.Dense" Class="flex-grow-0" Style="width:150px;" />
<MudIconButton Icon="@Icons.Filled.NavigateNext" Disabled=@(accounts!.Count < pageSize) OnClick="@(() => gotoPage += 1)" />
<MudSpacer />
<MudSelect @bind-Value="@filterAccounts" T="string" Label="Filter by type">
<MudSelectItem Value="@("All")" />
<MudSelectItem Value="@("User")" />
<MudSelectItem Value="@("Pool")" />
<MudSelectItem Value="@("ProtocolAccount")" />
</MudSelect>
</ToolBarContent>
<HeaderContent>
<MudTh>Id</MudTh>
<MudTh>Type</MudTh>
<MudTh>L1 address</MudTh>
<MudTh>Created At (UTC)</MudTh>
</HeaderContent>
<RowTemplate>
<MudTd DataLabel="Account Id">@LinkHelper.GetObjectLink(context)</MudTd>
<MudTd DataLabel="Type">@context.typeName</MudTd>
<MudTd DataLabel="L1Address"><L1AccountLink address="@context?.address" /></MudTd>
<MudTd DataLabel="CreatedAt">@context.createdAtTransaction?.verifiedAt</MudTd>
</RowTemplate>
</MudTable>


@code {
[Parameter]
[SupplyParameterFromQuery]
public string pageNumber { get; set; } = "1";

public int gotoPage
{
get
{
return Int32.Parse(pageNumber ?? "1");
}
set
{
navigateTo(value);
}
}

public bool isLoading = true;
public readonly int pageSize = 25;

private IList<Lexplorer.Models.Account>? accounts { get; set; } = new List<Lexplorer.Models.Account>();

[Parameter]
[SupplyParameterFromQuery]
public string? type { get; set; }

public string? filterAccounts
{
get
{
return type ?? "All";
}
set
{
type = (string.Equals(value ?? "All", "All", StringComparison.InvariantCultureIgnoreCase)) ? null : value;
navigateTo(gotoPage);
}
}

private void navigateTo(int page)
{
string URL = $"/account?pageNumber={page}";
if (type != null)
URL += $"&type={type}";
NavigationManager.NavigateTo(URL);
}

private CancellationTokenSource? cts;

protected override async Task OnParametersSetAsync()
{

//cancel any previous OnParametersSetAsync which might still be running
cts?.Cancel();

using (CancellationTokenSource localCTS = new CancellationTokenSource())
{
//give future calls a chance to cancel us; it is now safe to replace
//any previous value of cts, since we already cancelled it above
cts = localCTS;

try
{
isLoading = true;

string accountCacheKey = $"transactions-page{gotoPage}-type{type}";
accounts = await AppCache.GetOrAddAsyncNonNull(accountCacheKey,
async () => await LoopringGraphQLService.GetAccounts((gotoPage - 1) * pageSize, pageSize, type, localCTS.Token),
DateTimeOffset.UtcNow.AddMinutes(10));
isLoading = false;
StateHasChanged();
}
catch (OperationCanceledException)
{
}
catch (Exception e)
{
Trace.WriteLine(e.StackTrace + "\n" + e.Message);
}
//now for cleanup, we must clear cts, but only if it is still our localCTS, which we're about to dispose
//otherwise a new call has already replaced cts with it's own localCTS
Interlocked.CompareExchange<CancellationTokenSource?>(ref cts, null, localCTS);
}
}

}

64 changes: 64 additions & 0 deletions Shared/Services/LoopringGraphQLService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -468,6 +468,70 @@ query transactions(
return null;
}
}
public async Task<IList<Account>?> GetAccounts(int skip, int first, string? typeName = null, CancellationToken cancellationToken = default)
{
var accountsQuery = @"
query accounts(
$skip: Int
$first: Int
$orderBy: Account_orderBy
$orderDirection: OrderDirection
) {
accounts(
skip: $skip
first: $first
orderBy: $orderBy
orderDirection: $orderDirection
) {
...AccountFragment
...PoolFragment
...UserFragment
}
}"
+ GraphQLFragments.AccountFragment
+ GraphQLFragments.TokenFragment
+ GraphQLFragments.PoolFragment
+ GraphQLFragments.UserFragment
+ GraphQLFragments.AccountCreatedAtFragment;

var request = new RestRequest();
request.AddHeader("Content-Type", "application/json");

//since there is no way to filter for typename in Accounts_filter, we simply
//query a different entity, i.e. pools instead of accounts
string typePluralName = "accounts";
if (!String.IsNullOrEmpty(typeName))
{
//lower case, but first char only
typePluralName = Char.ToLower(typeName[0]) + typeName.Substring(1) + "s";
accountsQuery = accountsQuery.Replace("accounts(", $"{typePluralName}(");
}

request.AddJsonBody(new
{
query = accountsQuery,
variables = new
{
skip = skip,
first = first,
orderBy = "internalID",
orderDirection = "desc"
}
});

try
{
var response = await _client.PostAsync(request, cancellationToken);
JObject jresponse = JObject.Parse(response.Content!);
JToken? token = jresponse["data"]![typePluralName];
return token!.ToObject<IList<Account>>();
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
return null;
}
}
public async Task<Account?> GetAccount(string accountId, CancellationToken cancellationToken = default)
{
var accountQuery = @"
Expand Down
21 changes: 21 additions & 0 deletions xUnitTests/LoopringGraphTests/TestAccount.cs
Original file line number Diff line number Diff line change
Expand Up @@ -51,5 +51,26 @@ public async void GetAccountNFTSlots()
Assert.NotNull(slot.nft);
}
}

[Fact]
public async void GetAccounts()
{
IList<Account>? accounts = await service.GetAccounts(0, 10);
Assert.NotEmpty(accounts);
foreach (var account in accounts!)
{
Assert.NotNull(account);
}
}
[Fact]
public async void GetPools()
{
IList<Account>? accounts = await service.GetAccounts(0, 10, "Pool");
Assert.NotEmpty(accounts);
foreach (var account in accounts!)
{
Assert.IsType<Pool>(account);
}
}
}
}

0 comments on commit 8a6274b

Please sign in to comment.