mirror of
https://github.com/aljazceru/btcpayserver.git
synced 2025-12-17 22:14:26 +01:00
Edit view for Pull Payments (#4016)
Co-authored-by: Dennis Reimann <mail@dennisreimann.de>
This commit is contained in:
@@ -30,7 +30,6 @@ using Newtonsoft.Json.Linq;
|
|||||||
using OpenQA.Selenium;
|
using OpenQA.Selenium;
|
||||||
using OpenQA.Selenium.Support.Extensions;
|
using OpenQA.Selenium.Support.Extensions;
|
||||||
using OpenQA.Selenium.Support.UI;
|
using OpenQA.Selenium.Support.UI;
|
||||||
using Renci.SshNet.Security.Cryptography;
|
|
||||||
using Xunit;
|
using Xunit;
|
||||||
using Xunit.Abstractions;
|
using Xunit.Abstractions;
|
||||||
|
|
||||||
@@ -1300,6 +1299,46 @@ namespace BTCPayServer.Tests
|
|||||||
s.Driver.AssertElementNotFound(By.Id("ActionsDropdownToggle"));
|
s.Driver.AssertElementNotFound(By.Id("ActionsDropdownToggle"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
[Trait("Selenium", "Selenium")]
|
||||||
|
[Trait("Lightning", "Lightning")]
|
||||||
|
public async Task CanEditPullPaymentUI()
|
||||||
|
{
|
||||||
|
using var s = CreateSeleniumTester();
|
||||||
|
s.Server.ActivateLightning(LightningConnectionType.LndREST);
|
||||||
|
await s.StartAsync();
|
||||||
|
await s.Server.EnsureChannelsSetup();
|
||||||
|
s.RegisterNewUser(true);
|
||||||
|
s.CreateNewStore();
|
||||||
|
s.GenerateWallet("BTC", "", true, true);
|
||||||
|
await s.Server.ExplorerNode.GenerateAsync(1);
|
||||||
|
await s.FundStoreWallet(denomination: 50.0m);
|
||||||
|
|
||||||
|
s.GoToStore(s.StoreId, StoreNavPages.PullPayments);
|
||||||
|
|
||||||
|
s.Driver.FindElement(By.Id("NewPullPayment")).Click();
|
||||||
|
s.Driver.FindElement(By.Id("Name")).SendKeys("PP1");
|
||||||
|
s.Driver.FindElement(By.Id("Amount")).Clear();
|
||||||
|
s.Driver.FindElement(By.Id("Amount")).SendKeys("99.0");
|
||||||
|
s.Driver.FindElement(By.Id("Create")).Click();
|
||||||
|
s.Driver.FindElement(By.LinkText("View")).Click();
|
||||||
|
|
||||||
|
s.GoToStore(s.StoreId, StoreNavPages.PullPayments);
|
||||||
|
|
||||||
|
s.Driver.FindElement(By.LinkText("PP1")).Click();
|
||||||
|
var name = s.Driver.FindElement(By.Id("Name"));
|
||||||
|
name.Clear();
|
||||||
|
name.SendKeys("PP1 Edited");
|
||||||
|
var description = s.Driver.FindElement(By.ClassName("card-block"));
|
||||||
|
description.SendKeys("Description Edit");
|
||||||
|
s.Driver.FindElement(By.Id("SaveButton")).Click();
|
||||||
|
|
||||||
|
s.Driver.FindElement(By.LinkText("PP1 Edited")).Click();
|
||||||
|
|
||||||
|
Assert.Contains("Description Edit", s.Driver.PageSource);
|
||||||
|
Assert.Contains("PP1 Edited", s.Driver.PageSource);
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
[Trait("Selenium", "Selenium")]
|
[Trait("Selenium", "Selenium")]
|
||||||
[Trait("Lightning", "Lightning")]
|
[Trait("Lightning", "Lightning")]
|
||||||
|
|||||||
@@ -1,14 +1,16 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Globalization;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using BTCPayServer.Abstractions.Constants;
|
||||||
using BTCPayServer.Abstractions.Extensions;
|
using BTCPayServer.Abstractions.Extensions;
|
||||||
using BTCPayServer.Abstractions.Models;
|
using BTCPayServer.Abstractions.Models;
|
||||||
|
using BTCPayServer.Client;
|
||||||
using BTCPayServer.Client.Models;
|
using BTCPayServer.Client.Models;
|
||||||
using BTCPayServer.Data;
|
using BTCPayServer.Data;
|
||||||
using BTCPayServer.HostedServices;
|
using BTCPayServer.HostedServices;
|
||||||
using BTCPayServer.Models;
|
using BTCPayServer.Models;
|
||||||
|
using BTCPayServer.Models.WalletViewModels;
|
||||||
using BTCPayServer.Payments;
|
using BTCPayServer.Payments;
|
||||||
using BTCPayServer.Services;
|
using BTCPayServer.Services;
|
||||||
using BTCPayServer.Services.Rates;
|
using BTCPayServer.Services.Rates;
|
||||||
@@ -19,7 +21,6 @@ using NBitcoin;
|
|||||||
|
|
||||||
namespace BTCPayServer.Controllers
|
namespace BTCPayServer.Controllers
|
||||||
{
|
{
|
||||||
[AllowAnonymous]
|
|
||||||
public class UIPullPaymentController : Controller
|
public class UIPullPaymentController : Controller
|
||||||
{
|
{
|
||||||
private readonly ApplicationDbContextFactory _dbContextFactory;
|
private readonly ApplicationDbContextFactory _dbContextFactory;
|
||||||
@@ -41,7 +42,8 @@ namespace BTCPayServer.Controllers
|
|||||||
_payoutHandlers = payoutHandlers;
|
_payoutHandlers = payoutHandlers;
|
||||||
}
|
}
|
||||||
|
|
||||||
[Route("pull-payments/{pullPaymentId}")]
|
[AllowAnonymous]
|
||||||
|
[HttpGet("pull-payments/{pullPaymentId}")]
|
||||||
public async Task<IActionResult> ViewPullPayment(string pullPaymentId)
|
public async Task<IActionResult> ViewPullPayment(string pullPaymentId)
|
||||||
{
|
{
|
||||||
using var ctx = _dbContextFactory.CreateContext();
|
using var ctx = _dbContextFactory.CreateContext();
|
||||||
@@ -92,6 +94,64 @@ namespace BTCPayServer.Controllers
|
|||||||
return View(nameof(ViewPullPayment), vm);
|
return View(nameof(ViewPullPayment), vm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[HttpGet("stores/{storeId}/pull-payments/edit/{pullPaymentId}")]
|
||||||
|
[Authorize(Policy = Policies.CanModifyStoreSettings, AuthenticationSchemes = AuthenticationSchemes.Cookie)]
|
||||||
|
public async Task<IActionResult> EditPullPayment(string storeId, string pullPaymentId)
|
||||||
|
{
|
||||||
|
using var ctx = _dbContextFactory.CreateContext();
|
||||||
|
Data.PullPaymentData pp = await ctx.PullPayments.FindAsync(pullPaymentId);
|
||||||
|
if (pp == null && !string.IsNullOrEmpty(pullPaymentId))
|
||||||
|
{
|
||||||
|
return NotFound();
|
||||||
|
}
|
||||||
|
|
||||||
|
var vm = new UpdatePullPaymentModel(pp);
|
||||||
|
return View(vm);
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPost("stores/{storeId}/pull-payments/edit/{pullPaymentId}")]
|
||||||
|
[Authorize(Policy = Policies.CanModifyStoreSettings, AuthenticationSchemes = AuthenticationSchemes.Cookie)]
|
||||||
|
public async Task<IActionResult> EditPullPayment(string storeId, string pullPaymentId, UpdatePullPaymentModel viewModel)
|
||||||
|
{
|
||||||
|
using var ctx = _dbContextFactory.CreateContext();
|
||||||
|
|
||||||
|
var pp = await ctx.PullPayments.FindAsync(pullPaymentId);
|
||||||
|
if (pp == null && !string.IsNullOrEmpty(pullPaymentId))
|
||||||
|
{
|
||||||
|
return NotFound();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ModelState.IsValid)
|
||||||
|
{
|
||||||
|
return View(viewModel);
|
||||||
|
}
|
||||||
|
|
||||||
|
var blob = pp.GetBlob();
|
||||||
|
blob.Description = viewModel.Description ?? string.Empty;
|
||||||
|
blob.Name = viewModel.Name ?? string.Empty;
|
||||||
|
blob.View = new PullPaymentBlob.PullPaymentView()
|
||||||
|
{
|
||||||
|
Title = viewModel.Name ?? string.Empty,
|
||||||
|
Description = viewModel.Description ?? string.Empty,
|
||||||
|
CustomCSSLink = viewModel.CustomCSSLink,
|
||||||
|
Email = null,
|
||||||
|
EmbeddedCSS = viewModel.EmbeddedCSS,
|
||||||
|
};
|
||||||
|
|
||||||
|
pp.SetBlob(blob);
|
||||||
|
ctx.PullPayments.Update(pp);
|
||||||
|
await ctx.SaveChangesAsync();
|
||||||
|
|
||||||
|
TempData.SetStatusMessageModel(new StatusMessageModel
|
||||||
|
{
|
||||||
|
Message = "Pull payment updated successfully",
|
||||||
|
Severity = StatusMessageModel.StatusSeverity.Success
|
||||||
|
});
|
||||||
|
|
||||||
|
return RedirectToAction(nameof(UIStorePullPaymentsController.PullPayments), "UIStorePullPayments", new { storeId, pullPaymentId });
|
||||||
|
}
|
||||||
|
|
||||||
|
[AllowAnonymous]
|
||||||
[HttpPost("pull-payments/{pullPaymentId}/claim")]
|
[HttpPost("pull-payments/{pullPaymentId}/claim")]
|
||||||
public async Task<IActionResult> ClaimPullPayment(string pullPaymentId, ViewPullPaymentModel vm)
|
public async Task<IActionResult> ClaimPullPayment(string pullPaymentId, ViewPullPaymentModel vm)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ using System.ComponentModel.DataAnnotations;
|
|||||||
using Microsoft.AspNetCore.Mvc.Rendering;
|
using Microsoft.AspNetCore.Mvc.Rendering;
|
||||||
using BTCPayServer.Payments;
|
using BTCPayServer.Payments;
|
||||||
using BTCPayServer.Client.Models;
|
using BTCPayServer.Client.Models;
|
||||||
|
using BTCPayServer.Data;
|
||||||
|
|
||||||
namespace BTCPayServer.Models.WalletViewModels
|
namespace BTCPayServer.Models.WalletViewModels
|
||||||
{
|
{
|
||||||
@@ -70,4 +71,37 @@ namespace BTCPayServer.Models.WalletViewModels
|
|||||||
[Display(Name = "Automatically approve claims")]
|
[Display(Name = "Automatically approve claims")]
|
||||||
public bool AutoApproveClaims { get; set; } = false;
|
public bool AutoApproveClaims { get; set; } = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class UpdatePullPaymentModel
|
||||||
|
{
|
||||||
|
|
||||||
|
public string Id { get; set; }
|
||||||
|
|
||||||
|
public UpdatePullPaymentModel()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public UpdatePullPaymentModel(Data.PullPaymentData data)
|
||||||
|
{
|
||||||
|
if (data == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Id = data.Id;
|
||||||
|
var blob = data.GetBlob();
|
||||||
|
Name = blob.Name;
|
||||||
|
Description = blob.Description;
|
||||||
|
CustomCSSLink = blob.View.CustomCSSLink;
|
||||||
|
EmbeddedCSS = blob.View.EmbeddedCSS;
|
||||||
|
}
|
||||||
|
|
||||||
|
[MaxLength(30)]
|
||||||
|
public string Name { get; set; }
|
||||||
|
public string Description { get; set; }
|
||||||
|
[Display(Name = "Custom CSS URL")]
|
||||||
|
public string CustomCSSLink { get; set; }
|
||||||
|
[Display(Name = "Custom CSS Code")]
|
||||||
|
public string EmbeddedCSS { get; set; }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
92
BTCPayServer/Views/UIPullPayment/EditPullPayment.cshtml
Normal file
92
BTCPayServer/Views/UIPullPayment/EditPullPayment.cshtml
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
@using BTCPayServer.Views.Stores
|
||||||
|
@using BTCPayServer.Abstractions.Extensions
|
||||||
|
@model BTCPayServer.Models.WalletViewModels.UpdatePullPaymentModel
|
||||||
|
|
||||||
|
@{
|
||||||
|
ViewData.SetActivePage(StoreNavPages.Create, "Edit Pull Payment", Model.Id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@section PageHeadContent {
|
||||||
|
<link href="~/vendor/summernote/summernote-bs5.css" rel="stylesheet" asp-append-version="true" />
|
||||||
|
}
|
||||||
|
|
||||||
|
@section PageFootContent {
|
||||||
|
<partial name="_ValidationScriptsPartial" />
|
||||||
|
<script src="~/vendor/summernote/summernote-bs5.js" asp-append-version="true"></script>
|
||||||
|
}
|
||||||
|
|
||||||
|
<form method="post" asp-action="EditPullPayment" asp-route-storeId="@Context.GetRouteValue("storeId")" asp-route-pullPaymentId="@Model.Id">
|
||||||
|
<div class="sticky-header-setup"></div>
|
||||||
|
<div class="sticky-header d-sm-flex align-items-center justify-content-between">
|
||||||
|
<h2 class="mb-0">@ViewData["Title"]</h2>
|
||||||
|
<div class="d-flex gap-3 mt-3 mt-sm-0">
|
||||||
|
@if (string.IsNullOrEmpty(Model.Id))
|
||||||
|
{
|
||||||
|
<button type="submit" class="btn btn-primary" id="SaveButton">Create</button>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<button type="submit" class="btn btn-primary order-sm-1" id="SaveButton">Save</button>
|
||||||
|
<a class="btn btn-secondary" asp-action="ViewPullPayment" asp-route-pullPaymentId="@Model.Id" id="ViewPullPayment">View</a>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<partial name="_StatusMessage" />
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-xl-8 col-xxl-constrain">
|
||||||
|
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label asp-for="Name" class="form-label" data-required></label>
|
||||||
|
<input asp-for="Name" class="form-control" required />
|
||||||
|
<span asp-validation-for="Name" class="text-danger"></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-xl-10 col-xxl-constrain">
|
||||||
|
<div class="form-group">
|
||||||
|
<label asp-for="Description" class="form-label"></label>
|
||||||
|
<textarea asp-for="Description" class="form-control richtext"></textarea>
|
||||||
|
<span asp-validation-for="Description" class="text-danger"></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-xl-8 col-xxl-constrain">
|
||||||
|
<h4 class="mt-5 mb-2">Additional Options</h4>
|
||||||
|
<div class="form-group">
|
||||||
|
<div class="accordion" id="additional">
|
||||||
|
<div class="accordion-item">
|
||||||
|
<h2 class="accordion-header" id="additional-custom-css-header">
|
||||||
|
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#additional-custom-css" aria-expanded="false" aria-controls="additional-custom-css">
|
||||||
|
Custom CSS
|
||||||
|
<vc:icon symbol="caret-down" />
|
||||||
|
</button>
|
||||||
|
</h2>
|
||||||
|
<div id="additional-custom-css" class="accordion-collapse collapse" aria-labelledby="additional-custom-css-header">
|
||||||
|
<div class="accordion-body">
|
||||||
|
<div class="form-group">
|
||||||
|
<label asp-for="CustomCSSLink" class="form-label"></label>
|
||||||
|
<a href="https://docs.btcpayserver.org/Development/Theme/#2-bootstrap-themes" target="_blank" rel="noreferrer noopener">
|
||||||
|
<span class="fa fa-question-circle-o text-secondary" title="More information..."></span>
|
||||||
|
</a>
|
||||||
|
<input asp-for="CustomCSSLink" class="form-control" />
|
||||||
|
<span asp-validation-for="CustomCSSLink" class="text-danger"></span>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label asp-for="EmbeddedCSS" class="form-label"></label>
|
||||||
|
<textarea asp-for="EmbeddedCSS" rows="10" cols="40" class="form-control"></textarea>
|
||||||
|
<span asp-validation-for="EmbeddedCSS" class="text-danger"></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
@@ -215,8 +215,11 @@
|
|||||||
</main>
|
</main>
|
||||||
<footer class="pt-2 pb-4 d-print-none">
|
<footer class="pt-2 pb-4 d-print-none">
|
||||||
<p class="container text-center" permission="@Policies.CanViewStoreSettings">
|
<p class="container text-center" permission="@Policies.CanViewStoreSettings">
|
||||||
<a asp-controller="UIStorePullPayments" asp-action="Payouts" asp-route-storeId="@Model.StoreId">
|
<a asp-action="EditPullPayment"
|
||||||
Back to payouts
|
asp-controller="UIPullPayment"
|
||||||
|
asp-route-storeId="@Model.StoreId"
|
||||||
|
asp-route-pullPaymentId="@Model.Id">
|
||||||
|
Edit pull payment
|
||||||
</a>
|
</a>
|
||||||
</p>
|
</p>
|
||||||
<div class="container d-flex flex-wrap align-items-center justify-content-center">
|
<div class="container d-flex flex-wrap align-items-center justify-content-center">
|
||||||
|
|||||||
@@ -113,8 +113,8 @@
|
|||||||
{
|
{
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<a class="pp-payout"
|
<a asp-action="EditPullPayment"
|
||||||
asp-action="Payouts"
|
asp-controller="UIPullPayment"
|
||||||
asp-route-storeId="@Context.GetRouteValue("storeId")"
|
asp-route-storeId="@Context.GetRouteValue("storeId")"
|
||||||
asp-route-pullPaymentId="@pp.Id">
|
asp-route-pullPaymentId="@pp.Id">
|
||||||
@pp.Name
|
@pp.Name
|
||||||
@@ -133,10 +133,11 @@
|
|||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td class="text-end">
|
<td class="text-end">
|
||||||
<a asp-action="ViewPullPayment"
|
<a class="pp-payout"
|
||||||
asp-controller="UIPullPayment"
|
asp-action="Payouts"
|
||||||
|
asp-route-storeId="@Context.GetRouteValue("storeId")"
|
||||||
asp-route-pullPaymentId="@pp.Id">
|
asp-route-pullPaymentId="@pp.Id">
|
||||||
View
|
Payouts
|
||||||
</a>
|
</a>
|
||||||
@if (!pp.Archived)
|
@if (!pp.Archived)
|
||||||
{
|
{
|
||||||
@@ -151,6 +152,12 @@
|
|||||||
Archive
|
Archive
|
||||||
</a>
|
</a>
|
||||||
}
|
}
|
||||||
|
<span> - </span>
|
||||||
|
<a asp-action="ViewPullPayment"
|
||||||
|
asp-controller="UIPullPayment"
|
||||||
|
asp-route-pullPaymentId="@pp.Id">
|
||||||
|
View
|
||||||
|
</a>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user