mirror of
https://github.com/aljazceru/btcpayserver.git
synced 2025-12-17 22:14:26 +01:00
Add ability to set invoice status from details page (#2923)
* Add ability to set invoice status from details page * Remove unnecessary "using" statements * Add print styles * Fix Safari issues * Simplify JS * Update status badge class names * Update dropdown toggle padding * Adjust dropdown menu padding
This commit is contained in:
@@ -13,16 +13,12 @@ using BTCPayServer.Abstractions.Models;
|
||||
using BTCPayServer.Client;
|
||||
using BTCPayServer.Client.Models;
|
||||
using BTCPayServer.Data;
|
||||
using BTCPayServer.Events;
|
||||
using BTCPayServer.Filters;
|
||||
using BTCPayServer.Logging;
|
||||
using BTCPayServer.HostedServices;
|
||||
using BTCPayServer.Models;
|
||||
using BTCPayServer.Models.InvoicingModels;
|
||||
using BTCPayServer.Payments;
|
||||
using BTCPayServer.Payments.Lightning;
|
||||
using BTCPayServer.Rating;
|
||||
using BTCPayServer.Security;
|
||||
using BTCPayServer.Services.Invoices;
|
||||
using BTCPayServer.Services.Invoices.Export;
|
||||
using BTCPayServer.Services.Rates;
|
||||
@@ -104,6 +100,7 @@ namespace BTCPayServer.Controllers
|
||||
return NotFound();
|
||||
|
||||
var store = await _StoreRepository.FindStore(invoice.StoreId);
|
||||
var invoiceState = invoice.GetInvoiceState();
|
||||
var model = new InvoiceDetailsModel()
|
||||
{
|
||||
StoreId = store.Id,
|
||||
@@ -111,7 +108,7 @@ namespace BTCPayServer.Controllers
|
||||
StoreLink = Url.Action(nameof(StoresController.UpdateStore), "Stores", new { storeId = store.Id }),
|
||||
PaymentRequestLink = Url.Action(nameof(PaymentRequestController.ViewPaymentRequest), "PaymentRequest", new { id = invoice.Metadata.PaymentRequestId }),
|
||||
Id = invoice.Id,
|
||||
State = invoice.GetInvoiceState().ToString(),
|
||||
State = invoiceState.ToString(),
|
||||
TransactionSpeed = invoice.SpeedPolicy == SpeedPolicy.HighSpeed ? "high" :
|
||||
invoice.SpeedPolicy == SpeedPolicy.MediumSpeed ? "medium" :
|
||||
invoice.SpeedPolicy == SpeedPolicy.LowMediumSpeed ? "low-medium" :
|
||||
@@ -129,11 +126,13 @@ namespace BTCPayServer.Controllers
|
||||
Events = invoice.Events,
|
||||
PosData = PosDataParser.ParsePosData(invoice.Metadata.PosData),
|
||||
Archived = invoice.Archived,
|
||||
CanRefund = CanRefund(invoice.GetInvoiceState()),
|
||||
CanRefund = CanRefund(invoiceState),
|
||||
ShowCheckout = invoice.Status == InvoiceStatusLegacy.New,
|
||||
Deliveries = (await _InvoiceRepository.GetWebhookDeliveries(invoiceId))
|
||||
.Select(c => new Models.StoreViewModels.DeliveryViewModel(c))
|
||||
.ToList()
|
||||
.ToList(),
|
||||
CanMarkInvalid = invoiceState.CanMarkInvalid(),
|
||||
CanMarkComplete = invoiceState.CanMarkComplete(),
|
||||
};
|
||||
model.Addresses = invoice.HistoricalAddresses.Select(h =>
|
||||
new InvoiceDetailsModel.AddressModel
|
||||
|
||||
@@ -126,5 +126,8 @@ namespace BTCPayServer.Models.InvoicingModels
|
||||
public bool Archived { get; set; }
|
||||
public bool CanRefund { get; set; }
|
||||
public bool ShowCheckout { get; set; }
|
||||
public bool CanMarkComplete { get; set; }
|
||||
public bool CanMarkInvalid { get; set; }
|
||||
public bool CanMarkStatus => CanMarkComplete || CanMarkInvalid;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,6 +11,38 @@
|
||||
</style>
|
||||
}
|
||||
|
||||
@section PageFootContent {
|
||||
<script>
|
||||
function changeInvoiceState(invoiceId, newState) {
|
||||
var toggleButton = $("#markStatusDropdownMenuButton");
|
||||
toggleButton.attr("disabled", "disabled");
|
||||
|
||||
$.post(invoiceId + "/changestate/" + newState)
|
||||
.done(function (data) {
|
||||
var alertClassModifier = {
|
||||
"complete (marked)": 'success',
|
||||
"invalid (marked)": 'danger'
|
||||
}[data.statusString];
|
||||
var statusHtml = "<span class='fs-6 fw-normal badge bg-" + alertClassModifier + "'>" + data.statusString + " <span class='fa fa-check'></span></span>"
|
||||
toggleButton.replaceWith(statusHtml);
|
||||
})
|
||||
.fail(function () {
|
||||
toggleButton.removeAttr("disabled");
|
||||
alert("Invoice state update failed");
|
||||
});
|
||||
}
|
||||
|
||||
document.addEventListener("DOMContentLoaded", function () {
|
||||
$("[data-change-invoice-status-button]").click(function (e) {
|
||||
var id = e.currentTarget.getAttribute('data-id');
|
||||
var status = e.currentTarget.getAttribute('data-status');
|
||||
|
||||
changeInvoiceState(id, status);
|
||||
});
|
||||
});
|
||||
</script>
|
||||
}
|
||||
|
||||
<section class="invoice-details">
|
||||
<div class="container">
|
||||
<partial name="_StatusMessage" />
|
||||
@@ -19,7 +51,6 @@
|
||||
<h2 class="col-xs-12 col-lg-6 mb-4 mb-lg-0">@ViewData["Title"]</h2>
|
||||
<div class="col-xs-12 col-lg-6 mb-2 mb-lg-0 text-lg-end">
|
||||
<div class="d-inline-flex">
|
||||
|
||||
@if (Model.ShowCheckout)
|
||||
{
|
||||
<a asp-action="Checkout" class="invoice-checkout-link btn btn-primary text-nowrap ms-2" asp-route-invoiceId="@Model.Id">
|
||||
@@ -92,7 +123,33 @@
|
||||
</tr>
|
||||
<tr>
|
||||
<th>State</th>
|
||||
<td>@Model.State</td>
|
||||
<td>
|
||||
@if (Model.CanMarkStatus)
|
||||
{
|
||||
<div class="dropdown">
|
||||
<button class="btn btn-secondary btn-sm dropdown-toggle py-1 px-2" type="button" id="markStatusDropdownMenuButton" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
@Model.State
|
||||
</button>
|
||||
<div class="dropdown-menu" aria-labelledby="markStatusDropdownMenuButton">
|
||||
@if (Model.CanMarkInvalid)
|
||||
{
|
||||
<a class="dropdown-item" href="#" data-id="@Model.Id" data-status="invalid" data-change-invoice-status-button>
|
||||
Mark as invalid <span class="fa fa-times"></span>
|
||||
</a>
|
||||
}
|
||||
@if (Model.CanMarkComplete)
|
||||
{
|
||||
<a class="dropdown-item" href="#" data-id="@Model.Id" data-status="complete" data-change-invoice-status-button>
|
||||
Mark as complete <span class="fa fa-check-circle"></span>
|
||||
</a>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
else {
|
||||
@Model.State
|
||||
}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Created date</th>
|
||||
|
||||
@@ -337,6 +337,17 @@ h2 small .fa-question-circle-o {
|
||||
.toasted-container {
|
||||
display: none !important;
|
||||
}
|
||||
#markStatusDropdownMenuButton {
|
||||
border: 0;
|
||||
background: transparent;
|
||||
padding: 0 !important;
|
||||
color: inherit;
|
||||
font-weight: var(--btcpay-font-weight-normal);
|
||||
font-size: var(--btcpay-body-font-size);
|
||||
}
|
||||
#markStatusDropdownMenuButton::after {
|
||||
content: none;
|
||||
}
|
||||
}
|
||||
|
||||
/* Richtext editor */
|
||||
|
||||
Reference in New Issue
Block a user