Edit view for Pull Payments (#4016)

Co-authored-by: Dennis Reimann <mail@dennisreimann.de>
This commit is contained in:
Davide Oggioni 2022-08-11 14:30:42 +02:00 committed by GitHub
parent 7f41a1ef09
commit 8c8a5a4f5e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 246 additions and 11 deletions

View File

@ -30,7 +30,6 @@ using Newtonsoft.Json.Linq;
using OpenQA.Selenium;
using OpenQA.Selenium.Support.Extensions;
using OpenQA.Selenium.Support.UI;
using Renci.SshNet.Security.Cryptography;
using Xunit;
using Xunit.Abstractions;
@ -1300,6 +1299,46 @@ namespace BTCPayServer.Tests
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]
[Trait("Selenium", "Selenium")]
[Trait("Lightning", "Lightning")]

View File

@ -1,14 +1,16 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Threading.Tasks;
using BTCPayServer.Abstractions.Constants;
using BTCPayServer.Abstractions.Extensions;
using BTCPayServer.Abstractions.Models;
using BTCPayServer.Client;
using BTCPayServer.Client.Models;
using BTCPayServer.Data;
using BTCPayServer.HostedServices;
using BTCPayServer.Models;
using BTCPayServer.Models.WalletViewModels;
using BTCPayServer.Payments;
using BTCPayServer.Services;
using BTCPayServer.Services.Rates;
@ -19,7 +21,6 @@ using NBitcoin;
namespace BTCPayServer.Controllers
{
[AllowAnonymous]
public class UIPullPaymentController : Controller
{
private readonly ApplicationDbContextFactory _dbContextFactory;
@ -41,7 +42,8 @@ namespace BTCPayServer.Controllers
_payoutHandlers = payoutHandlers;
}
[Route("pull-payments/{pullPaymentId}")]
[AllowAnonymous]
[HttpGet("pull-payments/{pullPaymentId}")]
public async Task<IActionResult> ViewPullPayment(string pullPaymentId)
{
using var ctx = _dbContextFactory.CreateContext();
@ -92,6 +94,64 @@ namespace BTCPayServer.Controllers
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")]
public async Task<IActionResult> ClaimPullPayment(string pullPaymentId, ViewPullPaymentModel vm)
{

View File

@ -5,6 +5,7 @@ using System.ComponentModel.DataAnnotations;
using Microsoft.AspNetCore.Mvc.Rendering;
using BTCPayServer.Payments;
using BTCPayServer.Client.Models;
using BTCPayServer.Data;
namespace BTCPayServer.Models.WalletViewModels
{
@ -70,4 +71,37 @@ namespace BTCPayServer.Models.WalletViewModels
[Display(Name = "Automatically approve claims")]
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; }
}
}

View 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>

View File

@ -215,8 +215,11 @@
</main>
<footer class="pt-2 pb-4 d-print-none">
<p class="container text-center" permission="@Policies.CanViewStoreSettings">
<a asp-controller="UIStorePullPayments" asp-action="Payouts" asp-route-storeId="@Model.StoreId">
Back to payouts
<a asp-action="EditPullPayment"
asp-controller="UIPullPayment"
asp-route-storeId="@Model.StoreId"
asp-route-pullPaymentId="@Model.Id">
Edit pull payment
</a>
</p>
<div class="container d-flex flex-wrap align-items-center justify-content-center">

View File

@ -113,8 +113,8 @@
{
<tr>
<td>
<a class="pp-payout"
asp-action="Payouts"
<a asp-action="EditPullPayment"
asp-controller="UIPullPayment"
asp-route-storeId="@Context.GetRouteValue("storeId")"
asp-route-pullPaymentId="@pp.Id">
@pp.Name
@ -133,10 +133,11 @@
</div>
</td>
<td class="text-end">
<a asp-action="ViewPullPayment"
asp-controller="UIPullPayment"
<a class="pp-payout"
asp-action="Payouts"
asp-route-storeId="@Context.GetRouteValue("storeId")"
asp-route-pullPaymentId="@pp.Id">
View
Payouts
</a>
@if (!pp.Archived)
{
@ -151,6 +152,12 @@
Archive
</a>
}
<span> - </span>
<a asp-action="ViewPullPayment"
asp-controller="UIPullPayment"
asp-route-pullPaymentId="@pp.Id">
View
</a>
</td>
</tr>
}