mirror of
https://github.com/btcpayserver/btcpayserver.git
synced 2025-02-20 13:34:37 +01:00
Revert "Payment redesign" (#1962)
This commit is contained in:
parent
182d67881d
commit
4174fa648d
17 changed files with 555 additions and 566 deletions
|
@ -806,7 +806,7 @@ namespace BTCPayServer.Tests
|
|||
s.Driver.FindElement(By.Id("ClaimedAmount")).Clear();
|
||||
s.Driver.FindElement(By.Id("ClaimedAmount")).SendKeys("20" + Keys.Enter);
|
||||
s.AssertHappyMessage();
|
||||
Assert.Contains("Awaiting Approval", s.Driver.PageSource);
|
||||
Assert.Contains("AwaitingApproval", s.Driver.PageSource);
|
||||
|
||||
var viewPullPaymentUrl = s.Driver.Url;
|
||||
// This one should have nothing
|
||||
|
@ -848,7 +848,8 @@ namespace BTCPayServer.Tests
|
|||
s.Driver.Navigate().GoToUrl(viewPullPaymentUrl);
|
||||
txs = s.Driver.FindElements(By.ClassName("transaction-link"));
|
||||
Assert.Equal(2, txs.Count);
|
||||
Assert.Contains("In Progress", s.Driver.PageSource);
|
||||
Assert.Contains("InProgress", s.Driver.PageSource);
|
||||
|
||||
|
||||
await s.Server.ExplorerNode.GenerateAsync(1);
|
||||
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
using System;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
using BTCPayServer;
|
||||
using BTCPayServer.Data;
|
||||
|
@ -70,13 +69,13 @@ namespace BTCPayServer.Controllers
|
|||
CurrencyData = cd,
|
||||
LastUpdated = DateTime.Now,
|
||||
Payouts = payouts
|
||||
.Select(entity => new ViewPullPaymentModel.PayoutLine
|
||||
.Select(entity => new ViewPullPaymentModel.PayoutLine()
|
||||
{
|
||||
Id = entity.Entity.Id,
|
||||
Amount = entity.Blob.Amount,
|
||||
AmountFormatted = _currencyNameTable.FormatCurrency(entity.Blob.Amount, blob.Currency),
|
||||
Currency = blob.Currency,
|
||||
Status = Regex.Replace(entity.Entity.State.ToString(), "(\\B[A-Z])", " $1"),
|
||||
Status = entity.Entity.State.ToString(),
|
||||
Destination = entity.Blob.Destination.Address.ToString(),
|
||||
Link = GetTransactionLink(_networkProvider.GetNetwork<BTCPayNetwork>(entity.Entity.GetPaymentMethodId().CryptoCode), entity.TransactionId),
|
||||
TransactionId = entity.TransactionId
|
||||
|
|
|
@ -29,9 +29,9 @@
|
|||
@if (env.OnionUrl != null)
|
||||
{
|
||||
<div class="text-center">
|
||||
<a href="@env.OnionUrl" target="_onion" class="btn btn-sm btn-outline-onion d-inline-flex align-items-center text-nowrap p-2" data-clipboard="@env.OnionUrl" style="min-width:117px;">
|
||||
<a href="@env.OnionUrl" target="_onion" class="btn btn-sm btn-outline-onion d-inline-flex align-items-center text-nowrap p-2" data-clipboard="@env.OnionUrl">
|
||||
<img src="~/img/icons/onion-purple.svg" height="20" class="mr-2" asp-append-version="true" />
|
||||
<span data-clipboard-confirm="Copied URL ✔">Copy Tor URL</span>
|
||||
Copy Tor URL
|
||||
</a>
|
||||
</div>
|
||||
}
|
||||
|
|
|
@ -33,9 +33,9 @@
|
|||
@if (env.OnionUrl != null)
|
||||
{
|
||||
<div class="text-center">
|
||||
<a href="@env.OnionUrl" target="_onion" class="btn btn-sm btn-outline-onion d-inline-flex align-items-center text-nowrap p-2" data-clipboard="@env.OnionUrl" style="min-width:117px;">
|
||||
<a href="@env.OnionUrl" target="_onion" class="btn btn-sm btn-outline-onion d-inline-flex align-items-center text-nowrap p-2" data-clipboard="@env.OnionUrl">
|
||||
<img src="~/img/icons/onion-purple.svg" height="20" class="mr-2" asp-append-version="true" />
|
||||
<span data-clipboard-confirm="Copied URL ✔">Copy Tor URL</span>
|
||||
Copy Tor URL
|
||||
</a>
|
||||
</div>
|
||||
}
|
||||
|
|
|
@ -33,8 +33,9 @@
|
|||
{
|
||||
<style type="text/css">
|
||||
body {
|
||||
background: rgba(25, 25, 25, 0.9);
|
||||
background: rgba(55, 58, 60, 0.4);
|
||||
}
|
||||
|
||||
.close-icon {
|
||||
display: flex;
|
||||
}
|
||||
|
@ -43,25 +44,25 @@
|
|||
</head>
|
||||
<body>
|
||||
<noscript>
|
||||
<div style="padding:2em;text-align:center;">
|
||||
<center style="padding: 2em">
|
||||
<h2>Javascript is currently disabled in your browser.</h2>
|
||||
<h5>Please enable Javascript and refresh this page for the best experience.</h5>
|
||||
|
||||
<p>Alternatively, click below to continue to our HTML-only invoice.</p>
|
||||
|
||||
<a href="/invoice-noscript?id=@Model.InvoiceId" style="text-decoration:underline;color:blue">
|
||||
<a href="/invoice-noscript?id=@Model.InvoiceId" style="text-decoration: underline; color: blue">
|
||||
Continue to javascript-disabled invoice >
|
||||
</a>
|
||||
</div>
|
||||
</center>
|
||||
</noscript>
|
||||
|
||||
<!--[if lte IE 8]>
|
||||
<div style="padding:2em;text-align:center;">
|
||||
<center style="padding: 2em">
|
||||
<form action="/invoice-noscript" method="GET">
|
||||
<button style="text-decoration: underline; color: blue">Continue to legacy browser compatible invoice page
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</center>
|
||||
<![endif]-->
|
||||
|
||||
<invoice>
|
||||
|
|
175
BTCPayServer/Views/PaymentRequest/MinimalPaymentRequest.cshtml
Normal file
175
BTCPayServer/Views/PaymentRequest/MinimalPaymentRequest.cshtml
Normal file
|
@ -0,0 +1,175 @@
|
|||
@model BTCPayServer.Models.PaymentRequestViewModels.ViewPaymentRequestViewModel
|
||||
|
||||
<div class="container">
|
||||
<div class="row w-100 p-0 m-0" style="height: 100vh">
|
||||
<div class="mx-auto my-auto w-100">
|
||||
<div class="card">
|
||||
<h1 class="card-header px-3">
|
||||
@Model.Title
|
||||
<span class="text-muted float-right text-center">@Model.Status</span>
|
||||
</h1>
|
||||
<div class="card-body px-0 pt-0 pb-0">
|
||||
<div class="row">
|
||||
<div class="col-sm-12 col-md-12 col-lg-6">
|
||||
<table class="table table-light mb-0">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="px-3 h2 text-muted">Request amount:</td>
|
||||
<td class="px-3 h2 text-nowrap text-right">@Model.AmountFormatted</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="px-3 h2 text-muted">Paid so far:</td>
|
||||
<td class="px-3 h2 text-nowrap text-right">@Model.AmountCollectedFormatted</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="px-3 h2 text-muted">Amount due:</td>
|
||||
<td class="px-3 h2 text-nowrap text-right">@Model.AmountDueFormatted</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
@if (Model.Description != null && Model.Description != "" && Model.Description != "<br>")
|
||||
{
|
||||
<div class="w-100 px-3 pt-4 pb-3">@Safe.Raw(Model.Description)</div>
|
||||
}
|
||||
</div>
|
||||
<div class="col-sm-12 col-md-12 col-lg-6 pt-2">
|
||||
<div class="table-responsive">
|
||||
<table class="table border-top-0">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="border-top-0" scope="col">Invoice #</th>
|
||||
<th class="border-top-0">Price</th>
|
||||
<th class="border-top-0">Expiry</th>
|
||||
<th class="border-top-0">Status</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@if (Model.Invoices == null && !Model.Invoices.Any())
|
||||
{
|
||||
<tr>
|
||||
<td colspan="4" class="text-center">No payments made yet</td>
|
||||
</tr>
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var invoice in Model.Invoices)
|
||||
{
|
||||
<tr class="bg-light">
|
||||
<td scope="row">@invoice.Id</td>
|
||||
<td>@invoice.Amount @invoice.Currency</td>
|
||||
<td>@invoice.ExpiryDate.ToString("g")</td>
|
||||
<td>@invoice.Status</td>
|
||||
</tr>
|
||||
if (invoice.Payments != null && invoice.Payments.Any())
|
||||
{
|
||||
<tr class="bg-light">
|
||||
<td colspan="4" class=" px-2 py-1 border-top-0">
|
||||
|
||||
<div class="table-responsive">
|
||||
<table class="table table-bordered">
|
||||
<tr>
|
||||
<th class="p-1" style="max-width: 300px">Tx Id</th>
|
||||
<th class="p-1">Payment Method</th>
|
||||
<th class="p-1">Amount</th>
|
||||
<th class="p-1">Link</th>
|
||||
</tr>
|
||||
@foreach (var payment in invoice.Payments)
|
||||
{
|
||||
<tr class="d-flex">
|
||||
<td class="p-1 m-0 d-print-none d-block" style="max-width: 300px">
|
||||
<div style="width: 100%; overflow-x: auto; overflow-wrap: initial;">@payment.Id</div>
|
||||
</td>
|
||||
<td class="p-1 m-0 d-none d-print-table-cell" style="max-width: 150px;">
|
||||
@payment.Id
|
||||
</td>
|
||||
<td class="p-1">@payment.PaymentMethod</td>
|
||||
<td class="p-1">@payment.Amount</td>
|
||||
<td class="p-1 d-print-none">
|
||||
@if (!string.IsNullOrEmpty(payment.Link))
|
||||
{
|
||||
<a :href="@payment.Link" target="_blank">Link</a>
|
||||
}
|
||||
</td>
|
||||
<td class="p-1 d-none d-print-table-cell" style="max-width: 150px;">
|
||||
@payment.Link
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
</table>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
}
|
||||
}
|
||||
@if (Model.IsPending && !Model.Archived)
|
||||
{
|
||||
<tr>
|
||||
<td colspan="4" class="text-center">
|
||||
@if (Model.AllowCustomPaymentAmounts && !Model.AnyPendingInvoice)
|
||||
{
|
||||
<form method="get" asp-action="PayPaymentRequest">
|
||||
|
||||
<div class="input-group m-auto" style="max-width: 250px">
|
||||
<input
|
||||
class="form-control"
|
||||
type="number"
|
||||
name="amount"
|
||||
|
||||
value="@Model.AmountDue"
|
||||
max="@Model.AmountDue"
|
||||
step="any"
|
||||
placeholder="Amount"
|
||||
required>
|
||||
<div class="input-group-append">
|
||||
<span class='input-group-text'>@Model.Currency.ToUpper()</span>
|
||||
<button
|
||||
class="btn btn-primary"
|
||||
type="submit">
|
||||
Pay now
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
}
|
||||
else
|
||||
{
|
||||
<a class="btn btn-primary btn-lg d-print-none mt-1" asp-action="PayPaymentRequest">
|
||||
Pay now
|
||||
</a>
|
||||
if (Model.AnyPendingInvoice && !Model.PendingInvoiceHasPayments)
|
||||
{
|
||||
<form method="get" asp-action="CancelUnpaidPendingInvoice">
|
||||
<button class="btn btn-secondary btn-lg mt-1" type="submit">
|
||||
Cancel current invoice</button>
|
||||
</form>
|
||||
}
|
||||
}
|
||||
</td>
|
||||
</tr>
|
||||
}else if (Model.Archived)
|
||||
{
|
||||
<tr>
|
||||
<td colspan="4" class="text-center">
|
||||
<button type="button" class="btn btn-secondary" disabled>Archived</button>
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="card-footer text-muted d-flex justify-content-between">
|
||||
|
||||
<div >Updated @Model.LastUpdated.ToString("g")</div>
|
||||
<div >
|
||||
<span class="text-muted">Powered by </span><a href="https://btcpayserver.org" target="_blank">BTCPay Server</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
|
@ -1,7 +1,6 @@
|
|||
@model BTCPayServer.Models.PaymentRequestViewModels.ViewPaymentRequestViewModel
|
||||
|
||||
@addTagHelper *, BundlerMinifier.TagHelpers
|
||||
@inject BTCPayServer.Services.BTCPayServerEnvironment env
|
||||
@inject BTCPayServer.HostedServices.CssThemeManager themeManager
|
||||
@{
|
||||
ViewData["Title"] = Model.Title;
|
||||
|
@ -9,313 +8,221 @@
|
|||
}
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="en" @(env.IsDeveloping ? " data-devenv" : "")>
|
||||
<html class="h-100">
|
||||
<head>
|
||||
<title>@Model.Title</title>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="robots" content="noindex,nofollow">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||||
<meta name="robots" content="noindex, nofollow">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||
<link href="@Context.Request.GetRelativePathOrAbsolute(themeManager.BootstrapUri)" rel="stylesheet" />
|
||||
<link href="@Context.Request.GetRelativePathOrAbsolute(themeManager.ThemeUri)" rel="stylesheet" />
|
||||
<bundle name="wwwroot/bundles/payment-request-bundle.min.css" asp-append-version="true"></bundle>
|
||||
@if (Model.CustomCSSLink != null)
|
||||
{
|
||||
<link href="@Model.CustomCSSLink" rel="stylesheet" />
|
||||
}
|
||||
<script type="text/javascript">
|
||||
var srvModel = @Safe.Json(Model);
|
||||
</script>
|
||||
<bundle name="wwwroot/bundles/payment-request-bundle.min.js" asp-append-version="true"></bundle>
|
||||
@*We need to make sure btcpay.js is not bundled, else it will not work if there is a RootPath*@
|
||||
<script src="~/modal/btcpay.js" asp-append-version="true"></script>
|
||||
@if (!Context.Request.Query.ContainsKey("simple"))
|
||||
{
|
||||
<script type="text/javascript">
|
||||
var srvModel = @Safe.Json(Model);
|
||||
</script>
|
||||
<bundle name="wwwroot/bundles/payment-request-bundle-1.min.js" asp-append-version="true"></bundle>
|
||||
<bundle name="wwwroot/bundles/payment-request-bundle-2.min.js" asp-append-version="true"></bundle>
|
||||
@*We need to make sure btcpay.js is not bundled, else it will not work if there is a RootPath*@
|
||||
<script src="~/modal/btcpay.js" asp-append-version="true"></script>
|
||||
}
|
||||
|
||||
<bundle name="wwwroot/bundles/payment-request-bundle.min.css" asp-append-version="true"></bundle>
|
||||
|
||||
@Safe.Raw(Model.EmbeddedCSS)
|
||||
<noscript>
|
||||
<style>
|
||||
.hide-when-js, [v-cloak] { display: block !important; }
|
||||
.only-for-js { display: none !important; }
|
||||
</style>
|
||||
</noscript>
|
||||
</head>
|
||||
<body class="h-100">
|
||||
<div id="app" class="h-100 d-flex flex-column">
|
||||
<nav id="mainNav" class="navbar sticky-top py-3 py-lg-4 d-print-block">
|
||||
<div class="container">
|
||||
<div class="row align-items-center" style="width:calc(100% + 30px)">
|
||||
<div class="col-12 col-md-8 col-lg-9">
|
||||
<div class="row">
|
||||
<div class="col col-12 col-lg-8">
|
||||
<h1 class="h3" v-text="srvModel.title">@Model.Title</h1>
|
||||
</div>
|
||||
<div class="col col-12 col-sm-6 col-lg-8 d-flex align-items-center">
|
||||
<span class="text-muted text-nowrap">Last Updated</span>
|
||||
|
||||
<span class="text-nowrap" v-text="lastUpdated" v-cloak>@Model.LastUpdated.ToString("g")</span>
|
||||
<button type="button" class="btn btn-link d-none d-lg-inline-block d-print-none border-0 p-0 ml-4 only-for-js" v-on:click="window.print" v-cloak>
|
||||
Print
|
||||
</button>
|
||||
<button type="button" class="btn btn-link d-none d-lg-inline-block d-print-none border-0 p-0 ml-4 only-for-js" v-on:click="copyLink" v-cloak>
|
||||
Copy Link
|
||||
</button>
|
||||
</div>
|
||||
<div class="col col-12 col-sm-6 text-sm-right col-lg-4 mt-lg-n4 pt-lg-1 d-print-none">
|
||||
@if (Model.IsPending && !Model.Archived && Model.ExpiryDate.HasValue)
|
||||
{
|
||||
<noscript>@Model.Status</noscript>
|
||||
}
|
||||
<template v-if="srvModel.isPending && !srvModel.archived && endDiff">
|
||||
<span class="text-muted">Expires in</span> {{endDiff}}
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12 pt-3 pb-2 col-md-4 py-md-0 col-lg-3 d-print-none">
|
||||
<noscript>
|
||||
@if (Model.IsPending && !Model.Archived)
|
||||
{
|
||||
@if (Model.AllowCustomPaymentAmounts && !Model.AnyPendingInvoice)
|
||||
{
|
||||
<form method="get" asp-action="PayPaymentRequest" asp-route-id="@Model.Id">
|
||||
<div class="row">
|
||||
<div class="col col-12 col-sm-6 col-md-12">
|
||||
<div class="input-group">
|
||||
<input type="number" class="form-control text-right hide-number-spin" name="amount" value="@Model.AmountDue" @if (!Model.AllowCustomPaymentAmounts) { @("readonly") } max="@Model.AmountDue" step="any" placeholder="Amount" required>
|
||||
<div class="input-group-append">
|
||||
<span class="input-group-text">@Model.Currency.ToUpper()</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col mt-2 col-12 col-sm-6 mt-sm-0 col-md-12 mt-md-2">
|
||||
<button class="btn btn-primary w-100 text-nowrap" type="submit">Pay Invoice</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
}
|
||||
else
|
||||
{
|
||||
<a class="btn btn-primary d-inline-block w-100 text-nowrap @if (!(Model.AnyPendingInvoice && !Model.PendingInvoiceHasPayments)) { @("btn-lg") }" asp-action="PayPaymentRequest" asp-route-id="@Model.Id">
|
||||
Pay Invoice
|
||||
</a>
|
||||
if (Model.AnyPendingInvoice && !Model.PendingInvoiceHasPayments)
|
||||
{
|
||||
<form method="get" asp-action="CancelUnpaidPendingInvoice" asp-route-id="@Model.Id" class="mt-2">
|
||||
<button class="btn btn-outline-secondary w-100 text-nowrap" type="submit">Cancel Invoice</button>
|
||||
</form>
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
<div class="h2 text-md-right">
|
||||
<span class="badge @if (Model.Status == "Settled") { @("badge-primary") } else if (Model.Status == "Expired") { @("badge-danger") } else { @("badge-info") }">
|
||||
@Model.Status
|
||||
@if (Model.Archived)
|
||||
{
|
||||
<span>(archived)</span>
|
||||
}
|
||||
</span>
|
||||
</div>
|
||||
}
|
||||
</noscript>
|
||||
<template v-if="srvModel.isPending && !srvModel.archived" class="d-print-none">
|
||||
<template v-if="srvModel.allowCustomPaymentAmounts && !srvModel.anyPendingInvoice">
|
||||
<form v-on:submit="submitCustomAmountForm">
|
||||
<div class="row">
|
||||
<div class="col col-12 col-sm-6 col-md-12">
|
||||
<div class="input-group">
|
||||
<input type="number" class="form-control text-right hide-number-spin" v-model="customAmount" :readonly="!srvModel.allowCustomPaymentAmounts" :max="srvModel.amountDue" placeholder="Amount" required>
|
||||
<div class="input-group-append">
|
||||
<span class="input-group-text">{{currency}}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col mt-2 col-12 col-sm-6 mt-sm-0 col-md-12 mt-md-2">
|
||||
<button class="btn btn-primary w-100 text-nowrap" v-bind:class="{ 'btn-disabled': loading}" :disabled="loading" type="submit">
|
||||
<div v-if="loading" class="spinner-grow spinner-grow-sm" role="status">
|
||||
<span class="sr-only">Loading...</span>
|
||||
</div>
|
||||
Pay Invoice
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</template>
|
||||
<body>
|
||||
|
||||
<partial name="_StatusMessage" />
|
||||
@if (Context.Request.Query.ContainsKey("simple"))
|
||||
{
|
||||
@await Html.PartialAsync("MinimalPaymentRequest", Model)
|
||||
}
|
||||
else
|
||||
{
|
||||
<noscript>
|
||||
@await Html.PartialAsync("MinimalPaymentRequest", Model)
|
||||
</noscript>
|
||||
|
||||
<div class="container" id="app" v-cloak>
|
||||
<div class="row w-100 p-0 m-0" style="height: 100vh">
|
||||
<div class="mx-auto my-auto w-100">
|
||||
<div class="card">
|
||||
<h1 class="card-header px-3">
|
||||
{{srvModel.title}}
|
||||
|
||||
<span class="text-muted float-right text-center">
|
||||
<template v-if="settled">Settled</template>
|
||||
<template v-else>
|
||||
<button class="btn btn-primary w-100 d-flex align-items-center justify-content-center text-nowrap" :class="{ 'btn-lg': !(srvModel.anyPendingInvoice && !srvModel.pendingInvoiceHasPayments)}" v-on:click="pay(null)" :disabled="loading">
|
||||
<div v-if="loading" class="spinner-grow spinner-grow-sm mr-2" role="status">
|
||||
<span class="sr-only">Loading...</span>
|
||||
</div>
|
||||
<span>Pay Invoice</span>
|
||||
</button>
|
||||
<button class="btn btn-outline-secondary mt-2 w-100 d-flex align-items-center justify-content-center text-nowrap" v-if="srvModel.anyPendingInvoice && !srvModel.pendingInvoiceHasPayments" v-on:click="cancelPayment()" :disabled="loading">
|
||||
<span v-if="loading" class="spinner-grow spinner-grow-sm mr-2" role="status">
|
||||
<span class="sr-only">Loading...</span>
|
||||
</span>
|
||||
<span>Cancel Invoice</span>
|
||||
</button>
|
||||
<template v-if="ended">Request Expired</template>
|
||||
<template v-else-if="endDiff">Expires in {{endDiff}}</template>
|
||||
<template v-else>{{srvModel.status}}</template>
|
||||
</template>
|
||||
</template>
|
||||
<template v-else>
|
||||
<div class="h2 text-md-right">
|
||||
<span class="badge" :class="{ 'badge-primary': srvModel.status === 'Settled', 'badge-danger': srvModel.status === 'Expired', 'badge-info': (srvModel.status !== 'Settled' && srvModel.status !== 'Expired') }">
|
||||
{{srvModel.status}}
|
||||
<span v-if="srvModel.archived">(archived)</span>
|
||||
</span>
|
||||
</span>
|
||||
</h1>
|
||||
<div class="card-body px-0 pt-0 pb-0">
|
||||
<div class="row">
|
||||
<div class="col-sm-12 col-md-12 col-lg-6">
|
||||
<table class="table table-light mb-0">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="px-3 h2 text-muted">Request amount:</td>
|
||||
<td class="px-3 h2 text-nowrap text-right">{{srvModel.amountFormatted}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="px-3 h2 text-muted">Paid so far:</td>
|
||||
<td class="px-3 h2 text-nowrap text-right">{{srvModel.amountCollectedFormatted}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="px-3 h2 text-muted">Amount due:</td>
|
||||
<td class="px-3 h2 text-nowrap text-right">{{srvModel.amountDueFormatted}}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<div
|
||||
v-if="srvModel.description && srvModel.description !== '' && srvModel.description !== '<br>'"
|
||||
v-html="srvModel.description"
|
||||
class="w-100 px-3 pt-4 pb-3"
|
||||
></div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<main class="flex-grow-1 py-4">
|
||||
<div class="container">
|
||||
@await Html.PartialAsync("_StatusMessage", new ViewDataDictionary(ViewData){ { "Margin", "mb-4" } })
|
||||
<div class="row">
|
||||
<div class="col col-12 col-lg-6 mb-4">
|
||||
<div class="jumbotron h-100 m-0 p-sm-5">
|
||||
<h2 class="h4 mb-3">Invoice Summary</h2>
|
||||
<div v-html="srvModel.description">
|
||||
@if (!string.IsNullOrEmpty(Model.Description) && Model.Description != "<br>")
|
||||
{
|
||||
@Safe.Raw(Model.Description)
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col col-12 col-lg-6 mb-4">
|
||||
<div class="jumbotron h-100 m-0 p-sm-5">
|
||||
<h2 class="h4 mb-3">Payment Details</h2>
|
||||
<dl class="mb-0 mt-md-4">
|
||||
<div class="d-flex flex-column mb-4">
|
||||
<dt class="h4 font-weight-normal text-nowrap text-primary order-2 order-sm-1 mb-0" v-text="srvModel.amountDueFormatted">@Model.AmountDueFormatted</dt>
|
||||
<dd class="text-muted order-1 order-sm-2 mb-1">Amount due</dd>
|
||||
</div>
|
||||
<div class="progress bg-light d-none d-sm-flex mb-sm-4 d-print-none" style="height:5px">
|
||||
<div class="progress-bar bg-primary" role="progressbar" style="width:@((Model.AmountCollected/Model.Amount)*100)%" v-bind:style="{ width: (srvModel.amountCollected/srvModel.amount*100) + '%' }"></div>
|
||||
</div>
|
||||
<div class="d-flex flex-column mb-4 d-sm-inline-flex mb-sm-0">
|
||||
<dt class="h4 font-weight-normal text-nowrap order-2 order-sm-1 mb-0" v-text="srvModel.amountCollectedFormatted">@Model.AmountCollectedFormatted</dt>
|
||||
<dd class="text-muted order-1 order-sm-2 mb-1">Amount paid</dd>
|
||||
</div>
|
||||
<div class="d-flex flex-column mb-0 d-sm-inline-flex float-sm-right">
|
||||
<dt class="h4 font-weight-normal text-nowrap order-2 order-sm-1 mb-0" v-text="srvModel.amountFormatted">@Model.AmountFormatted</dt>
|
||||
<dd class="text-muted text-sm-right order-1 order-sm-2 mb-1">Total requested</dd>
|
||||
</div>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<div class="jumbotron h-100 m-0 p-sm-5">
|
||||
<h2 class="h4 mb-3">Payment History</h2>
|
||||
<div class="table-responsive">
|
||||
<noscript>
|
||||
@if (Model.Invoices == null || !Model.Invoices.Any())
|
||||
{
|
||||
<p class="text-muted">No payments made yet.</p>
|
||||
}
|
||||
else
|
||||
{
|
||||
<table class="table my-0">
|
||||
<thead>
|
||||
<tr class="table-borderless">
|
||||
<th class="font-weight-normal text-secondary" scope="col">Invoice Id</th>
|
||||
<th class="font-weight-normal text-secondary">Price</th>
|
||||
<th class="font-weight-normal text-secondary">Expiry</th>
|
||||
<th class="font-weight-normal text-secondary text-right">Status</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach (var invoice in Model.Invoices)
|
||||
{
|
||||
<tr>
|
||||
<td>@invoice.Id</td>
|
||||
<td>@invoice.Amount @invoice.Currency</td>
|
||||
<td>@invoice.ExpiryDate.ToString("g")</td>
|
||||
<td class="text-right">@invoice.Status</td>
|
||||
</tr>
|
||||
if (invoice.Payments != null && invoice.Payments.Any())
|
||||
{
|
||||
<tr class="table-borderless table-light">
|
||||
<th colspan="2" class="pl-3 font-weight-normal text-secondary">TX Id</th>
|
||||
<th class="font-weight-normal text-secondary">Payment Method</th>
|
||||
<th class="font-weight-normal text-secondary text-right">Amount</th>
|
||||
</tr>
|
||||
@foreach (var payment in invoice.Payments)
|
||||
{
|
||||
<tr class="table-borderless table-light">
|
||||
<td colspan="2" class="pl-3 text-break">
|
||||
@if (!string.IsNullOrEmpty(payment.Link))
|
||||
{
|
||||
<a href="@payment.Link" target="_blank">@payment.Id</a>
|
||||
}
|
||||
else
|
||||
{
|
||||
<span>@payment.Id</span>
|
||||
}
|
||||
</td>
|
||||
<td>@payment.PaymentMethod</td>
|
||||
<td class="text-right">@payment.Amount</td>
|
||||
</tr>
|
||||
}
|
||||
}
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
}
|
||||
</noscript>
|
||||
|
||||
<template v-if="!srvModel.invoices || srvModel.invoices.length == 0">
|
||||
<p class="text-muted">No payments made yet.</p>
|
||||
</template>
|
||||
<template v-else v-for="invoice of srvModel.invoices" :key="invoice.id">
|
||||
<table class="table my-0">
|
||||
<div class="col-sm-12 col-md-12 col-lg-6">
|
||||
<div class="table-responsive">
|
||||
<table class="table table-light border-top-0 ">
|
||||
<thead>
|
||||
<tr class="table-borderless">
|
||||
<th class="font-weight-normal text-secondary" scope="col">Invoice Id</th>
|
||||
<th class="font-weight-normal text-secondary">Price</th>
|
||||
<th class="font-weight-normal text-secondary">Expiry</th>
|
||||
<th class="font-weight-normal text-secondary text-right">Status</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="border-top-0" scope="col">Invoice #</th>
|
||||
<th class="border-top-0">Price</th>
|
||||
<th class="border-top-0">Expiry</th>
|
||||
<th class="border-top-0">Status</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-if="!srvModel.invoices || srvModel.invoices.length == 0">
|
||||
<td colspan="4" class="text-center">No payments made yet</td>
|
||||
</tr>
|
||||
<template v-else v-for="invoice of srvModel.invoices" :key="invoice.id">
|
||||
<tr>
|
||||
<td>{{invoice.id}}</td>
|
||||
<td scope="row">{{invoice.id}}</td>
|
||||
<td>{{invoice.amountFormatted}}</td>
|
||||
<td>{{moment(invoice.expiryDate).format('L HH:mm')}}</td>
|
||||
<td class="text-right">{{invoice.status}}</td>
|
||||
<td>{{invoice.status}}</td>
|
||||
</tr>
|
||||
<template v-if="invoice.payments && invoice.payments.length > 0">
|
||||
<tr class="table-borderless table-light">
|
||||
<th colspan="2" class="pl-3 font-weight-normal text-secondary">TX Id</th>
|
||||
<th class="font-weight-normal text-secondary">Payment Method</th>
|
||||
<th class="font-weight-normal text-secondary text-right">Amount</th>
|
||||
</tr>
|
||||
<tr v-for="payment of invoice.payments" class="table-borderless table-light">
|
||||
<td colspan="2" class="pl-3 text-break">
|
||||
<a v-if="payment.link" :href="payment.link" target="_blank">{{payment.id}}</a>
|
||||
<span v-else>{{payment.id}}</span>
|
||||
</td>
|
||||
<td>{{formatPaymentMethod(payment.paymentMethod)}}</td>
|
||||
<td class="text-right">{{payment.amount.noExponents()}}</td>
|
||||
</tr>
|
||||
</template>
|
||||
<tr v-if="invoice.payments && invoice.payments.length > 0">
|
||||
<td colspan="4" class=" px-2 py-1 border-top-0">
|
||||
|
||||
<div class="table-responsive">
|
||||
<table class="table table-bordered">
|
||||
<tr>
|
||||
<th class="p-1" style="max-width: 300px">Tx Id</th>
|
||||
<th class="p-1">Payment Method</th>
|
||||
<th class="p-1">Amount</th>
|
||||
<th class="p-1">Link</th>
|
||||
</tr>
|
||||
<tr v-for="payment of invoice.payments">
|
||||
<td class="p-1 m-0 d-print-none d-block" style="max-width: 300px">
|
||||
<div style="width: 100%; overflow-x: auto; overflow-wrap: initial;">{{payment.id}}</div>
|
||||
</td>
|
||||
<td class="p-1 m-0 d-none d-print-table-cell" style="max-width: 150px;">
|
||||
{{payment.id}}
|
||||
</td>
|
||||
<td class="p-1">{{formatPaymentMethod(payment.paymentMethod)}}</td>
|
||||
<td class="p-1">{{payment.amount.noExponents()}}</td>
|
||||
<td class="p-1 d-print-none">
|
||||
<a v-if="payment.link" :href="payment.link" target="_blank">Link</a>
|
||||
</td>
|
||||
<td class="p-1 d-none d-print-table-cell" style="max-width: 150px;">
|
||||
{{payment.link}}
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</template>
|
||||
<tr v-if="srvModel.archived">
|
||||
<td colspan="4" class="text-center">
|
||||
<button type="button" class="btn btn-secondary" disabled>Archived</button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr v-else-if="!ended && (srvModel.amountDue) > 0" class="d-print-none">
|
||||
<td colspan="4" class="text-center">
|
||||
|
||||
<template v-if="srvModel.allowCustomPaymentAmounts && !srvModel.anyPendingInvoice">
|
||||
<form v-on:submit="submitCustomAmountForm">
|
||||
|
||||
<div class="input-group m-auto" style="max-width: 250px">
|
||||
<input
|
||||
:readonly="!srvModel.allowCustomPaymentAmounts"
|
||||
class="form-control"
|
||||
type="number"
|
||||
v-model="customAmount"
|
||||
:max="srvModel.amountDue"
|
||||
step="any"
|
||||
placeholder="Amount"
|
||||
required>
|
||||
<div class="input-group-append">
|
||||
<span class='input-group-text'>{{currency}}</span>
|
||||
<button
|
||||
class="btn btn-primary"
|
||||
v-bind:class="{ 'btn-disabled': loading}"
|
||||
:disabled="loading"
|
||||
type="submit">
|
||||
<div v-if="loading" class="spinner-grow spinner-grow-sm" role="status">
|
||||
<span class="sr-only">Loading...</span>
|
||||
</div>
|
||||
Pay now
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</template>
|
||||
|
||||
<template v-else>
|
||||
<button class="btn btn-primary btn-lg mt-1" v-on:click="pay(null)"
|
||||
:disabled="loading">
|
||||
<div v-if="loading" class="spinner-grow spinner-grow-sm" role="status">
|
||||
<span class="sr-only">Loading...</span>
|
||||
</div>
|
||||
|
||||
Pay now
|
||||
</button>
|
||||
<button class="btn btn-secondary btn-lg mt-1"
|
||||
v-if="srvModel.anyPendingInvoice && !srvModel.pendingInvoiceHasPayments"
|
||||
v-on:click="cancelPayment()"
|
||||
:disabled="loading">
|
||||
<div v-if="loading" class="spinner-grow spinner-grow-sm" role="status">
|
||||
<span class="sr-only">Loading...</span>
|
||||
</div>
|
||||
|
||||
Cancel current invoice</button>
|
||||
</template>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="card-footer text-muted d-flex justify-content-between">
|
||||
<div>
|
||||
<span v-on:click="print" class="btn-link d-print-none" style="cursor: pointer"> <span class="fa fa-print"></span> Print</span>
|
||||
<span>Updated {{lastUpdated}}</span>
|
||||
</div>
|
||||
<div>
|
||||
<span class="text-muted">Powered by </span><a href="https://btcpayserver.org" target="_blank">BTCPay Server</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
<footer class="pt-2 pb-4 d-print-none">
|
||||
<div class="container text-center">
|
||||
Powered by <a href="https://btcpayserver.org" target="_blank">BTCPay Server</a>
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -2,14 +2,14 @@
|
|||
@model BTCPayServer.Models.ViewPullPaymentModel
|
||||
|
||||
@addTagHelper *, BundlerMinifier.TagHelpers
|
||||
@inject BTCPayServer.Services.BTCPayServerEnvironment env
|
||||
@inject BTCPayServer.HostedServices.CssThemeManager themeManager
|
||||
@{
|
||||
ViewData["Title"] = Model.Title;
|
||||
Layout = null;
|
||||
}
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="en" @(env.IsDeveloping ? " data-devenv" : "")>
|
||||
<html class="h-100">
|
||||
<head>
|
||||
<title>@ViewData["Title"]</title>
|
||||
<meta charset="utf-8" />
|
||||
|
@ -18,189 +18,155 @@
|
|||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||
<link href="@Context.Request.GetRelativePathOrAbsolute(themeManager.BootstrapUri)" rel="stylesheet" />
|
||||
<link href="@Context.Request.GetRelativePathOrAbsolute(themeManager.ThemeUri)" rel="stylesheet" />
|
||||
<bundle name="wwwroot/bundles/payment-request-bundle.min.css" asp-append-version="true"></bundle>
|
||||
@if (Model.CustomCSSLink != null)
|
||||
{
|
||||
<link href="@Model.CustomCSSLink" rel="stylesheet" />
|
||||
}
|
||||
|
||||
<bundle name="wwwroot/bundles/payment-request-bundle.min.css" asp-append-version="true"></bundle>
|
||||
|
||||
@Safe.Raw(Model.EmbeddedCSS)
|
||||
<noscript>
|
||||
<style>
|
||||
.hide-when-js, [v-cloak] { display: block !important; }
|
||||
.only-for-js { display: none !important; }
|
||||
</style>
|
||||
</noscript>
|
||||
</head>
|
||||
<body class="h-100">
|
||||
<div class="h-100 d-flex flex-column">
|
||||
@if (Model.IsPending)
|
||||
{
|
||||
<nav id="mainNav" class="navbar sticky-top py-3 py-lg-4 d-print-block">
|
||||
<div class="container">
|
||||
<form asp-action="ClaimPullPayment" asp-route-pullPaymentId="@Model.Id" class="w-100">
|
||||
<div class="row align-items-center" style="width:calc(100% + 30px)">
|
||||
<div class="col-12 mb-3 col-lg-6 mb-lg-0">
|
||||
<input class="form-control form-control-lg text-monospace w-100" asp-for="Destination" placeholder="Enter destination address to claim funds …" required style="font-size:.9rem;height:42px;">
|
||||
</div>
|
||||
<div class="col-12 mb-3 col-sm-6 mb-sm-0 col-lg-3">
|
||||
<div class="input-group">
|
||||
<input type="number" class="form-control form-control-lg text-right hide-number-spin" asp-for="ClaimedAmount" max="@Model.AmountDue" min="@Model.MinimumClaim" step="any" placeholder="Amount" required>
|
||||
<div class="input-group-append">
|
||||
<span class="input-group-text px-3">@Model.Currency.ToUpper()</span>
|
||||
<body>
|
||||
<div class="container" style="max-width:960px;">
|
||||
|
||||
<div class="row w-100 p-0 m-0" style="height: 100vh">
|
||||
<div class="mx-auto my-auto w-100">
|
||||
@if (TempData.HasStatusMessage())
|
||||
{
|
||||
<partial name="_StatusMessage" />
|
||||
}
|
||||
@if (!this.ViewContext.ModelState.IsValid)
|
||||
{
|
||||
@Html.ValidationSummary(string.Empty, new { @class = "alert alert-danger pb-0 text-center" })
|
||||
}
|
||||
|
||||
<div class="card">
|
||||
@if (!Model.Title.IsNullOrWhiteSpace())
|
||||
{
|
||||
<h1 class="card-header px-3">
|
||||
@Model.Title
|
||||
<span class="text-muted float-right text-center">@Model.Status</span>
|
||||
</h1>
|
||||
}
|
||||
@if (Model.IsPending)
|
||||
{
|
||||
<div class="card-body" style="padding-left:.75rem;padding-right:.75rem;">
|
||||
<form asp-action="ClaimPullPayment" asp-route-pullPaymentId="@Model.Id">
|
||||
<div class="row">
|
||||
<div class="col-12 mb-2 col-lg-6 mb-lg-0">
|
||||
<input class="form-control text-monospace w-100"
|
||||
asp-for="Destination"
|
||||
placeholder="Destination address"
|
||||
required
|
||||
style="font-size:.9rem;height:38px;">
|
||||
</div>
|
||||
<div class="col-12 mb-2 col-sm-6 mb-sm-0 col-lg-3">
|
||||
<div class="input-group">
|
||||
<input class="form-control"
|
||||
asp-for="ClaimedAmount"
|
||||
type="number"
|
||||
max="@Model.AmountDue"
|
||||
min="@Model.MinimumClaim"
|
||||
step="any"
|
||||
placeholder="Amount"
|
||||
required>
|
||||
<div class="input-group-append">
|
||||
<span class='input-group-text'>@Model.Currency.ToUpper()</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12 col-sm-6 col-lg-3">
|
||||
<button class="form-control btn btn-primary" type="submit">Claim now</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12 col-sm-6 col-lg-3">
|
||||
<button class="btn btn-lg btn-primary w-100 text-nowrap" type="submit">Claim Funds</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</nav>
|
||||
}
|
||||
|
||||
<main class="flex-grow-1 py-4">
|
||||
<div class="container">
|
||||
@await Html.PartialAsync("_StatusMessage", new ViewDataDictionary(ViewData){ { "Margin", "mb-4" } })
|
||||
@if (!ViewContext.ModelState.IsValid)
|
||||
{
|
||||
@Html.ValidationSummary(string.Empty, new { @class = "alert alert-danger mb-4 pb-0 text-center" })
|
||||
</form>
|
||||
</div>
|
||||
}
|
||||
<div class="row">
|
||||
<div class="col col-12 col-lg-6 mb-4">
|
||||
<div class="jumbotron h-100 m-0 p-sm-5">
|
||||
@if (!Model.Title.IsNullOrWhiteSpace())
|
||||
{
|
||||
<h2 class="h4 mb-3">@Model.Title</h2>
|
||||
}
|
||||
<div class="d-flex align-items-center">
|
||||
<span class="text-muted text-nowrap">Last Updated</span>
|
||||
|
||||
<span class="text-nowrap">@Model.LastUpdated.ToString("g")</span>
|
||||
<button type="button" class="btn btn-link d-none d-lg-inline-block d-print-none border-0 p-0 ml-4 only-for-js" id="copyLink">
|
||||
Copy Link
|
||||
</button>
|
||||
</div>
|
||||
@if (!string.IsNullOrEmpty(Model.ResetIn))
|
||||
{
|
||||
<p>
|
||||
<span class="text-muted text-nowrap">Reset in</span>
|
||||
|
||||
<span class="text-nowrap">@Model.ResetIn</span>
|
||||
</p>
|
||||
}
|
||||
@if (!string.IsNullOrEmpty(Model.Description) && Model.Description != "<br>")
|
||||
{
|
||||
<div>@Safe.Raw(Model.Description)</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
<div class="col col-12 col-lg-6 mb-4">
|
||||
<div class="jumbotron h-100 m-0 p-sm-5">
|
||||
<h2 class="h4 mb-3">Payment Details</h2>
|
||||
<dl class="mb-0 mt-md-4">
|
||||
<div class="d-flex flex-column mb-4">
|
||||
<dt class="h4 font-weight-normal text-nowrap text-primary order-2 order-sm-1 mb-0">@Model.AmountDueFormatted</dt>
|
||||
<dd class="text-muted order-1 order-sm-2 mb-1">Available claim</dd>
|
||||
</div>
|
||||
<div class="progress bg-light d-none d-sm-flex mb-sm-4 d-print-none" style="height:5px">
|
||||
<div class="progress-bar bg-primary" role="progressbar" style="width:@((Model.AmountCollected / Model.Amount) * 100)%"></div>
|
||||
</div>
|
||||
<div class="d-flex flex-column mb-4 d-sm-inline-flex mb-sm-0">
|
||||
<dt class="h4 font-weight-normal text-nowrap order-2 order-sm-1 mb-0">@Model.AmountCollectedFormatted</dt>
|
||||
<dd class="text-muted order-1 order-sm-2 mb-1">Already claimed</dd>
|
||||
</div>
|
||||
<div class="d-flex flex-column mb-0 d-sm-inline-flex float-sm-right">
|
||||
<dt class="h4 font-weight-normal text-nowrap order-2 order-sm-1 mb-0">@Model.AmountFormatted</dt>
|
||||
<dd class="text-muted text-sm-right order-1 order-sm-2 mb-1">Claim limit</dd>
|
||||
</div>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<div class="jumbotron h-100 m-0 p-sm-5">
|
||||
<h2 class="h4 mb-3">Awaiting Claims</h2>
|
||||
<div class="table-responsive">
|
||||
@if (Model.Payouts.Any())
|
||||
<div class="card-body px-0 pt-0 pb-0">
|
||||
<div class="row">
|
||||
<div class="col-sm-12 col-md-12 col-lg-6">
|
||||
<h5 style="margin:1rem .75rem;">Pull payment details</h5>
|
||||
<table class="table mb-lg-0 border-top-0">
|
||||
<tr class="bg-light">
|
||||
<td class="font-weight-bold">Claim limit:</td>
|
||||
<td class="text-right">@Model.AmountFormatted</td>
|
||||
</tr>
|
||||
<tr class="bg-light">
|
||||
<td class="font-weight-bold">Already claimed:</td>
|
||||
<td class="text-right">@Model.AmountCollectedFormatted</td>
|
||||
</tr>
|
||||
<tr class="bg-light">
|
||||
<td class="font-weight-bold">Available claim:</td>
|
||||
<td class="text-right">@Model.AmountDueFormatted</td>
|
||||
</tr>
|
||||
@if (Model.ResetIn != String.Empty)
|
||||
{
|
||||
<table class="table my-0">
|
||||
<thead>
|
||||
<tr class="table-borderless">
|
||||
<th class="font-weight-normal text-secondary" scope="col">Destination</th>
|
||||
<th class="font-weight-normal text-secondary text-right text-nowrap">Amount requested</th>
|
||||
<th class="font-weight-normal text-secondary text-right">Status</th>
|
||||
<tr class="bg-light">
|
||||
<td class="font-weight-bold">Reset in:</td>
|
||||
<td class="text-right">@Model.ResetIn</td>
|
||||
</tr>
|
||||
}
|
||||
</table>
|
||||
@if (Model.Description != null && Model.Description != "" && Model.Description != "<br>")
|
||||
{
|
||||
<div class="w-100 px-3 pt-4 pb-3">@Safe.Raw(Model.Description)</div>
|
||||
}
|
||||
</div>
|
||||
<div class="col-sm-12 col-md-12 col-lg-6">
|
||||
<h5 style="margin:1rem .75rem;">Awaiting claims</h5>
|
||||
@if (Model.Payouts.Any())
|
||||
{
|
||||
foreach (var invoice in Model.Payouts)
|
||||
{
|
||||
<table class="table border-top-0 mt-3 mb-0">
|
||||
<tr class="bg-light">
|
||||
<td class="font-weight-bold">Status</td>
|
||||
<td class="text-right">@invoice.Status</td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach (var invoice in Model.Payouts)
|
||||
<tr class="bg-light">
|
||||
<td class="font-weight-bold">Amount claimed</td>
|
||||
<td class="text-right">@invoice.AmountFormatted</td>
|
||||
</tr>
|
||||
<tr class="bg-light">
|
||||
<td class="font-weight-bold">Destination</td>
|
||||
<td class="text-right text-break">
|
||||
<code>@invoice.Destination</code>
|
||||
</td>
|
||||
</tr>
|
||||
@if (!String.IsNullOrEmpty(invoice.Link))
|
||||
{
|
||||
<tr>
|
||||
<td class="text-break">
|
||||
@invoice.Destination
|
||||
</td>
|
||||
<td class="text-right">@invoice.AmountFormatted</td>
|
||||
<td class="text-right text-nowrap">
|
||||
@{
|
||||
string textClass;
|
||||
switch (invoice.Status)
|
||||
{
|
||||
case "Completed":
|
||||
case "In Progress":
|
||||
textClass = "text-success";
|
||||
break;
|
||||
case "Cancelled":
|
||||
textClass = "text-danger";
|
||||
break;
|
||||
default:
|
||||
textClass = "text-warning";
|
||||
break;
|
||||
}
|
||||
}
|
||||
@if (!string.IsNullOrEmpty(invoice.Link))
|
||||
{
|
||||
<a class="transaction-link @textClass" href="@invoice.Link">@invoice.Status</a>
|
||||
}
|
||||
else
|
||||
{
|
||||
<span class="@textClass">@invoice.Status</span>
|
||||
}
|
||||
</td>
|
||||
<tr class="bg-light">
|
||||
<td class="font-weight-bold">Transaction</td>
|
||||
<td class="text-right text-truncate" style="max-width: 100px;"><a class="transaction-link" href="@invoice.Link">@invoice.TransactionId</a></td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
}
|
||||
else
|
||||
{
|
||||
<p class="text-muted">No claim made yet.</p>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
<p class="text-secondary">No claim made yet</p>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-footer text-muted">
|
||||
<div class="row">
|
||||
<div class="col-12 col-sm-6">
|
||||
Updated @Model.LastUpdated.ToString("g")
|
||||
</div>
|
||||
<div class="col-12 col-sm-6 text-sm-right">
|
||||
Powered by <a href="https://btcpayserver.org" target="_blank">BTCPay Server</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
<footer class="pt-2 pb-4 d-print-none">
|
||||
<div class="container text-center">
|
||||
Powered by <a href="https://btcpayserver.org" target="_blank">BTCPay Server</a>
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
document.getElementById("copyLink").addEventListener("click", function (e) {
|
||||
if (navigator.clipboard) {
|
||||
e.preventDefault();
|
||||
var button = e.currentTarget;
|
||||
if (!button.dataset.initialText) button.dataset.initialText = button.innerText;
|
||||
navigator.clipboard.writeText(window.location).then(function () {
|
||||
button.innerText = 'Copied ✔';
|
||||
setTimeout(function() { button.innerText = button.dataset.initialText; }, 2500);
|
||||
});
|
||||
button.blur();
|
||||
}
|
||||
});
|
||||
</script>
|
||||
</div>
|
||||
<style>
|
||||
tbody + tbody { padding-top: 1.5rem; }
|
||||
</style>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -21,10 +21,3 @@
|
|||
<bundle name="wwwroot/bundles/main-bundle.min.css" asp-append-version="true" />
|
||||
@* JS *@
|
||||
<bundle name="wwwroot/bundles/main-bundle.min.js" asp-append-version="true" />
|
||||
@* Non-JS *@
|
||||
<noscript>
|
||||
<style>
|
||||
.hide-when-js, [v-cloak] { display: block !important; }
|
||||
.only-for-js { display: none !important; }
|
||||
</style>
|
||||
</noscript>
|
||||
|
|
|
@ -5,13 +5,30 @@
|
|||
@inject BTCPayServer.HostedServices.CssThemeManager themeManager
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="en"@(env.IsDeveloping ? " data-devenv" : "")>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<partial name="Header" />
|
||||
|
||||
@RenderSection("HeadScripts", required: false)
|
||||
@RenderSection("HeaderContent", false)
|
||||
|
||||
|
||||
<noscript>
|
||||
<style>
|
||||
.hide-when-js {
|
||||
display: block !important;
|
||||
}
|
||||
|
||||
.only-for-js {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
[v-cloak]::before {
|
||||
content: "" !important;
|
||||
}
|
||||
</style>
|
||||
</noscript>
|
||||
</head>
|
||||
|
||||
<body id="page-top">
|
||||
|
|
|
@ -4,10 +4,10 @@
|
|||
|
||||
@if (parsedModel != null)
|
||||
{
|
||||
<div class="alert alert-@parsedModel.SeverityCSS @(parsedModel.AllowDismiss? "alert-dismissible":"" ) @(ViewData["Margin"] ?? "mb-5") text-break" role="alert">
|
||||
<div class="alert alert-@parsedModel.SeverityCSS @(parsedModel.AllowDismiss? "alert-dismissible":"" ) mb-5 text-break" role="alert">
|
||||
@if (parsedModel.AllowDismiss)
|
||||
{
|
||||
<button type="button" class="close only-for-js" data-dismiss="alert" aria-label="Close">
|
||||
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
}
|
||||
|
|
|
@ -166,7 +166,7 @@
|
|||
]
|
||||
},
|
||||
{
|
||||
"outputFileName": "wwwroot/bundles/payment-request-bundle.min.js",
|
||||
"outputFileName": "wwwroot/bundles/payment-request-bundle-1.min.js",
|
||||
"inputFiles": [
|
||||
"wwwroot/vendor/vuejs/vue.min.js",
|
||||
"wwwroot/vendor/babel-polyfill/polyfill.min.js",
|
||||
|
@ -174,8 +174,13 @@
|
|||
"wwwroot/vendor/bootstrap-vue/bootstrap-vue.js",
|
||||
"wwwroot/vendor/signalr/signalr.js",
|
||||
"wwwroot/vendor/animejs/anime.min.js",
|
||||
"wwwroot/vendor/moment/moment.min.js",
|
||||
"wwwroot/payment-request/**/*.js"
|
||||
]
|
||||
},
|
||||
{
|
||||
"outputFileName": "wwwroot/bundles/payment-request-bundle-2.min.js",
|
||||
"inputFiles": [
|
||||
"wwwroot/vendor/moment/moment.min.js"
|
||||
],
|
||||
"minify": {
|
||||
"enabled": false
|
||||
|
@ -186,7 +191,7 @@
|
|||
"inputFiles": [
|
||||
"wwwroot/vendor/font-awesome/css/font-awesome.min.css",
|
||||
"wwwroot/vendor/bootstrap-vue/bootstrap-vue.css",
|
||||
"wwwroot/main/site.css"
|
||||
"wwwroot/payment-request/**/*.css"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
|
|
@ -176,14 +176,8 @@ pre {
|
|||
background-color: lightgray;
|
||||
}
|
||||
|
||||
/* Fix for small table showing unnecessary scrollbars */
|
||||
.table-responsive .table-sm {
|
||||
width: 100% !important;
|
||||
}
|
||||
|
||||
[v-cloak] { display:none }
|
||||
[v-cloak-loading] > * { display:none }
|
||||
[v-cloak-loading]::before { content: "loading…" }
|
||||
[v-cloak] > * { display:none }
|
||||
[v-cloak]::before { content: "loading…" }
|
||||
|
||||
.cursor-pointer{
|
||||
cursor: pointer;
|
||||
|
@ -248,54 +242,3 @@ pre {
|
|||
display: inline-block;
|
||||
margin-top: .5rem;
|
||||
}
|
||||
|
||||
/* Chrome, Safari, Edge, Opera */
|
||||
input[type=number].hide-number-spin::-webkit-outer-spin-button,
|
||||
input[type=number].hide-number-spin::-webkit-inner-spin-button {
|
||||
-webkit-appearance: none;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/* Firefox */
|
||||
input[type=number].hide-number-spin {
|
||||
-moz-appearance: textfield;
|
||||
}
|
||||
|
||||
/* Bootstrap Responsive Helper */
|
||||
html[data-devenv]:before {
|
||||
display: inline-block;
|
||||
position: fixed;
|
||||
z-index: 1000;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: var(--btcpay-bg-dark);
|
||||
color: var(--btcpay-color-dark-text);
|
||||
opacity: .7;
|
||||
padding: 4px 5px 3px 7px;
|
||||
font-size: 10px;
|
||||
border-top-left-radius: 4px;
|
||||
}
|
||||
|
||||
@media (max-width: 575px) { html[data-devenv]:before { content: 'XS'; } }
|
||||
@media (min-width: 576px) and (max-width: 767px) { html[data-devenv]:before { content: 'SM'; } }
|
||||
@media (min-width: 768px) and (max-width: 991px) { html[data-devenv]:before { content: 'MD'; } }
|
||||
@media (min-width: 992px) and (max-width: 1199px) { html[data-devenv]:before { content: 'LG'; } }
|
||||
@media (min-width: 1200px) { html[data-devenv]:before { content: 'XL'; } }
|
||||
@media print { html[data-devenv]:before { content: none; } }
|
||||
|
||||
/* Print */
|
||||
@media print {
|
||||
.jumbotron {
|
||||
padding: 1rem 0 !important;
|
||||
}
|
||||
}
|
||||
|
||||
/* Richtext editor */
|
||||
.note-editor .table.table-sm {
|
||||
border-collapse: collapse !important;
|
||||
}
|
||||
|
||||
.note-editor .table.table-sm th,
|
||||
.note-editor .table.table-sm td {
|
||||
border: 1px dotted var(--btcpay-color-neutral-400);
|
||||
}
|
||||
|
|
|
@ -85,17 +85,7 @@ $(function () {
|
|||
e.preventDefault();
|
||||
var item = e.currentTarget;
|
||||
var text = item.getAttribute('data-clipboard');
|
||||
var confirm = item.querySelector('[data-clipboard-confirm]') || item;
|
||||
var message = confirm.getAttribute('data-clipboard-confirm') || 'Copied ✔';
|
||||
if (!confirm.dataset.clipboardInitialText) {
|
||||
confirm.dataset.clipboardInitialText = confirm.innerText;
|
||||
console.log(confirm.clientWidth)
|
||||
confirm.style.minWidth = confirm.clientWidth + 'px';
|
||||
}
|
||||
navigator.clipboard.writeText(text).then(function () {
|
||||
confirm.innerText = message;
|
||||
setTimeout(function(){ confirm.innerText = confirm.dataset.clipboardInitialText; }, 2500);
|
||||
});
|
||||
navigator.clipboard.writeText(text);
|
||||
item.blur();
|
||||
}
|
||||
});
|
||||
|
|
|
@ -1,11 +1,6 @@
|
|||
$(document).ready(function() {
|
||||
|
||||
$(".richtext").summernote({
|
||||
minHeight: 300,
|
||||
tableClassName: 'table table-sm',
|
||||
insertTableMaxSize: {
|
||||
col: 5,
|
||||
row: 10
|
||||
}
|
||||
minHeight: 300
|
||||
});
|
||||
});
|
||||
|
|
|
@ -18,6 +18,7 @@ function addLoadEvent(func) {
|
|||
addLoadEvent(function (ev) {
|
||||
Vue.use(Toasted);
|
||||
|
||||
|
||||
app = new Vue({
|
||||
el: '#app',
|
||||
data: function () {
|
||||
|
@ -28,6 +29,7 @@ addLoadEvent(function (ev) {
|
|||
ended: false,
|
||||
endDiff: "",
|
||||
active: true,
|
||||
lastUpdated: "",
|
||||
loading: false,
|
||||
timeoutState: "",
|
||||
customAmount: null
|
||||
|
@ -39,12 +41,6 @@ addLoadEvent(function (ev) {
|
|||
},
|
||||
settled: function () {
|
||||
return this.srvModel.amountDue <= 0;
|
||||
},
|
||||
lastUpdated: function () {
|
||||
return this.srvModel.lastUpdated && moment(this.srvModel.lastUpdated).calendar();
|
||||
},
|
||||
active: function () {
|
||||
return !this.ended;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
@ -53,6 +49,7 @@ addLoadEvent(function (ev) {
|
|||
var endDateM = moment(this.srvModel.expiryDate);
|
||||
this.endDate = endDateM.format('MMMM Do YYYY');
|
||||
this.ended = endDateM.isBefore(moment());
|
||||
|
||||
} else {
|
||||
this.ended = false;
|
||||
this.endDate = null;
|
||||
|
@ -67,6 +64,8 @@ addLoadEvent(function (ev) {
|
|||
this.endDiff = mDiffD > 0 ? mDiffD + " days" : mDiffH > 0 ? mDiffH + " hours" : mDiffM > 0 ? mDiffM + " minutes" : mDiffS > 0 ? mDiffS + " seconds" : "";
|
||||
}
|
||||
|
||||
this.lastUpdated = moment(this.srvModel.lastUpdated).calendar();
|
||||
this.active = !this.ended;
|
||||
setTimeout(this.updateComputed, 1000);
|
||||
},
|
||||
setLoading: function (val) {
|
||||
|
@ -84,18 +83,6 @@ addLoadEvent(function (ev) {
|
|||
|
||||
eventAggregator.$emit("pay", amount);
|
||||
},
|
||||
copyLink: function (e) {
|
||||
if (navigator.clipboard) {
|
||||
e.preventDefault();
|
||||
var button = e.currentTarget;
|
||||
if (!button.dataset.initialText) button.dataset.initialText = button.innerText;
|
||||
navigator.clipboard.writeText(window.location).then(function () {
|
||||
button.innerText = 'Copied ✔';
|
||||
setTimeout(function() { button.innerText = button.dataset.initialText; }, 2500);
|
||||
});
|
||||
button.blur();
|
||||
}
|
||||
},
|
||||
cancelPayment: function (amount) {
|
||||
this.setLoading(true);
|
||||
var self = this;
|
||||
|
@ -113,6 +100,9 @@ addLoadEvent(function (ev) {
|
|||
return str;
|
||||
|
||||
},
|
||||
print:function(){
|
||||
window.print();
|
||||
},
|
||||
submitCustomAmountForm : function(e){
|
||||
if (e) {
|
||||
e.preventDefault();
|
||||
|
@ -125,10 +115,10 @@ addLoadEvent(function (ev) {
|
|||
}
|
||||
},
|
||||
mounted: function () {
|
||||
|
||||
this.customAmount = (this.srvModel.amountDue || 0).noExponents();
|
||||
hubListener.connect();
|
||||
var self = this;
|
||||
|
||||
eventAggregator.$on("invoice-created", function (invoiceId) {
|
||||
self.setLoading(false);
|
||||
btcpay.showInvoice(invoiceId);
|
||||
|
|
7
BTCPayServer/wwwroot/payment-request/styles/main.css
Normal file
7
BTCPayServer/wwwroot/payment-request/styles/main.css
Normal file
|
@ -0,0 +1,7 @@
|
|||
[v-cloak] > * {
|
||||
display: none
|
||||
}
|
||||
|
||||
[v-cloak]::before {
|
||||
content: "loading…"
|
||||
}
|
Loading…
Add table
Reference in a new issue