mirror of
https://github.com/aljazceru/btcpayserver.git
synced 2026-02-11 17:24:21 +01:00
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:
@@ -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";
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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
|
||||
});
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user