mirror of
https://github.com/btcpayserver/btcpayserver.git
synced 2024-11-19 09:54:30 +01:00
Wallet: Delete custom labels (#5324)
* Tom Select improvements * Wallet: Delete custom labels Closes #5237.
This commit is contained in:
parent
44df8cf0c5
commit
77d8e202d3
@ -385,7 +385,8 @@ retry:
|
||||
EqualJsContent(expected, actual);
|
||||
|
||||
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);
|
||||
|
||||
actual = GetFileContent("BTCPayServer", "wwwroot", "vendor", "dom-confetti", "dom-confetti.min.js").Trim();
|
||||
|
@ -3,7 +3,7 @@
|
||||
@model BTCPayServer.Components.LabelManager.LabelViewModel
|
||||
@{
|
||||
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,
|
||||
excludeTypes = Safe.Json(Model.ExcludeTypes)
|
||||
});
|
||||
|
@ -1381,9 +1381,9 @@ namespace BTCPayServer.Controllers
|
||||
return Ok();
|
||||
}
|
||||
|
||||
[HttpGet("{walletId}/labels")]
|
||||
[HttpGet("{walletId}/labels.json")]
|
||||
[IgnoreAntiforgeryToken]
|
||||
public async Task<IActionResult> GetLabels(
|
||||
public async Task<IActionResult> LabelsJson(
|
||||
[ModelBinder(typeof(WalletIdModelBinder))] WalletId walletId,
|
||||
bool excludeTypes,
|
||||
string? type = null,
|
||||
@ -1397,14 +1397,62 @@ namespace BTCPayServer.Controllers
|
||||
: await WalletRepository.GetWalletLabels(walletObjectId);
|
||||
return Ok(labels
|
||||
.Where(l => !excludeTypes || !WalletObjectData.Types.AllTypes.Contains(l.Label))
|
||||
.Select(tuple => new
|
||||
.Select(tuple => new WalletLabelModel
|
||||
{
|
||||
label = tuple.Label,
|
||||
color = tuple.Color,
|
||||
textColor = ColorPalette.Default.TextColor(tuple.Color)
|
||||
Label = tuple.Label,
|
||||
Color = 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)
|
||||
{
|
||||
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; }
|
||||
}
|
@ -563,6 +563,18 @@ namespace BTCPayServer.Services
|
||||
await RemoveWalletObjectLink(labelObjId, id);
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
|
@ -16,7 +16,6 @@
|
||||
<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/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"/>
|
||||
}
|
||||
|
||||
@ -200,6 +199,11 @@
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary mt-2" id="SavePaymentSettings">Save Payment Settings</button>
|
||||
</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>
|
||||
|
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>
|
||||
}
|
||||
|
@ -33,7 +33,7 @@ async function initLabelManager (elementId) {
|
||||
: '--label-bg:var(--btcpay-neutral-300);--label-fg:var(--btcpay-neutral-800)'
|
||||
|
||||
if (element) {
|
||||
const { fetchUrl, updateUrl, walletId, walletObjectType, walletObjectId, labels,selectElement } = element.dataset;
|
||||
const { fetchUrl, updateUrl, walletId, walletObjectType, walletObjectId, labels, selectElement } = element.dataset;
|
||||
const commonCallId = `walletLabels-${walletId}`;
|
||||
if (!window[commonCallId]) {
|
||||
window[commonCallId] = fetch(fetchUrl, {
|
||||
@ -44,7 +44,6 @@ async function initLabelManager (elementId) {
|
||||
},
|
||||
}).then(res => res.json());
|
||||
}
|
||||
const selectElementI = document.getElementById(selectElement);
|
||||
const items = element.value.split(',').filter(x => !!x);
|
||||
const options = await window[commonCallId].then(labels => {
|
||||
const newItems = items.filter(item => !labels.find(label => label.label === item));
|
||||
@ -92,7 +91,8 @@ async function initLabelManager (elementId) {
|
||||
}));
|
||||
},
|
||||
async onChange (values) {
|
||||
if(selectElementI){
|
||||
const selectElementI = selectElement ? document.getElementById(selectElement) : null;
|
||||
if (selectElementI){
|
||||
while (selectElementI.options.length > 0) {
|
||||
selectElementI.remove(0);
|
||||
}
|
||||
|
File diff suppressed because one or more lines are too long
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
Loading…
Reference in New Issue
Block a user