diff --git a/BTCPayServer.Tests/BTCPayServer.Tests.csproj b/BTCPayServer.Tests/BTCPayServer.Tests.csproj index c8fbe1850..558d28098 100644 --- a/BTCPayServer.Tests/BTCPayServer.Tests.csproj +++ b/BTCPayServer.Tests/BTCPayServer.Tests.csproj @@ -23,7 +23,7 @@ - + all diff --git a/BTCPayServer.Tests/SeleniumTests.cs b/BTCPayServer.Tests/SeleniumTests.cs index c28b1841d..2dcc8a208 100644 --- a/BTCPayServer.Tests/SeleniumTests.cs +++ b/BTCPayServer.Tests/SeleniumTests.cs @@ -92,9 +92,8 @@ namespace BTCPayServer.Tests Assert.Contains("App updated", s.FindAlertMessage().Text); s.Driver.FindElement(By.Id("ViewApp")).Click(); - var windows = s.Driver.WindowHandles; - Assert.Equal(2, windows.Count); - s.Driver.SwitchTo().Window(windows[1]); + s.Driver.SwitchTo().Window(s.Driver.WindowHandles.Last()); + s.Driver.FindElement(By.CssSelector("button[type='submit']")).Click(); Assert.Contains("Enter your email", s.Driver.PageSource); @@ -103,6 +102,9 @@ namespace BTCPayServer.Tests s.PayInvoice(true); var invoiceId = s.Driver.Url[(s.Driver.Url.LastIndexOf("/", StringComparison.Ordinal) + 1)..]; + s.Driver.Close(); + s.Driver.SwitchTo().Window(s.Driver.WindowHandles.First()); + s.GoToInvoice(invoiceId); Assert.Contains("aa@aa.com", s.Driver.PageSource); @@ -116,13 +118,19 @@ namespace BTCPayServer.Tests s.Driver.FindElement(By.XPath("//a[starts-with(@id, 'Edit-')]")).Click(); var editUrl = s.Driver.Url; + s.Driver.FindElement(By.Id("ViewPaymentRequest")).Click(); + s.Driver.SwitchTo().Window(s.Driver.WindowHandles.Last()); + s.Driver.FindElement(By.CssSelector("[data-test='form-button']")).Click(); Assert.Contains("Enter your email", s.Driver.PageSource); s.Driver.FindElement(By.Name("buyerEmail")).SendKeys("aa@aa.com"); s.Driver.FindElement(By.CssSelector("input[type='submit']")).Click(); invoiceId = s.Driver.Url.Split('/').Last(); + s.Driver.Close(); + s.Driver.SwitchTo().Window(s.Driver.WindowHandles.First()); + s.Driver.Navigate().GoToUrl(editUrl); Assert.Contains("aa@aa.com", s.Driver.PageSource); var invoice = await s.Server.PayTester.GetService().GetInvoice(invoiceId); @@ -1193,13 +1201,13 @@ namespace BTCPayServer.Tests var editUrl = s.Driver.Url; s.Driver.FindElement(By.Id("ViewPaymentRequest")).Click(); + s.Driver.SwitchTo().Window(s.Driver.WindowHandles.Last()); var viewUrl = s.Driver.Url; - - Assert.Equal("Amount due", s.Driver.FindElement(By.CssSelector("[data-test='amount-due-title']")).Text); - Assert.Equal("Pay Invoice", s.Driver.FindElement(By.CssSelector("[data-test='pay-button']")).Text.Trim()); + Assert.Equal("Pay Invoice", s.Driver.FindElement(By.Id("PayInvoice")).Text.Trim()); + s.Driver.Close(); + s.Driver.SwitchTo().Window(s.Driver.WindowHandles.First()); // expire - s.GoToUrl(editUrl); s.Driver.ExecuteJavaScript("document.getElementById('ExpiryDate').value = '2021-01-21T21:00:00.000Z'"); s.Driver.FindElement(By.Id("SaveButton")).Click(); s.Driver.FindElement(By.XPath("//a[starts-with(@id, 'Edit-')]")).Click(); @@ -1219,12 +1227,28 @@ namespace BTCPayServer.Tests Assert.True(s.Driver.FindElement(By.Id("Currency")).Enabled); s.GoToUrl(viewUrl); - s.Driver.AssertElementNotFound(By.CssSelector("[data-test='status']")); - Assert.Equal("Pay Invoice", s.Driver.FindElement(By.CssSelector("[data-test='pay-button']")).Text.Trim()); + Assert.Equal("Pay Invoice", s.Driver.FindElement(By.Id("PayInvoice")).Text.Trim()); - // test invoice creation, click with JS, because the button is inside a sticky header - s.Driver.ExecuteJavaScript("document.querySelector('[data-test=\"pay-button\"]').click()"); - s.Driver.WaitUntilAvailable(By.Id("Checkout-v2")); + // test invoice creation + s.Driver.FindElement(By.Id("PayInvoice")).Click(); + TestUtils.Eventually(() => + { + s.Driver.WaitUntilAvailable(By.Name("btcpay")); + + var frameElement = s.Driver.FindElement(By.Name("btcpay")); + Assert.True(frameElement.Displayed); + var iframe = s.Driver.SwitchTo().Frame(frameElement); + iframe.WaitUntilAvailable(By.Id("Checkout-v2")); + + IWebElement closebutton = null; + TestUtils.Eventually(() => + { + closebutton = iframe.FindElement(By.Id("close")); + Assert.True(closebutton.Displayed); + }); + closebutton.Click(); + s.Driver.AssertElementNotFound(By.Name("btcpay")); + }); // amount and currency should not be editable, because invoice exists s.GoToUrl(editUrl); @@ -1248,32 +1272,45 @@ namespace BTCPayServer.Tests // payment s.GoToUrl(viewUrl); - s.Driver.ExecuteJavaScript("document.querySelector('[data-test=\"pay-button\"]').click()"); - - // Pay full amount - s.PayInvoice(); - - // Processing + s.Driver.FindElement(By.Id("PayInvoice")).Click(); TestUtils.Eventually(() => { - var processingSection = s.Driver.WaitForElement(By.Id("processing")); - Assert.True(processingSection.Displayed); - Assert.Contains("Payment Received", processingSection.Text); - Assert.Contains("Your payment has been received and is now processing", processingSection.Text); - }); + s.Driver.WaitUntilAvailable(By.Name("btcpay")); + + var frameElement = s.Driver.FindElement(By.Name("btcpay")); + Assert.True(frameElement.Displayed); + var iframe = s.Driver.SwitchTo().Frame(frameElement); + iframe.WaitUntilAvailable(By.Id("Checkout-v2")); + + // Pay full amount + s.PayInvoice(); + + // Processing + TestUtils.Eventually(() => + { + var processingSection = s.Driver.WaitForElement(By.Id("processing")); + Assert.True(processingSection.Displayed); + Assert.Contains("Payment Received", processingSection.Text); + Assert.Contains("Your payment has been received and is now processing", processingSection.Text); + }); - s.GoToUrl(viewUrl); - Assert.Equal("Processing", s.Driver.WaitForElement(By.CssSelector("[data-test='status']")).Text); - s.Driver.Navigate().Back(); + s.Driver.SwitchTo().Window(s.Driver.WindowHandles[0]); + Assert.Equal("Processing", s.Driver.WaitForElement(By.CssSelector("[data-test='status']")).Text); + s.Driver.SwitchTo().Frame(frameElement); - // Mine - s.MineBlockOnInvoiceCheckout(); - TestUtils.Eventually(() => - { - Assert.Contains("Mined 1 block", - s.Driver.WaitForElement(By.Id("CheatSuccessMessage")).Text); + // Mine + s.MineBlockOnInvoiceCheckout(); + TestUtils.Eventually(() => + { + Assert.Contains("Mined 1 block", + s.Driver.WaitForElement(By.Id("CheatSuccessMessage")).Text); + }); + + s.Driver.FindElement(By.Id("close")).Click(); + s.Driver.AssertElementNotFound(By.Name("btcpay")); }); - s.GoToUrl(viewUrl); + + s.Driver.SwitchTo().Window(s.Driver.WindowHandles[0]); Assert.Equal("Settled", s.Driver.WaitForElement(By.CssSelector("[data-test='status']")).Text); } @@ -1769,7 +1806,12 @@ namespace BTCPayServer.Tests 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.Driver.SwitchTo().Window(s.Driver.WindowHandles.Last()); + Assert.Contains("PP1", s.Driver.PageSource); + s.Driver.Close(); + s.Driver.SwitchTo().Window(s.Driver.WindowHandles.First()); s.GoToStore(s.StoreId, StoreNavPages.PullPayments); @@ -1780,9 +1822,9 @@ namespace BTCPayServer.Tests 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(); - + + s.Driver.FindElement(By.LinkText("View")).Click(); + s.Driver.SwitchTo().Window(s.Driver.WindowHandles.Last()); Assert.Contains("Description Edit", s.Driver.PageSource); Assert.Contains("PP1 Edited", s.Driver.PageSource); } @@ -1808,7 +1850,12 @@ namespace BTCPayServer.Tests 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.Driver.SwitchTo().Window(s.Driver.WindowHandles.Last()); + Assert.Contains("PP1", s.Driver.PageSource); + s.Driver.Close(); + s.Driver.SwitchTo().Window(s.Driver.WindowHandles.First()); s.GoToStore(s.StoreId, StoreNavPages.PullPayments); @@ -1820,6 +1867,7 @@ namespace BTCPayServer.Tests // This should select the first View, ie, the last one PP2 s.Driver.FindElement(By.LinkText("View")).Click(); + s.Driver.SwitchTo().Window(s.Driver.WindowHandles.Last()); var address = await s.Server.ExplorerNode.GetNewAddressAsync(); s.Driver.FindElement(By.Id("Destination")).SendKeys(address.ToString()); s.Driver.FindElement(By.Id("ClaimedAmount")).Clear(); @@ -1841,6 +1889,9 @@ namespace BTCPayServer.Tests Assert.Contains("Awaiting Approval", s.Driver.PageSource); var viewPullPaymentUrl = s.Driver.Url; + s.Driver.Close(); + s.Driver.SwitchTo().Window(s.Driver.WindowHandles.First()); + // This one should have nothing s.GoToStore(s.StoreId, StoreNavPages.PullPayments); var payouts = s.Driver.FindElements(By.ClassName("pp-payout")); @@ -1918,8 +1969,10 @@ namespace BTCPayServer.Tests s.Driver.FindElement(By.Id("Currency")).Clear(); s.Driver.FindElement(By.Id("Currency")).SendKeys("BTC"); s.Driver.FindElement(By.Id("Create")).Click(); - s.Driver.FindElement(By.LinkText("View")).Click(); + s.Driver.FindElement(By.LinkText("View")).Click(); + s.Driver.SwitchTo().Window(s.Driver.WindowHandles.Last()); + address = await s.Server.ExplorerNode.GetNewAddressAsync(); s.Driver.FindElement(By.Id("Destination")).SendKeys(address.ToString()); s.Driver.FindElement(By.Id("ClaimedAmount")).SendKeys(Keys.Enter); @@ -1932,6 +1985,8 @@ namespace BTCPayServer.Tests s.Driver.FindElement(By.Id($"{PayoutState.AwaitingApproval}-approve")).Click(); s.FindAlertMessage(); var tx = await s.Server.ExplorerNode.SendToAddressAsync(address, Money.FromUnit(0.001m, MoneyUnit.BTC)); + s.Driver.Close(); + s.Driver.SwitchTo().Window(s.Driver.WindowHandles.First()); s.GoToStore(s.StoreId, StoreNavPages.Payouts); @@ -1970,6 +2025,7 @@ namespace BTCPayServer.Tests s.Driver.FindElement(By.Id("Currency")).SendKeys("BTC"); s.Driver.FindElement(By.Id("Create")).Click(); s.Driver.FindElement(By.LinkText("View")).Click(); + s.Driver.SwitchTo().Window(s.Driver.WindowHandles.Last()); // Bitcoin-only, SelectedPaymentMethod should not be displayed s.Driver.ElementDoesNotExist(By.Id("SelectedPaymentMethod")); @@ -1993,6 +2049,8 @@ namespace BTCPayServer.Tests s.FindAlertMessage(); Assert.Contains(PayoutState.AwaitingApproval.GetStateString(), s.Driver.PageSource); + s.Driver.Close(); + s.Driver.SwitchTo().Window(s.Driver.WindowHandles.First()); s.GoToStore(newStore.storeId, StoreNavPages.Payouts); s.Driver.FindElement(By.Id($"{new PaymentMethodId("BTC", PaymentTypes.LightningLike)}-view")).Click(); @@ -2000,10 +2058,10 @@ namespace BTCPayServer.Tests s.Driver.FindElement(By.ClassName("mass-action-select-all")).Click(); s.Driver.FindElement(By.Id($"{PayoutState.AwaitingApproval}-approve-pay")).Click(); Assert.Contains(bolt, s.Driver.PageSource); - Assert.Contains($"{payoutAmount.ToString()} BTC", s.Driver.PageSource); + Assert.Contains($"{payoutAmount} BTC", s.Driver.PageSource); s.Driver.FindElement(By.CssSelector("#pay-invoices-form")).Submit(); - s.FindAlertMessage(StatusMessageModel.StatusSeverity.Success); + s.FindAlertMessage(); s.GoToStore(newStore.storeId, StoreNavPages.Payouts); s.Driver.FindElement(By.Id($"{new PaymentMethodId("BTC", PaymentTypes.LightningLike)}-view")).Click(); @@ -2028,16 +2086,21 @@ namespace BTCPayServer.Tests s.Driver.SetCheckbox(By.Id("AutoApproveClaims"), true); s.Driver.FindElement(By.Id("Amount")).Clear(); s.Driver.FindElement(By.Id("Amount")).SendKeys("99.0" + Keys.Enter); - s.FindAlertMessage(StatusMessageModel.StatusSeverity.Success); + s.FindAlertMessage(); + s.Driver.FindElement(By.LinkText("View")).Click(); + s.Driver.SwitchTo().Window(s.Driver.WindowHandles.Last()); + address = await s.Server.ExplorerNode.GetNewAddressAsync(); s.Driver.FindElement(By.Id("Destination")).Clear(); s.Driver.FindElement(By.Id("Destination")).SendKeys(address.ToString()); s.Driver.FindElement(By.Id("ClaimedAmount")).Clear(); s.Driver.FindElement(By.Id("ClaimedAmount")).SendKeys("20" + Keys.Enter); - s.FindAlertMessage(StatusMessageModel.StatusSeverity.Success); + s.FindAlertMessage(); Assert.Contains(PayoutState.AwaitingPayment.GetStateString(), s.Driver.PageSource); + s.Driver.Close(); + s.Driver.SwitchTo().Window(s.Driver.WindowHandles.First()); // LNURL Withdraw support check with BTC denomination s.GoToStore(s.StoreId, StoreNavPages.PullPayments); @@ -2048,8 +2111,11 @@ namespace BTCPayServer.Tests s.Driver.FindElement(By.Id("Amount")).SendKeys("0.0000001"); s.Driver.FindElement(By.Id("Currency")).Clear(); s.Driver.FindElement(By.Id("Currency")).SendKeys("BTC" + Keys.Enter); - s.FindAlertMessage(StatusMessageModel.StatusSeverity.Success); + s.FindAlertMessage(); + s.Driver.FindElement(By.LinkText("View")).Click(); + s.Driver.SwitchTo().Window(s.Driver.WindowHandles.Last()); + s.Driver.FindElement(By.CssSelector("#lnurlwithdraw-button")).Click(); s.Driver.WaitForElement(By.Id("qr-code-data-input")); @@ -2075,6 +2141,8 @@ namespace BTCPayServer.Tests Assert.Contains(PayoutState.Completed.GetStateString(), s.Driver.PageSource); Assert.Equal(LightningInvoiceStatus.Paid, (await s.Server.CustomerLightningD.GetInvoice(bolt2.Id)).Status); }); + s.Driver.Close(); + s.Driver.SwitchTo().Window(s.Driver.WindowHandles.First()); s.GoToStore(s.StoreId, StoreNavPages.PullPayments); s.Driver.FindElement(By.Id("NewPullPayment")).Click(); @@ -2084,8 +2152,11 @@ namespace BTCPayServer.Tests s.Driver.FindElement(By.Id("Amount")).SendKeys("0.0000001"); s.Driver.FindElement(By.Id("Currency")).Clear(); s.Driver.FindElement(By.Id("Currency")).SendKeys("BTC" + Keys.Enter); - s.FindAlertMessage(StatusMessageModel.StatusSeverity.Success); + s.FindAlertMessage(); + s.Driver.FindElement(By.LinkText("View")).Click(); + s.Driver.SwitchTo().Window(s.Driver.WindowHandles.Last()); + s.Driver.FindElement(By.CssSelector("#lnurlwithdraw-button")).Click(); lnurl = new Uri(LNURL.LNURL.Parse(s.Driver.FindElement(By.Id("qr-code-data-input")).GetAttribute("value"), out _).ToString().Replace("https", "http")); @@ -2109,6 +2180,8 @@ namespace BTCPayServer.Tests Assert.Contains(PayoutState.AwaitingApproval.GetStateString(), s.Driver.PageSource); }); + s.Driver.Close(); + s.Driver.SwitchTo().Window(s.Driver.WindowHandles.First()); // LNURL Withdraw support check with SATS denomination s.GoToStore(s.StoreId, StoreNavPages.PullPayments); @@ -2119,8 +2192,11 @@ namespace BTCPayServer.Tests s.Driver.FindElement(By.Id("Amount")).SendKeys("21021"); s.Driver.FindElement(By.Id("Currency")).Clear(); s.Driver.FindElement(By.Id("Currency")).SendKeys("SATS" + Keys.Enter); - s.FindAlertMessage(StatusMessageModel.StatusSeverity.Success); + s.FindAlertMessage(); + s.Driver.FindElement(By.LinkText("View")).Click(); + s.Driver.SwitchTo().Window(s.Driver.WindowHandles.Last()); + s.Driver.FindElement(By.CssSelector("#lnurlwithdraw-button")).Click(); lnurl = new Uri(LNURL.LNURL.Parse(s.Driver.FindElement(By.Id("qr-code-data-input")).GetAttribute("value"), out _).ToString().Replace("https", "http")); s.Driver.FindElement(By.CssSelector("button[data-bs-dismiss='modal']")).Click(); @@ -2145,6 +2221,7 @@ namespace BTCPayServer.Tests Assert.Contains(PayoutState.Completed.GetStateString(), s.Driver.PageSource); Assert.Equal(LightningInvoiceStatus.Paid, (await s.Server.CustomerLightningD.GetInvoice(bolt2.Id)).Status); }); + s.Driver.Close(); } [Fact] @@ -2534,13 +2611,16 @@ namespace BTCPayServer.Tests s.Driver.FindElement(By.Id("Create")).Click(); s.Driver.FindElement(By.LinkText("View")).Click(); - s.Driver.FindElement(By.Id("Destination")).SendKeys(lnurl); - + s.Driver.SwitchTo().Window(s.Driver.WindowHandles.Last()); var pullPaymentId = s.Driver.Url.Split('/').Last(); + + s.Driver.FindElement(By.Id("Destination")).SendKeys(lnurl); s.Driver.FindElement(By.Id("ClaimedAmount")).Clear(); s.Driver.FindElement(By.Id("ClaimedAmount")).SendKeys("0.0000001" + Keys.Enter); s.FindAlertMessage(); - + + s.Driver.Close(); + s.Driver.SwitchTo().Window(s.Driver.WindowHandles.First()); s.GoToStore(s.StoreId, StoreNavPages.PullPayments); var payouts = s.Driver.FindElements(By.ClassName("pp-payout")); payouts[0].Click(); diff --git a/BTCPayServer/ColorPalette.cs b/BTCPayServer/ColorPalette.cs index f057aa8a1..462a4350b 100644 --- a/BTCPayServer/ColorPalette.cs +++ b/BTCPayServer/ColorPalette.cs @@ -13,14 +13,20 @@ namespace BTCPayServer { return Regex.Match(color, Pattern).Success; } - public string TextColor(string bgColor) + + public Color TextColor(Color bg) { int nThreshold = 105; - var bg = ColorTranslator.FromHtml(bgColor); - int bgDelta = Convert.ToInt32((bg.R * 0.299) + (bg.G * 0.587) + (bg.B * 0.114)); - Color color = (255 - bgDelta < nThreshold) ? Color.Black : Color.White; + int bgDelta = Convert.ToInt32(bg.R * 0.299 + bg.G * 0.587 + bg.B * 0.114); + return 255 - bgDelta < nThreshold ? Color.Black : Color.White; + } + + public string TextColor(string bg) + { + var color = TextColor(FromHtml(bg)); return ColorTranslator.ToHtml(color).ToLowerInvariant(); } + // Borrowed from https://github.com/ManageIQ/guides/blob/master/labels.md public static readonly ColorPalette Default = new ColorPalette(new string[] { "#fbca04", @@ -31,6 +37,7 @@ namespace BTCPayServer "#cdcdcd", "#cc317c", }); + private ColorPalette(string[] labels) { Labels = labels; @@ -98,5 +105,10 @@ namespace BTCPayServer var color = AdjustBrightness(ColorTranslator.FromHtml(html), correctionFactor); return ColorTranslator.ToHtml(color); } + + public Color FromHtml(string html) + { + return ColorTranslator.FromHtml(html); + } } } diff --git a/BTCPayServer/Controllers/UIInvoiceController.UI.cs b/BTCPayServer/Controllers/UIInvoiceController.UI.cs index b973be1f0..801dbb0d8 100644 --- a/BTCPayServer/Controllers/UIInvoiceController.UI.cs +++ b/BTCPayServer/Controllers/UIInvoiceController.UI.cs @@ -254,6 +254,7 @@ namespace BTCPayServer.Controllers Amount = paymentEntity.PaidAmount.Gross, Paid = paymentEntity.InvoicePaidAmount.Net, ReceivedDate = paymentEntity.ReceivedTime.DateTime, + AmountFormatted = _displayFormatter.Currency(paymentEntity.PaidAmount.Gross, paymentEntity.PaidAmount.Currency, DisplayFormatter.CurrencyFormat.None), PaidFormatted = _displayFormatter.Currency(paymentEntity.InvoicePaidAmount.Net, i.Currency, DisplayFormatter.CurrencyFormat.Symbol), RateFormatted = _displayFormatter.Currency(paymentEntity.Rate, i.Currency, DisplayFormatter.CurrencyFormat.Symbol), PaymentMethod = paymentMethodId.ToPrettyString(), diff --git a/BTCPayServer/Controllers/UIPaymentRequestController.cs b/BTCPayServer/Controllers/UIPaymentRequestController.cs index 9ecf81b65..895569c6f 100644 --- a/BTCPayServer/Controllers/UIPaymentRequestController.cs +++ b/BTCPayServer/Controllers/UIPaymentRequestController.cs @@ -205,6 +205,7 @@ namespace BTCPayServer.Controllers var storeBlob = store.GetStoreBlob(); vm.StoreName = store.StoreName; + vm.StoreWebsite = store.StoreWebsite; vm.BrandColor = storeBlob.BrandColor; vm.LogoFileId = storeBlob.LogoFileId; vm.CssFileId = storeBlob.CssFileId; diff --git a/BTCPayServer/Models/PaymentRequestViewModels/ListPaymentRequestsViewModel.cs b/BTCPayServer/Models/PaymentRequestViewModels/ListPaymentRequestsViewModel.cs index 018359fcc..6ba0252a6 100644 --- a/BTCPayServer/Models/PaymentRequestViewModels/ListPaymentRequestsViewModel.cs +++ b/BTCPayServer/Models/PaymentRequestViewModels/ListPaymentRequestsViewModel.cs @@ -72,7 +72,11 @@ namespace BTCPayServer.Models.PaymentRequestViewModels [Display(Name = "Expiration Date")] public DateTime? ExpiryDate { get; set; } - [Required] public string Title { get; set; } + + [Required] + public string Title { get; set; } + + [Display(Name = "Memo")] public string Description { get; set; } [Display(Name = "Store")] @@ -87,7 +91,8 @@ namespace BTCPayServer.Models.PaymentRequestViewModels [Display(Name = "Custom CSS Code")] public string EmbeddedCSS { get; set; } - [Display(Name = "Allow payee to create invoices in their own denomination")] + + [Display(Name = "Allow payee to create invoices with custom amounts")] public bool AllowCustomPaymentAmounts { get; set; } public Dictionary FormResponse { get; set; } @@ -151,6 +156,7 @@ namespace BTCPayServer.Models.PaymentRequestViewModels public string CssFileId { get; set; } public string BrandColor { get; set; } public string StoreName { get; set; } + public string StoreWebsite { get; set; } public string EmbeddedCSS { get; set; } public string CustomCSSLink { get; set; } @@ -208,6 +214,7 @@ namespace BTCPayServer.Models.PaymentRequestViewModels { public string PaymentMethod { get; set; } public decimal Amount { get; set; } + public string AmountFormatted { get; set; } public string RateFormatted { get; set; } public decimal Paid { get; set; } public string PaidFormatted { get; set; } diff --git a/BTCPayServer/Models/WalletViewModels/PullPaymentsModel.cs b/BTCPayServer/Models/WalletViewModels/PullPaymentsModel.cs index 86b48fa35..311f1709f 100644 --- a/BTCPayServer/Models/WalletViewModels/PullPaymentsModel.cs +++ b/BTCPayServer/Models/WalletViewModels/PullPaymentsModel.cs @@ -98,9 +98,13 @@ namespace BTCPayServer.Models.WalletViewModels [MaxLength(30)] public string Name { get; set; } + + [Display(Name = "Memo")] 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; } } diff --git a/BTCPayServer/PaymentRequest/PaymentRequestService.cs b/BTCPayServer/PaymentRequest/PaymentRequestService.cs index 4a744dfce..2201bbcab 100644 --- a/BTCPayServer/PaymentRequest/PaymentRequestService.cs +++ b/BTCPayServer/PaymentRequest/PaymentRequestService.cs @@ -135,6 +135,7 @@ namespace BTCPayServer.PaymentRequest Amount = paymentEntity.PaidAmount.Gross, Paid = paymentEntity.InvoicePaidAmount.Net, ReceivedDate = paymentEntity.ReceivedTime.DateTime, + AmountFormatted = _displayFormatter.Currency(paymentEntity.PaidAmount.Gross, paymentEntity.PaidAmount.Currency, DisplayFormatter.CurrencyFormat.None), PaidFormatted = _displayFormatter.Currency(paymentEntity.InvoicePaidAmount.Net, blob.Currency, DisplayFormatter.CurrencyFormat.Symbol), RateFormatted = _displayFormatter.Currency(paymentEntity.Rate, blob.Currency, DisplayFormatter.CurrencyFormat.Symbol), PaymentMethod = paymentMethodId.ToPrettyString(), diff --git a/BTCPayServer/Views/Shared/LayoutHeadStoreBranding.cshtml b/BTCPayServer/Views/Shared/LayoutHeadStoreBranding.cshtml index e4c0b7045..64a826d0d 100644 --- a/BTCPayServer/Views/Shared/LayoutHeadStoreBranding.cshtml +++ b/BTCPayServer/Views/Shared/LayoutHeadStoreBranding.cshtml @@ -10,20 +10,30 @@ } @if (!string.IsNullOrEmpty(Model.BrandColor)) { - var brandColor = Model.BrandColor; - var accentColor = ColorPalette.Default.AdjustBrightness(brandColor, (float)-0.15); - var complement = ColorPalette.Default.TextColor(brandColor).ToLowerInvariant(); - var complementColor = $"var(--btcpay-{(complement == "black" ? "black" : "white")})"; + var brand = Model.BrandColor; + var brandColor = ColorPalette.Default.FromHtml(brand); + var brandRgbValues = $"{brandColor.R}, {brandColor.G}, {brandColor.B}"; + var accent = ColorPalette.Default.AdjustBrightness(brand, (float)-0.15); + var complement = ColorPalette.Default.TextColor(brand); + var complementVar = $"var(--btcpay-{(complement == "black" ? "black" : "white")})"; } diff --git a/BTCPayServer/Views/UIInvoice/CheckoutV2.cshtml b/BTCPayServer/Views/UIInvoice/CheckoutV2.cshtml index 455b90e55..72fdaa1ce 100644 --- a/BTCPayServer/Views/UIInvoice/CheckoutV2.cshtml +++ b/BTCPayServer/Views/UIInvoice/CheckoutV2.cshtml @@ -303,6 +303,7 @@ + @if (Env.CheatMode) diff --git a/BTCPayServer/Views/UIInvoice/InvoiceReceipt.cshtml b/BTCPayServer/Views/UIInvoice/InvoiceReceipt.cshtml index 419dd8157..4bcc2aea3 100644 --- a/BTCPayServer/Views/UIInvoice/InvoiceReceipt.cshtml +++ b/BTCPayServer/Views/UIInvoice/InvoiceReceipt.cshtml @@ -108,23 +108,21 @@

Payment Details

- +
- - - - + + + + @foreach (var payment in Model.Payments) { - - - - - + + + @if (!string.IsNullOrEmpty(payment.Destination)) { @@ -132,7 +130,7 @@ - @@ -143,20 +141,20 @@ - } - } +
DatePaymentPaidRateDatePaidPayment
@payment.ReceivedDate.ToBrowserDate()@payment.Amount @payment.PaymentMethod@payment.PaidFormatted@payment.RateFormatted@payment.ReceivedDate.ToBrowserDate()@payment.PaidFormatted@payment.AmountFormatted @payment.PaymentMethod
Destination +
Payment Proof +
@foreach (var payment in Model.Payments) {
- @payment.PaidFormatted = @payment.Amount @payment.PaymentMethod, Rate: @payment.RateFormatted + @payment.PaidFormatted = @payment.AmountFormatted @payment.PaymentMethod, Rate: @payment.RateFormatted @if (!string.IsNullOrEmpty(payment.PaymentProof)) {
Proof: @payment.PaymentProof
diff --git a/BTCPayServer/Views/UIInvoice/InvoiceReceiptPrint.cshtml b/BTCPayServer/Views/UIInvoice/InvoiceReceiptPrint.cshtml index 30294f031..81af5dd6b 100644 --- a/BTCPayServer/Views/UIInvoice/InvoiceReceiptPrint.cshtml +++ b/BTCPayServer/Views/UIInvoice/InvoiceReceiptPrint.cshtml @@ -45,7 +45,7 @@ else @foreach (var payment in Model.Payments) {

 

-

@payment.Amount @payment.PaymentMethod

+

@payment.AmountFormatted @payment.PaymentMethod

Rate: @payment.RateFormatted

= @payment.PaidFormatted

} diff --git a/BTCPayServer/Views/UIPaymentRequest/EditPaymentRequest.cshtml b/BTCPayServer/Views/UIPaymentRequest/EditPaymentRequest.cshtml index 3ac7dcf07..d8c846812 100644 --- a/BTCPayServer/Views/UIPaymentRequest/EditPaymentRequest.cshtml +++ b/BTCPayServer/Views/UIPaymentRequest/EditPaymentRequest.cshtml @@ -33,7 +33,7 @@ else { - View + View }
diff --git a/BTCPayServer/Views/UIPaymentRequest/GetPaymentRequests.cshtml b/BTCPayServer/Views/UIPaymentRequest/GetPaymentRequests.cshtml index 28e75a21c..eab74ac30 100644 --- a/BTCPayServer/Views/UIPaymentRequest/GetPaymentRequests.cshtml +++ b/BTCPayServer/Views/UIPaymentRequest/GetPaymentRequests.cshtml @@ -111,7 +111,7 @@
- View + View -
- @if (Model.IsPending && !Model.Archived && Model.ExpiryDate.HasValue) - { - - } - -
-
-
-
-