mirror of
https://github.com/aljazceru/btcpayserver.git
synced 2025-12-17 22:14:26 +01:00
Added bootstrap paging buttons to the invoice list page and fixed paging buttons.
This commit is contained in:
@@ -447,8 +447,11 @@ namespace BTCPayServer.Controllers
|
|||||||
Count = count,
|
Count = count,
|
||||||
StatusMessage = StatusMessage
|
StatusMessage = StatusMessage
|
||||||
};
|
};
|
||||||
|
InvoiceQuery invoiceQuery = GetInvoiceQuery(searchTerm);
|
||||||
var list = await ListInvoicesProcess(searchTerm, skip, count);
|
model.Total = await _InvoiceRepository.GetInvoicesTotal(invoiceQuery);
|
||||||
|
invoiceQuery.Count = count;
|
||||||
|
invoiceQuery.Skip = skip;
|
||||||
|
var list = await _InvoiceRepository.GetInvoices(invoiceQuery);
|
||||||
foreach (var invoice in list)
|
foreach (var invoice in list)
|
||||||
{
|
{
|
||||||
var state = invoice.GetInvoiceState();
|
var state = invoice.GetInvoiceState();
|
||||||
@@ -468,14 +471,12 @@ namespace BTCPayServer.Controllers
|
|||||||
return View(model);
|
return View(model);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<InvoiceEntity[]> ListInvoicesProcess(string searchTerm = null, int skip = 0, int count = 50)
|
private InvoiceQuery GetInvoiceQuery(string searchTerm = null)
|
||||||
{
|
{
|
||||||
var filterString = new SearchString(searchTerm);
|
var filterString = new SearchString(searchTerm);
|
||||||
var list = await _InvoiceRepository.GetInvoices(new InvoiceQuery()
|
var invoiceQuery = new InvoiceQuery()
|
||||||
{
|
{
|
||||||
TextSearch = filterString.TextSearch,
|
TextSearch = filterString.TextSearch,
|
||||||
Count = count,
|
|
||||||
Skip = skip,
|
|
||||||
UserId = GetUserId(),
|
UserId = GetUserId(),
|
||||||
Unusual = !filterString.Filters.ContainsKey("unusual") ? null
|
Unusual = !filterString.Filters.ContainsKey("unusual") ? null
|
||||||
: !bool.TryParse(filterString.Filters["unusual"].First(), out var r) ? (bool?)null
|
: !bool.TryParse(filterString.Filters["unusual"].First(), out var r) ? (bool?)null
|
||||||
@@ -485,9 +486,8 @@ namespace BTCPayServer.Controllers
|
|||||||
StoreId = filterString.Filters.ContainsKey("storeid") ? filterString.Filters["storeid"].ToArray() : null,
|
StoreId = filterString.Filters.ContainsKey("storeid") ? filterString.Filters["storeid"].ToArray() : null,
|
||||||
ItemCode = filterString.Filters.ContainsKey("itemcode") ? filterString.Filters["itemcode"].ToArray() : null,
|
ItemCode = filterString.Filters.ContainsKey("itemcode") ? filterString.Filters["itemcode"].ToArray() : null,
|
||||||
OrderId = filterString.Filters.ContainsKey("orderid") ? filterString.Filters["orderid"].ToArray() : null
|
OrderId = filterString.Filters.ContainsKey("orderid") ? filterString.Filters["orderid"].ToArray() : null
|
||||||
});
|
};
|
||||||
|
return invoiceQuery;
|
||||||
return list;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
@@ -497,7 +497,10 @@ namespace BTCPayServer.Controllers
|
|||||||
{
|
{
|
||||||
var model = new InvoiceExport(_NetworkProvider, _CurrencyNameTable);
|
var model = new InvoiceExport(_NetworkProvider, _CurrencyNameTable);
|
||||||
|
|
||||||
var invoices = await ListInvoicesProcess(searchTerm, 0, int.MaxValue);
|
InvoiceQuery invoiceQuery = GetInvoiceQuery(searchTerm);
|
||||||
|
invoiceQuery.Count = int.MaxValue;
|
||||||
|
invoiceQuery.Skip = 0;
|
||||||
|
var invoices = await _InvoiceRepository.GetInvoices(invoiceQuery);
|
||||||
var res = model.Process(invoices, format);
|
var res = model.Process(invoices, format);
|
||||||
|
|
||||||
var cd = new ContentDisposition
|
var cd = new ContentDisposition
|
||||||
|
|||||||
@@ -15,6 +15,10 @@ namespace BTCPayServer.Models.InvoicingModels
|
|||||||
{
|
{
|
||||||
get; set;
|
get; set;
|
||||||
}
|
}
|
||||||
|
public int Total
|
||||||
|
{
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
public string SearchTerm
|
public string SearchTerm
|
||||||
{
|
{
|
||||||
get; set;
|
get; set;
|
||||||
|
|||||||
@@ -420,91 +420,108 @@ retry:
|
|||||||
return entity;
|
return entity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private IQueryable<Data.InvoiceData> GetInvoiceQuery(ApplicationDbContext context, InvoiceQuery queryObject)
|
||||||
|
{
|
||||||
|
IQueryable<Data.InvoiceData> query = context.Invoices;
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(queryObject.InvoiceId))
|
||||||
|
{
|
||||||
|
query = query.Where(i => i.Id == queryObject.InvoiceId);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (queryObject.StoreId != null && queryObject.StoreId.Length > 0)
|
||||||
|
{
|
||||||
|
var stores = queryObject.StoreId.ToHashSet();
|
||||||
|
query = query.Where(i => stores.Contains(i.StoreDataId));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (queryObject.UserId != null)
|
||||||
|
{
|
||||||
|
query = query.Where(i => i.StoreData.UserStores.Any(u => u.ApplicationUserId == queryObject.UserId));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(queryObject.TextSearch))
|
||||||
|
{
|
||||||
|
var ids = new HashSet<string>(SearchInvoice(queryObject.TextSearch));
|
||||||
|
if (ids.Count == 0)
|
||||||
|
{
|
||||||
|
// Hacky way to return an empty query object. The nice way is much too elaborate:
|
||||||
|
// https://stackoverflow.com/questions/33305495/how-to-return-empty-iqueryable-in-an-async-repository-method
|
||||||
|
return query.Where(x => false);
|
||||||
|
}
|
||||||
|
query = query.Where(i => ids.Contains(i.Id));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (queryObject.StartDate != null)
|
||||||
|
query = query.Where(i => queryObject.StartDate.Value <= i.Created);
|
||||||
|
|
||||||
|
if (queryObject.EndDate != null)
|
||||||
|
query = query.Where(i => i.Created <= queryObject.EndDate.Value);
|
||||||
|
|
||||||
|
if (queryObject.OrderId != null && queryObject.OrderId.Length > 0)
|
||||||
|
{
|
||||||
|
var statusSet = queryObject.OrderId.ToHashSet();
|
||||||
|
query = query.Where(i => statusSet.Contains(i.OrderId));
|
||||||
|
}
|
||||||
|
if (queryObject.ItemCode != null && queryObject.ItemCode.Length > 0)
|
||||||
|
{
|
||||||
|
var statusSet = queryObject.ItemCode.ToHashSet();
|
||||||
|
query = query.Where(i => statusSet.Contains(i.ItemCode));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (queryObject.Status != null && queryObject.Status.Length > 0)
|
||||||
|
{
|
||||||
|
var statusSet = queryObject.Status.ToHashSet();
|
||||||
|
query = query.Where(i => statusSet.Contains(i.Status));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (queryObject.Unusual != null)
|
||||||
|
{
|
||||||
|
var unused = queryObject.Unusual.Value;
|
||||||
|
query = query.Where(i => unused == (i.Status == "invalid" || i.ExceptionStatus != null));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (queryObject.ExceptionStatus != null && queryObject.ExceptionStatus.Length > 0)
|
||||||
|
{
|
||||||
|
var exceptionStatusSet = queryObject.ExceptionStatus.Select(s => NormalizeExceptionStatus(s)).ToHashSet();
|
||||||
|
query = query.Where(i => exceptionStatusSet.Contains(i.ExceptionStatus));
|
||||||
|
}
|
||||||
|
|
||||||
|
query = query.OrderByDescending(q => q.Created);
|
||||||
|
|
||||||
|
if (queryObject.Skip != null)
|
||||||
|
query = query.Skip(queryObject.Skip.Value);
|
||||||
|
|
||||||
|
if (queryObject.Count != null)
|
||||||
|
query = query.Take(queryObject.Count.Value);
|
||||||
|
|
||||||
|
return query;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<int> GetInvoicesTotal(InvoiceQuery queryObject)
|
||||||
|
{
|
||||||
|
using (var context = _ContextFactory.CreateContext())
|
||||||
|
{
|
||||||
|
var query = GetInvoiceQuery(context, queryObject);
|
||||||
|
return await query.CountAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public async Task<InvoiceEntity[]> GetInvoices(InvoiceQuery queryObject)
|
public async Task<InvoiceEntity[]> GetInvoices(InvoiceQuery queryObject)
|
||||||
{
|
{
|
||||||
using (var context = _ContextFactory.CreateContext())
|
using (var context = _ContextFactory.CreateContext())
|
||||||
{
|
{
|
||||||
IQueryable<Data.InvoiceData> query = context
|
var query = GetInvoiceQuery(context, queryObject);
|
||||||
.Invoices
|
query = query.Include(o => o.Payments)
|
||||||
.Include(o => o.Payments)
|
|
||||||
.Include(o => o.RefundAddresses);
|
.Include(o => o.RefundAddresses);
|
||||||
if (queryObject.IncludeAddresses)
|
if (queryObject.IncludeAddresses)
|
||||||
query = query.Include(o => o.HistoricalAddressInvoices).Include(o => o.AddressInvoices);
|
query = query.Include(o => o.HistoricalAddressInvoices).Include(o => o.AddressInvoices);
|
||||||
if (queryObject.IncludeEvents)
|
if (queryObject.IncludeEvents)
|
||||||
query = query.Include(o => o.Events);
|
query = query.Include(o => o.Events);
|
||||||
if (!string.IsNullOrEmpty(queryObject.InvoiceId))
|
|
||||||
{
|
|
||||||
query = query.Where(i => i.Id == queryObject.InvoiceId);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (queryObject.StoreId != null && queryObject.StoreId.Length > 0)
|
|
||||||
{
|
|
||||||
var stores = queryObject.StoreId.ToHashSet();
|
|
||||||
query = query.Where(i => stores.Contains(i.StoreDataId));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (queryObject.UserId != null)
|
|
||||||
{
|
|
||||||
query = query.Where(i => i.StoreData.UserStores.Any(u => u.ApplicationUserId == queryObject.UserId));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(queryObject.TextSearch))
|
|
||||||
{
|
|
||||||
var ids = new HashSet<string>(SearchInvoice(queryObject.TextSearch));
|
|
||||||
if (ids.Count == 0)
|
|
||||||
return Array.Empty<InvoiceEntity>();
|
|
||||||
query = query.Where(i => ids.Contains(i.Id));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (queryObject.StartDate != null)
|
|
||||||
query = query.Where(i => queryObject.StartDate.Value <= i.Created);
|
|
||||||
|
|
||||||
if (queryObject.EndDate != null)
|
|
||||||
query = query.Where(i => i.Created <= queryObject.EndDate.Value);
|
|
||||||
|
|
||||||
if (queryObject.OrderId != null && queryObject.OrderId.Length > 0)
|
|
||||||
{
|
|
||||||
var statusSet = queryObject.OrderId.ToHashSet();
|
|
||||||
query = query.Where(i => statusSet.Contains(i.OrderId));
|
|
||||||
}
|
|
||||||
if (queryObject.ItemCode != null && queryObject.ItemCode.Length > 0)
|
|
||||||
{
|
|
||||||
var statusSet = queryObject.ItemCode.ToHashSet();
|
|
||||||
query = query.Where(i => statusSet.Contains(i.ItemCode));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (queryObject.Status != null && queryObject.Status.Length > 0)
|
|
||||||
{
|
|
||||||
var statusSet = queryObject.Status.ToHashSet();
|
|
||||||
query = query.Where(i => statusSet.Contains(i.Status));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (queryObject.Unusual != null)
|
|
||||||
{
|
|
||||||
var unused = queryObject.Unusual.Value;
|
|
||||||
query = query.Where(i => unused == (i.Status == "invalid" || i.ExceptionStatus != null));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (queryObject.ExceptionStatus != null && queryObject.ExceptionStatus.Length > 0)
|
|
||||||
{
|
|
||||||
var exceptionStatusSet = queryObject.ExceptionStatus.Select(s => NormalizeExceptionStatus(s)).ToHashSet();
|
|
||||||
query = query.Where(i => exceptionStatusSet.Contains(i.ExceptionStatus));
|
|
||||||
}
|
|
||||||
|
|
||||||
query = query.OrderByDescending(q => q.Created);
|
|
||||||
|
|
||||||
if (queryObject.Skip != null)
|
|
||||||
query = query.Skip(queryObject.Skip.Value);
|
|
||||||
|
|
||||||
if (queryObject.Count != null)
|
|
||||||
query = query.Take(queryObject.Count.Value);
|
|
||||||
|
|
||||||
var data = await query.ToArrayAsync().ConfigureAwait(false);
|
var data = await query.ToArrayAsync().ConfigureAwait(false);
|
||||||
|
|
||||||
return data.Select(ToEntity).ToArray();
|
return data.Select(ToEntity).ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private string NormalizeExceptionStatus(string status)
|
private string NormalizeExceptionStatus(string status)
|
||||||
|
|||||||
@@ -142,23 +142,31 @@
|
|||||||
}
|
}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
<span>
|
|
||||||
@if (Model.Skip != 0)
|
<nav aria-label="...">
|
||||||
{
|
<ul class="pagination">
|
||||||
<a href="@Url.Action("ListInvoices", new
|
<li class="page-item @(Model.Skip == 0 ? "disabled" : null)">
|
||||||
|
<a class="page-link" tabindex="-1" href="@Url.Action("ListInvoices", new
|
||||||
{
|
{
|
||||||
searchTerm = Model.SearchTerm,
|
searchTerm = Model.SearchTerm,
|
||||||
skip = Math.Max(0, Model.Skip - Model.Count),
|
skip = Math.Max(0, Model.Skip - Model.Count),
|
||||||
count = Model.Count,
|
count = Model.Count,
|
||||||
})"><<</a><span> - </span>
|
})">Previous</a>
|
||||||
}
|
</li>
|
||||||
<a href="@Url.Action("ListInvoices", new
|
<li class="page-item disabled">
|
||||||
{
|
<span class="page-link">@(Model.Skip + 1) to @(Model.Skip + Model.Invoices.Count) of @Model.Total</span>
|
||||||
searchTerm = Model.SearchTerm,
|
</li>
|
||||||
skip = Model.Skip + Model.Count,
|
<li class="page-item @(Model.Total > (Model.Skip + Model.Invoices.Count) ? null : "disabled")">
|
||||||
count = Model.Count,
|
<a class="page-link" href="@Url.Action("ListInvoices", new
|
||||||
})">>></a>
|
{
|
||||||
</span>
|
searchTerm = Model.SearchTerm,
|
||||||
|
skip = Model.Skip + Model.Count,
|
||||||
|
count = Model.Count,
|
||||||
|
})">Next</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user