mirror of
https://github.com/btcpayserver/btcpayserver.git
synced 2025-01-19 05:33:31 +01:00
Improve Lightning node info view (#2066)
* Cleanups * Add store name * Unify js/non-js HTML
This commit is contained in:
parent
ab780485b2
commit
ec31a4fe17
@ -41,20 +41,21 @@ namespace BTCPayServer.Controllers
|
||||
var paymentMethodDetails = GetExistingLightningSupportedPaymentMethod(cryptoCode, store);
|
||||
var network = _BtcPayNetworkProvider.GetNetwork<BTCPayNetwork>(cryptoCode);
|
||||
var nodeInfo =
|
||||
await _LightningLikePaymentHandler.GetNodeInfo(this.Request.IsOnion(), paymentMethodDetails,
|
||||
await _LightningLikePaymentHandler.GetNodeInfo(Request.IsOnion(), paymentMethodDetails,
|
||||
network);
|
||||
|
||||
return View(new ShowLightningNodeInfoViewModel()
|
||||
return View(new ShowLightningNodeInfoViewModel
|
||||
{
|
||||
Available = true,
|
||||
NodeInfo = nodeInfo.ToString(),
|
||||
CryptoCode = cryptoCode,
|
||||
CryptoImage = GetImage(paymentMethodDetails.PaymentId, network)
|
||||
CryptoImage = GetImage(paymentMethodDetails.PaymentId, network),
|
||||
StoreName = store.StoreName
|
||||
});
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return View(new ShowLightningNodeInfoViewModel() { Available = false, CryptoCode = cryptoCode });
|
||||
return View(new ShowLightningNodeInfoViewModel { Available = false, CryptoCode = cryptoCode });
|
||||
}
|
||||
}
|
||||
|
||||
@ -83,5 +84,6 @@ namespace BTCPayServer.Controllers
|
||||
public bool Available { get; set; }
|
||||
public string CryptoCode { get; set; }
|
||||
public string CryptoImage { get; set; }
|
||||
public string StoreName { get; set; }
|
||||
}
|
||||
}
|
||||
|
@ -79,7 +79,7 @@ namespace BTCPayServer.Payments.Lightning
|
||||
}
|
||||
catch (OperationCanceledException) when (cts.IsCancellationRequested)
|
||||
{
|
||||
throw new PaymentMethodUnavailableException($"The lightning node did not reply in a timely manner");
|
||||
throw new PaymentMethodUnavailableException("The lightning node did not reply in a timely manner");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@ -87,7 +87,7 @@ namespace BTCPayServer.Payments.Lightning
|
||||
}
|
||||
}
|
||||
var nodeInfo = await test;
|
||||
return new LightningLikePaymentMethodDetails()
|
||||
return new LightningLikePaymentMethodDetails
|
||||
{
|
||||
BOLT11 = lightningInvoice.BOLT11,
|
||||
InvoiceId = lightningInvoice.Id,
|
||||
@ -98,19 +98,19 @@ namespace BTCPayServer.Payments.Lightning
|
||||
public async Task<NodeInfo> GetNodeInfo(bool preferOnion, LightningSupportedPaymentMethod supportedPaymentMethod, BTCPayNetwork network)
|
||||
{
|
||||
if (!_Dashboard.IsFullySynched(network.CryptoCode, out var summary))
|
||||
throw new PaymentMethodUnavailableException($"Full node not available");
|
||||
throw new PaymentMethodUnavailableException("Full node not available");
|
||||
|
||||
using (var cts = new CancellationTokenSource(LIGHTNING_TIMEOUT))
|
||||
{
|
||||
var client = _lightningClientFactory.Create(supportedPaymentMethod.GetLightningUrl(), network);
|
||||
LightningNodeInformation info = null;
|
||||
LightningNodeInformation info;
|
||||
try
|
||||
{
|
||||
info = await client.GetInfo(cts.Token);
|
||||
}
|
||||
catch (OperationCanceledException) when (cts.IsCancellationRequested)
|
||||
{
|
||||
throw new PaymentMethodUnavailableException($"The lightning node did not reply in a timely manner");
|
||||
throw new PaymentMethodUnavailableException("The lightning node did not reply in a timely manner");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@ -119,7 +119,7 @@ namespace BTCPayServer.Payments.Lightning
|
||||
var nodeInfo = info.NodeInfoList.FirstOrDefault(i => i.IsTor == preferOnion) ?? info.NodeInfoList.FirstOrDefault();
|
||||
if (nodeInfo == null)
|
||||
{
|
||||
throw new PaymentMethodUnavailableException($"No lightning node public address has been configured");
|
||||
throw new PaymentMethodUnavailableException("No lightning node public address has been configured");
|
||||
}
|
||||
|
||||
var blocksGap = summary.Status.ChainHeight - info.BlockHeight;
|
||||
|
@ -6,30 +6,25 @@
|
||||
Layout = null;
|
||||
}
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<title>@Model.CryptoCode LN Node Info</title>
|
||||
<title>@Model.StoreName – @Model.CryptoCode Lightning Node</title>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||
<link rel="apple-touch-icon" href="~/img/icons/icon-512x512.png" asp-append-version="true">
|
||||
<link rel="apple-touch-startup-image" href="~/img/splash.png" asp-append-version="true">
|
||||
|
||||
<link rel="manifest" href="~/manifest.json">
|
||||
|
||||
<link href="@this.Context.Request.GetRelativePathOrAbsolute(themeManager.BootstrapUri)" rel="stylesheet" asp-append-version="true" />
|
||||
<link href="@this.Context.Request.GetRelativePathOrAbsolute(themeManager.ThemeUri)" rel="stylesheet" asp-append-version="true" />
|
||||
<link href="@Context.Request.GetRelativePathOrAbsolute(themeManager.BootstrapUri)" rel="stylesheet" asp-append-version="true" />
|
||||
<link href="@Context.Request.GetRelativePathOrAbsolute(themeManager.ThemeUri)" rel="stylesheet" asp-append-version="true" />
|
||||
<link href="~/vendor/font-awesome/css/font-awesome.min.css" rel="stylesheet" asp-append-version="true" />
|
||||
|
||||
<bundle name="wwwroot/bundles/lightning-node-info-bundle.min.js" asp-append-version="true" />
|
||||
<script type="text/javascript">
|
||||
var srvModel = @Safe.Json(Model);
|
||||
|
||||
|
||||
window.onload = function() {
|
||||
Vue.use(Toasted);
|
||||
var app = new Vue({
|
||||
new Vue({
|
||||
el: '#app',
|
||||
components: {
|
||||
qrcode: VueQrcode
|
||||
@ -38,27 +33,25 @@
|
||||
srvModel: srvModel
|
||||
},
|
||||
mounted: function() {
|
||||
|
||||
this.$nextTick(function() {
|
||||
var copyInput = new Clipboard('.copy');
|
||||
|
||||
copyInput.on("success",
|
||||
function(e) {
|
||||
Vue.toasted.show('Copied',
|
||||
{
|
||||
iconPack: "fontawesome",
|
||||
icon: "copy",
|
||||
duration: 5000
|
||||
});
|
||||
copyInput.on("success", function() {
|
||||
Vue.toasted.show('Copied', {
|
||||
iconPack: "fontawesome",
|
||||
icon: "copy",
|
||||
duration: 5000
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
</script>
|
||||
<style>
|
||||
[v-cloak] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.qr-icon {
|
||||
height: 64px;
|
||||
width: 64px;
|
||||
@ -75,10 +68,10 @@
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.qr-container svg {
|
||||
width: 256px;
|
||||
height: 256px;
|
||||
}
|
||||
.qr-container svg {
|
||||
width: 256px;
|
||||
height: 256px;
|
||||
}
|
||||
|
||||
.copy {
|
||||
cursor: copy;
|
||||
@ -86,59 +79,32 @@
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<noscript>
|
||||
<div class="container">
|
||||
<div class="row " style="height: 100vh">
|
||||
<div class="col-md-8 col-sm-12 col-lg-6 mx-auto my-auto ">
|
||||
<div class="col-md-8 col-sm-12 col-lg-6 mx-auto my-auto ">
|
||||
<div class="card border-0">
|
||||
<div class="row"></div>
|
||||
<h1 class="card-title text-center">
|
||||
@Model.CryptoCode Lightning Node - @(Model.Available ? "Online" : "Unavailable")
|
||||
<small class="@(Model.Available ? "text-success" : "text-danger")">
|
||||
<span class="fa fa-circle "></span>
|
||||
</small>
|
||||
</h1>
|
||||
@if (Model.Available)
|
||||
{
|
||||
<div class="card-body m-sm-0 p-sm-0">
|
||||
<div class="input-group">
|
||||
<input type="text" class="form-control " readonly="readonly" asp-for="NodeInfo" id="peer-info" />
|
||||
<div class="input-group-append">
|
||||
<span class="input-group-text fa fa-copy"> </span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</noscript>
|
||||
<div id="app" class="container">
|
||||
<div class="row " style="height: 100vh">
|
||||
<div class="col-md-8 col-sm-12 col-lg-6 mx-auto my-auto ">
|
||||
<div class="row" style="height:100vh">
|
||||
<div class="col-md-8 col-sm-12 col-lg-6 mx-auto my-auto">
|
||||
<div class="card border-0">
|
||||
<div class="row"></div>
|
||||
<h1 class="card-title text-center">
|
||||
{{srvModel.cryptoCode}} Lightning Node
|
||||
- {{srvModel.available? "Online" : "Unavailable"}}
|
||||
<small v-bind:class="{ 'text-success': srvModel.available, 'text-danger': !srvModel.available }">
|
||||
<span class="fa fa-circle "></span>
|
||||
</small>
|
||||
</h1>
|
||||
<div class="card-body m-sm-0 p-sm-0" v-if="srvModel.available">
|
||||
<div class="qr-container mb-2">
|
||||
<img v-bind:src="srvModel.cryptoImage" class="qr-icon" />
|
||||
<qrcode v-bind:value="srvModel.nodeInfo" :options="{ width: 256, margin: 1, color: {dark:'#000', light:'#f5f5f7'} }" tag="svg">
|
||||
</qrcode>
|
||||
<div class="card-body p-4">
|
||||
<h1 class="card-title text-center" v-text="srvModel.storeName">@Model.StoreName</h1>
|
||||
<h2 class="card-subtitle text-center text-secondary mb-2">
|
||||
<span v-text="srvModel.cryptoCode">@Model.CryptoCode</span>
|
||||
Lightning Node
|
||||
</h2>
|
||||
<h3 class="card-title text-center">
|
||||
<span v-text="srvModel.available ? 'Online' : 'Unavailable'">
|
||||
@(Model.Available ? "Online" : "Unavailable")
|
||||
</span>
|
||||
<small class="text-@(Model.Available ? "success" : "danger")" :class="{ 'text-success': srvModel.available, 'text-danger': !srvModel.available }">
|
||||
<span class="fa fa-circle"></span>
|
||||
</small>
|
||||
</h3>
|
||||
<div class="qr-container my-3" v-cloak v-if="srvModel.available">
|
||||
<img src="" alt="@Model.CryptoCode" class="qr-icon" :src="srvModel.cryptoImage" v-bind:alt="srvModel.cryptoCode" />
|
||||
<qrcode v-bind:value="srvModel.nodeInfo" :options="{ width: 256, margin: 1, color: {dark:'#000', light:'#f5f5f7'} }" tag="svg"></qrcode>
|
||||
</div>
|
||||
<div class="input-group copy" data-clipboard-target="#vue-peer-info">
|
||||
<input type="text" class=" form-control " readonly="readonly" :value="srvModel.nodeInfo" id="vue-peer-info" />
|
||||
<div data-clipboard-target="#peer-info" class="input-group copy d-@(Model.Available ? "flex" : "none")" :class="{ 'd-flex': srvModel.available, 'd-none': !srvModel.available }">
|
||||
<input type="text" class="form-control" readonly="readonly" asp-for="NodeInfo" id="peer-info" :value="srvModel.nodeInfo" />
|
||||
<div class="input-group-append">
|
||||
<span class="input-group-text fa fa-copy"> </span>
|
||||
<span class="input-group-text fa fa-copy py-2"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
Loading…
Reference in New Issue
Block a user