Fix labels not showing multiple payouts payments (#3729)

* Fix labels not showing multiple payouts payments

* Improve label tooltip

Makes it more readable

* Cleanup code

* Fix overflowing text in order ID field in invoices table (#3765)

close #3714

Co-authored-by: Dennis Reimann <mail@dennisreimann.de>
Co-authored-by: nicolas.dorier <nicolas.dorier@gmail.com>
Co-authored-by: Umar Bolatov <bolatovumar@gmail.com>
This commit is contained in:
Andrew Camilleri
2022-05-23 03:25:46 +02:00
committed by GitHub
parent 2254a5960e
commit c7d0537bf9
7 changed files with 103 additions and 36 deletions

View File

@@ -513,9 +513,8 @@ namespace BTCPayServer.Tests
{
Assert.Single(info.Labels);
var l = Assert.IsType<PayoutLabel>(info.Labels["payout"]);
Assert.Equal("pullPaymentId", l.PullPaymentId);
Assert.Single(Assert.Single(l.PullPaymentPayouts, k => k.Key == "pullPaymentId").Value, "payoutId");
Assert.Equal("walletId", l.WalletId);
Assert.Equal("payoutId", l.PayoutId);
}
var payoutId = "payoutId";

View File

@@ -411,7 +411,10 @@ public class BitcoinLikePayoutHandler : IPayoutHandler
var walletId = new WalletId(payout.StoreDataId, newTransaction.CryptoCode);
_eventAggregator.Publish(new UpdateTransactionLabel(walletId,
newTransaction.NewTransactionEvent.TransactionData.TransactionHash,
UpdateTransactionLabel.PayoutTemplate(payout.Id, payout.PullPaymentDataId, walletId.ToString())));
UpdateTransactionLabel.PayoutTemplate(new ()
{
{payout.PullPaymentDataId?? "", new List<string>{payout.Id}}
}, walletId.ToString())));
}
else
{

View File

@@ -14,6 +14,7 @@ using BTCPayServer.Services.Apps;
using BTCPayServer.Services.Labels;
using BTCPayServer.Services.PaymentRequests;
using NBitcoin;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
namespace BTCPayServer.HostedServices
@@ -75,31 +76,46 @@ namespace BTCPayServer.HostedServices
var walletBlobInfo = await _walletRepository.GetWalletInfo(updateTransactionLabel.WalletId);
await Task.WhenAll(updateTransactionLabel.TransactionLabels.Select(async pair =>
{
if (!walletTransactionsInfo.TryGetValue(pair.Key.ToString(), out var walletTransactionInfo))
var txId = pair.Key.ToString();
var coloredLabels = pair.Value;
if (!walletTransactionsInfo.TryGetValue(txId, out var walletTransactionInfo))
{
walletTransactionInfo = new WalletTransactionInfo();
}
foreach (var label in pair.Value)
bool walletNeedUpdate = false;
foreach (var cl in coloredLabels)
{
walletBlobInfo.LabelColors.TryAdd(label.label.Text, label.color);
}
await _walletRepository.SetWalletInfo(updateTransactionLabel.WalletId, walletBlobInfo);
var update = false;
foreach (var label in pair.Value)
{
if (walletTransactionInfo.Labels.TryAdd(label.label.Text, label.label))
if (walletBlobInfo.LabelColors.TryGetValue(cl.label.Text, out var currentColor))
{
update = true;
if (currentColor != cl.color)
{
walletNeedUpdate = true;
walletBlobInfo.LabelColors[cl.label.Text] = currentColor;
}
}
else
{
walletNeedUpdate = true;
walletBlobInfo.LabelColors.AddOrReplace(cl.label.Text, cl.color);
}
}
if (update)
if (walletNeedUpdate)
await _walletRepository.SetWalletInfo(updateTransactionLabel.WalletId, walletBlobInfo);
foreach (var cl in coloredLabels)
{
await _walletRepository.SetWalletTransactionInfo(updateTransactionLabel.WalletId,
pair.Key.ToString(), walletTransactionInfo);
var label = cl.label;
if (walletTransactionInfo.Labels.TryGetValue(label.Text, out var existingLabel))
{
label = label.Merge(existingLabel);
}
walletTransactionInfo.Labels.AddOrReplace(label.Text, label);
}
await _walletRepository.SetWalletTransactionInfo(updateTransactionLabel.WalletId,
txId, walletTransactionInfo);
}));
}
}
@@ -146,12 +162,11 @@ namespace BTCPayServer.HostedServices
return ("#51b13e", new ReferenceLabel("pj-exposed", invoice));
}
public static (string color, Label label) PayoutTemplate(string payoutId, string pullPaymentId, string walletId)
public static (string color, Label label) PayoutTemplate(Dictionary<string, List<string>> pullPaymentToPayouts, string walletId)
{
return ("#3F88AF", new PayoutLabel()
{
PayoutId = payoutId,
PullPaymentId = pullPaymentId,
PullPaymentPayouts = pullPaymentToPayouts,
WalletId = walletId
});
}

View File

@@ -179,8 +179,10 @@ namespace BTCPayServer.PayoutProcessors.OnChain
{
_eventAggregator.Publish(new UpdateTransactionLabel(walletId,
txHash,
UpdateTransactionLabel.PayoutTemplate(payoutData.Id, payoutData.PullPaymentDataId,
walletId.ToString())));
UpdateTransactionLabel.PayoutTemplate(new ()
{
{payoutData.PullPaymentDataId?? "", new List<string>{payoutData.Id}}
}, walletId.ToString())));
}
await Task.WhenAny(tcs.Task, task);
}

View File

@@ -1,5 +1,8 @@
using System;
using System.Collections.Generic;
using System.Linq;
using BTCPayServer.Client.Models;
using NBitcoin;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
@@ -8,6 +11,11 @@ namespace BTCPayServer.Services.Labels
public abstract class Label : LabelData
{
public virtual Label Merge(LabelData other)
{
return this;
}
static void FixLegacy(JObject jObj, ReferenceLabel refLabel)
{
if (refLabel.Reference is null && jObj.ContainsKey("id"))
@@ -16,8 +24,11 @@ namespace BTCPayServer.Services.Labels
}
static void FixLegacy(JObject jObj, PayoutLabel payoutLabel)
{
if (payoutLabel.PayoutId is null)
payoutLabel.PayoutId = jObj["id"].Value<string>();
if (jObj.ContainsKey("id") && payoutLabel.PullPaymentPayouts.Count is 0)
{
var pullPaymentId = jObj["pullPaymentId"]?.Value<string>() ?? string.Empty;
payoutLabel.PullPaymentPayouts.Add(pullPaymentId, new List<string>() { jObj["id"].Value<string>() });
}
FixLegacy(jObj, (Label)payoutLabel);
}
static void FixLegacy(JObject jObj, Label label)
@@ -111,8 +122,23 @@ namespace BTCPayServer.Services.Labels
Type = "payout";
Text = "payout";
}
public string PayoutId { get; set; }
public Dictionary<string, List<string>> PullPaymentPayouts { get; set; } = new();
public string WalletId { get; set; }
public string PullPaymentId { get; set; }
public override Label Merge(LabelData other)
{
if (other is not PayoutLabel otherPayoutLabel) return base.Merge(other);
foreach (var pullPaymentPayout in otherPayoutLabel.PullPaymentPayouts)
{
if (!PullPaymentPayouts.TryGetValue(pullPaymentPayout.Key, out var pullPaymentPayouts))
{
pullPaymentPayouts = new List<string>();
PullPaymentPayouts.Add(pullPaymentPayout.Key, pullPaymentPayouts);
}
pullPaymentPayouts.AddRange(pullPaymentPayout.Value);
}
return base.Merge(other);
}
}
}

View File

@@ -3,6 +3,7 @@ using System;
using System.Drawing;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
@@ -57,6 +58,15 @@ namespace BTCPayServer.Services.Labels
Color = color,
TextColor = TextColor(color)
};
string PayoutLabelText(KeyValuePair<string, List<string>> pair)
{
if (pair.Value.Count == 1)
return $"Paid a payout of a pull payment ({pair.Key})";
else
return $"Paid payouts of a pull payment ({pair.Key})";
}
if (uncoloredLabel is ReferenceLabel refLabel)
{
var refInLabel = string.IsNullOrEmpty(refLabel.Reference) ? string.Empty : $"({refLabel.Reference})";
@@ -90,13 +100,15 @@ namespace BTCPayServer.Services.Labels
}
else if (uncoloredLabel is PayoutLabel payoutLabel)
{
coloredLabel.Tooltip =
$"Paid a payout{(payoutLabel.PullPaymentId is null ? string.Empty : $" of a pull payment ({payoutLabel.PullPaymentId})")}";
coloredLabel.Tooltip = payoutLabel.PullPaymentPayouts.Count > 1
? $"<ul>{string.Join(string.Empty, payoutLabel.PullPaymentPayouts.Select(pair => $"<li>{PayoutLabelText(pair)}</li>"))}</ul>"
: payoutLabel.PullPaymentPayouts.Select(PayoutLabelText).ToString();
coloredLabel.Link = string.IsNullOrEmpty(payoutLabel.WalletId)
? null
: _linkGenerator.PayoutLink(payoutLabel.WalletId,
payoutLabel.PullPaymentId, PayoutState.Completed, request.Scheme, request.Host,
: _linkGenerator.PayoutLink(payoutLabel.WalletId, null, PayoutState.Completed, request.Scheme, request.Host,
request.PathBase);
}
return coloredLabel;
}

View File

@@ -17,7 +17,12 @@
max-width: 200px;
}
}
/* pull actions area, so that it is besides the search form */
@@media (min-width: 1200px) {
#Actions {
margin-top: -4rem;
}
}
.unconf > * {
opacity: 0.5;
}
@@ -49,11 +54,14 @@
border: 0;
}
/* pull actions area, so that it is besides the search form */
@@media (min-width: 1200px) {
#Actions {
margin-top: -4rem;
}
.label-tooltip .tooltip-inner {
max-width: 15rem;
text-align: left;
}
.label-tooltip ul {
margin: 0;
padding-left: var(--btcpay-space-m);
}
</style>
}
@@ -161,7 +169,9 @@
<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>