mirror of
https://github.com/aljazceru/btcpayserver.git
synced 2025-12-18 14:34:23 +01:00
Wallet: Delete custom labels (#5324)
* Tom Select improvements * Wallet: Delete custom labels Closes #5237.
This commit is contained in:
@@ -385,7 +385,8 @@ retry:
|
|||||||
EqualJsContent(expected, actual);
|
EqualJsContent(expected, actual);
|
||||||
|
|
||||||
actual = GetFileContent("BTCPayServer", "wwwroot", "vendor", "tom-select", "tom-select.complete.min.js").Trim();
|
actual = GetFileContent("BTCPayServer", "wwwroot", "vendor", "tom-select", "tom-select.complete.min.js").Trim();
|
||||||
expected = (await (await client.GetAsync($"https://cdn.jsdelivr.net/npm/tom-select@2.2.2/dist/js/tom-select.complete.min.js")).Content.ReadAsStringAsync()).Trim();
|
version = Regex.Match(actual, "Tom Select v([0-9]+.[0-9]+.[0-9]+)").Groups[1].Value;
|
||||||
|
expected = (await (await client.GetAsync($"https://cdn.jsdelivr.net/npm/tom-select@{version}/dist/js/tom-select.complete.min.js")).Content.ReadAsStringAsync()).Trim();
|
||||||
EqualJsContent(expected, actual);
|
EqualJsContent(expected, actual);
|
||||||
|
|
||||||
actual = GetFileContent("BTCPayServer", "wwwroot", "vendor", "dom-confetti", "dom-confetti.min.js").Trim();
|
actual = GetFileContent("BTCPayServer", "wwwroot", "vendor", "dom-confetti", "dom-confetti.min.js").Trim();
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
@model BTCPayServer.Components.LabelManager.LabelViewModel
|
@model BTCPayServer.Components.LabelManager.LabelViewModel
|
||||||
@{
|
@{
|
||||||
var elementId = "a" + Encoders.Base58.EncodeData(RandomUtils.GetBytes(16));
|
var elementId = "a" + Encoders.Base58.EncodeData(RandomUtils.GetBytes(16));
|
||||||
var fetchUrl = Url.Action("GetLabels", "UIWallets", new {
|
var fetchUrl = Url.Action("LabelsJson", "UIWallets", new {
|
||||||
walletId = Model.WalletObjectId.WalletId,
|
walletId = Model.WalletObjectId.WalletId,
|
||||||
excludeTypes = Safe.Json(Model.ExcludeTypes)
|
excludeTypes = Safe.Json(Model.ExcludeTypes)
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1381,9 +1381,9 @@ namespace BTCPayServer.Controllers
|
|||||||
return Ok();
|
return Ok();
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet("{walletId}/labels")]
|
[HttpGet("{walletId}/labels.json")]
|
||||||
[IgnoreAntiforgeryToken]
|
[IgnoreAntiforgeryToken]
|
||||||
public async Task<IActionResult> GetLabels(
|
public async Task<IActionResult> LabelsJson(
|
||||||
[ModelBinder(typeof(WalletIdModelBinder))] WalletId walletId,
|
[ModelBinder(typeof(WalletIdModelBinder))] WalletId walletId,
|
||||||
bool excludeTypes,
|
bool excludeTypes,
|
||||||
string? type = null,
|
string? type = null,
|
||||||
@@ -1397,14 +1397,62 @@ namespace BTCPayServer.Controllers
|
|||||||
: await WalletRepository.GetWalletLabels(walletObjectId);
|
: await WalletRepository.GetWalletLabels(walletObjectId);
|
||||||
return Ok(labels
|
return Ok(labels
|
||||||
.Where(l => !excludeTypes || !WalletObjectData.Types.AllTypes.Contains(l.Label))
|
.Where(l => !excludeTypes || !WalletObjectData.Types.AllTypes.Contains(l.Label))
|
||||||
.Select(tuple => new
|
.Select(tuple => new WalletLabelModel
|
||||||
{
|
{
|
||||||
label = tuple.Label,
|
Label = tuple.Label,
|
||||||
color = tuple.Color,
|
Color = tuple.Color,
|
||||||
textColor = ColorPalette.Default.TextColor(tuple.Color)
|
TextColor = ColorPalette.Default.TextColor(tuple.Color)
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[HttpGet("{walletId}/labels")]
|
||||||
|
public async Task<IActionResult> WalletLabels(
|
||||||
|
[ModelBinder(typeof(WalletIdModelBinder))]
|
||||||
|
WalletId walletId)
|
||||||
|
{
|
||||||
|
if (walletId.StoreId == null)
|
||||||
|
return NotFound();
|
||||||
|
|
||||||
|
var labels = await WalletRepository.GetWalletLabels(walletId);
|
||||||
|
|
||||||
|
var vm = new WalletLabelsModel
|
||||||
|
{
|
||||||
|
WalletId = walletId,
|
||||||
|
Labels = labels
|
||||||
|
.Where(l => !WalletObjectData.Types.AllTypes.Contains(l.Label))
|
||||||
|
.Select(tuple => new WalletLabelModel
|
||||||
|
{
|
||||||
|
Label = tuple.Label,
|
||||||
|
Color = tuple.Color,
|
||||||
|
TextColor = ColorPalette.Default.TextColor(tuple.Color)
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
|
return View(vm);
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPost("{walletId}/labels/{id}/remove")]
|
||||||
|
public async Task<IActionResult> RemoveWalletLabel(
|
||||||
|
[ModelBinder(typeof(WalletIdModelBinder))]
|
||||||
|
WalletId walletId, string id)
|
||||||
|
{
|
||||||
|
if (walletId.StoreId == null)
|
||||||
|
return NotFound();
|
||||||
|
|
||||||
|
var labels = new[] { id };
|
||||||
|
;
|
||||||
|
if (await WalletRepository.RemoveWalletLabels(walletId, labels))
|
||||||
|
{
|
||||||
|
TempData[WellKnownTempData.SuccessMessage] = "The label has been successfully removed.";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TempData[WellKnownTempData.ErrorMessage] = "The label could not be removed.";
|
||||||
|
}
|
||||||
|
|
||||||
|
return RedirectToAction(nameof(WalletLabels), new { walletId });
|
||||||
|
}
|
||||||
|
|
||||||
private string GetImage(PaymentMethodId paymentMethodId, BTCPayNetwork network)
|
private string GetImage(PaymentMethodId paymentMethodId, BTCPayNetwork network)
|
||||||
{
|
{
|
||||||
var res = paymentMethodId.PaymentType == PaymentTypes.BTCLike
|
var res = paymentMethodId.PaymentType == PaymentTypes.BTCLike
|
||||||
|
|||||||
16
BTCPayServer/Models/WalletViewModels/WalletLabelsModel.cs
Normal file
16
BTCPayServer/Models/WalletViewModels/WalletLabelsModel.cs
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace BTCPayServer.Models.WalletViewModels;
|
||||||
|
|
||||||
|
public class WalletLabelsModel
|
||||||
|
{
|
||||||
|
public WalletId WalletId { get; set; }
|
||||||
|
public IEnumerable<WalletLabelModel> Labels { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class WalletLabelModel
|
||||||
|
{
|
||||||
|
public string Label { get; set; }
|
||||||
|
public string Color { get; set; }
|
||||||
|
public string TextColor { get; set; }
|
||||||
|
}
|
||||||
@@ -564,6 +564,18 @@ namespace BTCPayServer.Services
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<bool> RemoveWalletLabels(WalletId id, params string[] labels)
|
||||||
|
{
|
||||||
|
ArgumentNullException.ThrowIfNull(id);
|
||||||
|
var count = 0;
|
||||||
|
foreach (var l in labels.Select(l => l.Trim()))
|
||||||
|
{
|
||||||
|
var labelObjId = new WalletObjectId(id, WalletObjectData.Types.Label, l);
|
||||||
|
count += await RemoveWalletObjects(labelObjId) ? 1 : 0;
|
||||||
|
}
|
||||||
|
return count > 0;
|
||||||
|
}
|
||||||
|
|
||||||
public async Task SetWalletObject(WalletObjectId id, JObject? data)
|
public async Task SetWalletObject(WalletObjectId id, JObject? data)
|
||||||
{
|
{
|
||||||
ArgumentNullException.ThrowIfNull(id);
|
ArgumentNullException.ThrowIfNull(id);
|
||||||
|
|||||||
@@ -16,7 +16,6 @@
|
|||||||
<script src="~/vendor/vue-qrcode/vue-qrcode.min.js" asp-append-version="true"></script>
|
<script src="~/vendor/vue-qrcode/vue-qrcode.min.js" asp-append-version="true"></script>
|
||||||
<script src="~/vendor/ur-registry/urlib.min.js" asp-append-version="true"></script>
|
<script src="~/vendor/ur-registry/urlib.min.js" asp-append-version="true"></script>
|
||||||
<script src="~/vendor/vue-qrcode-reader/VueQrcodeReader.umd.min.js" asp-append-version="true"></script>
|
<script src="~/vendor/vue-qrcode-reader/VueQrcodeReader.umd.min.js" asp-append-version="true"></script>
|
||||||
|
|
||||||
<link href="~/vendor/vue-qrcode-reader/vue-qrcode-reader.css" rel="stylesheet" asp-append-version="true"/>
|
<link href="~/vendor/vue-qrcode-reader/vue-qrcode-reader.css" rel="stylesheet" asp-append-version="true"/>
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -200,6 +199,11 @@
|
|||||||
</div>
|
</div>
|
||||||
<button type="submit" class="btn btn-primary mt-2" id="SavePaymentSettings">Save Payment Settings</button>
|
<button type="submit" class="btn btn-primary mt-2" id="SavePaymentSettings">Save Payment Settings</button>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
|
<h3 class="mt-5">Labels</h3>
|
||||||
|
<p>
|
||||||
|
<a asp-controller="UIWallets" asp-action="WalletLabels" asp-route-walletId="@Model.WalletId">Manage labels</a>
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
52
BTCPayServer/Views/UIWallets/WalletLabels.cshtml
Normal file
52
BTCPayServer/Views/UIWallets/WalletLabels.cshtml
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
@using BTCPayServer.Abstractions.Models
|
||||||
|
@model WalletLabelsModel
|
||||||
|
@{
|
||||||
|
var walletId = Context.GetRouteValue("walletId").ToString();
|
||||||
|
Layout = "../Shared/_NavLayout.cshtml";
|
||||||
|
ViewData.SetActivePage(WalletsNavPages.Settings, "Wallet Labels", walletId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@section PageFootContent {
|
||||||
|
<script>
|
||||||
|
delegate('click', '.btn-delete', event => { event.preventDefault() })
|
||||||
|
</script>
|
||||||
|
}
|
||||||
|
|
||||||
|
<h3>@ViewData["Title"]</h3>
|
||||||
|
|
||||||
|
@if (Model.Labels.Any())
|
||||||
|
{
|
||||||
|
<table class="table table-hover table-responsive-md">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Label</th>
|
||||||
|
<th class="text-end">Actions</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
@foreach (var label in Model.Labels)
|
||||||
|
{
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<div class="transaction-label" style="--label-bg:@label.Color;--label-fg:@label.TextColor">
|
||||||
|
<span>@label.Label</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td class="text-end">
|
||||||
|
<form method="post" asp-action="RemoveWalletLabel" asp-route-walletId="@Model.WalletId" asp-route-id="@label.Label">
|
||||||
|
<button class="btn btn-link btn-delete p-0" type="submit" data-bs-toggle="modal" data-bs-target="#ConfirmModal" data-description="The label <strong>@Html.Encode(label.Label)</strong> will be removed from this wallet and its associated transactions." data-confirm-input="DELETE">Remove</button>
|
||||||
|
</form>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<partial name="_Confirm" model="@(new ConfirmModel("Remove label", "This label will be removed from this wallet and its associated transactions.", "Remove"))" />
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<p class="text-secondary mt-3">
|
||||||
|
There are no custom labels yet. You can create custom labels by assigning them to your <a asp-action="WalletTransactions" asp-route-walletId="@walletId">transactions</a>.
|
||||||
|
</p>
|
||||||
|
}
|
||||||
|
|
||||||
@@ -44,7 +44,6 @@ async function initLabelManager (elementId) {
|
|||||||
},
|
},
|
||||||
}).then(res => res.json());
|
}).then(res => res.json());
|
||||||
}
|
}
|
||||||
const selectElementI = document.getElementById(selectElement);
|
|
||||||
const items = element.value.split(',').filter(x => !!x);
|
const items = element.value.split(',').filter(x => !!x);
|
||||||
const options = await window[commonCallId].then(labels => {
|
const options = await window[commonCallId].then(labels => {
|
||||||
const newItems = items.filter(item => !labels.find(label => label.label === item));
|
const newItems = items.filter(item => !labels.find(label => label.label === item));
|
||||||
@@ -92,6 +91,7 @@ async function initLabelManager (elementId) {
|
|||||||
}));
|
}));
|
||||||
},
|
},
|
||||||
async onChange (values) {
|
async onChange (values) {
|
||||||
|
const selectElementI = selectElement ? document.getElementById(selectElement) : null;
|
||||||
if (selectElementI){
|
if (selectElementI){
|
||||||
while (selectElementI.options.length > 0) {
|
while (selectElementI.options.length > 0) {
|
||||||
selectElementI.remove(0);
|
selectElementI.remove(0);
|
||||||
|
|||||||
1
BTCPayServer/wwwroot/vendor/tom-select/tom-select.bootstrap5.min.css.map
vendored
Normal file
1
BTCPayServer/wwwroot/vendor/tom-select/tom-select.bootstrap5.min.css.map
vendored
Normal file
File diff suppressed because one or more lines are too long
1
BTCPayServer/wwwroot/vendor/tom-select/tom-select.complete.min.js.map
vendored
Normal file
1
BTCPayServer/wwwroot/vendor/tom-select/tom-select.complete.min.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user