Improve Lightning node info view (#2066)

* Cleanups

* Add store name

* Unify js/non-js HTML
This commit is contained in:
Dennis Reimann 2020-11-17 08:57:14 +01:00 committed by GitHub
parent ab780485b2
commit ec31a4fe17
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 52 additions and 84 deletions

View File

@ -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; }
}
}

View File

@ -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;

View File

@ -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>