mirror of
https://github.com/btcpayserver/btcpayserver.git
synced 2025-01-19 05:33:31 +01:00
b334e1aa00
Fixes styling issues introduced in #4074, because the `max-width` was to small for localized dates. Also adds the ability to choose the prefered initial display format, which can be the localized or relative date.
255 lines
9.8 KiB
Plaintext
255 lines
9.8 KiB
Plaintext
@model ListTransactionsViewModel
|
|
|
|
@{
|
|
var walletId = Context.GetRouteValue("walletId").ToString();
|
|
var labelFilter = Context.Request.Query["labelFilter"].ToString();
|
|
|
|
Layout = "../Shared/_NavLayout.cshtml";
|
|
ViewData.SetActivePage(WalletsNavPages.Transactions, $"{Model.CryptoCode} Transactions", walletId);
|
|
}
|
|
|
|
@section PageHeadContent {
|
|
<style>
|
|
.smMaxWidth {
|
|
max-width: 125px;
|
|
}
|
|
|
|
@@media (min-width: 990px) {
|
|
.smMaxWidth {
|
|
max-width: 200px;
|
|
}
|
|
}
|
|
|
|
/* pull actions area, so that it is besides the search form */
|
|
@@media (min-width: 1200px) {
|
|
#Filter + #Dropdowns {
|
|
margin-top: -4rem;
|
|
float: right;
|
|
}
|
|
|
|
#Filter + #Dropdowns #Actions {
|
|
order: 1;
|
|
}
|
|
}
|
|
|
|
.unconf > * {
|
|
opacity: 0.5;
|
|
}
|
|
|
|
.badge-container {
|
|
display: flex;
|
|
flex-wrap: nowrap;
|
|
}
|
|
|
|
.removeTransactionLabelForm {
|
|
display: inline;
|
|
position: absolute;
|
|
right: 4px;
|
|
}
|
|
|
|
.removeTransactionLabelForm button {
|
|
cursor: pointer;
|
|
display: inline;
|
|
padding: 0;
|
|
background-color: transparent;
|
|
border: 0;
|
|
}
|
|
|
|
.label-tooltip .tooltip-inner {
|
|
max-width: 15rem;
|
|
text-align: left;
|
|
}
|
|
|
|
.label-tooltip ul {
|
|
margin: 0;
|
|
padding-left: var(--btcpay-space-m);
|
|
}
|
|
|
|
#LoadingIndicator {
|
|
margin-bottom: 1.5rem;
|
|
}
|
|
</style>
|
|
}
|
|
|
|
@section PageFootContent {
|
|
@*Without async, somehow selenium do not manage to click on links in this page*@
|
|
<script src="~/modal/btcpay.js" asp-append-version="true" async></script>
|
|
|
|
@* Custom Range Modal *@
|
|
<script>
|
|
let observer = null;
|
|
let $loadMore = document.getElementById('LoadMore');
|
|
const $actions = document.getElementById('ListActions');
|
|
const $list = document.getElementById('WalletTransactionsList');
|
|
const $indicator = document.getElementById('LoadingIndicator');
|
|
|
|
delegate('click', '#selectAllCheckbox', e => {
|
|
document.querySelectorAll(".selector").forEach(checkbox => {
|
|
checkbox.checked = e.target.checked;
|
|
});
|
|
});
|
|
|
|
delegate('click', '#GoToTop', () => {
|
|
window.scrollTo({ top: 0, behavior: 'smooth' });
|
|
});
|
|
|
|
delegate('click', '#LoadMore', async () => {
|
|
$loadMore.setAttribute('disabled', 'disabled');
|
|
await loadMoreTransactions();
|
|
});
|
|
|
|
if ($actions && $actions.offsetTop - window.innerHeight > 0) {
|
|
document.getElementById('GoToTop').classList.remove('d-none');
|
|
}
|
|
|
|
const count = @Safe.Json(Model.Count);
|
|
const skipInitial = @Safe.Json(Model.Skip);
|
|
const loadMoreUrl = @Safe.Json(Url.Action("WalletTransactions", new { walletId, labelFilter, skip = Model.Skip, count = Model.Count }));
|
|
let skip = @Safe.Json(Model.Skip);
|
|
|
|
async function loadMoreTransactions() {
|
|
$indicator.classList.remove('d-none');
|
|
|
|
const skipNext = skip + count;
|
|
const url = loadMoreUrl.replace(`skip=${skipInitial}`, `skip=${skipNext}`)
|
|
const response = await fetch(url, {
|
|
headers: {
|
|
'Accept': 'text/html',
|
|
'X-Requested-With': 'XMLHttpRequest'
|
|
}
|
|
});
|
|
|
|
if (response.ok) {
|
|
const html = await response.text();
|
|
$list.innerHTML += html;
|
|
skip = skipNext;
|
|
|
|
if ($loadMore) {
|
|
// remove load more button
|
|
$loadMore.remove();
|
|
$loadMore = null;
|
|
|
|
// switch to infinite scroll mode
|
|
observer = new IntersectionObserver(async entries => {
|
|
const { isIntersecting } = entries[0];
|
|
if (isIntersecting) {
|
|
await loadMoreTransactions();
|
|
}
|
|
}, { rootMargin: '128px' });
|
|
|
|
// the actions div marks the end of the list table
|
|
observer.observe($actions);
|
|
}
|
|
|
|
if (html.trim() === '') {
|
|
// in case the response html was empty, remove the observer and stop loading
|
|
observer.unobserve($actions);
|
|
}
|
|
} else if ($loadMore) {
|
|
$loadMore.removeAttribute('disabled');
|
|
}
|
|
|
|
$indicator.classList.add('d-none');
|
|
formatDateTimes(document.getElementById('switchTimeFormat').dataset.mode);
|
|
}
|
|
</script>
|
|
}
|
|
|
|
@if (Model.Transactions.Any())
|
|
{
|
|
@if (Model.Labels.Any())
|
|
{
|
|
<div class="col-xl-7 col-xxl-8 mb-4" id="Filter">
|
|
<div class="input-group">
|
|
<span class="input-group-text">Filter</span>
|
|
<div class="form-control d-flex flex-wrap gap-2 align-items-center">
|
|
@foreach (var label in Model.Labels)
|
|
{
|
|
<a asp-route-labelFilter="@label.Text" class="badge position-relative text-white flex-grow-0" style="background-color:@label.Color;color:@label.TextColor !important;">@label.Text</a>
|
|
}
|
|
</div>
|
|
@if (labelFilter != null)
|
|
{
|
|
<a asp-route-labelFilter="" class="btn btn-secondary d-flex align-items-center">Clear filter</a>
|
|
}
|
|
</div>
|
|
</div>
|
|
}
|
|
<div class="d-inline-flex align-items-center gap-3" id="Dropdowns">
|
|
<div class="dropdown ms-auto" id="Actions">
|
|
<button class="btn btn-secondary dropdown-toggle" type="button" id="ActionsDropdownToggle" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
|
Actions
|
|
</button>
|
|
<div class="dropdown-menu dropdown-menu-end" aria-labelledby="ActionsDropdownToggle">
|
|
<form id="WalletActions" method="post" asp-action="WalletActions" asp-route-walletId="@walletId">
|
|
<button id="BumpFee" name="command" type="submit" class="dropdown-item" value="cpfp">Bump fee (CPFP)</button>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
<div class="dropdown d-inline-flex align-items-center gap-3" id="Export">
|
|
<button class="btn btn-secondary dropdown-toggle" type="button" id="ExportDropdownToggle" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
|
Export
|
|
</button>
|
|
<div class="dropdown-menu" aria-labelledby="ExportDropdownToggle">
|
|
<a asp-action="Export" asp-route-walletId="@walletId" asp-route-format="csv" asp-route-labelFilter="@labelFilter" class="dropdown-item export-link" target="_blank" id="ExportCSV">CSV</a>
|
|
<a asp-action="Export" asp-route-walletId="@walletId" asp-route-format="json" asp-route-labelFilter="@labelFilter" class="dropdown-item export-link" target="_blank" id="ExportJSON">JSON</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div style="clear:both"></div>
|
|
|
|
<div class="row">
|
|
<div class="col table-responsive-md" id="walletTable">
|
|
<table class="table table-hover">
|
|
<thead class="thead-inverse">
|
|
<tr>
|
|
<th style="width:2rem;" class="only-for-js">
|
|
<input id="selectAllCheckbox" type="checkbox" class="form-check-input" />
|
|
</th>
|
|
<th class="w-150px">
|
|
<div class="d-flex align-items-center gap-1">
|
|
Date
|
|
<button type="button" class="btn btn-link p-0 fa fa-clock-o switch-time-format" title="Switch date format" id="switchTimeFormat"></button>
|
|
</div>
|
|
</th>
|
|
<th class="text-start">Label</th>
|
|
<th>Transaction Id</th>
|
|
<th class="text-end">Amount</th>
|
|
<th class="text-end" style="min-width:60px"></th>
|
|
</tr>
|
|
</thead>
|
|
<tbody id="WalletTransactionsList">
|
|
<partial name="_WalletTransactionsList" model="Model" />
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
<noscript>
|
|
<vc:pager view-model="Model"/>
|
|
</noscript>
|
|
|
|
<div class="text-center only-for-js d-none" id="LoadingIndicator">
|
|
<div class="spinner-border spinner-border-sm text-secondary ms-2" role="status">
|
|
<span class="visually-hidden">Loading...</span>
|
|
</div>
|
|
</div>
|
|
<div class="d-flex flex-wrap align-items-center justify-content-center gap-3 mb-5 only-for-js" id="ListActions">
|
|
<button type="button" class="btn btn-secondary d-flex align-items-center" id="LoadMore">
|
|
Load more
|
|
</button>
|
|
<button type="button" class="btn btn-secondary d-none" id="GoToTop">Go to top</button>
|
|
</div>
|
|
}
|
|
else
|
|
{
|
|
<p class="text-secondary mt-3">
|
|
There are no transactions yet.
|
|
</p>
|
|
}
|
|
|
|
<p class="mt-4 mb-0">
|
|
If BTCPay Server shows you an invalid balance, <a asp-action="WalletRescan" asp-route-walletId="@Context.GetRouteValue("walletId")">rescan your wallet</a>.
|
|
<br />
|
|
If some transactions appear in BTCPay Server, but are missing in another wallet, <a href="https://docs.btcpayserver.org/FAQ/Wallet/#missing-payments-in-my-software-or-hardware-wallet" rel="noreferrer noopener">follow these instructions</a>.
|
|
</p>
|