mirror of
https://github.com/btcpayserver/btcpayserver.git
synced 2025-02-20 13:34:37 +01:00
Do not always provide counting in list views (#3696)
This commit is contained in:
parent
a40429e219
commit
e16a718bde
25 changed files with 66 additions and 90 deletions
|
@ -836,37 +836,6 @@ namespace BTCPayServer.Tests
|
|||
$"enddate:{time.AddSeconds(-1).ToString("yyyy-MM-dd HH:mm:ss")}");
|
||||
}
|
||||
|
||||
[Fact(Timeout = LongRunningTestTimeout)]
|
||||
[Trait("Integration", "Integration")]
|
||||
public async Task CanListNotifications()
|
||||
{
|
||||
using var tester = CreateServerTester();
|
||||
await tester.StartAsync();
|
||||
var acc = tester.NewAccount();
|
||||
acc.GrantAccess(true);
|
||||
acc.RegisterDerivationScheme("BTC");
|
||||
|
||||
const string newVersion = "1.0.4.4";
|
||||
var ctrl = acc.GetController<UINotificationsController>();
|
||||
var resp = await ctrl.Generate(newVersion);
|
||||
|
||||
var vm = Assert.IsType<Models.NotificationViewModels.IndexViewModel>(
|
||||
Assert.IsType<ViewResult>(await ctrl.Index()).Model);
|
||||
|
||||
Assert.True(vm.Skip == 0);
|
||||
Assert.True(vm.Count == 50);
|
||||
Assert.True(vm.Total == 1);
|
||||
Assert.True(vm.Items.Count == 1);
|
||||
|
||||
var fn = vm.Items.First();
|
||||
var now = DateTimeOffset.UtcNow;
|
||||
Assert.True(fn.Created >= now.AddSeconds(-3));
|
||||
Assert.True(fn.Created <= now);
|
||||
Assert.Equal($"New version {newVersion} released!", fn.Body);
|
||||
Assert.Equal($"https://github.com/btcpayserver/btcpayserver/releases/tag/v{newVersion}", fn.ActionLink);
|
||||
Assert.False(fn.Seen);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Integration", "Integration")]
|
||||
public async Task CanGetRates()
|
||||
|
@ -2450,7 +2419,7 @@ namespace BTCPayServer.Tests
|
|||
|
||||
Assert.True(vm.Skip == 0);
|
||||
Assert.True(vm.Count == 50);
|
||||
Assert.True(vm.Total == 1);
|
||||
Assert.Null(vm.Total);
|
||||
Assert.True(vm.Items.Count == 1);
|
||||
|
||||
var fn = vm.Items.First();
|
||||
|
|
|
@ -1,39 +1,45 @@
|
|||
@model BasePagingViewModel
|
||||
|
||||
@{
|
||||
var pageSizeOptions = new [] { 50, 100, 250, 500 };
|
||||
var pageSizeOptions = new[] { 50, 100, 250, 500 };
|
||||
}
|
||||
|
||||
@if (Model.Total > pageSizeOptions.Min())
|
||||
@if (Model.Total is null || Model.Total.Value > pageSizeOptions.Min())
|
||||
{
|
||||
<nav aria-label="..." class="w-100 clearfix">
|
||||
@if (Model.Total > Model.Count)
|
||||
@if (Model.Total is null || Model.Total.Value > Model.Count)
|
||||
{
|
||||
<ul class="pagination float-start">
|
||||
<li class="page-item @(Model.Skip == 0 ? "disabled" : null)">
|
||||
<a class="page-link" tabindex="-1" href="@NavigatePages(-1, Model.Count)">«</a>
|
||||
</li>
|
||||
<li class="page-item disabled">
|
||||
@if (Model.Total <= Model.Count)
|
||||
@if (Model.Total is null)
|
||||
{
|
||||
<span class="page-link">
|
||||
@(Model.Skip + 1)–@(Model.Skip + Model.Count)
|
||||
</span>
|
||||
}
|
||||
else if (Model.Total.Value <= Model.Count)
|
||||
{
|
||||
<span class="page-link">
|
||||
1–@Model.Total
|
||||
1–@Model.Total.Value
|
||||
</span>
|
||||
}
|
||||
else
|
||||
{
|
||||
<span class="page-link">
|
||||
@(Model.Skip + 1)–@(Model.Skip + Model.Count), Total: @Model.Total
|
||||
@(Model.Skip + 1)–@(Model.Skip + Model.Count), Total: @Model.Total.Value
|
||||
</span>
|
||||
}
|
||||
</li>
|
||||
<li class="page-item @(Model.Total > (Model.Skip + Model.Count) ? null : "disabled")">
|
||||
<li class="page-item @(((Model.Total is null && Model.CurrentPageCount >= Model.Count) || (Model.Total is not null && Model.Total.Value > (Model.Skip + Model.Count))) ? null : "disabled")">
|
||||
<a class="page-link" href="@NavigatePages(1, Model.Count)">»</a>
|
||||
</li>
|
||||
</ul>
|
||||
}
|
||||
|
||||
@if (Model.Total >= pageSizeOptions.Min())
|
||||
@if (Model.Total is null || Model.Total.Value >= pageSizeOptions.Min())
|
||||
{
|
||||
<ul class="pagination float-end">
|
||||
<li class="page-item disabled">
|
||||
|
@ -41,7 +47,7 @@
|
|||
</li>
|
||||
@foreach (int pageSize in pageSizeOptions)
|
||||
{
|
||||
if (Model.Total >= pageSize)
|
||||
if (Model.Total is null || Model.Total.Value >= pageSize)
|
||||
{
|
||||
<li class="page-item @(Model.Count == pageSize ? "active" : null)">
|
||||
<a class="page-link" href="@NavigatePages(0, pageSize)">@pageSize</a>
|
||||
|
|
|
@ -38,7 +38,7 @@ namespace BTCPayServer.Controllers.Greenfield
|
|||
{
|
||||
var prs = await _paymentRequestRepository.FindPaymentRequests(
|
||||
new PaymentRequestQuery() { StoreId = storeId, IncludeArchived = includeArchived });
|
||||
return Ok(prs.Items.Select(FromModel));
|
||||
return Ok(prs.Select(FromModel));
|
||||
}
|
||||
|
||||
[Authorize(Policy = Policies.CanViewPaymentRequests, AuthenticationSchemes = AuthenticationSchemes.Greenfield)]
|
||||
|
@ -48,12 +48,12 @@ namespace BTCPayServer.Controllers.Greenfield
|
|||
var pr = await _paymentRequestRepository.FindPaymentRequests(
|
||||
new PaymentRequestQuery() { StoreId = storeId, Ids = new[] { paymentRequestId } });
|
||||
|
||||
if (pr.Total == 0)
|
||||
if (pr.Length == 0)
|
||||
{
|
||||
return PaymentRequestNotFound();
|
||||
}
|
||||
|
||||
return Ok(FromModel(pr.Items.First()));
|
||||
return Ok(FromModel(pr.First()));
|
||||
}
|
||||
|
||||
[Authorize(Policy = Policies.CanModifyPaymentRequests,
|
||||
|
@ -63,12 +63,12 @@ namespace BTCPayServer.Controllers.Greenfield
|
|||
{
|
||||
var pr = await _paymentRequestRepository.FindPaymentRequests(
|
||||
new PaymentRequestQuery() { StoreId = storeId, Ids = new[] { paymentRequestId }, IncludeArchived = false });
|
||||
if (pr.Total == 0)
|
||||
if (pr.Length == 0)
|
||||
{
|
||||
return PaymentRequestNotFound();
|
||||
}
|
||||
|
||||
var updatedPr = pr.Items.First();
|
||||
var updatedPr = pr.First();
|
||||
updatedPr.Archived = true;
|
||||
await _paymentRequestRepository.CreateOrUpdatePaymentRequest(updatedPr);
|
||||
return Ok();
|
||||
|
@ -111,12 +111,12 @@ namespace BTCPayServer.Controllers.Greenfield
|
|||
request.Currency ??= StoreData.GetStoreBlob().DefaultCurrency;
|
||||
var pr = await _paymentRequestRepository.FindPaymentRequests(
|
||||
new PaymentRequestQuery() { StoreId = storeId, Ids = new[] { paymentRequestId } });
|
||||
if (pr.Total == 0)
|
||||
if (pr.Length == 0)
|
||||
{
|
||||
return PaymentRequestNotFound();
|
||||
}
|
||||
|
||||
var updatedPr = pr.Items.First();
|
||||
var updatedPr = pr.First();
|
||||
updatedPr.SetBlob(request);
|
||||
|
||||
return Ok(FromModel(await _paymentRequestRepository.CreateOrUpdatePaymentRequest(updatedPr)));
|
||||
|
|
|
@ -821,7 +821,6 @@ namespace BTCPayServer.Controllers
|
|||
|
||||
InvoiceQuery invoiceQuery = GetInvoiceQuery(model.SearchTerm, model.TimezoneOffset ?? 0);
|
||||
invoiceQuery.StoreId = model.StoreIds;
|
||||
var counting = _InvoiceRepository.GetInvoicesTotal(invoiceQuery);
|
||||
invoiceQuery.Take = model.Count;
|
||||
invoiceQuery.Skip = model.Skip;
|
||||
var list = await _InvoiceRepository.GetInvoices(invoiceQuery);
|
||||
|
@ -845,7 +844,6 @@ namespace BTCPayServer.Controllers
|
|||
Details = InvoicePopulatePayments(invoice),
|
||||
});
|
||||
}
|
||||
model.Total = await counting;
|
||||
return View(model);
|
||||
}
|
||||
|
||||
|
|
|
@ -120,15 +120,6 @@ namespace BTCPayServer.Controllers
|
|||
return View(model);
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
public async Task<IActionResult> Generate(string version)
|
||||
{
|
||||
if (_env.NetworkType != NBitcoin.ChainName.Regtest)
|
||||
return NotFound();
|
||||
await _notificationSender.SendNotification(new AdminScope(), new NewVersionNotification(version));
|
||||
return RedirectToAction(nameof(Index));
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[Authorize(AuthenticationSchemes = AuthenticationSchemes.Cookie, Policy = Policies.CanManageNotificationsForUser)]
|
||||
public async Task<IActionResult> FlipRead(string id)
|
||||
|
|
|
@ -74,8 +74,7 @@ namespace BTCPayServer.Controllers
|
|||
IncludeArchived = includeArchived
|
||||
});
|
||||
|
||||
model.Total = result.Total;
|
||||
model.Items = result.Items.Select(data => new ViewPaymentRequestViewModel(data)).ToList();
|
||||
model.Items = result.Select(data => new ViewPaymentRequestViewModel(data)).ToList();
|
||||
return View(model);
|
||||
}
|
||||
|
||||
|
|
|
@ -68,7 +68,6 @@ namespace BTCPayServer.Controllers
|
|||
Disabled = u.LockoutEnabled && u.LockoutEnd != null && DateTimeOffset.UtcNow < u.LockoutEnd.Value.UtcDateTime
|
||||
})
|
||||
.ToListAsync();
|
||||
model.Total = await usersQuery.CountAsync();
|
||||
|
||||
return View(model);
|
||||
}
|
||||
|
|
|
@ -192,7 +192,7 @@ namespace BTCPayServer.Controllers
|
|||
|
||||
var vm = this.ParseListQuery(new PullPaymentsModel
|
||||
{
|
||||
Skip = skip, Count = count, Total = await ppsQuery.CountAsync(), ActiveState = pullPaymentState
|
||||
Skip = skip, Count = count, ActiveState = pullPaymentState
|
||||
});
|
||||
|
||||
switch (pullPaymentState)
|
||||
|
@ -533,11 +533,11 @@ namespace BTCPayServer.Controllers
|
|||
.ToDictionary(pair => pair.Key, pair => pair.Value);
|
||||
|
||||
payoutRequest = payoutRequest.Where(p => p.State == vm.PayoutState);
|
||||
vm.Total = await payoutRequest.CountAsync();
|
||||
payoutRequest = payoutRequest.Skip(vm.Skip).Take(vm.Count);
|
||||
|
||||
var payouts = await payoutRequest.OrderByDescending(p => p.Date)
|
||||
.Select(o => new { Payout = o, PullPayment = o.PullPaymentData }).ToListAsync();
|
||||
|
||||
foreach (var item in payouts)
|
||||
{
|
||||
var ppBlob = item.PullPayment?.GetBlob();
|
||||
|
|
|
@ -281,7 +281,7 @@ namespace BTCPayServer.Controllers
|
|||
var transactions = await wallet.FetchTransactions(paymentMethod.AccountDerivation);
|
||||
var walletBlob = await walletBlobAsync;
|
||||
var walletTransactionsInfo = await walletTransactionsInfoAsync;
|
||||
var model = new ListTransactionsViewModel { Skip = skip, Count = count, Total = 0 };
|
||||
var model = new ListTransactionsViewModel { Skip = skip, Count = count };
|
||||
if (labelFilter != null)
|
||||
{
|
||||
model.PaginationQuery = new Dictionary<string, object> { { "labelFilter", labelFilter } };
|
||||
|
|
|
@ -8,6 +8,7 @@ using BTCPayServer.Data;
|
|||
using BTCPayServer.Logging;
|
||||
using BTCPayServer.Services;
|
||||
using BTCPayServer.Services.Invoices;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
|
@ -58,7 +59,7 @@ namespace BTCPayServer.HostedServices
|
|||
}
|
||||
|
||||
var invoiceQuery = new InvoiceQuery { IncludeArchived = true };
|
||||
var totalCount = await _invoiceRepository.GetInvoicesTotal(invoiceQuery);
|
||||
var totalCount = await CountInvoices();
|
||||
const int PAGE_SIZE = 1000;
|
||||
var totalPages = Math.Ceiling(totalCount * 1.0m / PAGE_SIZE);
|
||||
Logs.PayServer.LogInformation($"Importing {totalCount} invoices into the search table in {totalPages - startFromPage} pages");
|
||||
|
@ -118,5 +119,11 @@ namespace BTCPayServer.HostedServices
|
|||
}
|
||||
Logs.PayServer.LogInformation($"Full invoice search import successful");
|
||||
}
|
||||
|
||||
private Task<int> CountInvoices()
|
||||
{
|
||||
using var ctx = _dbContextFactory.CreateContext();
|
||||
return ctx.Invoices.CountAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,10 +7,12 @@ namespace BTCPayServer.Models
|
|||
{
|
||||
public int Skip { get; set; } = 0;
|
||||
public int Count { get; set; } = 50;
|
||||
public int Total { get; set; }
|
||||
public int? Total { get; set; }
|
||||
[DisplayFormat(ConvertEmptyStringToNull = false)]
|
||||
public string SearchTerm { get; set; }
|
||||
public int? TimezoneOffset { get; set; }
|
||||
public Dictionary<string, object> PaginationQuery { get; set; }
|
||||
|
||||
public abstract int CurrentPageCount { get; }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ namespace BTCPayServer.Models.InvoicingModels
|
|||
public class InvoicesModel : BasePagingViewModel
|
||||
{
|
||||
public List<InvoiceModel> Invoices { get; set; } = new List<InvoiceModel>();
|
||||
public override int CurrentPageCount => Invoices.Count;
|
||||
public string[] StoreIds { get; set; }
|
||||
public string StoreId { get; set; }
|
||||
public bool IncludeArchived { get; set; }
|
||||
|
|
|
@ -6,5 +6,7 @@ namespace BTCPayServer.Models.NotificationViewModels
|
|||
public class IndexViewModel : BasePagingViewModel
|
||||
{
|
||||
public List<NotificationViewModel> Items { get; set; }
|
||||
|
||||
public override int CurrentPageCount => Items.Count;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@ namespace BTCPayServer.Models.PaymentRequestViewModels
|
|||
public class ListPaymentRequestsViewModel : BasePagingViewModel
|
||||
{
|
||||
public List<ViewPaymentRequestViewModel> Items { get; set; }
|
||||
public override int CurrentPageCount => Items.Count;
|
||||
}
|
||||
|
||||
public class UpdatePaymentRequestViewModel
|
||||
|
|
|
@ -17,6 +17,7 @@ namespace BTCPayServer.Models.ServerViewModels
|
|||
public IEnumerable<string> Roles { get; set; }
|
||||
}
|
||||
public List<UserViewModel> Users { get; set; } = new List<UserViewModel>();
|
||||
public override int CurrentPageCount => Users.Count;
|
||||
public Dictionary<string, string> Roles { get; set; }
|
||||
}
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@ namespace BTCPayServer.Models.WalletViewModels
|
|||
}
|
||||
public HashSet<ColoredLabel> Labels { get; set; } = new HashSet<ColoredLabel>();
|
||||
public List<TransactionViewModel> Transactions { get; set; } = new List<TransactionViewModel>();
|
||||
public override int CurrentPageCount => Transactions.Count;
|
||||
public string CryptoCode { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@ namespace BTCPayServer.Models.WalletViewModels
|
|||
public string PaymentMethodId { get; set; }
|
||||
|
||||
public List<PayoutModel> Payouts { get; set; }
|
||||
public override int CurrentPageCount => Payouts.Count;
|
||||
public IEnumerable<PaymentMethodId> PaymentMethods { get; set; }
|
||||
public PayoutState PayoutState { get; set; }
|
||||
public string PullPaymentName { get; set; }
|
||||
|
|
|
@ -33,6 +33,7 @@ namespace BTCPayServer.Models.WalletViewModels
|
|||
}
|
||||
|
||||
public List<PullPaymentModel> PullPayments { get; set; } = new List<PullPaymentModel>();
|
||||
public override int CurrentPageCount => PullPayments.Count;
|
||||
public string PaymentMethodId { get; set; }
|
||||
public IEnumerable<PaymentMethodId> PaymentMethods { get; set; }
|
||||
public PullPaymentState ActiveState { get; set; } = PullPaymentState.Active;
|
||||
|
|
|
@ -122,12 +122,11 @@ namespace BTCPayServer.PaymentRequest
|
|||
private async Task CheckingPendingPayments(CancellationToken cancellationToken)
|
||||
{
|
||||
Logs.PayServer.LogInformation("Starting payment request expiration watcher");
|
||||
var (total, items) = await _PaymentRequestRepository.FindPaymentRequests(new PaymentRequestQuery()
|
||||
var items = await _PaymentRequestRepository.FindPaymentRequests(new PaymentRequestQuery()
|
||||
{
|
||||
Status = new[] { Client.Models.PaymentRequestData.PaymentRequestStatus.Pending }
|
||||
}, cancellationToken);
|
||||
|
||||
Logs.PayServer.LogInformation($"{total} pending payment requests being checked since last run");
|
||||
Logs.PayServer.LogInformation($"{items.Length} pending payment requests being checked since last run");
|
||||
await Task.WhenAll(items.Select(i => _PaymentRequestService.UpdatePaymentRequestStateIfNeeded(i))
|
||||
.ToArray());
|
||||
}
|
||||
|
|
|
@ -736,13 +736,6 @@ namespace BTCPayServer.Services.Invoices
|
|||
return query;
|
||||
}
|
||||
|
||||
public async Task<int> GetInvoicesTotal(InvoiceQuery queryObject)
|
||||
{
|
||||
using var context = _applicationDbContextFactory.CreateContext();
|
||||
var query = GetInvoiceQuery(context, queryObject);
|
||||
return await query.CountAsync();
|
||||
}
|
||||
|
||||
public async Task<InvoiceEntity[]> GetInvoices(InvoiceQuery queryObject)
|
||||
{
|
||||
using var context = _applicationDbContextFactory.CreateContext();
|
||||
|
|
|
@ -48,7 +48,7 @@ namespace BTCPayServer.Services.Notifications
|
|||
UserId = userId
|
||||
});
|
||||
entry.SetAbsoluteExpiration(TimeSpan.FromMilliseconds(_cacheExpiryMs));
|
||||
var res = new NotificationsViewModel { Last5 = resp.Items, UnseenCount = resp.Count };
|
||||
var res = new NotificationsViewModel { Last5 = resp.Items, UnseenCount = resp.Count.Value };
|
||||
entry.Value = res;
|
||||
return res;
|
||||
});
|
||||
|
@ -68,14 +68,20 @@ namespace BTCPayServer.Services.Notifications
|
|||
return $"notifications-{userId}";
|
||||
}
|
||||
|
||||
public async Task<(List<NotificationViewModel> Items, int Count)> GetNotifications(NotificationsQuery query)
|
||||
public async Task<(List<NotificationViewModel> Items, int? Count)> GetNotifications(NotificationsQuery query)
|
||||
{
|
||||
await using var dbContext = _factory.CreateContext();
|
||||
|
||||
var queryables = GetNotificationsQueryable(dbContext, query);
|
||||
var items = (await queryables.withPaging.ToListAsync()).Select(ToViewModel).Where(model => model != null).ToList();
|
||||
|
||||
return (Items: (await queryables.withPaging.ToListAsync()).Select(ToViewModel).Where(model => model != null).ToList(),
|
||||
Count: await queryables.withoutPaging.CountAsync());
|
||||
int? count = null;
|
||||
if (query.Seen is false)
|
||||
{
|
||||
// Unseen notifications aren't likely to be too huge, so count should be fast
|
||||
count = await queryables.withoutPaging.CountAsync();
|
||||
}
|
||||
return (Items: items, Count: count);
|
||||
}
|
||||
|
||||
private (IQueryable<NotificationData> withoutPaging, IQueryable<NotificationData> withPaging)
|
||||
|
|
|
@ -76,7 +76,7 @@ namespace BTCPayServer.Services.PaymentRequests
|
|||
await context.SaveChangesAsync(cancellationToken);
|
||||
}
|
||||
|
||||
public async Task<(int Total, PaymentRequestData[] Items)> FindPaymentRequests(PaymentRequestQuery query, CancellationToken cancellationToken = default)
|
||||
public async Task<PaymentRequestData[]> FindPaymentRequests(PaymentRequestQuery query, CancellationToken cancellationToken = default)
|
||||
{
|
||||
using var context = _ContextFactory.CreateContext();
|
||||
var queryable = context.PaymentRequests.Include(data => data.StoreData).AsQueryable();
|
||||
|
@ -109,8 +109,6 @@ namespace BTCPayServer.Services.PaymentRequests
|
|||
i.StoreData != null && i.StoreData.UserStores.Any(u => u.ApplicationUserId == query.UserId));
|
||||
}
|
||||
|
||||
var total = await queryable.CountAsync(cancellationToken);
|
||||
|
||||
queryable = queryable.OrderByDescending(u => u.Created);
|
||||
|
||||
if (query.Skip.HasValue)
|
||||
|
@ -122,7 +120,8 @@ namespace BTCPayServer.Services.PaymentRequests
|
|||
{
|
||||
queryable = queryable.Take(query.Count.Value);
|
||||
}
|
||||
return (total, await queryable.ToArrayAsync(cancellationToken));
|
||||
var items = await queryable.ToArrayAsync(cancellationToken);
|
||||
return items;
|
||||
}
|
||||
|
||||
public async Task<InvoiceEntity[]> GetInvoicesForPaymentRequest(string paymentRequestId,
|
||||
|
|
|
@ -243,7 +243,7 @@
|
|||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<form class="@(Model.Total > 0 ? "col-xl-7 col-xxl-8 " : "")mb-4" asp-action="ListInvoices" asp-route-storeId="@Model.StoreId" method="get">
|
||||
<form class="@(Model.Invoices.Count > 0 ? "col-xl-7 col-xxl-8 " : "")mb-4" asp-action="ListInvoices" asp-route-storeId="@Model.StoreId" method="get">
|
||||
<input type="hidden" asp-for="Count" />
|
||||
<input asp-for="TimezoneOffset" type="hidden" />
|
||||
<div class="input-group">
|
||||
|
@ -278,7 +278,7 @@
|
|||
<span asp-validation-for="SearchTerm" class="text-danger"></span>
|
||||
</form>
|
||||
|
||||
@if (Model.Total > 0)
|
||||
@if (Model.Invoices.Count > 0)
|
||||
{
|
||||
<form method="post" id="MassAction" asp-action="MassAction" class="">
|
||||
<div class="d-inline-flex align-items-center pb-2 float-xl-end mb-2 gap-3">
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
Settings
|
||||
</a>
|
||||
</div>
|
||||
@if (Model.Total > 0)
|
||||
@if (Model.Items.Count > 0)
|
||||
{
|
||||
<form method="post" asp-action="MassAction">
|
||||
<div class="row button-row">
|
||||
|
@ -34,7 +34,7 @@
|
|||
<thead>
|
||||
<tr>
|
||||
<th width="30px" class="only-for-js">
|
||||
@if (Model.Total > 0)
|
||||
@if (Model.Items.Count > 0)
|
||||
{
|
||||
<input name="selectedItems" id="selectAllCheckbox" type="checkbox" class="form-check-input" />
|
||||
}
|
||||
|
|
|
@ -49,7 +49,7 @@
|
|||
|
||||
<div class="row">
|
||||
<div class="col-lg-12">
|
||||
@if (Model.Total > 0)
|
||||
@if (Model.Items.Count > 0)
|
||||
{
|
||||
<table class="table table-hover table-responsive-md">
|
||||
<thead>
|
||||
|
|
Loading…
Add table
Reference in a new issue