btcpayserver/BTCPayServer/Views/UIWallets/WalletTransactions.cshtml
2022-05-24 16:13:45 +02:00

297 lines
15 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;
}
.switchTimeFormat {
display: block;
max-width: 125px;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.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);
}
</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>
delegate('click', '#switchTimeFormat', switchTimeFormat);
delegate('click', '#selectAllCheckbox', e => {
document.querySelectorAll(".selector").forEach(checkbox => {
checkbox.checked = e.target.checked;
});
});
</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">
<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 style="max-width:125px;">
Date
<a id="switchTimeFormat" href="#">
<span class="fa fa-clock-o" title="Switch date format"></span>
</a>
</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>
@foreach (var transaction in Model.Transactions)
{
<tr>
<td class="only-for-js">
<input name="selectedTransactions" type="checkbox" class="selector form-check-input" form="WalletActions" value="@transaction.Id"/>
</td>
<td>
<span class="switchTimeFormat" data-switch="@transaction.Timestamp.ToTimeAgo()">
@transaction.Timestamp.ToBrowserDate()
</span>
</td>
<td class="text-start">
@if (transaction.Labels.Any())
{
<div class="d-flex flex-wrap gap-2 align-items-center">
@foreach (var label in transaction.Labels)
{
<div class="badge-container rounded-2" style="background-color:@label.Color;">
<div
class="badge transactionLabel position-relative d-block"
style="background-color:@label.Color;padding-right: 16px; z-index: 1;"
data-bs-html="true"
data-bs-toggle="tooltip"
data-bs-custom-class="label-tooltip"
title="@label.Tooltip">
<a asp-route-labelFilter="@label.Text" style="color:@label.TextColor !important;">@label.Text</a>
<form
asp-route-walletId="@Context.GetRouteValue("walletId")"
asp-action="ModifyTransaction"
method="post"
class="removeTransactionLabelForm">
<input type="hidden" name="transactionId" value="@transaction.Id"/>
<button
name="removelabel"
style="color: @label.Color; filter: brightness(0.5);"
type="submit"
value="@label.Text">
<span class="fa fa-close"></span>
</button>
</form>
</div>
@if (!string.IsNullOrEmpty(label.Link))
{
<a href="@label.Link" target="_blank" class="badge transaction-details-icon" style="background-color: @label.Color; filter: brightness(1.1);" rel="noreferrer noopener">
<span class="fa fa-info-circle" title="Transaction details" style="color: @label.Color; filter: brightness(0.5);">
<span class="visually-hidden">Transaction details</span>
</span>
</a>
}
</div>
}
</div>
}
</td>
<td class="smMaxWidth text-truncate @(transaction.IsConfirmed ? "" : "unconf")">
<a href="@transaction.Link" target="_blank" rel="noreferrer noopener">
@transaction.Id
</a>
</td>
@if (transaction.Positive)
{
<td class="text-end text-success">@transaction.Balance</td>
}
else
{
<td class="text-end text-danger">@transaction.Balance</td>
}
<td class="text-end">
<div class="dropstart d-inline-block me-2">
<span class="fa fa-tags cursor-pointer" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false"></span>
<div class="dropdown-menu">
<form asp-action="ModifyTransaction" method="post" style="width:260px;"
asp-route-walletId="@Context.GetRouteValue("walletId")">
<input type="hidden" name="transactionId" value="@transaction.Id"/>
<div class="input-group input-group-sm p-2">
<input name="addlabel" placeholder="Label name" maxlength="20" type="text" class="form-control form-control-sm"/>
<button type="submit" class="btn btn-primary btn-sm"><span class="fa fa-plus"></span></button>
</div>
@if (Model.Labels.Count > 0)
{
<div class="dropdown-divider"></div>
<div class="py-2 px-3 d-flex flex-wrap gap-2">
@foreach (var label in Model.Labels)
{
@if (transaction.Labels.Contains(label))
{
<button name="removelabel" class="bg-transparent border-0 p-0" type="submit" value="@label.Text"><span class="badge" style="background-color:@label.Color;color:@label.TextColor"><span class="fa fa-check"></span> @label.Text</span></button>
}
else
{
<button name="addlabelclick" class="bg-transparent border-0 p-0" type="submit" value="@label.Text"><span class="badge" style="background-color:@label.Color;color:@label.TextColor">@label.Text</span></button>
}
}
</div>
}
</form>
</div>
</div>
<div class="dropstart d-inline-block">
@if (string.IsNullOrEmpty(transaction.Comment))
{
<span class="fa fa-comment cursor-pointer" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false"></span>
}
else
{
<span class="fa fa-commenting cursor-pointer" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false"></span>
}
<div class="dropdown-menu">
<form asp-action="ModifyTransaction" method="post" style="width:260px;"
asp-route-walletId="@Context.GetRouteValue("walletId")">
<input type="hidden" name="transactionId" value="@transaction.Id"/>
<div class="input-group p-2">
<textarea name="addcomment" maxlength="200" rows="2" cols="20" class="form-control form-control-sm p-1">@transaction.Comment</textarea>
</div>
<div class="p-2">
<button type="submit" class="btn btn-primary btn-sm w-100">Save comment</button>
</div>
</form>
</div>
</div>
</td>
</tr>
}
</tbody>
</table>
</div>
</div>
<vc:pager view-model="Model"/>
}
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>