mirror of
https://github.com/aljazceru/btcpayserver.git
synced 2025-12-17 05:54:26 +01:00
Refactor access to the ViewModel of the MainLayout (#6970)
This commit is contained in:
@@ -2,6 +2,7 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using BTCPayServer.Abstractions.Models;
|
||||
using Microsoft.AspNetCore.Html;
|
||||
using Microsoft.AspNetCore.Mvc.ViewFeatures;
|
||||
|
||||
@@ -35,16 +36,28 @@ namespace BTCPayServer.Abstractions.Extensions
|
||||
SetActivePage(viewData, activePage.ToString(), activePage.GetType().ToString(), title, activeId);
|
||||
}
|
||||
|
||||
public static void SetActivePage(this ViewDataDictionary viewData, string activePage, string category, string title = null, string activeId = null)
|
||||
public static void SetTitle(this ViewDataDictionary viewData, string title) => viewData["Title"] = title;
|
||||
public static string GetTitle(this ViewDataDictionary viewData) => viewData["Title"]?.ToString();
|
||||
|
||||
public static void SetLayoutModel(this ViewDataDictionary viewData, LayoutModel model)
|
||||
{
|
||||
// Page Title
|
||||
viewData["Title"] = title ?? activePage;
|
||||
viewData["Title"] = model.Title ?? model.MenuItemId;
|
||||
// Navigation
|
||||
viewData[ACTIVE_PAGE_KEY] = activePage;
|
||||
viewData[ACTIVE_ID_KEY] = activeId;
|
||||
SetActiveCategory(viewData, category);
|
||||
viewData[ACTIVE_PAGE_KEY] = model.MenuItemId;
|
||||
viewData[ACTIVE_ID_KEY] = model.SubMenuItemId;
|
||||
SetActiveCategory(viewData, model.ActiveCategory);
|
||||
}
|
||||
|
||||
public static bool IsCategory(this ViewDataDictionary viewData, string category) =>
|
||||
viewData.TryGetValue(ACTIVE_CATEGORY_KEY, out var k) && category == k as string;
|
||||
|
||||
public static bool IsCategory(this ViewDataDictionary viewData, WellKnownCategories category) =>
|
||||
IsCategory(viewData, LayoutModel.Map(category));
|
||||
|
||||
public static void SetActivePage(this ViewDataDictionary viewData, string activePage, string category, string title = null, string activeId = null)
|
||||
=> viewData.SetLayoutModel(new(activePage, title){ SubMenuItemId = activeId, ActiveCategory = category } );
|
||||
|
||||
public static void SetActiveCategory<T>(this ViewDataDictionary viewData, T activeCategory)
|
||||
{
|
||||
SetActiveCategory(viewData, activeCategory.ToString());
|
||||
@@ -55,6 +68,7 @@ namespace BTCPayServer.Abstractions.Extensions
|
||||
viewData[ACTIVE_CATEGORY_KEY] = activeCategory;
|
||||
}
|
||||
|
||||
[Obsolete("Use IsCategory instead")]
|
||||
public static bool IsCategoryActive(this ViewDataDictionary viewData, string category, object id = null)
|
||||
{
|
||||
if (!viewData.ContainsKey(ACTIVE_CATEGORY_KEY)) return false;
|
||||
@@ -65,6 +79,7 @@ namespace BTCPayServer.Abstractions.Extensions
|
||||
return categoryMatch && idMatch;
|
||||
}
|
||||
|
||||
[Obsolete("Use IsCategory instead")]
|
||||
public static bool IsCategoryActive<T>(this ViewDataDictionary viewData, T category, object id = null)
|
||||
{
|
||||
return IsCategoryActive(viewData, category.ToString(), id);
|
||||
@@ -98,17 +113,20 @@ namespace BTCPayServer.Abstractions.Extensions
|
||||
return IsCategoryActive(viewData, category, id) ? ACTIVE_CLASS : null;
|
||||
}
|
||||
|
||||
[Obsolete("Use the tagHelper layout-menu-item instead")]
|
||||
public static string ActivePageClass<T>(this ViewDataDictionary viewData, T page, object id = null)
|
||||
where T : IConvertible
|
||||
{
|
||||
return ActivePageClass(viewData, page.ToString(), page.GetType().ToString(), id);
|
||||
}
|
||||
|
||||
[Obsolete("Use the tagHelper layout-menu-item instead")]
|
||||
public static string ActivePageClass(this ViewDataDictionary viewData, string page, string category, object id = null)
|
||||
{
|
||||
return IsPageActive(viewData, page, category, id) ? ACTIVE_CLASS : null;
|
||||
}
|
||||
|
||||
[Obsolete("Use the tagHelper layout-menu-item instead")]
|
||||
public static string ActivePageClass<T>(this ViewDataDictionary viewData, IEnumerable<T> pages, object id = null) where T : IConvertible
|
||||
{
|
||||
return IsPageActive(viewData, pages, id) ? ACTIVE_CLASS : null;
|
||||
|
||||
36
BTCPayServer.Abstractions/Models/LayoutModel.cs
Normal file
36
BTCPayServer.Abstractions/Models/LayoutModel.cs
Normal file
@@ -0,0 +1,36 @@
|
||||
#nullable enable
|
||||
using NBitcoin;
|
||||
|
||||
namespace BTCPayServer.Abstractions.Models;
|
||||
|
||||
public record WellKnownCategories(string CategoryId)
|
||||
{
|
||||
public static readonly WellKnownCategories Server = new("BTCPayServer.Views.Server.ServerNavPages");
|
||||
public static readonly WellKnownCategories Store = new("BTCPayServer.Views.Stores.StoreNavPages");
|
||||
public static readonly WellKnownCategories Wallet = new("BTCPayServer.Views.Wallets.WalletsNavPages");
|
||||
public static WellKnownCategories ForWallet(string cryptoCode) => new(
|
||||
$"BTCPayServer.Views.Wallets.WalletsNavPages.{cryptoCode.ToUpperInvariant()}");
|
||||
public static WellKnownCategories ForLightning(string cryptoCode) => new(
|
||||
$"LightningPages.{cryptoCode.ToUpperInvariant()}");
|
||||
}
|
||||
|
||||
public class LayoutModel(string menuItemId, string? title = null)
|
||||
{
|
||||
public static string Map(WellKnownCategories c) => c.CategoryId;
|
||||
|
||||
public LayoutModel SetCategory(WellKnownCategories category)
|
||||
{
|
||||
ActiveCategory = Map(category);
|
||||
return this;
|
||||
}
|
||||
public LayoutModel SetCategory(string category)
|
||||
{
|
||||
ActiveCategory = category;
|
||||
return this;
|
||||
}
|
||||
|
||||
public string? ActiveCategory { get; set; }
|
||||
public string MenuItemId { get; set; } = menuItemId;
|
||||
public string? Title { get; set; } = title;
|
||||
public string? SubMenuItemId { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
using Microsoft.AspNetCore.Mvc.Rendering;
|
||||
using Microsoft.AspNetCore.Mvc.ViewFeatures;
|
||||
using Microsoft.AspNetCore.Razor.TagHelpers;
|
||||
|
||||
namespace BTCPayServer.Abstractions.TagHelpers;
|
||||
|
||||
[HtmlTargetElement(Attributes = "[layout-menu-item]")]
|
||||
public class LayoutMenuItemTagHelper : TagHelper
|
||||
{
|
||||
private const string ActivePageKey = "ActivePage";
|
||||
private const string ActiveClass = "active";
|
||||
[ViewContext]
|
||||
public ViewContext ViewContext { get; set; }
|
||||
public string LayoutMenuItem { get; set; }
|
||||
public override void Process(TagHelperContext context, TagHelperOutput output)
|
||||
{
|
||||
output.Attributes.Add("id", $"menu-item-{LayoutMenuItem}");
|
||||
var viewData = ViewContext.ViewData;
|
||||
var match = viewData.ContainsKey(ActivePageKey) && viewData[ActivePageKey]?.ToString() == LayoutMenuItem;
|
||||
output.Attributes.Add("class", $"menu-item nav-link {(match ? ActiveClass : "")}");
|
||||
}
|
||||
}
|
||||
@@ -91,7 +91,7 @@ public class MultisigTests : UnitTestBase
|
||||
s.TestLogs.LogInformation($"Multisig wallet setup: {multisigDerivationScheme}");
|
||||
|
||||
// fetch address from receive page
|
||||
await s.Page.ClickAsync("#WalletNav-Receive");
|
||||
await s.GoToWallet(navPages: WalletsNavPages.Receive);
|
||||
|
||||
var addressElement = s.Page.Locator("#Address");
|
||||
await addressElement.ClickAsync();
|
||||
@@ -101,7 +101,7 @@ public class MultisigTests : UnitTestBase
|
||||
await s.Page.ClickAsync("#CancelWizard");
|
||||
|
||||
// we are creating a pending transaction
|
||||
await s.Page.ClickAsync("#WalletNav-Send");
|
||||
await s.GoToWallet(navPages: WalletsNavPages.Send);
|
||||
await s.Page.FillAsync("#Outputs_0__DestinationAddress", address);
|
||||
var amount = "0.1";
|
||||
await s.Page.FillAsync("#Outputs_0__Amount", amount);
|
||||
@@ -127,7 +127,7 @@ public class MultisigTests : UnitTestBase
|
||||
Assert.False(await s.Page.Locator("//a[text()='Broadcast']").IsVisibleAsync());
|
||||
|
||||
// Abort pending transaction flow
|
||||
await s.Page.ClickAsync("#WalletNav-Send");
|
||||
await s.GoToWallet(navPages: WalletsNavPages.Send);
|
||||
await s.Page.FillAsync("#Outputs_0__DestinationAddress", address);
|
||||
await s.Page.FillAsync("#Outputs_0__Amount", "0.2");
|
||||
await s.Page.ClickAsync("#CreatePendingTransaction");
|
||||
|
||||
@@ -148,7 +148,7 @@ fruit tea:
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Integration", "Integration")]
|
||||
[Trait("Playwright", "Playwright")]
|
||||
public async Task CanExportInvoicesWithMetadata()
|
||||
{
|
||||
await using var s = CreatePlaywrightTester();
|
||||
|
||||
@@ -47,7 +47,7 @@ namespace BTCPayServer.Tests
|
||||
var psbt = await ExtractPSBT(s);
|
||||
|
||||
await s.GoToStore(hot.storeId);
|
||||
await s.GoToWallet(navPages: Views.Wallets.WalletsNavPages.PSBT);
|
||||
await s.GoToWallet(s.WalletId, navPages: Views.Wallets.WalletsNavPages.PSBT);
|
||||
await s.Page.Locator("[name='PSBT']").FillAsync(psbt);
|
||||
await s.Page.ClickAsync("#Decode");
|
||||
await s.Page.ClickAsync("#SignTransaction");
|
||||
@@ -72,7 +72,7 @@ namespace BTCPayServer.Tests
|
||||
var skeletonPSBT = psbtParsed;
|
||||
|
||||
await s.GoToStore(cold.storeId);
|
||||
await s.GoToWallet(navPages: Views.Wallets.WalletsNavPages.PSBT);
|
||||
await s.GoToWallet(s.WalletId, navPages: Views.Wallets.WalletsNavPages.PSBT);
|
||||
await s.Page.Locator("[name='PSBT']").FillAsync(skeletonPSBT.ToBase64());
|
||||
await s.Page.ClickAsync("#Decode");
|
||||
await s.Page.ClickAsync("#SignTransaction");
|
||||
@@ -96,7 +96,7 @@ namespace BTCPayServer.Tests
|
||||
|
||||
// Let's if we can combine the updated psbt (which has hdkeys, but no sig)
|
||||
// with the signed psbt (which has sig, but no hdkeys)
|
||||
await s.GoToWallet(navPages: Views.Wallets.WalletsNavPages.PSBT);
|
||||
await s.GoToWallet(s.WalletId, navPages: Views.Wallets.WalletsNavPages.PSBT);
|
||||
await s.Page.Locator("[name='PSBT']").FillAsync(psbtParsed.ToBase64());
|
||||
await s.Page.ClickAsync("#Decode");
|
||||
await s.Page.ClickAsync("#PSBTOptionsAdvancedHeader");
|
||||
|
||||
@@ -7,21 +7,17 @@ using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
using BTCPayServer.Abstractions.Extensions;
|
||||
using BTCPayServer.Abstractions.Models;
|
||||
using BTCPayServer.Blazor.VaultBridge.Elements;
|
||||
using BTCPayServer.Client.Models;
|
||||
using BTCPayServer.Data;
|
||||
using BTCPayServer.Lightning;
|
||||
using BTCPayServer.Lightning.CLightning;
|
||||
using BTCPayServer.Views.Manage;
|
||||
using BTCPayServer.Views.Server;
|
||||
using BTCPayServer.Views.Stores;
|
||||
using BTCPayServer.Views.Wallets;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Playwright;
|
||||
using NBitcoin;
|
||||
using NBitcoin.RPC;
|
||||
using OpenQA.Selenium;
|
||||
using Xunit;
|
||||
|
||||
namespace BTCPayServer.Tests
|
||||
@@ -52,7 +48,8 @@ namespace BTCPayServer.Tests
|
||||
Browser = await playwright.Chromium.LaunchAsync(new BrowserTypeLaunchOptions
|
||||
{
|
||||
Headless = Server.PayTester.InContainer,
|
||||
SlowMo = 0 // 50 if you want to slow down
|
||||
SlowMo = 0, // 50 if you want to slow down
|
||||
Args = ["--disable-frame-rate-limit"] // Fix slowness on linux (https://github.com/microsoft/playwright/issues/34625#issuecomment-2822015672)
|
||||
});
|
||||
var context = await Browser.NewContextAsync();
|
||||
Page = await context.NewPageAsync();
|
||||
@@ -67,7 +64,7 @@ namespace BTCPayServer.Tests
|
||||
{
|
||||
if (storeId is null)
|
||||
{
|
||||
await Page.Locator("#StoreNav-Invoices").ClickAsync();
|
||||
await Page.Locator("#menu-item-Invoices").ClickAsync();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -117,21 +114,51 @@ namespace BTCPayServer.Tests
|
||||
await GoToUrl($"/i/{invoiceId}");
|
||||
}
|
||||
|
||||
public async Task GoToWallet(WalletId walletId = null, WalletsNavPages navPages = WalletsNavPages.Send)
|
||||
public async Task GoToWallet(WalletId walletId = null, WalletsNavPages? navPages = null)
|
||||
{
|
||||
var walletPage = GetWalletIdFromUrl();
|
||||
// If null, we try to go to the wallet of the current page
|
||||
if (walletId is null)
|
||||
{
|
||||
if (walletPage is not null)
|
||||
walletId = WalletId.Parse(walletPage);
|
||||
walletId ??= WalletId;
|
||||
if (walletId is not null && walletId.ToString() != walletPage)
|
||||
await GoToUrl($"wallets/{walletId}");
|
||||
if (navPages == WalletsNavPages.PSBT)
|
||||
}
|
||||
// If not, we browse to the wallet before going to subpages
|
||||
else
|
||||
{
|
||||
await Page.Locator("#WalletNav-Send").ClickAsync();
|
||||
await GoToUrl($"wallets/{walletId}");
|
||||
}
|
||||
var cryptoCode = walletId?.CryptoCode ?? "BTC";
|
||||
if (navPages is null)
|
||||
{
|
||||
await Page.GetByTestId("Wallet-" + cryptoCode).Locator("a").ClickAsync();
|
||||
}
|
||||
else if (navPages == WalletsNavPages.PSBT)
|
||||
{
|
||||
await Page.Locator($"#menu-item-Send-{cryptoCode}").ClickAsync();
|
||||
await Page.Locator("#PSBT").ClickAsync();
|
||||
}
|
||||
else if (navPages != WalletsNavPages.Transactions)
|
||||
else
|
||||
{
|
||||
await Page.Locator($"#WalletNav-{navPages}").ClickAsync();
|
||||
await Page.Locator($"#menu-item-{navPages}-{cryptoCode}").ClickAsync();
|
||||
}
|
||||
}
|
||||
|
||||
private string GetWalletIdFromUrl()
|
||||
{
|
||||
var m = Regex.Match(Page.Url, "wallets/([^/]+)");
|
||||
if (m.Success)
|
||||
return m.Groups[1].Value;
|
||||
|
||||
m = Regex.Match(Page.Url, "([^/]+)/onchain/([^/]+)");
|
||||
if (m.Success)
|
||||
return new WalletId(m.Groups[1].Value, m.Groups[2].Value).ToString();
|
||||
return null;
|
||||
}
|
||||
|
||||
public async Task<ILocator> FindAlertMessage(StatusMessageModel.StatusSeverity severity = StatusMessageModel.StatusSeverity.Success, string partialText = null)
|
||||
{
|
||||
var locator = await FindAlertMessage(new[] { severity });
|
||||
@@ -219,7 +246,7 @@ namespace BTCPayServer.Tests
|
||||
Assert.Equal("Recommendation (Kraken)", selectedOption?.Trim());
|
||||
await Page.Locator("#PreferredExchange").SelectOptionAsync(new SelectOptionValue { Label = preferredExchange });
|
||||
await Page.ClickAsync("#Create");
|
||||
await Page.ClickAsync("#StoreNav-General");
|
||||
await GoToStore(StoreNavPages.General);
|
||||
var storeId = await Page.InputValueAsync("#Id");
|
||||
if (keepId)
|
||||
StoreId = storeId;
|
||||
@@ -232,7 +259,8 @@ namespace BTCPayServer.Tests
|
||||
var isImport = !string.IsNullOrEmpty(seed);
|
||||
await GoToWalletSettings(cryptoCode);
|
||||
// Replace previous wallet case
|
||||
if (await Page.Locator("#ActionsDropdownToggle").IsVisibleAsync())
|
||||
var isSettings = Page.Url.EndsWith("/settings");
|
||||
if (isSettings)
|
||||
{
|
||||
TestLogs.LogInformation($"Replacing the wallet");
|
||||
await Page.ClickAsync("#ActionsDropdownToggle");
|
||||
@@ -296,7 +324,7 @@ namespace BTCPayServer.Tests
|
||||
}
|
||||
public async Task Logout()
|
||||
{
|
||||
await Page.Locator("#Nav-Account").ClickAsync();
|
||||
await Page.Locator("#menu-item-Account").ClickAsync();
|
||||
await Page.Locator("#Nav-Logout").ClickAsync();
|
||||
}
|
||||
|
||||
@@ -330,24 +358,24 @@ namespace BTCPayServer.Tests
|
||||
|
||||
public async Task GoToProfile(ManageNavPages navPages = ManageNavPages.Index)
|
||||
{
|
||||
await Page.ClickAsync("#Nav-Account");
|
||||
await Page.ClickAsync("#menu-item-Account");
|
||||
await Page.ClickAsync("#Nav-ManageAccount");
|
||||
if (navPages != ManageNavPages.Index)
|
||||
{
|
||||
await Page.ClickAsync($"#SectionNav-{navPages.ToString()}");
|
||||
await Page.ClickAsync($"#menu-item-{navPages.ToString()}");
|
||||
}
|
||||
}
|
||||
|
||||
public async Task GoToServer(ServerNavPages navPages = ServerNavPages.Policies)
|
||||
{
|
||||
await Page.ClickAsync("#Nav-ServerSettings");
|
||||
await Page.ClickAsync("#menu-item-Policies");
|
||||
if (navPages != ServerNavPages.Policies)
|
||||
{
|
||||
await Page.ClickAsync($"#SectionNav-{navPages}");
|
||||
await Page.ClickAsync($"#menu-item-{navPages}");
|
||||
}
|
||||
}
|
||||
|
||||
public async Task ClickOnAllSectionLinks(string sectionSelector = "#SectionNav")
|
||||
public async Task ClickOnAllSectionLinks(string sectionSelector = "#menu-item")
|
||||
{
|
||||
List<string> links = [];
|
||||
foreach (var locator in await Page.Locator($"{sectionSelector} .nav-link").AllAsync())
|
||||
@@ -441,11 +469,11 @@ namespace BTCPayServer.Tests
|
||||
|
||||
public async Task GoToLightningSettings(string cryptoCode = "BTC")
|
||||
{
|
||||
await Page.ClickAsync($"#StoreNav-Lightning{cryptoCode}");
|
||||
await Page.GetByTestId("Lightning-" + cryptoCode).ClickAsync();
|
||||
// if Lightning is already set up we need to navigate to the settings
|
||||
if ((await Page.ContentAsync()).Contains("id=\"StoreNav-LightningSettings\""))
|
||||
if ((await Page.ContentAsync()).Contains($"id=\"menu-item-LightningSettings-{cryptoCode}\""))
|
||||
{
|
||||
await Page.ClickAsync("#StoreNav-LightningSettings");
|
||||
await Page.ClickAsync($"#menu-item-LightningSettings-{cryptoCode}");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -456,8 +484,8 @@ namespace BTCPayServer.Tests
|
||||
|
||||
public async Task GoToWalletSettings(string cryptoCode = "BTC")
|
||||
{
|
||||
await Page.ClickAsync($"#StoreNav-Wallet{cryptoCode}");
|
||||
var walletNavSettings = Page.Locator("#WalletNav-Settings");
|
||||
await Page.GetByTestId("Wallet-" + cryptoCode).Locator("a").ClickAsync();
|
||||
var walletNavSettings = Page.Locator($"#menu-item-Settings-{cryptoCode}");
|
||||
if (await walletNavSettings.CountAsync() > 0)
|
||||
await walletNavSettings.ClickAsync();
|
||||
}
|
||||
@@ -476,9 +504,9 @@ namespace BTCPayServer.Tests
|
||||
if (WalletId != null)
|
||||
WalletId = new WalletId(storeId, WalletId.CryptoCode);
|
||||
if (storeNavPage != StoreNavPages.General)
|
||||
await Page.Locator($"#StoreNav-{StoreNavPages.General}").ClickAsync();
|
||||
await Page.Locator($"#menu-item-{StoreNavPages.General}").ClickAsync();
|
||||
}
|
||||
await Page.Locator($"#StoreNav-{storeNavPage}").ClickAsync();
|
||||
await Page.Locator($"#menu-item-{storeNavPage}").ClickAsync();
|
||||
}
|
||||
public async Task ClickCancel()
|
||||
{
|
||||
@@ -561,7 +589,7 @@ namespace BTCPayServer.Tests
|
||||
{
|
||||
if (string.IsNullOrEmpty(name))
|
||||
name = $"{type}-{Guid.NewGuid().ToString()[..14]}";
|
||||
await Page.Locator($"#StoreNav-Create{type}").ClickAsync();
|
||||
await Page.Locator($"#menu-item-CreateApp-{type}").ClickAsync();
|
||||
await Page.Locator("[name='AppName']").FillAsync(name);
|
||||
await ClickPagePrimary();
|
||||
await FindAlertMessage(partialText: "App successfully created");
|
||||
|
||||
@@ -71,10 +71,7 @@ namespace BTCPayServer.Tests
|
||||
await s.InitializeBTCPayServer();
|
||||
// Point Of Sale
|
||||
var appName = $"PoS-{Guid.NewGuid().ToString()[..21]}";
|
||||
await s.Page.ClickAsync("#StoreNav-CreatePointOfSale");
|
||||
await s.Page.FillAsync("#AppName", appName);
|
||||
await s.ClickPagePrimary();
|
||||
await s.FindAlertMessage(partialText: "App successfully created");
|
||||
await s.CreateApp("PointOfSale", appName);
|
||||
await s.Page.SelectOptionAsync("#FormId", "Email");
|
||||
await s.ClickPagePrimary();
|
||||
await s.FindAlertMessage(partialText: "App updated");
|
||||
@@ -94,7 +91,7 @@ namespace BTCPayServer.Tests
|
||||
await s.GoToUrl($"/invoices/{invoiceId}/");
|
||||
Assert.Contains("aa@aa.com", await s.Page.ContentAsync());
|
||||
// Payment Request
|
||||
await s.Page.ClickAsync("#StoreNav-PaymentRequests");
|
||||
await s.Page.ClickAsync("#menu-item-PaymentRequests");
|
||||
await s.ClickPagePrimary();
|
||||
await s.Page.FillAsync("#Title", "Pay123");
|
||||
await s.Page.FillAsync("#Amount", "700");
|
||||
@@ -142,9 +139,11 @@ namespace BTCPayServer.Tests
|
||||
await s.GoToHome();
|
||||
await s.GoToStore();
|
||||
await s.GoToStore(StoreNavPages.Forms);
|
||||
await s.Page.WaitForLoadStateAsync();
|
||||
Assert.Contains("Custom Form 1", await s.Page.ContentAsync());
|
||||
await s.Page.GetByRole(AriaRole.Link, new() { Name = "Remove" }).ClickAsync();
|
||||
await s.ConfirmDeleteModal();
|
||||
await s.Page.WaitForLoadStateAsync();
|
||||
Assert.DoesNotContain("Custom Form 1", await s.Page.ContentAsync());
|
||||
await s.ClickPagePrimary();
|
||||
await s.Page.FillAsync("[name='Name']", "Custom Form 2");
|
||||
@@ -169,7 +168,7 @@ namespace BTCPayServer.Tests
|
||||
await s.ClickPagePrimary();
|
||||
await s.GoToStore(StoreNavPages.Forms);
|
||||
Assert.Contains("Custom Form 3", await s.Page.ContentAsync());
|
||||
await s.Page.ClickAsync("#StoreNav-PaymentRequests");
|
||||
await s.Page.ClickAsync("#menu-item-PaymentRequests");
|
||||
await s.ClickPagePrimary();
|
||||
var selectOptions = await s.Page.Locator("#FormId >> option").CountAsync();
|
||||
Assert.Equal(4, selectOptions);
|
||||
@@ -584,7 +583,7 @@ namespace BTCPayServer.Tests
|
||||
Assert.Equal("Can Use Store?" ,await s.Page.InputValueAsync("#Name"));
|
||||
await s.Page.FillAsync("#Name", "Just changed it!");
|
||||
await s.Page.ClickAsync("#Create");
|
||||
await s.Page.ClickAsync("#StoreNav-General");
|
||||
await s.GoToStore();
|
||||
var newStoreId = await s.Page.InputValueAsync("#Id");
|
||||
Assert.NotEqual(newStoreId, s.StoreId);
|
||||
|
||||
@@ -875,8 +874,7 @@ namespace BTCPayServer.Tests
|
||||
await s.GenerateWallet(cryptoCode, "", true);
|
||||
|
||||
//let's test quickly the wallet send page
|
||||
await s.Page.ClickAsync($"#StoreNav-Wallet{cryptoCode}");
|
||||
await s.Page.ClickAsync("#WalletNav-Send");
|
||||
await s.GoToWallet(navPages: WalletsNavPages.Send);
|
||||
//you cannot use the Sign with NBX option without saving private keys when generating the wallet.
|
||||
Assert.DoesNotContain("nbx-seed", await s.Page.ContentAsync());
|
||||
Assert.Equal(0, await s.Page.Locator("#GoBack").CountAsync());
|
||||
@@ -884,7 +882,7 @@ namespace BTCPayServer.Tests
|
||||
await s.Page.WaitForSelectorAsync("text=Destination Address field is required");
|
||||
Assert.Equal(0, await s.Page.Locator("#GoBack").CountAsync());
|
||||
await s.Page.ClickAsync("#CancelWizard");
|
||||
await s.Page.ClickAsync("#WalletNav-Receive");
|
||||
await s.GoToWallet(navPages: WalletsNavPages.Receive);
|
||||
|
||||
//generate a receiving address
|
||||
await s.Page.WaitForSelectorAsync("#address-tab .qr-container");
|
||||
@@ -1038,8 +1036,7 @@ namespace BTCPayServer.Tests
|
||||
// Assert that the added label is associated with the transaction
|
||||
await wt.AssertHasLabels("tx-label");
|
||||
|
||||
await s.Page.ClickAsync($"#StoreNav-Wallet{cryptoCode}");
|
||||
await s.Page.ClickAsync("#WalletNav-Send");
|
||||
await s.GoToWallet(navPages: WalletsNavPages.Send);
|
||||
|
||||
var jack = new Key().PubKey.Hash.GetAddress(Network.RegTest);
|
||||
await ws.FillAddress(jack);
|
||||
@@ -1090,7 +1087,7 @@ namespace BTCPayServer.Tests
|
||||
Assert.Equal(settingsUri.ToString(), s.Page.Url);
|
||||
|
||||
// Once more, test the cancel link of the wallet send page leads back to the previous page
|
||||
await s.Page.ClickAsync("#WalletNav-Send");
|
||||
await s.GoToWallet(navPages: WalletsNavPages.Send);
|
||||
cancelUrl = await s.Page.Locator("#CancelWizard").GetAttributeAsync("href");
|
||||
Assert.EndsWith(settingsUri.AbsolutePath, cancelUrl);
|
||||
// no previous page in the wizard, hence no back button
|
||||
@@ -1230,7 +1227,7 @@ namespace BTCPayServer.Tests
|
||||
|
||||
// Create a payment request
|
||||
await s.GoToStore();
|
||||
await s.Page.ClickAsync("#StoreNav-PaymentRequests");
|
||||
await s.Page.ClickAsync("#menu-item-PaymentRequests");
|
||||
await s.ClickPagePrimary();
|
||||
await s.Page.FillAsync("#Title", "Test Payment Request");
|
||||
await s.Page.FillAsync("#Amount", "0.1");
|
||||
@@ -1272,7 +1269,7 @@ namespace BTCPayServer.Tests
|
||||
await s.Page.WaitForLoadStateAsync();
|
||||
|
||||
await s.GoToStore();
|
||||
await s.Page.ClickAsync("#StoreNav-PaymentRequests");
|
||||
await s.Page.ClickAsync("#menu-item-PaymentRequests");
|
||||
await s.Page.WaitForLoadStateAsync();
|
||||
|
||||
var opening2 = s.Page.Context.WaitForPageAsync();
|
||||
@@ -1288,7 +1285,7 @@ namespace BTCPayServer.Tests
|
||||
}
|
||||
|
||||
await s.GoToStore();
|
||||
await s.Page.ClickAsync("#StoreNav-PaymentRequests");
|
||||
await s.Page.ClickAsync("#menu-item-PaymentRequests");
|
||||
await s.Page.WaitForLoadStateAsync();
|
||||
|
||||
var listContent = await s.Page.ContentAsync();
|
||||
@@ -1349,14 +1346,14 @@ namespace BTCPayServer.Tests
|
||||
Assert.Equal("1", await s.Page.Locator("#NotificationsBadge").TextContentAsync());
|
||||
});
|
||||
|
||||
await s.Page.Locator("#NotificationsHandle").ClickAsync();
|
||||
Assert.Matches($"New user {unapproved.RegisterDetails.Email} requires approval", await s.Page.Locator("#NotificationsList .notification").TextContentAsync());
|
||||
await s.Page.Locator("#NotificationsMarkAllAsSeen").ClickAsync();
|
||||
await s.Page.ClickAsync("#NotificationsHandle");
|
||||
await s.Page.Locator($"#NotificationsList .notification:has-text('New user {unapproved.RegisterDetails.Email} requires approval')").WaitForAsync();
|
||||
await s.Page.ClickAsync("#NotificationsMarkAllAsSeen");
|
||||
|
||||
await s.GoToServer(ServerNavPages.Policies);
|
||||
Assert.True(await s.Page.Locator("#EnableRegistration").IsCheckedAsync());
|
||||
Assert.True(await s.Page.Locator("#RequiresUserApproval").IsCheckedAsync());
|
||||
await s.Page.Locator("#RequiresUserApproval").ClickAsync();
|
||||
await s.Page.ClickAsync("#RequiresUserApproval");
|
||||
await s.ClickPagePrimary();
|
||||
await s.FindAlertMessage(partialText: "Policies updated successfully");
|
||||
Assert.False(await s.Page.Locator("#RequiresUserApproval").IsCheckedAsync());
|
||||
@@ -1702,7 +1699,7 @@ namespace BTCPayServer.Tests
|
||||
await s.Page.GetAttributeAsync("#AccountKeys_0__AccountKeyPath", "value"));
|
||||
|
||||
// Transactions list is empty
|
||||
await s.Page.ClickAsync($"#StoreNav-Wallet{cryptoCode}");
|
||||
await s.GoToWallet();
|
||||
await s.Page.WaitForSelectorAsync("#WalletTransactions[data-loaded='true']");
|
||||
Assert.Contains("There are no transactions yet", await s.Page.Locator("#WalletTransactions").TextContentAsync());
|
||||
}
|
||||
@@ -1829,7 +1826,7 @@ namespace BTCPayServer.Tests
|
||||
];
|
||||
|
||||
await s.Server.ExplorerNode.GenerateAsync(1);
|
||||
await s.GoToWallet(walletId);
|
||||
await s.GoToWallet(walletId, WalletsNavPages.Send);
|
||||
await s.Page.ClickAsync("#toggleInputSelection");
|
||||
|
||||
var input = s.Page.Locator("input[placeholder^='Filter']");
|
||||
@@ -1885,11 +1882,11 @@ namespace BTCPayServer.Tests
|
||||
(string storeName, _) = await s.CreateNewStore();
|
||||
|
||||
// Check status in navigation
|
||||
await s.Page.Locator("#StoreNav-LightningBTC .btcpay-status--pending").WaitForAsync();
|
||||
await s.Page.Locator("#menu-item-LightningSettings-BTC .btcpay-status--pending").WaitForAsync();
|
||||
|
||||
// Set up LN node
|
||||
await s.AddLightningNode();
|
||||
await s.Page.Locator("#StoreNav-LightningBTC .btcpay-status--enabled").WaitForAsync();
|
||||
await s.Page.Locator("#menu-item-Lightning-BTC .btcpay-status--enabled").WaitForAsync();
|
||||
|
||||
// Check public node info for availability
|
||||
var opening = s.Page.Context.WaitForPageAsync();
|
||||
@@ -1915,7 +1912,7 @@ namespace BTCPayServer.Tests
|
||||
await s.FindAlertMessage(partialText: "BTC Lightning node updated.");
|
||||
|
||||
// Check offline state is communicated in nav item
|
||||
await s.Page.Locator("#StoreNav-LightningBTC .btcpay-status--disabled").WaitForAsync();
|
||||
await s.Page.Locator("#menu-item-Lightning-BTC .btcpay-status--disabled").WaitForAsync();
|
||||
|
||||
// Check public node info for availability
|
||||
opening = s.Page.Context.WaitForPageAsync();
|
||||
@@ -2098,8 +2095,9 @@ namespace BTCPayServer.Tests
|
||||
await s.Page.SetCheckedAsync("#AutoApproveClaims", true);
|
||||
await s.ClickPagePrimary();
|
||||
|
||||
var o = s.Page.Context.WaitForPageAsync();
|
||||
await s.Page.ClickAsync("text=View");
|
||||
var newPage = await s.Page.Context.WaitForPageAsync();
|
||||
var newPage = await o;
|
||||
|
||||
var address = await s.Server.ExplorerNode.GetNewAddressAsync();
|
||||
await newPage.FillAsync("#Destination", address.ToString());
|
||||
@@ -2198,7 +2196,7 @@ namespace BTCPayServer.Tests
|
||||
// The delivery is done asynchronously, so small wait here
|
||||
await Task.Delay(500);
|
||||
await s.GoToStore();
|
||||
await s.Page.ClickAsync("#StoreNav-Webhooks");
|
||||
await s.GoToStore(StoreNavPages.Webhooks);
|
||||
await s.Page.ClickAsync("text=Modify");
|
||||
var redeliverElements = await s.Page.Locator("button.redeliver").AllAsync();
|
||||
|
||||
@@ -2235,8 +2233,9 @@ namespace BTCPayServer.Tests
|
||||
|
||||
private static async Task CanBrowseContentAsync(PlaywrightTester s)
|
||||
{
|
||||
var newPageDoing = s.Page.Context.WaitForPageAsync();
|
||||
await s.Page.ClickAsync(".delivery-content");
|
||||
var newPage = await s.Page.Context.WaitForPageAsync();
|
||||
var newPage = await newPageDoing;
|
||||
var bodyText = await newPage.Locator("body").TextContentAsync();
|
||||
JObject.Parse(bodyText);
|
||||
await newPage.CloseAsync();
|
||||
|
||||
@@ -222,7 +222,7 @@ retry:
|
||||
Assert.Equal("Recommendation (Kraken)", rateSource.SelectedOption.Text);
|
||||
rateSource.SelectByText("CoinGecko");
|
||||
Driver.WaitForElement(By.Id("Create")).Click();
|
||||
Driver.FindElement(By.Id("StoreNav-General")).Click();
|
||||
Driver.FindElement(By.Id("menu-item-General")).Click();
|
||||
var storeId = Driver.WaitForElement(By.Id("Id")).GetAttribute("value");
|
||||
if (keepId)
|
||||
StoreId = storeId;
|
||||
@@ -415,7 +415,7 @@ retry:
|
||||
{
|
||||
if (!Driver.PageSource.Contains("id=\"Nav-Logout\""))
|
||||
GoToUrl("/account");
|
||||
Driver.FindElement(By.Id("Nav-Account")).Click();
|
||||
Driver.FindElement(By.Id("menu-item-Account")).Click();
|
||||
Driver.FindElement(By.Id("Nav-Logout")).Click();
|
||||
}
|
||||
|
||||
@@ -447,27 +447,27 @@ retry:
|
||||
|
||||
if (storeNavPage != StoreNavPages.General)
|
||||
{
|
||||
Driver.FindElement(By.Id($"StoreNav-{StoreNavPages.General}")).Click();
|
||||
Driver.FindElement(By.Id($"menu-item-{StoreNavPages.General}")).Click();
|
||||
}
|
||||
Driver.FindElement(By.Id($"StoreNav-{storeNavPage}")).Click();
|
||||
Driver.FindElement(By.Id($"menu-item-{storeNavPage}")).Click();
|
||||
}
|
||||
|
||||
public void GoToWalletSettings(string cryptoCode = "BTC")
|
||||
{
|
||||
Driver.FindElement(By.Id($"StoreNav-Wallet{cryptoCode}")).Click();
|
||||
if (Driver.PageSource.Contains("id=\"WalletNav-Settings\""))
|
||||
Driver.FindElement(By.CssSelector($"[data-testid=\"Wallet-{cryptoCode}\"] a")).Click();
|
||||
if (Driver.PageSource.Contains($"id=\"menu-item-Settings-{cryptoCode}\""))
|
||||
{
|
||||
Driver.FindElement(By.Id("WalletNav-Settings")).Click();
|
||||
Driver.FindElement(By.Id($"menu-item-Settings-{cryptoCode}")).Click();
|
||||
}
|
||||
}
|
||||
|
||||
public void GoToLightningSettings(string cryptoCode = "BTC")
|
||||
{
|
||||
Driver.FindElement(By.Id($"StoreNav-Lightning{cryptoCode}")).Click();
|
||||
Driver.FindElement(By.CssSelector($"[data-testid=\"Lightning-{cryptoCode}\"]")).Click();
|
||||
// if Lightning is already set up we need to navigate to the settings
|
||||
if (Driver.PageSource.Contains("id=\"StoreNav-LightningSettings\""))
|
||||
if (Driver.PageSource.Contains($"id=\"menu-item-LightningSettings-{cryptoCode}\""))
|
||||
{
|
||||
Driver.FindElement(By.Id("StoreNav-LightningSettings")).Click();
|
||||
Driver.FindElement(By.Id($"menu-item-LightningSettings-{cryptoCode}")).Click();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -480,7 +480,7 @@ retry:
|
||||
public void GoToInvoiceCheckout(string invoiceId = null)
|
||||
{
|
||||
invoiceId ??= InvoiceId;
|
||||
Driver.FindElement(By.Id("StoreNav-Invoices")).Click();
|
||||
Driver.FindElement(By.Id("menu-item-Invoices")).Click();
|
||||
Driver.FindElement(By.Id($"invoice-checkout-{invoiceId}")).Click();
|
||||
CheckForJSErrors();
|
||||
Driver.WaitUntilAvailable(By.Id("Checkout"));
|
||||
@@ -495,7 +495,7 @@ retry:
|
||||
{
|
||||
if (storeId is null)
|
||||
{
|
||||
Driver.FindElement(By.Id("StoreNav-Invoices")).Click();
|
||||
Driver.FindElement(By.Id("menu-item-Invoices")).Click();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -506,11 +506,11 @@ retry:
|
||||
|
||||
public void GoToProfile(ManageNavPages navPages = ManageNavPages.Index)
|
||||
{
|
||||
Driver.WaitForAndClick(By.Id("Nav-Account"));
|
||||
Driver.WaitForAndClick(By.Id("menu-item-Account"));
|
||||
Driver.WaitForAndClick(By.Id("Nav-ManageAccount"));
|
||||
if (navPages != ManageNavPages.Index)
|
||||
{
|
||||
Driver.WaitForAndClick(By.Id($"SectionNav-{navPages.ToString()}"));
|
||||
Driver.WaitForAndClick(By.Id($"menu-item-{navPages.ToString()}"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -614,12 +614,12 @@ retry:
|
||||
Driver.Navigate().GoToUrl(new Uri(ServerUri, $"wallets/{walletId}"));
|
||||
if (navPages == WalletsNavPages.PSBT)
|
||||
{
|
||||
Driver.FindElement(By.Id("WalletNav-Send")).Click();
|
||||
Driver.FindElement(By.Id($"menu-item-Send-{walletId.CryptoCode}")).Click();
|
||||
Driver.FindElement(By.Id("PSBT")).Click();
|
||||
}
|
||||
else if (navPages != WalletsNavPages.Transactions)
|
||||
{
|
||||
Driver.FindElement(By.Id($"WalletNav-{navPages}")).Click();
|
||||
Driver.FindElement(By.Id($"menu-item-{navPages}-{walletId.CryptoCode}")).Click();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -630,10 +630,10 @@ retry:
|
||||
|
||||
public void GoToServer(ServerNavPages navPages = ServerNavPages.Policies)
|
||||
{
|
||||
Driver.FindElement(By.Id("Nav-ServerSettings")).Click();
|
||||
Driver.FindElement(By.Id("menu-item-Policies")).Click();
|
||||
if (navPages != ServerNavPages.Policies)
|
||||
{
|
||||
Driver.FindElement(By.Id($"SectionNav-{navPages}")).Click();
|
||||
Driver.FindElement(By.Id($"menu-item-{navPages}")).Click();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -671,7 +671,7 @@ retry:
|
||||
{
|
||||
if (string.IsNullOrEmpty(name))
|
||||
name = $"{type}-{Guid.NewGuid().ToString()[..14]}";
|
||||
Driver.FindElement(By.Id($"StoreNav-Create{type}")).Click();
|
||||
Driver.FindElement(By.Id($"menu-item-CreateApp-{type}")).Click();
|
||||
Driver.FindElement(By.Name("AppName")).SendKeys(name);
|
||||
ClickPagePrimary();
|
||||
Assert.Contains("App successfully created", FindAlertMessage().Text);
|
||||
|
||||
@@ -165,7 +165,7 @@ namespace BTCPayServer.Tests
|
||||
Assert.True(s.Driver.FindElement(By.Id("Dashboard")).Displayed);
|
||||
|
||||
// setup offchain wallet
|
||||
s.Driver.FindElement(By.Id("StoreNav-LightningBTC")).Click();
|
||||
s.Driver.FindElement(By.CssSelector("[data-testid='Lightning-BTC']")).Click();
|
||||
s.AddLightningNode();
|
||||
s.Driver.AssertNoError();
|
||||
var successAlert = s.FindAlertMessage();
|
||||
@@ -449,16 +449,16 @@ namespace BTCPayServer.Tests
|
||||
|
||||
// Archive
|
||||
s.Driver.SwitchTo().Window(windows[0]);
|
||||
Assert.True(s.Driver.ElementDoesNotExist(By.Id("Nav-ArchivedApps")));
|
||||
Assert.True(s.Driver.ElementDoesNotExist(By.Id("menu-item-AppsNavPages")));
|
||||
s.Driver.FindElement(By.Id("btn-archive-toggle")).Click();
|
||||
Assert.Contains("The app has been archived and will no longer appear in the apps list by default.", s.FindAlertMessage().Text);
|
||||
|
||||
Assert.True(s.Driver.ElementDoesNotExist(By.Id("ViewApp")));
|
||||
Assert.Contains("1 Archived App", s.Driver.FindElement(By.Id("Nav-ArchivedApps")).Text);
|
||||
Assert.Contains("1 Archived App", s.Driver.FindElement(By.Id("menu-item-AppsNavPages")).Text);
|
||||
s.Driver.Navigate().GoToUrl(posBaseUrl);
|
||||
Assert.Contains("Page not found", s.Driver.Title, StringComparison.OrdinalIgnoreCase);
|
||||
s.Driver.Navigate().Back();
|
||||
s.Driver.FindElement(By.Id("Nav-ArchivedApps")).Click();
|
||||
s.Driver.FindElement(By.Id("menu-item-AppsNavPages")).Click();
|
||||
|
||||
// Unarchive
|
||||
s.Driver.FindElement(By.Id($"App-{appId}")).Click();
|
||||
@@ -527,17 +527,17 @@ namespace BTCPayServer.Tests
|
||||
s.Driver.SwitchTo().Window(windows[0]);
|
||||
|
||||
// Archive
|
||||
Assert.True(s.Driver.ElementDoesNotExist(By.Id("Nav-ArchivedApps")));
|
||||
Assert.True(s.Driver.ElementDoesNotExist(By.Id("menu-item-AppsNavPages")));
|
||||
s.Driver.SwitchTo().Window(windows[0]);
|
||||
s.Driver.FindElement(By.Id("btn-archive-toggle")).Click();
|
||||
Assert.Contains("The app has been archived and will no longer appear in the apps list by default.", s.FindAlertMessage().Text);
|
||||
|
||||
Assert.True(s.Driver.ElementDoesNotExist(By.Id("ViewApp")));
|
||||
Assert.Contains("1 Archived App", s.Driver.FindElement(By.Id("Nav-ArchivedApps")).Text);
|
||||
Assert.Contains("1 Archived App", s.Driver.FindElement(By.Id("menu-item-AppsNavPages")).Text);
|
||||
s.Driver.Navigate().GoToUrl(cfUrl);
|
||||
Assert.Contains("Page not found", s.Driver.Title, StringComparison.OrdinalIgnoreCase);
|
||||
s.Driver.Navigate().Back();
|
||||
s.Driver.FindElement(By.Id("Nav-ArchivedApps")).Click();
|
||||
s.Driver.FindElement(By.Id("menu-item-AppsNavPages")).Click();
|
||||
|
||||
// Unarchive
|
||||
s.Driver.FindElement(By.Id($"App-{appId}")).Click();
|
||||
@@ -612,14 +612,14 @@ namespace BTCPayServer.Tests
|
||||
await s.StartAsync();
|
||||
s.RegisterNewUser();
|
||||
s.CreateNewStore();
|
||||
s.Driver.FindElement(By.Id("StoreNav-PaymentRequests")).Click();
|
||||
s.Driver.FindElement(By.Id("menu-item-PaymentRequests")).Click();
|
||||
|
||||
// Should give us an error message if we try to create a payment request before adding a wallet
|
||||
s.ClickPagePrimary();
|
||||
Assert.Contains("To create a payment request, you need to", s.Driver.PageSource);
|
||||
|
||||
s.AddDerivationScheme();
|
||||
s.Driver.FindElement(By.Id("StoreNav-PaymentRequests")).Click();
|
||||
s.Driver.FindElement(By.Id("menu-item-PaymentRequests")).Click();
|
||||
s.ClickPagePrimary();
|
||||
s.Driver.FindElement(By.Id("Title")).SendKeys("Pay123");
|
||||
s.Driver.FindElement(By.Id("Amount")).Clear();
|
||||
@@ -1483,11 +1483,11 @@ namespace BTCPayServer.Tests
|
||||
//ln address tests
|
||||
s.CreateNewStore();
|
||||
//ensure ln address is not available as Lightning is not enable
|
||||
s.Driver.AssertElementNotFound(By.Id("StoreNav-LightningAddress"));
|
||||
s.Driver.AssertElementNotFound(By.Id("menu-item-LightningAddress"));
|
||||
|
||||
s.AddLightningNode(LightningConnectionType.LndREST, false);
|
||||
|
||||
s.Driver.FindElement(By.Id("StoreNav-LightningAddress")).Click();
|
||||
s.Driver.FindElement(By.Id("menu-item-LightningAddress")).Click();
|
||||
|
||||
s.Driver.ToggleCollapse("AddAddress");
|
||||
var lnaddress1 = Guid.NewGuid().ToString();
|
||||
|
||||
@@ -226,7 +226,8 @@ public class SubscriptionTests(ITestOutputHelper testOutputHelper) : UnitTestBas
|
||||
{
|
||||
await portal.Downgrade("Basic Plan");
|
||||
unused = GetUnusedPeriodValue(usedDays: 7, planPrice: 99.0m, daysInPeriod: DaysInThisMonth());
|
||||
totalRefunded += await portal.AssertRefunded(unused);
|
||||
unused = await portal.AssertRefunded(unused);
|
||||
totalRefunded += unused;
|
||||
});
|
||||
|
||||
Assert.Equal(unused, credited.Amount);
|
||||
@@ -241,7 +242,8 @@ public class SubscriptionTests(ITestOutputHelper testOutputHelper) : UnitTestBas
|
||||
await portal.GoTo7Days();
|
||||
await portal.Upgrade("Pro Plan");
|
||||
unused = GetUnusedPeriodValue(usedDays: 7, planPrice: 29.0m, daysInPeriod: DaysInThisMonth());
|
||||
totalRefunded += await portal.AssertRefunded(unused);
|
||||
unused = await portal.AssertRefunded(unused);
|
||||
totalRefunded += unused;
|
||||
expectedBalance = totalRefunded - 29.0m - 99.0m - 99.0m;
|
||||
await portal.AssertCredit(creditBalance: $"${expectedBalance:F2}");
|
||||
|
||||
@@ -253,14 +255,24 @@ public class SubscriptionTests(ITestOutputHelper testOutputHelper) : UnitTestBas
|
||||
await s.Server.WaitForEvent<SubscriptionEvent.PlanStarted>(async () =>
|
||||
{
|
||||
await portal.Upgrade("Enterprise Plan");
|
||||
await invoice.AssertContent(new()
|
||||
{
|
||||
TotalFiat = USD(299m - expectedBalance - unused)
|
||||
});
|
||||
await s.PayInvoice(mine: true);
|
||||
});
|
||||
await invoice.ClickRedirect();
|
||||
totalRefunded += await portal.AssertRefunded(unused);
|
||||
unused = await portal.AssertRefunded(unused);
|
||||
totalRefunded += unused;
|
||||
await s.Page.EvaluateAsync("window.scrollTo(0, document.body.scrollHeight)");
|
||||
await s.TakeScreenshot("upgrade2.png");
|
||||
await portal.AssertCreditHistory(
|
||||
[
|
||||
"Upgrade to new plan 'Enterprise Plan'",
|
||||
"Credit purchase"
|
||||
],
|
||||
[
|
||||
"-$" + (299m - unused).ToString("F2", CultureInfo.InvariantCulture),
|
||||
"$" + (299m - expectedBalance - unused).ToString("F2", CultureInfo.InvariantCulture)
|
||||
]);
|
||||
expectedBalance = 0m;
|
||||
await portal.AssertCredit(creditBalance: $"${expectedBalance:F2}");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -759,7 +771,10 @@ public class SubscriptionTests(ITestOutputHelper testOutputHelper) : UnitTestBas
|
||||
var match = Regex.Match(text!, @"\((.*?) USD has been refunded\)");
|
||||
var v = decimal.Parse(match.Groups[1].Value, CultureInfo.InvariantCulture);
|
||||
var diff = Math.Abs(refunded - v);
|
||||
Assert.True(diff < 2.0m);
|
||||
if (diff >= 3.0m)
|
||||
{
|
||||
Assert.Fail($"Expected {refunded} USD, but got {v} USD");
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
@@ -769,13 +784,16 @@ public class SubscriptionTests(ITestOutputHelper testOutputHelper) : UnitTestBas
|
||||
Assert.Equal(plan, name);
|
||||
}
|
||||
|
||||
public async Task AssertCreditHistory(List<string> creditLines)
|
||||
public async Task AssertCreditHistory(List<string> creditLines, List<string>? creditAmounts = null)
|
||||
{
|
||||
var rows = await s.Page.QuerySelectorAllAsync(".credit-history tr td:nth-child(2)");
|
||||
var descriptions = await s.Page.QuerySelectorAllAsync(".credit-history tr td:nth-child(2)");
|
||||
var credits = await s.Page.QuerySelectorAllAsync(".credit-history tr td:nth-child(3)");
|
||||
for (int i = 0; i < creditLines.Count; i++)
|
||||
{
|
||||
var txt = await rows[i].InnerTextAsync();
|
||||
var txt = await descriptions[i].InnerTextAsync();
|
||||
Assert.StartsWith(creditLines[i], txt);
|
||||
if (creditAmounts is not null)
|
||||
Assert.Equal(creditAmounts[i], await credits[i].InnerTextAsync());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ public class WalletTests(ITestOutputHelper helper) : UnitTestBase(helper)
|
||||
var txs = (await client.ShowOnChainWalletTransactions(s.StoreId, "BTC")).Select(t => t.TransactionHash).ToArray();
|
||||
Assert.Equal(3, txs.Length);
|
||||
|
||||
var w = await s.GoToWalletTransactions();
|
||||
var w = await s.GoToWalletTransactions(s.WalletId);
|
||||
await w.BumpFee(txs[0]);
|
||||
|
||||
// Because a single transaction is selected, we should be able to select CPFP only (Because no change are available, we can't do RBF)
|
||||
@@ -145,7 +145,7 @@ public class WalletTests(ITestOutputHelper helper) : UnitTestBase(helper)
|
||||
|
||||
for (int i = 0; i < 5; i++)
|
||||
{
|
||||
var txs = await s.GoToWalletTransactions();
|
||||
var txs = await s.GoToWalletTransactions(s.WalletId);
|
||||
await txs.SelectAll();
|
||||
await txs.BumpFeeSelected();
|
||||
await s.ClickPagePrimary();
|
||||
|
||||
@@ -1,12 +1,8 @@
|
||||
@using BTCPayServer.Views.Server
|
||||
@using BTCPayServer.Views.Stores
|
||||
@using BTCPayServer.Views.Invoice
|
||||
@using BTCPayServer.Views.Manage
|
||||
@using BTCPayServer.Views.PaymentRequest
|
||||
@using BTCPayServer.Views.Wallets
|
||||
@using BTCPayServer.Client
|
||||
@using BTCPayServer.Components.ThemeSwitch
|
||||
@using BTCPayServer.Components.UIExtensionPoint
|
||||
@using BTCPayServer.Plugins
|
||||
@using BTCPayServer.Services
|
||||
@using BTCPayServer.Views.Apps
|
||||
@@ -33,45 +29,45 @@
|
||||
<div class="accordion-body">
|
||||
<ul class="navbar-nav">
|
||||
<li class="nav-item" permission="@Policies.CanModifyStoreSettings">
|
||||
<a id="StoreNav-@(nameof(StoreNavPages.Dashboard))" asp-area="" asp-controller="UIStores" asp-action="Dashboard" asp-route-storeId="@Model.Store.Id" class="nav-link @ViewData.ActivePageClass(StoreNavPages.Dashboard)">
|
||||
<a layout-menu-item="@nameof(StoreNavPages.Dashboard)" asp-area="" asp-controller="UIStores" asp-action="Dashboard" asp-route-storeId="@Model.Store.Id">
|
||||
<vc:icon symbol="nav-dashboard"/>
|
||||
<span text-translate="true">Dashboard</span>
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item" permission="@Policies.CanViewStoreSettings">
|
||||
<a id="StoreNav-@(nameof(StoreNavPages.General))" asp-area="" asp-controller="UIStores" asp-action="GeneralSettings" asp-route-storeId="@Model.Store.Id" class="nav-link @ViewData.ActivePageClass(StoreNavPages.General)">
|
||||
<a layout-menu-item="General" asp-area="" asp-controller="UIStores" asp-action="GeneralSettings" asp-route-storeId="@Model.Store.Id">
|
||||
<vc:icon symbol="nav-store-settings"/>
|
||||
<span text-translate="true">Settings</span>
|
||||
</a>
|
||||
</li>
|
||||
@if (ViewData.IsPageActive([StoreNavPages.General, StoreNavPages.Rates, StoreNavPages.CheckoutAppearance, StoreNavPages.Tokens, StoreNavPages.Users, StoreNavPages.Roles, StoreNavPages.Webhooks, StoreNavPages.PayoutProcessors, StoreNavPages.Emails, StoreNavPages.Forms]))
|
||||
@if (ViewData.IsCategory(WellKnownCategories.Store))
|
||||
{
|
||||
<li class="nav-item nav-item-sub" permission="@Policies.CanViewStoreSettings">
|
||||
<a id="StoreNav-@(nameof(StoreNavPages.Rates))" class="nav-link @ViewData.ActivePageClass(StoreNavPages.Rates)" asp-controller="UIStores" asp-action="Rates" asp-route-storeId="@Model.Store.Id" text-translate="true">Rates</a>
|
||||
<a layout-menu-item="@(nameof(StoreNavPages.Rates))" asp-controller="UIStores" asp-action="Rates" asp-route-storeId="@Model.Store.Id" text-translate="true">Rates</a>
|
||||
</li>
|
||||
<li class="nav-item nav-item-sub" permission="@Policies.CanViewStoreSettings">
|
||||
<a id="StoreNav-@(nameof(StoreNavPages.CheckoutAppearance))" class="nav-link @ViewData.ActivePageClass(StoreNavPages.CheckoutAppearance)" asp-controller="UIStores" asp-action="CheckoutAppearance" asp-route-storeId="@Model.Store.Id" text-translate="true">Checkout Appearance</a>
|
||||
<a layout-menu-item="@(nameof(StoreNavPages.CheckoutAppearance))" asp-controller="UIStores" asp-action="CheckoutAppearance" asp-route-storeId="@Model.Store.Id" text-translate="true">Checkout Appearance</a>
|
||||
</li>
|
||||
<li class="nav-item nav-item-sub" permission="@Policies.CanViewStoreSettings">
|
||||
<a id="StoreNav-@(nameof(StoreNavPages.Tokens))" class="nav-link @ViewData.ActivePageClass(StoreNavPages.Tokens)" asp-controller="UIStores" asp-action="ListTokens" asp-route-storeId="@Model.Store.Id" text-translate="true">Access Tokens</a>
|
||||
<a layout-menu-item="@nameof(StoreNavPages.Tokens)" asp-controller="UIStores" asp-action="ListTokens" asp-route-storeId="@Model.Store.Id" text-translate="true">Access Tokens</a>
|
||||
</li>
|
||||
<li class="nav-item nav-item-sub" permission="@Policies.CanViewStoreSettings">
|
||||
<a id="StoreNav-@(nameof(StoreNavPages.Users))" class="nav-link @ViewData.ActivePageClass(StoreNavPages.Users)" asp-controller="UIStores" asp-action="StoreUsers" asp-route-storeId="@Model.Store.Id" text-translate="true">Users</a>
|
||||
<a layout-menu-item="@(nameof(StoreNavPages.Users))" asp-controller="UIStores" asp-action="StoreUsers" asp-route-storeId="@Model.Store.Id" text-translate="true">Users</a>
|
||||
</li>
|
||||
<li class="nav-item nav-item-sub" permission="@Policies.CanViewStoreSettings">
|
||||
<a id="StoreNav-@(nameof(StoreNavPages.Roles))" class="nav-link @ViewData.ActivePageClass(StoreNavPages.Roles)" asp-controller="UIStores" asp-action="ListRoles" asp-route-storeId="@Model.Store.Id" text-translate="true">Roles</a>
|
||||
<a layout-menu-item="@(nameof(StoreNavPages.Roles))" asp-controller="UIStores" asp-action="ListRoles" asp-route-storeId="@Model.Store.Id" text-translate="true">Roles</a>
|
||||
</li>
|
||||
<li class="nav-item nav-item-sub" permission="@Policies.CanViewStoreSettings">
|
||||
<a id="StoreNav-@(nameof(StoreNavPages.Webhooks))" class="nav-link @ViewData.ActivePageClass(StoreNavPages.Webhooks)" asp-area="Webhooks" asp-controller="UIStoreWebhooks" asp-action="Webhooks" asp-route-storeId="@Model.Store.Id" text-translate="true">Webhooks</a>
|
||||
<a layout-menu-item="@(nameof(StoreNavPages.Webhooks))" asp-area="Webhooks" asp-controller="UIStoreWebhooks" asp-action="Webhooks" asp-route-storeId="@Model.Store.Id" text-translate="true">Webhooks</a>
|
||||
</li>
|
||||
<li class="nav-item nav-item-sub" permission="@Policies.CanViewStoreSettings">
|
||||
<a id="StoreNav-@(nameof(StoreNavPages.PayoutProcessors))" class="nav-link @ViewData.ActivePageClass(StoreNavPages.PayoutProcessors)" asp-controller="UIPayoutProcessors" asp-action="ConfigureStorePayoutProcessors" asp-route-storeId="@Model.Store.Id" text-translate="true">Payout Processors</a>
|
||||
<a layout-menu-item="@(nameof(StoreNavPages.PayoutProcessors))" asp-controller="UIPayoutProcessors" asp-action="ConfigureStorePayoutProcessors" asp-route-storeId="@Model.Store.Id" text-translate="true">Payout Processors</a>
|
||||
</li>
|
||||
<li class="nav-item nav-item-sub" permission="@Policies.CanViewStoreSettings">
|
||||
<a id="StoreNav-@(nameof(StoreNavPages.Emails))" class="nav-link @ViewData.ActivePageClass(StoreNavPages.Emails)" asp-area="@EmailsPlugin.Area" asp-controller="UIStoresEmail" asp-action="StoreEmailSettings" asp-route-storeId="@Model.Store.Id" text-translate="true">Emails</a>
|
||||
<a layout-menu-item="@(nameof(StoreNavPages.Emails))" asp-area="@EmailsPlugin.Area" asp-controller="UIStoresEmail" asp-action="StoreEmailSettings" asp-route-storeId="@Model.Store.Id" text-translate="true">Emails</a>
|
||||
</li>
|
||||
<li class="nav-item nav-item-sub" permission="@Policies.CanViewStoreSettings">
|
||||
<a id="StoreNav-@(nameof(StoreNavPages.Forms))" class="nav-link @ViewData.ActivePageClass(StoreNavPages.Forms)" asp-controller="UIForms" asp-action="FormsList" asp-route-storeId="@Model.Store.Id" text-translate="true">Forms</a>
|
||||
<a layout-menu-item="@(nameof(StoreNavPages.Forms))" asp-controller="UIForms" asp-action="FormsList" asp-route-storeId="@Model.Store.Id" text-translate="true">Forms</a>
|
||||
</li>
|
||||
}
|
||||
<vc:ui-extension-point location="store-nav" model="@Model"/>
|
||||
@@ -88,39 +84,43 @@
|
||||
@foreach (var scheme in Model.DerivationSchemes.OrderBy(scheme => scheme.Collapsed))
|
||||
{
|
||||
var isSetUp = !string.IsNullOrWhiteSpace(scheme.Value);
|
||||
var categoryId = $"{Model.Store.Id}-{scheme.WalletId.CryptoCode}";
|
||||
<li class="nav-item">
|
||||
<li class="nav-item" data-testid="Wallet-@scheme.Crypto">
|
||||
@if (isSetUp && scheme.WalletSupported)
|
||||
{
|
||||
<a asp-area="" asp-controller="UIWallets" asp-action="WalletTransactions" asp-route-walletId="@scheme.WalletId" class="nav-link @ViewData.ActivePageClass([WalletsNavPages.Transactions], scheme.WalletId.ToString())" id="@($"StoreNav-Wallet{scheme.Crypto}")">
|
||||
<a layout-menu-item="@nameof(WalletsNavPages.Transactions)-@scheme.Crypto" asp-area="" asp-controller="UIWallets" asp-action="WalletTransactions" asp-route-walletId="@scheme.WalletId">
|
||||
<span class="me-2 btcpay-status btcpay-status--@(scheme.Enabled ? "enabled" : "pending")"></span>
|
||||
<span>@PrettyName.PrettyName(scheme.PaymentMethodId)</span>
|
||||
</a>
|
||||
}
|
||||
else
|
||||
{
|
||||
<a asp-area="" asp-controller="UIStores" asp-action="SetupWallet" asp-route-cryptoCode="@scheme.Crypto" asp-route-storeId="@Model.Store.Id" class="nav-link @ViewData.ActivePageClass(StoreNavPages.OnchainSettings)" id="@($"StoreNav-Wallet{scheme.Crypto}")">
|
||||
<a asp-area="" asp-controller="UIStores" asp-action="SetupWallet" asp-route-cryptoCode="@scheme.Crypto" asp-route-storeId="@Model.Store.Id">
|
||||
<span class="me-2 btcpay-status btcpay-status--@(scheme.Enabled ? "enabled" : "pending")"></span>
|
||||
<span>@PrettyName.PrettyName(scheme.PaymentMethodId)</span>
|
||||
</a>
|
||||
}
|
||||
</li>
|
||||
@if (ViewData.IsCategoryActive(typeof(WalletsNavPages), scheme.WalletId.ToString()) || ViewData.IsPageActive([WalletsNavPages.Settings], scheme.WalletId.ToString()) || ViewData.IsPageActive([StoreNavPages.OnchainSettings], categoryId))
|
||||
@if (ViewData.IsCategory(WellKnownCategories.ForWallet(scheme.Crypto)))
|
||||
{
|
||||
@if (!scheme.ReadonlyWallet)
|
||||
{
|
||||
<li class="nav-item nav-item-sub">
|
||||
<a id="WalletNav-Send" class="nav-link @ViewData.ActivePageClass([WalletsNavPages.Send, WalletsNavPages.PSBT], scheme.WalletId.ToString())" asp-area="" asp-controller="UIWallets" asp-action="WalletSend" asp-route-walletId="@scheme.WalletId" text-translate="true">Send</a>
|
||||
<a layout-menu-item="@nameof(WalletsNavPages.Send)-@scheme.Crypto"
|
||||
asp-area="" asp-controller="UIWallets" asp-action="WalletSend" asp-route-walletId="@scheme.WalletId" text-translate="true">Send</a>
|
||||
</li>
|
||||
}
|
||||
|
||||
|
||||
<li class="nav-item nav-item-sub">
|
||||
<a id="WalletNav-Receive" class="nav-link @ViewData.ActivePageClass(WalletsNavPages.Receive, scheme.WalletId.ToString())" asp-area="" asp-controller="UIWallets" asp-action="WalletReceive" asp-route-walletId="@scheme.WalletId" text-translate="true">Receive</a>
|
||||
<a
|
||||
layout-menu-item="@nameof(WalletsNavPages.Receive)-@scheme.Crypto"
|
||||
asp-area="" asp-controller="UIWallets" asp-action="WalletReceive" asp-route-walletId="@scheme.WalletId" text-translate="true">Receive</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item nav-item-sub">
|
||||
<a id="WalletNav-Settings" class="nav-link @ViewData.ActivePageClass(WalletsNavPages.Settings, scheme.WalletId.ToString()) @ViewData.ActivePageClass(StoreNavPages.OnchainSettings, categoryId)" asp-area="" asp-controller="UIStores" asp-action="WalletSettings" asp-route-cryptoCode="@scheme.WalletId.CryptoCode" asp-route-storeId="@scheme.WalletId.StoreId" text-translate="true">Settings</a>
|
||||
<a
|
||||
layout-menu-item="@nameof(WalletsNavPages.Settings)-@scheme.Crypto"
|
||||
asp-area="" asp-controller="UIStores" asp-action="WalletSettings" asp-route-cryptoCode="@scheme.WalletId.CryptoCode" asp-route-storeId="@scheme.WalletId.StoreId" text-translate="true">Settings</a>
|
||||
</li>
|
||||
<vc:ui-extension-point location="wallet-nav" model="@Model" />
|
||||
}
|
||||
@@ -134,23 +134,29 @@
|
||||
var status = scheme.Enabled
|
||||
? scheme.Available ? "enabled" : "disabled"
|
||||
: "pending";
|
||||
<a asp-area="" asp-controller="UIStores" asp-action="Lightning" asp-route-cryptoCode="@scheme.CryptoCode" asp-route-storeId="@Model.Store.Id" class="nav-link @ViewData.ActivePageClass(StoreNavPages.Lightning, $"{Model.Store.Id}-{scheme.CryptoCode}")" id="@($"StoreNav-Lightning{scheme.CryptoCode}")">
|
||||
<a
|
||||
data-testid="Lightning-@scheme.CryptoCode"
|
||||
layout-menu-item="@nameof(StoreNavPages.Lightning)-@scheme.CryptoCode"
|
||||
asp-area="" asp-controller="UIStores" asp-action="Lightning" asp-route-cryptoCode="@scheme.CryptoCode" asp-route-storeId="@Model.Store.Id">
|
||||
<span class="me-2 btcpay-status btcpay-status--@status"></span>
|
||||
<span>@PrettyName.PrettyName(scheme.PaymentMethodId)</span>
|
||||
</a>
|
||||
}
|
||||
else
|
||||
{
|
||||
<a asp-area="" asp-controller="UIStores" asp-action="SetupLightningNode" asp-route-cryptoCode="@scheme.CryptoCode" asp-route-storeId="@Model.Store.Id" class="nav-link @ViewData.ActivePageClass(StoreNavPages.LightningSettings, $"{Model.Store.Id}-{scheme.CryptoCode}")" id="@($"StoreNav-Lightning{scheme.CryptoCode}")">
|
||||
<a
|
||||
data-testid="Lightning-@scheme.CryptoCode"
|
||||
layout-menu-item="@nameof(StoreNavPages.LightningSettings)-@scheme.CryptoCode"
|
||||
asp-area="" asp-controller="UIStores" asp-action="SetupLightningNode" asp-route-cryptoCode="@scheme.CryptoCode" asp-route-storeId="@Model.Store.Id">
|
||||
<span class="me-2 btcpay-status btcpay-status--@(scheme.Enabled ? "enabled" : "pending")"></span>
|
||||
<span>@PrettyName.PrettyName(scheme.PaymentMethodId)</span>
|
||||
</a>
|
||||
}
|
||||
</li>
|
||||
@if (ViewData.IsPageActive([StoreNavPages.Lightning, StoreNavPages.LightningSettings], $"{Model.Store.Id}-{scheme.CryptoCode}"))
|
||||
@if (ViewData.IsCategory(WellKnownCategories.ForLightning(scheme.CryptoCode)))
|
||||
{
|
||||
<li class="nav-item nav-item-sub">
|
||||
<a id="StoreNav-@(nameof(StoreNavPages.LightningSettings))" class="nav-link @ViewData.ActivePageClass(StoreNavPages.LightningSettings)" asp-controller="UIStores" asp-action="LightningSettings" asp-route-storeId="@Model.Store.Id" asp-route-cryptoCode="@scheme.CryptoCode" text-translate="true">Settings</a>
|
||||
<a layout-menu-item="@(nameof(StoreNavPages.LightningSettings))-@scheme.CryptoCode" asp-controller="UIStores" asp-action="LightningSettings" asp-route-storeId="@Model.Store.Id" asp-route-cryptoCode="@scheme.CryptoCode" text-translate="true">Settings</a>
|
||||
</li>
|
||||
<vc:ui-extension-point location="lightning-nav" model="@Model"/>
|
||||
}
|
||||
@@ -170,34 +176,36 @@
|
||||
<div class="accordion-body">
|
||||
<ul class="navbar-nav">
|
||||
<li class="nav-item" permission="@Policies.CanViewInvoices">
|
||||
<a asp-area="" asp-controller="UIInvoice" asp-action="ListInvoices" asp-route-storeId="@Model.Store.Id" class="nav-link @ViewData.ActiveCategoryClass(typeof(InvoiceNavPages))" id="StoreNav-Invoices">
|
||||
<a layout-menu-item="Invoices" asp-area="" asp-controller="UIInvoice" asp-action="ListInvoices" asp-route-storeId="@Model.Store.Id">
|
||||
<vc:icon symbol="nav-invoices"/>
|
||||
<span text-translate="true">Invoices</span>
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item" permission="@Policies.CanViewReports">
|
||||
<a asp-area="" asp-controller="UIReports" asp-action="StoreReports" asp-route-storeId="@Model.Store.Id" class="nav-link @ViewData.ActivePageClass(StoreNavPages.Reporting)" id="SectionNav-Reporting">
|
||||
<a layout-menu-item="@nameof(StoreNavPages.Reporting)" asp-area="" asp-controller="UIReports" asp-action="StoreReports" asp-route-storeId="@Model.Store.Id">
|
||||
<vc:icon symbol="nav-reporting" />
|
||||
<span text-translate="true">Reporting</span>
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item" permission="@Policies.CanViewPaymentRequests">
|
||||
<a asp-area="" asp-controller="UIPaymentRequest" asp-action="GetPaymentRequests" asp-route-storeId="@Model.Store.Id" class="nav-link @ViewData.ActiveCategoryClass(typeof(PaymentRequestsNavPages))" id="StoreNav-PaymentRequests">
|
||||
<a layout-menu-item="PaymentRequests" asp-area="" asp-controller="UIPaymentRequest" asp-action="GetPaymentRequests" asp-route-storeId="@Model.Store.Id">
|
||||
<vc:icon symbol="nav-payment-requests"/>
|
||||
<span text-translate="true">Requests</span>
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item" permission="@Policies.CanViewPullPayments">
|
||||
<a asp-area="" asp-controller="UIStorePullPayments" asp-action="PullPayments" asp-route-storeId="@Model.Store.Id" class="nav-link @ViewData.ActivePageClass(StoreNavPages.PullPayments)" id="StoreNav-PullPayments">
|
||||
<a layout-menu-item="@nameof(StoreNavPages.PullPayments)" asp-area="" asp-controller="UIStorePullPayments" asp-action="PullPayments" asp-route-storeId="@Model.Store.Id">
|
||||
<vc:icon symbol="nav-pull-payments"/>
|
||||
<span text-translate="true">Pull Payments</span>
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item" permission="@Policies.CanViewPayouts">
|
||||
<a asp-area=""
|
||||
<a
|
||||
layout-menu-item="@nameof(StoreNavPages.Payouts)"
|
||||
asp-area=""
|
||||
asp-controller="UIStorePullPayments" asp-action="Payouts"
|
||||
asp-route-pullPaymentId=""
|
||||
asp-route-storeId="@Model.Store.Id" class="nav-link @ViewData.ActivePageClass(StoreNavPages.Payouts)" id="StoreNav-Payouts">
|
||||
asp-route-storeId="@Model.Store.Id">
|
||||
<vc:icon symbol="nav-payouts"/>
|
||||
<span text-translate="true">Payouts</span>
|
||||
</a>
|
||||
@@ -226,7 +234,7 @@
|
||||
</ul>
|
||||
<ul class="navbar-nav">
|
||||
<li class="nav-item" permission="@Policies.CanModifyServerSettings">
|
||||
<a asp-area="" asp-controller="UIServer" asp-action="ListPlugins" class="nav-link @ViewData.ActivePageClass(ServerNavPages.Plugins)" id="Nav-ManagePlugins">
|
||||
<a layout-menu-item="@nameof(ServerNavPages.Plugins)" asp-area="" asp-controller="UIServer" asp-action="ListPlugins">
|
||||
@if (PluginService.GetDisabledPlugins().Any())
|
||||
{
|
||||
<span class="me-2 btcpay-status btcpay-status--disabled"></span>
|
||||
@@ -241,7 +249,7 @@
|
||||
@if (Model.Store != null && Model.ArchivedAppsCount > 0)
|
||||
{
|
||||
<li class="nav-item nav-item-sub" permission="@Policies.CanModifyStoreSettings">
|
||||
<a asp-area="" asp-controller="UIApps" asp-action="ListApps" asp-route-storeId="@Model.Store.Id" asp-route-archived="true" class="nav-link @ViewData.ActivePageClass(AppsNavPages.Index)" id="Nav-ArchivedApps">
|
||||
<a layout-menu-item="@nameof(AppsNavPages)" asp-area="" asp-controller="UIApps" asp-action="ListApps" asp-route-storeId="@Model.Store.Id" asp-route-archived="true">
|
||||
@Model.ArchivedAppsCount Archived App@(Model.ArchivedAppsCount == 1 ? "" : "s")
|
||||
</a>
|
||||
</li>
|
||||
@@ -292,48 +300,48 @@
|
||||
{
|
||||
<ul id="mainNavSettings" class="navbar-nav border-top p-3 px-lg-4">
|
||||
<li class="nav-item" permission="@Policies.CanModifyServerSettings">
|
||||
<a asp-area="" asp-controller="UIServer" asp-action="Policies" class="nav-link @ViewData.ActivePageClass(ServerNavPages.Policies)" id="Nav-ServerSettings">
|
||||
<a layout-menu-item="@nameof(ServerNavPages.Policies)" asp-area="" asp-controller="UIServer" asp-action="Policies">
|
||||
<vc:icon symbol="nav-server-settings"/>
|
||||
<span text-translate="true">Server Settings</span>
|
||||
</a>
|
||||
</li>
|
||||
@if (ViewData.IsCategoryActive(typeof(ServerNavPages)) && !ViewData.IsPageActive([ServerNavPages.Plugins]))
|
||||
@if (ViewData.IsCategory(WellKnownCategories.Server))
|
||||
{
|
||||
<li class="nav-item nav-item-sub" permission="@Policies.CanModifyServerSettings">
|
||||
<a asp-controller="UIServer" id="SectionNav-@ServerNavPages.Users" class="nav-link @ViewData.ActivePageClass(ServerNavPages.Users)" asp-action="ListUsers" text-translate="true">Users</a>
|
||||
<a layout-menu-item="@nameof(ServerNavPages.Users)" asp-controller="UIServer" asp-action="ListUsers" text-translate="true">Users</a>
|
||||
</li>
|
||||
<li class="nav-item nav-item-sub" permission="@Policies.CanModifyServerSettings">
|
||||
<a asp-controller="UIServer" id="SectionNav-@ServerNavPages.Roles" class="nav-link @ViewData.ActivePageClass(ServerNavPages.Roles)" asp-action="ListRoles" text-translate="true">Roles</a>
|
||||
<a layout-menu-item="@nameof(ServerNavPages.Roles)" asp-controller="UIServer" asp-action="ListRoles" text-translate="true">Roles</a>
|
||||
</li>
|
||||
<li class="nav-item nav-item-sub" permission="@Policies.CanModifyServerSettings">
|
||||
<a asp-controller="UIServer" id="SectionNav-@ServerNavPages.Emails" class="nav-link @ViewData.ActivePageClass(ServerNavPages.Emails)" asp-action="Emails" text-translate="true">Email</a>
|
||||
<a layout-menu-item="Server-@nameof(ServerNavPages.Emails)" asp-controller="UIServer" asp-action="Emails" text-translate="true">Email</a>
|
||||
</li>
|
||||
<li class="nav-item nav-item-sub" permission="@Policies.CanModifyServerSettings">
|
||||
<a asp-controller="UIServer" id="SectionNav-@ServerNavPages.Services" class="nav-link @ViewData.ActivePageClass(ServerNavPages.Services)" asp-action="Services" text-translate="true">Services</a>
|
||||
<a layout-menu-item="@nameof(ServerNavPages.Services)" asp-controller="UIServer" asp-action="Services" text-translate="true">Services</a>
|
||||
</li>
|
||||
<li class="nav-item nav-item-sub" permission="@Policies.CanModifyServerSettings">
|
||||
<a asp-controller="UIServer" id="SectionNav-@ServerNavPages.Branding" class="nav-link @ViewData.ActivePageClass(ServerNavPages.Branding)" asp-action="Branding" text-translate="true">Branding</a>
|
||||
<a layout-menu-item="@nameof(ServerNavPages.Branding)" asp-controller="UIServer" asp-action="Branding" text-translate="true">Branding</a>
|
||||
</li>
|
||||
<li class="nav-item nav-item-sub" permission="@Policies.CanModifyServerSettings">
|
||||
<a asp-controller="UIServer" id="SectionNav-@ServerNavPages.Translations" class="nav-link @ViewData.ActivePageClass(ServerNavPages.Translations)" asp-action="ListDictionaries" text-translate="true">Translations</a>
|
||||
<a layout-menu-item="@nameof(ServerNavPages.Translations)" asp-controller="UIServer" asp-action="ListDictionaries" text-translate="true">Translations</a>
|
||||
</li>
|
||||
@if (BtcPayServerOptions.DockerDeployment)
|
||||
{
|
||||
<li class="nav-item nav-item-sub" permission="@Policies.CanModifyServerSettings">
|
||||
<a asp-controller="UIServer" id="SectionNav-@ServerNavPages.Maintenance" class="nav-link @ViewData.ActivePageClass(ServerNavPages.Maintenance)" asp-action="Maintenance" text-translate="true">Maintenance</a>
|
||||
<a layout-menu-item="@nameof(ServerNavPages.Maintenance)" asp-controller="UIServer" asp-action="Maintenance" text-translate="true">Maintenance</a>
|
||||
</li>
|
||||
}
|
||||
<li class="nav-item nav-item-sub" permission="@Policies.CanModifyServerSettings">
|
||||
<a asp-controller="UIServer" id="SectionNav-@ServerNavPages.Logs" class="nav-link @ViewData.ActivePageClass(ServerNavPages.Logs)" asp-action="LogsView" text-translate="true">Logs</a>
|
||||
<a layout-menu-item="@nameof(ServerNavPages.Logs)" asp-controller="UIServer" asp-action="LogsView" text-translate="true">Logs</a>
|
||||
</li>
|
||||
<li class="nav-item nav-item-sub" permission="@Policies.CanModifyServerSettings">
|
||||
<a asp-controller="UIServer" id="SectionNav-@ServerNavPages.Files" class="nav-link @ViewData.ActivePageClass(ServerNavPages.Files)" asp-action="Files" text-translate="true">Files</a>
|
||||
<a layout-menu-item="@nameof(ServerNavPages.Files)" asp-controller="UIServer" asp-action="Files" text-translate="true">Files</a>
|
||||
</li>
|
||||
|
||||
<vc:ui-extension-point location="server-nav" model="@Model"/>
|
||||
}
|
||||
<li class="nav-item dropup">
|
||||
<a class="nav-link @ViewData.ActivePageClass(ManageNavPages.Index)" role="button" data-bs-toggle="dropdown" data-bs-auto-close="outside" aria-expanded="false" id="Nav-Account">
|
||||
<a layout-menu-item="Account" role="button" data-bs-toggle="dropdown" data-bs-auto-close="outside" aria-expanded="false">
|
||||
<vc:icon symbol="nav-account"/>
|
||||
<span text-translate="true">Account</span>
|
||||
</a>
|
||||
@@ -347,11 +355,11 @@
|
||||
<strong class="d-block text-truncate" style="max-width:@(string.IsNullOrEmpty(Model.UserImageUrl) ? "195px" : "160px")">
|
||||
@if (string.IsNullOrEmpty(Model.UserName))
|
||||
{
|
||||
@(User.Identity.Name)
|
||||
@(User.Identity?.Name)
|
||||
}
|
||||
else
|
||||
{
|
||||
@($"{Model.UserName} ({User.Identity.Name})")
|
||||
@($"{Model.UserName} ({User.Identity?.Name})")
|
||||
}
|
||||
</strong>
|
||||
@if (User.IsInRole(Roles.ServerAdmin))
|
||||
@@ -387,22 +395,22 @@
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
@if (ViewData.IsCategoryActive(typeof(ManageNavPages)) || ViewData.IsPageActive([ManageNavPages.ChangePassword]))
|
||||
@if (ViewData.IsCategory(nameof(ManageNavPages)))
|
||||
{
|
||||
<li class="nav-item nav-item-sub">
|
||||
<a id="SectionNav-@ManageNavPages.ChangePassword.ToString()" class="nav-link @ViewData.ActivePageClass(ManageNavPages.ChangePassword)" asp-controller="UIManage" asp-action="ChangePassword" text-translate="true">Password</a>
|
||||
<a layout-menu-item="@nameof(ManageNavPages.ChangePassword)" asp-controller="UIManage" asp-action="ChangePassword" text-translate="true">Password</a>
|
||||
</li>
|
||||
<li class="nav-item nav-item-sub">
|
||||
<a id="SectionNav-@ManageNavPages.TwoFactorAuthentication.ToString()" class="nav-link @ViewData.ActivePageClass(ManageNavPages.TwoFactorAuthentication)" asp-controller="UIManage" asp-action="TwoFactorAuthentication" text-translate="true">Two-Factor Authentication</a>
|
||||
<a layout-menu-item="@nameof(ManageNavPages.TwoFactorAuthentication)" asp-controller="UIManage" asp-action="TwoFactorAuthentication" text-translate="true">Two-Factor Authentication</a>
|
||||
</li>
|
||||
<li class="nav-item nav-item-sub">
|
||||
<a id="SectionNav-@ManageNavPages.APIKeys.ToString()" class="nav-link @ViewData.ActivePageClass(ManageNavPages.APIKeys)" asp-controller="UIManage" asp-action="APIKeys" text-translate="true">API Keys</a>
|
||||
<a layout-menu-item="@nameof(ManageNavPages.APIKeys)" asp-controller="UIManage" asp-action="APIKeys" text-translate="true">API Keys</a>
|
||||
</li>
|
||||
<li class="nav-item nav-item-sub">
|
||||
<a id="SectionNav-@ManageNavPages.Notifications.ToString()" class="nav-link @ViewData.ActivePageClass(ManageNavPages.Notifications)" asp-controller="UIManage" asp-action="NotificationSettings" text-translate="true">Notifications</a>
|
||||
<a layout-menu-item="@nameof(ManageNavPages.Notifications)" asp-controller="UIManage" asp-action="NotificationSettings" text-translate="true">Notifications</a>
|
||||
</li>
|
||||
<li class="nav-item nav-item-sub">
|
||||
<a id="SectionNav-@ManageNavPages.LoginCodes.ToString()" class="nav-link @ViewData.ActivePageClass(ManageNavPages.LoginCodes)" asp-controller="UIManage" asp-action="LoginCodes" text-translate="true">Login Codes</a>
|
||||
<a layout-menu-item="@nameof(ManageNavPages.LoginCodes)" asp-controller="UIManage" asp-action="LoginCodes" text-translate="true">Login Codes</a>
|
||||
</li>
|
||||
<vc:ui-extension-point location="user-nav" model="@Model" />
|
||||
}
|
||||
|
||||
@@ -51,23 +51,19 @@ else
|
||||
@foreach (var option in Model.Options)
|
||||
{
|
||||
<li>
|
||||
<a asp-controller="UIStores" asp-action="Index" asp-route-storeId="@option.Value" class="dropdown-item@(option.Selected && ViewData.ActivePageClass(ServerNavPages.Stores) != "active" ? " active" : "")" id="StoreSelectorMenuItem-@option.Value">@StoreName(option.Text)</a>
|
||||
<a asp-controller="UIStores" asp-action="Index" asp-route-storeId="@option.Value" class="dropdown-item@(option.Selected && !ViewData.ContainsKey("StoreList"))" id="StoreSelectorMenuItem-@option.Value">@StoreName(option.Text)</a>
|
||||
</li>
|
||||
}
|
||||
@if (Model.Options.Any())
|
||||
{
|
||||
<li><hr class="dropdown-divider"></li>
|
||||
}
|
||||
<li><a asp-controller="UIUserStores" asp-action="CreateStore" class="dropdown-item @ViewData.ActivePageClass(StoreNavPages.Create)" id="StoreSelectorCreate" text-translate="true">Create Store</a></li>
|
||||
<li><a asp-controller="UIUserStores" asp-action="CreateStore" class="dropdown-item @(ViewData.ContainsKey("CreateStore") ? "active" : "")" id="StoreSelectorCreate" text-translate="true">Create Store</a></li>
|
||||
@if (Model.ArchivedCount > 0)
|
||||
{
|
||||
<li><hr class="dropdown-divider"></li>
|
||||
<li><a asp-controller="UIUserStores" asp-action="ListStores" asp-route-archived="true" class="dropdown-item @ViewData.ActivePageClass(StoreNavPages.Index)" id="StoreSelectorArchived">@(Model.ArchivedCount == 1 ? StringLocalizer["{0} Archived Store", Model.ArchivedCount] : StringLocalizer["{0} Archived Stores", Model.ArchivedCount])</a></li>
|
||||
<li><a asp-controller="UIUserStores" asp-action="ListStores" asp-route-archived="true" class="dropdown-item @(ViewData.ContainsKey("ArchivedStores") ? "active" : "")" id="StoreSelectorArchived">@(Model.ArchivedCount == 1 ? StringLocalizer["{0} Archived Store", Model.ArchivedCount] : StringLocalizer["{0} Archived Stores", Model.ArchivedCount])</a></li>
|
||||
}
|
||||
@*
|
||||
<li permission="@Policies.CanModifyServerSettings"><hr class="dropdown-divider"></li>
|
||||
<li permission="@Policies.CanModifyServerSettings"><a asp-controller="UIServer" asp-action="ListStores" class="dropdown-item @ViewData.ActivePageClass(ServerNavPages.Stores)" id="StoreSelectorAdminStores" text-translate="true">Admin Store Overview</a></li>
|
||||
*@
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
|
||||
@{
|
||||
var storeId = Context.GetStoreData().Id;
|
||||
ViewData.SetActivePage(StoreNavPages.Emails, StringLocalizer["Email Rules"], storeId);
|
||||
ViewData.SetLayoutModel(new LayoutModel(nameof(StoreNavPages.Emails), StringLocalizer["Email Rules"])
|
||||
.SetCategory(WellKnownCategories.Store));
|
||||
}
|
||||
<div class="sticky-header">
|
||||
<nav aria-label="breadcrumb">
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
@{
|
||||
var storeId = Context.GetStoreData().Id;
|
||||
bool isEdit = Model.Trigger != null;
|
||||
ViewData.SetActivePage(StoreNavPages.Emails, StringLocalizer[isEdit ? "Edit Email Rule" : "Create Email Rule"], storeId);
|
||||
ViewData.SetLayoutModel(new LayoutModel(nameof(StoreNavPages.Emails), StringLocalizer[isEdit ? "Edit Email Rule" : "Create Email Rule"])
|
||||
.SetCategory(WellKnownCategories.Store));
|
||||
}
|
||||
|
||||
@section PageHeadContent {
|
||||
|
||||
@@ -4,7 +4,8 @@
|
||||
@model BTCPayServer.Models.EmailsViewModel
|
||||
@{
|
||||
var storeId = Context.GetStoreData().Id;
|
||||
ViewData.SetActivePage(StoreNavPages.Emails, StringLocalizer["Email Rules"], storeId);
|
||||
ViewData.SetLayoutModel(new LayoutModel(nameof(StoreNavPages.Emails), StringLocalizer["Email Rules"])
|
||||
.SetCategory(WellKnownCategories.Store));
|
||||
}
|
||||
|
||||
<form method="post" autocomplete="off" permissioned="@Policies.CanModifyStoreSettings">
|
||||
|
||||
@@ -79,7 +79,6 @@ namespace BTCPayServer.Plugins.PointOfSale.Models
|
||||
[Display(Name = "Redirect invoice to redirect url automatically after paid")]
|
||||
public string RedirectAutomatically { get; set; } = string.Empty;
|
||||
|
||||
public string AppId { get; set; }
|
||||
public string SearchTerm { get; set; }
|
||||
|
||||
public SelectList RedirectAutomaticallySelectList =>
|
||||
|
||||
@@ -45,7 +45,6 @@ public partial class UIOfferingController(
|
||||
BTCPayServerEnvironment env,
|
||||
DisplayFormatter displayFormatter,
|
||||
EmailSenderFactory emailSenderFactory,
|
||||
IHtmlHelper htmlHelper,
|
||||
IEnumerable<EmailTriggerViewModel> emailTriggers
|
||||
) : UISubscriptionControllerBase(dbContextFactory, linkGenerator, stringLocalizer, subsService)
|
||||
{
|
||||
|
||||
@@ -16,14 +16,14 @@
|
||||
var appType = SubscriptionsAppType.AppType;
|
||||
var apps = Model.Apps.Where(app => app.AppType == appType).ToList();
|
||||
<li class="nav-item" permission="@Policies.CanModifyMembership">
|
||||
<a asp-area="Subscriptions" asp- asp-controller="UIOffering" asp-action="CreateOffering" asp-route-storeId="@store.Id" class="nav-link @ViewData.ActivePageClass(AppsNavPages.Create, appType)" id="@($"StoreNav-Create{appType}")">
|
||||
<a layout-menu-item="@nameof(SubscriptionsPlugin)" asp-area="Subscriptions" asp- asp-controller="UIOffering" asp-action="CreateOffering" asp-route-storeId="@store.Id">
|
||||
<vc:icon symbol="nav-reporting" />
|
||||
<span text-translate="true">Subscriptions</span>
|
||||
</a>
|
||||
</li>
|
||||
@if (apps.Any())
|
||||
{
|
||||
<li class="nav-item" not-permission="@Policies.CanModifyMembership" permission="@Policies.CanViewStoreSettings">
|
||||
<li layout-menu-item="@nameof(SubscriptionsPlugin)" not-permission="@Policies.CanModifyMembership" permission="@Policies.CanViewStoreSettings">
|
||||
<span class="nav-link">
|
||||
<vc:icon symbol="nav-reporting" />
|
||||
<span text-translate="true">Subscriptions</span>
|
||||
@@ -35,12 +35,12 @@
|
||||
var offeringId = app.Data.GetSettings<SubscriptionsAppType.AppConfig>().OfferingId ?? "";
|
||||
|
||||
<li class="nav-item nav-item-sub" permission="@Policies.CanViewMembership">
|
||||
<a asp-area="Subscriptions" asp-controller="UIOffering" asp-action="Offering" asp-route-storeId="@Model.Store.Id" asp-route-offeringId="@offeringId" asp-route-section="Plans" class="nav-link @ViewData.ActivePageClass(AppsNavPages.Update, @offeringId)" id="@($"StoreNav-Offering-{offeringId}")">
|
||||
<a layout-menu-item="@nameof(SubscriptionsPlugin)-@offeringId" asp-area="Subscriptions" asp-controller="UIOffering" asp-action="Offering" asp-route-storeId="@Model.Store.Id" asp-route-offeringId="@offeringId" asp-route-section="Plans">
|
||||
<span>@app.AppName</span>
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item nav-item-sub" not-permission="@Policies.CanViewMembership">
|
||||
<a asp-area="Subscriptions" asp-controller="UIOffering" asp-action="Offering" asp-route-storeId="@Model.Store.Id" asp-route-offeringId="@offeringId" asp-route-section="Plans" class="nav-link">
|
||||
<a layout-menu-item="@nameof(SubscriptionsPlugin)-@offeringId" asp-area="Subscriptions" asp-controller="UIOffering" asp-action="Offering" asp-route-storeId="@Model.Store.Id" asp-route-offeringId="@offeringId" asp-route-section="Plans" class="nav-link">
|
||||
<span>@app.AppName</span>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
@@ -1,19 +1,12 @@
|
||||
@model AddEditPlanViewModel
|
||||
@using BTCPayServer.Plugins.Subscriptions
|
||||
@model AddEditPlanViewModel
|
||||
|
||||
@{
|
||||
string storeId = (string)this.Context.GetRouteValue("storeId");
|
||||
string offeringId = (string)this.Context.GetRouteValue("offeringId");
|
||||
string submitLabel = "";
|
||||
if (Model.PlanId is null)
|
||||
{
|
||||
ViewData.SetActivePage(AppsNavPages.Update, StringLocalizer["Add plan"], offeringId);
|
||||
submitLabel = StringLocalizer["Create"];
|
||||
}
|
||||
else
|
||||
{
|
||||
ViewData.SetActivePage(AppsNavPages.Update, StringLocalizer["Edit plan"], offeringId);
|
||||
submitLabel = StringLocalizer["Save"];
|
||||
}
|
||||
var title = Model.PlanId is null ? StringLocalizer["Add plan"] : StringLocalizer["Edit plan"];
|
||||
var submitLabel = Model.PlanId is null ? StringLocalizer["Create"] : StringLocalizer["Save"];
|
||||
ViewData.SetLayoutModel(new LayoutModel($"{nameof(SubscriptionsPlugin)}-{offeringId}", title));
|
||||
}
|
||||
|
||||
<form method="post">
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
|
||||
@using BTCPayServer.Abstractions.Models
|
||||
@using BTCPayServer.Client
|
||||
@using BTCPayServer.Controllers
|
||||
@using BTCPayServer.Plugins.Subscriptions
|
||||
@model ConfigureOfferingViewModel
|
||||
|
||||
@{
|
||||
string offeringId = (string)this.Context.GetRouteValue("offeringId");
|
||||
ViewData.SetActivePage(AppsNavPages.Update, StringLocalizer["Configure offering"], offeringId);
|
||||
ViewData.SetLayoutModel(new LayoutModel($"{nameof(SubscriptionsPlugin)}-{offeringId}", StringLocalizer["Configure offering"]));
|
||||
string storeId = (string)this.Context.GetRouteValue("storeId");
|
||||
var deleteModal = new ConfirmModel(StringLocalizer["Delete offering"], StringLocalizer["This offering will be removed from this store."], StringLocalizer["Delete"])
|
||||
{
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
@using BTCPayServer.Services
|
||||
@using BTCPayServer.Plugins.Subscriptions
|
||||
@using BTCPayServer.Services
|
||||
@model CreateOfferingViewModel
|
||||
|
||||
@{
|
||||
ViewData.SetActivePage(StoreNavPages.Subscriptions, StringLocalizer["New offering"]);
|
||||
ViewData.SetLayoutModel(new LayoutModel(nameof(SubscriptionsPlugin), StringLocalizer["New offering"]));
|
||||
}
|
||||
|
||||
<form method="post">
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
@using BTCPayServer.Abstractions.Models
|
||||
@using BTCPayServer.Client
|
||||
@using BTCPayServer.Controllers
|
||||
@using BTCPayServer.Client
|
||||
@using BTCPayServer.Plugins.Emails
|
||||
@using BTCPayServer.Plugins.Subscriptions
|
||||
@using BTCPayServer.Plugins.Subscriptions.Controllers
|
||||
@using BTCPayServer.Services
|
||||
@model SubscriptionsViewModel
|
||||
@@ -11,7 +10,7 @@
|
||||
@{
|
||||
string storeId = (string)this.Context.GetRouteValue("storeId");
|
||||
string offeringId = (string)this.Context.GetRouteValue("offeringId");
|
||||
ViewData.SetActivePage(AppsNavPages.Update, StringLocalizer["Subscriptions"], offeringId);
|
||||
ViewData.SetLayoutModel(new LayoutModel($"{nameof(SubscriptionsPlugin)}-{offeringId}", StringLocalizer["Subscriptions"]));
|
||||
Csp.UnsafeEval();
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
@inject IEnumerable<AvailableWebhookViewModel> Webhooks
|
||||
@{
|
||||
var storeId = Context.GetStoreData().Id;
|
||||
ViewData.SetActivePage(StoreNavPages.Webhooks, StringLocalizer["Webhook"], storeId);
|
||||
ViewData.SetLayoutModel(new LayoutModel(nameof(StoreNavPages.Webhooks), StringLocalizer["Webhooks"]).SetCategory(WellKnownCategories.Store));
|
||||
}
|
||||
|
||||
@section PageHeadContent {
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
@using BTCPayServer.Abstractions.Models
|
||||
@using BTCPayServer.Client
|
||||
@model WebhooksViewModel
|
||||
@{
|
||||
ViewData.SetActivePage(StoreNavPages.Webhooks, StringLocalizer["Webhooks"], Context.GetStoreData().Id);
|
||||
ViewData.SetLayoutModel(new LayoutModel(nameof(StoreNavPages.Webhooks), StringLocalizer["Webhooks"]).SetCategory(WellKnownCategories.Store));
|
||||
}
|
||||
|
||||
<div class="sticky-header">
|
||||
|
||||
@@ -13,10 +13,8 @@
|
||||
|
||||
var storeId = Context.GetRouteValue("storeId") as string;
|
||||
var title = role is null ? StringLocalizer["Create role"] : StringLocalizer["Update Role"];
|
||||
if (storeId is null)
|
||||
ViewData.SetActivePage(ServerNavPages.Roles, title);
|
||||
else
|
||||
ViewData.SetActivePage(StoreNavPages.Roles, title, storeId);
|
||||
var category = storeId is null ? WellKnownCategories.Server : WellKnownCategories.Store;
|
||||
ViewData.SetLayoutModel(new LayoutModel(nameof(StoreNavPages.Roles), title).SetCategory(category));
|
||||
var storePolicies = Policies.AllPolicies.Where(Policies.IsStorePolicy).ToArray();
|
||||
}
|
||||
|
||||
|
||||
@@ -14,14 +14,14 @@
|
||||
var appType = AppService.GetAppType(CrowdfundAppType.AppType)!;
|
||||
var apps = Model.Apps.Where(app => app.AppType == appType.Type).ToList();
|
||||
<li class="nav-item" permission="@Policies.CanModifyStoreSettings">
|
||||
<a asp-area="" asp-controller="UIApps" asp-action="CreateApp" asp-route-storeId="@store.Id" asp-route-appType="@appType.Type" class="nav-link @ViewData.ActivePageClass(AppsNavPages.Create, appType.Type)" id="@($"StoreNav-Create{appType.Type}")">
|
||||
<a layout-menu-item="CreateApp-@appType.Type" asp-area="" asp-controller="UIApps" asp-action="CreateApp" asp-route-storeId="@store.Id" asp-route-appType="@appType.Type">
|
||||
<vc:icon symbol="nav-crowdfund" />
|
||||
<span text-translate="true">Crowdfund</span>
|
||||
</a>
|
||||
</li>
|
||||
@if (apps.Any())
|
||||
{
|
||||
<li class="nav-item" not-permission="@Policies.CanModifyStoreSettings" permission="@Policies.CanViewStoreSettings">
|
||||
<li layout-menu-item="CreateApp-@appType.Type" class="nav-item" not-permission="@Policies.CanModifyStoreSettings" permission="@Policies.CanViewStoreSettings">
|
||||
<span class="nav-link">
|
||||
<vc:icon symbol="nav-crowdfund" />
|
||||
<span text-translate="true">Crowdfund</span>
|
||||
@@ -31,12 +31,12 @@
|
||||
@foreach (var app in apps)
|
||||
{
|
||||
<li class="nav-item nav-item-sub" permission="@Policies.CanViewStoreSettings">
|
||||
<a asp-area="" asp-controller="UICrowdfund" asp-action="UpdateCrowdfund" asp-route-appId="@app.Id" class="nav-link @ViewData.ActivePageClass(AppsNavPages.Update, app.Id)" id="@($"StoreNav-App-{app.Id}")">
|
||||
<a layout-menu-item="@nameof(CrowdfundPlugin)-@app.Id" asp-area="" asp-controller="UICrowdfund" asp-action="UpdateCrowdfund" asp-route-appId="@app.Id">
|
||||
<span>@app.AppName</span>
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item nav-item-sub" not-permission="@Policies.CanViewStoreSettings">
|
||||
<a asp-area="" asp-controller="UICrowdfund" asp-action="ViewCrowdfund" asp-route-appId="@app.Id" class="nav-link">
|
||||
<a layout-menu-item="@nameof(CrowdfundPlugin)-@app.Id" asp-area="" asp-controller="UICrowdfund" asp-action="ViewCrowdfund" asp-route-appId="@app.Id">
|
||||
<span>@app.AppName</span>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
@@ -1,17 +1,18 @@
|
||||
@using System.Globalization
|
||||
@using BTCPayServer.Abstractions.Contracts
|
||||
@using BTCPayServer.Abstractions.Models
|
||||
@using BTCPayServer.Client
|
||||
@using BTCPayServer.TagHelpers
|
||||
@using BTCPayServer.Views.Apps
|
||||
@using Microsoft.AspNetCore.Mvc.TagHelpers
|
||||
@using BTCPayServer.Forms
|
||||
@using BTCPayServer.Plugins.Crowdfund
|
||||
@inject FormDataService FormDataService
|
||||
@inject IFileService FileService
|
||||
@inject BTCPayServer.Security.ContentSecurityPolicies Csp
|
||||
@model BTCPayServer.Plugins.Crowdfund.Models.UpdateCrowdfundViewModel
|
||||
@{
|
||||
ViewData.SetActivePage(AppsNavPages.Update, StringLocalizer["Update Crowdfund"], Model.AppId);
|
||||
// layout-menu-item="@nameof(CrowdfundPlugin)-@app.Id"
|
||||
ViewData.SetLayoutModel(new LayoutModel($"{nameof(CrowdfundPlugin)}-{Model.AppId}", StringLocalizer["Update Crowdfund"]));
|
||||
Csp.UnsafeEval();
|
||||
var canUpload = await FileService.IsAvailable();
|
||||
var checkoutFormOptions = await FormDataService.GetSelect(Model.StoreId, Model.FormId);
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
@if (store.IsLightningEnabled(cryptoCode) && store.IsLNUrlEnabled(cryptoCode))
|
||||
{
|
||||
<li class="nav-item" permission="@Policies.CanModifyStoreSettings">
|
||||
<a asp-area="" asp-controller="UILNURL" asp-action="EditLightningAddress" asp-route-storeId="@store.Id" class="nav-link @ViewData.ActivePageClass("LightningAddress", nameof(StoreNavPages))" id="StoreNav-LightningAddress">
|
||||
<a layout-menu-item="LightningAddress" asp-area="" asp-controller="UILNURL" asp-action="EditLightningAddress" asp-route-storeId="@store.Id">
|
||||
<vc:icon symbol="nav-lightning-address "/>
|
||||
<span text-translate="true">Lightning Address</span>
|
||||
</a>
|
||||
|
||||
@@ -6,10 +6,9 @@
|
||||
@{
|
||||
var storeId = Context.GetRouteValue("storeId") as string;
|
||||
var controller = ViewContext.RouteData.Values["controller"].ToString().TrimEnd("Controller", StringComparison.InvariantCultureIgnoreCase);
|
||||
if (string.IsNullOrEmpty(storeId))
|
||||
ViewData.SetActivePage(ServerNavPages.Roles, StringLocalizer["Roles"]);
|
||||
else
|
||||
ViewData.SetActivePage(StoreNavPages.Roles, StringLocalizer["Roles"], storeId);
|
||||
var category = string.IsNullOrEmpty(storeId) ? WellKnownCategories.Server : WellKnownCategories.Store;
|
||||
ViewData.SetLayoutModel(new LayoutModel(nameof(StoreNavPages.Roles), StringLocalizer["Roles"]).SetCategory(category));
|
||||
|
||||
var permission = string.IsNullOrEmpty(storeId) ? Policies.CanModifyServerSettings : Policies.CanModifyStoreSettings;
|
||||
var nextRoleSortOrder = (string) ViewData["NextRoleSortOrder"];
|
||||
var roleSortOrder = nextRoleSortOrder switch
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
@using BTCPayServer.Views.Stores
|
||||
@using Microsoft.AspNetCore.Mvc.TagHelpers
|
||||
@{
|
||||
ViewData.SetActivePage(StoreNavPages.PayButton, StringLocalizer["Pay Button"], Context.GetStoreData().Id);
|
||||
ViewData.SetLayoutModel(new(nameof(StoreNavPages.PayButton), StringLocalizer["Pay Button"]));
|
||||
}
|
||||
|
||||
<div class="sticky-header">
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
@if (store != null)
|
||||
{
|
||||
<li class="nav-item" permission="@Policies.CanModifyStoreSettings">
|
||||
<a asp-area="" asp-controller="UIPayButton" asp-action="PayButton" asp-route-storeId="@store.Id" class="nav-link @ViewData.ActivePageClass(StoreNavPages.PayButton)" id="StoreNav-PayButton">
|
||||
<a layout-menu-item="PayButton" asp-area="" asp-controller="UIPayButton" asp-action="PayButton" asp-route-storeId="@store.Id">
|
||||
<vc:icon symbol="nav-pay-button"/>
|
||||
<span text-translate="true">Pay Button</span>
|
||||
</a>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
@inject BTCPayNetworkProvider NetworkProvider
|
||||
@model BTCPayServer.Plugins.PayButton.Models.PayButtonViewModel
|
||||
@{
|
||||
ViewData.SetActivePage(StoreNavPages.PayButton, StringLocalizer["Pay Button"], Context.GetStoreData().Id);
|
||||
ViewData.SetLayoutModel(new(nameof(StoreNavPages.PayButton), StringLocalizer["Pay Button"]));
|
||||
Csp.UnsafeEval();
|
||||
}
|
||||
|
||||
|
||||
@@ -14,14 +14,14 @@
|
||||
var appType = AppService.GetAppType(PointOfSaleAppType.AppType)!;
|
||||
var apps = Model.Apps.Where(app => app.AppType == appType.Type).ToList();
|
||||
<li class="nav-item" permission="@Policies.CanModifyStoreSettings">
|
||||
<a asp-area="" asp-controller="UIApps" asp-action="CreateApp" asp-route-storeId="@store.Id" asp-route-appType="@appType.Type" class="nav-link @ViewData.ActivePageClass(AppsNavPages.Create, appType.Type)" id="@($"StoreNav-Create{appType.Type}")">
|
||||
<a layout-menu-item="CreateApp-@appType.Type" asp-area="" asp-controller="UIApps" asp-action="CreateApp" asp-route-storeId="@store.Id" asp-route-appType="@appType.Type">
|
||||
<vc:icon symbol="nav-pointofsale" />
|
||||
<span text-translate="true">Point of Sale</span>
|
||||
</a>
|
||||
</li>
|
||||
@if (apps.Any())
|
||||
{
|
||||
<li class="nav-item" not-permission="@Policies.CanModifyStoreSettings" permission="@Policies.CanViewStoreSettings">
|
||||
<li layout-menu-item="CreateApp-@appType.Type" not-permission="@Policies.CanModifyStoreSettings" permission="@Policies.CanViewStoreSettings">
|
||||
<span class="nav-link">
|
||||
<vc:icon symbol="nav-pointofsale" />
|
||||
<span text-translate="true">Point of Sale</span>
|
||||
@@ -31,12 +31,12 @@
|
||||
@foreach (var app in apps)
|
||||
{
|
||||
<li class="nav-item nav-item-sub" permission="@Policies.CanViewStoreSettings">
|
||||
<a asp-area="" asp-controller="UIPointOfSale" asp-action="UpdatePointOfSale" asp-route-appId="@app.Id" class="nav-link @ViewData.ActivePageClass(AppsNavPages.Update, app.Id)" id="@($"StoreNav-App-{app.Id}")">
|
||||
<a layout-menu-item="@nameof(PointOfSalePlugin)-@app.Id" asp-area="" asp-controller="UIPointOfSale" asp-action="UpdatePointOfSale" asp-route-appId="@app.Id">
|
||||
<span>@app.AppName</span>
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item nav-item-sub" not-permission="@Policies.CanViewStoreSettings">
|
||||
<a asp-area="" asp-controller="UIPointOfSale" asp-action="ViewPointOfSale" asp-route-appId="@app.Id" class="nav-link">
|
||||
<a layout-menu-item="@nameof(PointOfSalePlugin)-@app.Id" asp-area="" asp-controller="UIPointOfSale" asp-action="ViewPointOfSale" asp-route-appId="@app.Id">
|
||||
<span>@app.AppName</span>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
@using BTCPayServer.Abstractions.Models
|
||||
@using BTCPayServer.Views.Apps
|
||||
@using BTCPayServer.Client
|
||||
@using BTCPayServer.Plugins.PointOfSale
|
||||
@@ -9,7 +8,7 @@
|
||||
@inject BTCPayServer.Security.ContentSecurityPolicies Csp
|
||||
@model BTCPayServer.Plugins.PointOfSale.Models.UpdatePointOfSaleViewModel
|
||||
@{
|
||||
ViewData.SetActivePage(AppsNavPages.Update, StringLocalizer["Update Point of Sale"], Model.Id);
|
||||
ViewData.SetLayoutModel(new($"{nameof(PointOfSalePlugin)}-{Model.Id}",StringLocalizer["Update Point of Sale"]));
|
||||
Csp.UnsafeEval();
|
||||
var checkoutFormOptions = await FormDataService.GetSelect(Model.StoreId, Model.FormId);
|
||||
var posPath = Url.Action("ViewPointOfSale", "UIPointOfSale", new { appId = Model.Id });
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
@if (store != null)
|
||||
{
|
||||
<li class="nav-item" permission="@Policies.CanModifyStoreSettings">
|
||||
<a asp-area="" asp-controller="UIShopify" asp-action="EditShopify" asp-route-storeId="@store.Id" class="nav-link @ViewData.ActivePageClass("shopify", nameof(StoreNavPages))" id="StoreNav-Shopify">
|
||||
<a layout-menu-item="Shopify" asp-area="" asp-controller="UIShopify" asp-action="EditShopify" asp-route-storeId="@store.Id">
|
||||
<vc:icon symbol="logo-shopify" />
|
||||
<span text-translate="true">Shopify</span>
|
||||
</a>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
@model CreateAppViewModel
|
||||
@{
|
||||
ViewData.SetActivePage(AppsNavPages.Create, StringLocalizer["Create a new {0}", Model.AppType]);
|
||||
ViewData.SetLayoutModel(new($"CreateApp-{Model.AppType}", StringLocalizer["Create a new {0}", Model.AppType]));
|
||||
}
|
||||
|
||||
@section PageFootContent {
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
@using BTCPayServer.Services.Apps
|
||||
@using BTCPayServer.Abstractions.Models
|
||||
@using BTCPayServer.Client
|
||||
@model ListAppsViewModel
|
||||
@inject AppService AppService
|
||||
@{
|
||||
ViewData.SetActivePage(AppsNavPages.Index, "Apps");
|
||||
ViewData.SetLayoutModel(new(nameof(AppsNavPages), "Apps"));
|
||||
var nextAppNameSortOrder = (string)ViewData["AppNameNextSortOrder"];
|
||||
var nextAppTypeSortOrder = (string)ViewData["AppTypeNextSortOrder"];
|
||||
var nextStoreNameSortOrder = (string)ViewData["StoreNameNextSortOrder"];
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
@using Newtonsoft.Json.Linq
|
||||
@model Fido2NetLib.CredentialCreateOptions
|
||||
@{
|
||||
ViewData.SetActivePage(ManageNavPages.TwoFactorAuthentication, StringLocalizer["Register your security device"]);
|
||||
ViewData.SetLayoutModel(new(nameof(ManageNavPages.TwoFactorAuthentication), StringLocalizer["Register your security device"]));
|
||||
}
|
||||
|
||||
<div class="sticky-header">
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
@using Microsoft.AspNetCore.Mvc.TagHelpers
|
||||
@using BTCPayServer.Abstractions.Models
|
||||
@using BTCPayServer.Client
|
||||
@model List<BTCPayServer.Data.FormData>
|
||||
@{
|
||||
ViewData.SetActivePage(StoreNavPages.Forms, StringLocalizer["Forms"]);
|
||||
ViewData.SetLayoutModel(new LayoutModel(nameof(StoreNavPages.Forms), StringLocalizer["Forms"]).SetCategory(WellKnownCategories.Store));
|
||||
var storeId = Context.GetCurrentStoreId();
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
@using Microsoft.AspNetCore.Mvc.TagHelpers
|
||||
@using BTCPayServer.Abstractions.TagHelpers
|
||||
@{
|
||||
ViewData.SetActivePage(InvoiceNavPages.Create, StringLocalizer["Create Invoice"]);
|
||||
ViewData.SetLayoutModel(new("Invoices", StringLocalizer["Create Invoices"]));
|
||||
}
|
||||
|
||||
@section PageFootContent {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
@using BTCPayServer.Client
|
||||
@model InvoiceDetailsModel
|
||||
@{
|
||||
ViewData["Title"] = StringLocalizer["Invoice {0}", Model.Id];
|
||||
ViewData.SetLayoutModel(new("Invoices", StringLocalizer["Invoice {0}", Model.Id]));
|
||||
}
|
||||
|
||||
@section PageHeadContent {
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
namespace BTCPayServer.Views.Invoice
|
||||
{
|
||||
public enum InvoiceNavPages
|
||||
{
|
||||
Index, Create
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,7 @@
|
||||
@inject DisplayFormatter DisplayFormatter
|
||||
@model InvoicesModel
|
||||
@{
|
||||
ViewData.SetActivePage(InvoiceNavPages.Index, StringLocalizer["Invoices"]);
|
||||
ViewData.SetLayoutModel(new("Invoices", StringLocalizer["Invoices"]));
|
||||
var statusFilterCount = CountArrayFilter("status") + CountArrayFilter("exceptionstatus") + (HasBooleanFilter("includearchived") ? 1 : 0) + (HasBooleanFilter("unusual") ? 1 : 0);
|
||||
var hasDateFilter = HasArrayFilter("startdate") || HasArrayFilter("enddate");
|
||||
var appFilterCount = Model.Apps.Count(app => HasArrayFilter("appid", app.Id));
|
||||
|
||||
@@ -1,3 +1,2 @@
|
||||
@using BTCPayServer.Abstractions.Extensions
|
||||
@using BTCPayServer.Services.Invoices
|
||||
@using BTCPayServer.Views.Invoice
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
@using BTCPayServer.Abstractions.Extensions
|
||||
@using BTCPayServer.Views
|
||||
@using BTCPayServer.Views.Invoice
|
||||
@{
|
||||
ViewData.SetActiveCategory(typeof(InvoiceNavPages));
|
||||
}
|
||||
@@ -1,8 +1,7 @@
|
||||
@using BTCPayServer.Views.Stores
|
||||
@using BTCPayServer.Abstractions.Models
|
||||
@model UILNURLController.EditLightningAddressVM
|
||||
@{
|
||||
ViewData.SetActivePage("LightningAddress", nameof(StoreNavPages), StringLocalizer["Lightning Address"], Context.GetStoreData().Id);
|
||||
ViewData.SetLayoutModel(new LayoutModel("LightningAddress", StringLocalizer["Lightning Address"]).SetCategory(WellKnownCategories.Store));
|
||||
}
|
||||
|
||||
@section PageHeadContent {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
@using LNURL
|
||||
@model Uri
|
||||
@{
|
||||
ViewData.SetActivePage(ManageNavPages.TwoFactorAuthentication, StringLocalizer["Register your Lightning node for LNURL Auth"]);
|
||||
ViewData.SetLayoutModel(new(nameof(ManageNavPages.TwoFactorAuthentication), StringLocalizer["Register your Lightning node for LNURL Auth"]));
|
||||
var formats = new Dictionary<string, string>
|
||||
{
|
||||
{ "Bech32", LNURL.EncodeUri(Model, "login", true).ToString().ToUpperInvariant() },
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
@model BTCPayServer.PayoutProcessors.Lightning.UILightningAutomatedPayoutProcessorsController.LightningTransferViewModel
|
||||
@{
|
||||
var storeId = Context.GetStoreData().Id;
|
||||
ViewData.SetActivePage(StoreNavPages.PayoutProcessors, StringLocalizer["Lightning Payout Processor"], storeId);
|
||||
ViewData.SetLayoutModel(new(nameof(StoreNavPages.PayoutProcessors), StringLocalizer["Lightning Payout Processor"]));
|
||||
}
|
||||
|
||||
<form method="post" permissioned="@Policies.CanModifyStoreSettings">
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
@namespace BTCPayServer.Client
|
||||
@using BTCPayServer.Abstractions.Models
|
||||
@using BTCPayServer.Abstractions.TagHelpers
|
||||
@using BTCPayServer.TagHelpers
|
||||
@using Microsoft.AspNetCore.Html
|
||||
@@ -7,7 +6,8 @@
|
||||
@inject Security.ContentSecurityPolicies Csp
|
||||
@model BTCPayServer.Controllers.UIManageController.ApiKeysViewModel
|
||||
@{
|
||||
ViewData.SetActivePage(ManageNavPages.APIKeys, StringLocalizer["API Keys"]);
|
||||
ViewData.SetLayoutModel(new LayoutModel(nameof(ManageNavPages.APIKeys), StringLocalizer["API Keys"])
|
||||
.SetCategory(nameof(ManageNavPages)));
|
||||
Csp.UnsafeEval();
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
@model UIManageController.AddApiKeyViewModel
|
||||
|
||||
@{
|
||||
ViewData.SetActivePage(ManageNavPages.APIKeys, StringLocalizer["Generate API Key"]);
|
||||
ViewData.SetLayoutModel(new LayoutModel(nameof(ManageNavPages.APIKeys), StringLocalizer["Generate API Key"])
|
||||
.SetCategory(nameof(ManageNavPages)));
|
||||
}
|
||||
|
||||
@section PageHeadContent {
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
var store = string.IsNullOrEmpty(Model.StoreId) ? null : Model.Stores.FirstOrDefault(s => s.Id == Model.StoreId);
|
||||
var permissions = Model.Permissions?.Split(';') ?? Array.Empty<string>();
|
||||
var groupedPermissions = Permission.ToPermissions(permissions).GroupBy(permission => permission.Policy);
|
||||
ViewData["Title"] = $"Authorize {displayName ?? "Application"}";
|
||||
ViewData.SetTitle($"Authorize {displayName ?? "Application"}");
|
||||
Layout = "_LayoutWizard";
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
@model ChangePasswordViewModel
|
||||
@{
|
||||
ViewData.SetActivePage(ManageNavPages.ChangePassword, StringLocalizer["Change your password"]);
|
||||
ViewData.SetLayoutModel(new LayoutModel(nameof(ManageNavPages.ChangePassword), StringLocalizer["Change your password"])
|
||||
.SetCategory(nameof(ManageNavPages)));
|
||||
}
|
||||
|
||||
<form method="post">
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
@{
|
||||
var displayName = Model.ApplicationName ?? Model.ApplicationIdentifier;
|
||||
ViewData["Title"] = $"Authorize {displayName ?? "Application"}";
|
||||
ViewData.SetTitle($"Authorize {displayName ?? "Application"}");
|
||||
Layout = "_LayoutWizard";
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,8 @@
|
||||
@using Microsoft.AspNetCore.Mvc.TagHelpers
|
||||
@model EnableAuthenticatorViewModel
|
||||
@{
|
||||
ViewData.SetActivePage(ManageNavPages.TwoFactorAuthentication, StringLocalizer["Enable Authenticator App"]);
|
||||
ViewData.SetLayoutModel(new LayoutModel(nameof(ManageNavPages.TwoFactorAuthentication), StringLocalizer["Enable Authenticator App"])
|
||||
.SetCategory(nameof(ManageNavPages)));
|
||||
}
|
||||
<div class="sticky-header">
|
||||
<nav aria-label="breadcrumb">
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
@model GenerateRecoveryCodesViewModel
|
||||
@{
|
||||
ViewData.SetActivePage(ManageNavPages.TwoFactorAuthentication, StringLocalizer["Recovery codes"]);
|
||||
ViewData.SetLayoutModel(new LayoutModel(nameof(ManageNavPages.TwoFactorAuthentication), StringLocalizer["Recovery codes"])
|
||||
.SetCategory(nameof(ManageNavPages)));
|
||||
}
|
||||
|
||||
<h2 class="mb-2 mb-lg-3">@ViewData["Title"]</h2>
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
@using BTCPayServer.Abstractions.Contracts
|
||||
@using BTCPayServer.Abstractions.Models
|
||||
@using Microsoft.AspNetCore.Mvc.TagHelpers
|
||||
@inject IFileService FileService
|
||||
@model IndexViewModel
|
||||
@{
|
||||
ViewData.SetActivePage(ManageNavPages.Index, StringLocalizer["Update your account"]);
|
||||
ViewData.SetLayoutModel(new LayoutModel("Account", StringLocalizer["Update your account"])
|
||||
.SetCategory(nameof(ManageNavPages)));
|
||||
var canUpload = await FileService.IsAvailable();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
@inject UserManager<ApplicationUser> UserManager;
|
||||
@{
|
||||
ViewData.SetActivePage(ManageNavPages.LoginCodes, StringLocalizer["Login Codes"]);
|
||||
ViewData.SetLayoutModel(new LayoutModel(nameof(ManageNavPages.LoginCodes), StringLocalizer["Login Codes"])
|
||||
.SetCategory(nameof(ManageNavPages)));
|
||||
}
|
||||
|
||||
<div class="sticky-header">
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
@model BTCPayServer.Controllers.UIManageController.NotificationSettingsViewModel
|
||||
@{
|
||||
ViewData.SetActivePage(ManageNavPages.Notifications, StringLocalizer["Notification Settings"]);
|
||||
ViewData.SetLayoutModel(new LayoutModel(nameof(ManageNavPages.Notifications), StringLocalizer["Notification Settings"])
|
||||
.SetCategory(nameof(ManageNavPages)));
|
||||
}
|
||||
|
||||
<form method="post" asp-action="NotificationSettings">
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
@model BTCPayServer.Models.ManageViewModels.SetPasswordViewModel
|
||||
@{
|
||||
ViewData.SetActivePage(ManageNavPages.ChangePassword, StringLocalizer["Set your password"]);
|
||||
ViewData.SetLayoutModel(new LayoutModel(nameof(ManageNavPages.ChangePassword), StringLocalizer["Set your password"])
|
||||
.SetCategory(nameof(ManageNavPages)));
|
||||
}
|
||||
|
||||
<form method="post">
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
@using BTCPayServer.Abstractions.Models
|
||||
@model TwoFactorAuthenticationViewModel
|
||||
@{
|
||||
ViewData.SetActivePage(ManageNavPages.TwoFactorAuthentication, StringLocalizer["Two-Factor Authentication"]);
|
||||
ViewData.SetLayoutModel(new LayoutModel(nameof(ManageNavPages.TwoFactorAuthentication), StringLocalizer["Two-Factor Authentication"])
|
||||
.SetCategory(nameof(ManageNavPages)));
|
||||
}
|
||||
<div class="sticky-header">
|
||||
<h2 class="my-1">@ViewData["Title"]</h2>
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
@{
|
||||
var storeId = Context.GetStoreData().Id;
|
||||
var cryptoCode = Context.GetRouteValue("cryptocode")?.ToString();
|
||||
ViewData.SetActivePage(StoreNavPages.PayoutProcessors, StringLocalizer["On-Chain Payout Processor"], storeId);
|
||||
ViewData.SetLayoutModel(new(nameof(StoreNavPages.PayoutProcessors), StringLocalizer["On-Chain Payout Processor"]));
|
||||
}
|
||||
|
||||
<form method="post" permissioned="@Policies.CanModifyStoreSettings">
|
||||
|
||||
@@ -11,8 +11,7 @@
|
||||
@model BTCPayServer.Models.PaymentRequestViewModels.UpdatePaymentRequestViewModel
|
||||
@{
|
||||
var checkoutFormOptions = await FormDataService.GetSelect(Model.StoreId, Model.FormId);
|
||||
|
||||
ViewData.SetActivePage(PaymentRequestsNavPages.Create, string.IsNullOrEmpty(Model.Id) ? StringLocalizer["Create Payment Request"] : StringLocalizer["Edit Payment Request"], Model.Id);
|
||||
ViewData.SetLayoutModel(new LayoutModel("PaymentRequests", string.IsNullOrEmpty(Model.Id) ? StringLocalizer["Create Payment Request"] : StringLocalizer["Edit Payment Request"]));
|
||||
}
|
||||
|
||||
@section PageHeadContent {
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
@model BTCPayServer.Models.PaymentRequestViewModels.ListPaymentRequestsViewModel
|
||||
@{
|
||||
Layout = "_Layout";
|
||||
ViewData["Title"] = ViewLocalizer["Payment Requests"];
|
||||
ViewData.SetLayoutModel(new("PaymentRequests", StringLocalizer["Payment Requests"]));
|
||||
var storeId = Context.GetStoreData().Id;
|
||||
var statusFilterCount = CountArrayFilter("status") + (HasBooleanFilter("includearchived") ? 1 : 0);
|
||||
}
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
namespace BTCPayServer.Views.PaymentRequest
|
||||
{
|
||||
public enum PaymentRequestsNavPages
|
||||
{
|
||||
Index, Create
|
||||
}
|
||||
}
|
||||
@@ -1,2 +1 @@
|
||||
@using BTCPayServer.Abstractions.Extensions
|
||||
@using BTCPayServer.Views.PaymentRequest
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
@using BTCPayServer.Abstractions.Extensions
|
||||
@using BTCPayServer.Views
|
||||
@using BTCPayServer.Views.PaymentRequest
|
||||
@{
|
||||
ViewData.SetActiveCategory(typeof(PaymentRequestsNavPages));
|
||||
}
|
||||
@@ -1,11 +1,10 @@
|
||||
@using BTCPayServer.Views.Stores
|
||||
@using Microsoft.AspNetCore.Mvc.TagHelpers
|
||||
@using BTCPayServer.Abstractions.Models
|
||||
@using BTCPayServer.Client
|
||||
@model List<BTCPayServer.PayoutProcessors.UIPayoutProcessorsController.StorePayoutProcessorsView>
|
||||
@{
|
||||
var storeId = Context.GetStoreData().Id;
|
||||
ViewData.SetActivePage(StoreNavPages.PayoutProcessors, StringLocalizer["Payout Processors"], storeId);
|
||||
ViewData.SetLayoutModel(new LayoutModel(nameof(StoreNavPages.PayoutProcessors), StringLocalizer["Payout Processors"]).SetCategory(WellKnownCategories.Store));
|
||||
}
|
||||
<div class="sticky-header">
|
||||
<h2 class="my-1">@ViewData["Title"]</h2>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
@model BTCPayServer.Models.WalletViewModels.UpdatePullPaymentModel
|
||||
@{
|
||||
var storeId = Context.GetStoreData().Id;
|
||||
ViewData.SetActivePage(StoreNavPages.Create, StringLocalizer["Edit Pull Payment"], Model.Id);
|
||||
ViewData.SetLayoutModel(new(nameof(StoreNavPages.Create), StringLocalizer["Edit Pull Payment"]));
|
||||
}
|
||||
|
||||
@section PageHeadContent {
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
@inject BTCPayServer.Security.ContentSecurityPolicies Csp
|
||||
@model StoreReportsViewModel
|
||||
@{
|
||||
ViewData.SetActivePage(StoreNavPages.Reporting, StringLocalizer["Reporting"]);
|
||||
ViewData.SetLayoutModel(new(nameof(StoreNavPages.Reporting), StringLocalizer["Reporting"]));
|
||||
Csp.UnsafeEval();
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
@model BrandingViewModel;
|
||||
@inject IFileService FileService
|
||||
@{
|
||||
ViewData.SetActivePage(ServerNavPages.Branding, StringLocalizer["Branding"]);
|
||||
ViewData.SetLayoutModel(new LayoutModel(nameof(ServerNavPages.Branding), StringLocalizer["Branding"])
|
||||
.SetCategory(WellKnownCategories.Server));
|
||||
var canUpload = await FileService.IsAvailable();
|
||||
var themeExtension = ((ThemeExtension[])Enum.GetValues(typeof(ThemeExtension))).Select(t =>
|
||||
new SelectListItem(typeof(ThemeExtension).DisplayName(t.ToString()), t == ThemeExtension.Custom ? null : t.ToString()));
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
@model LndServicesViewModel
|
||||
@{
|
||||
ViewData.SetActivePage(ServerNavPages.Services, StringLocalizer["Core Lightning {0}", Model.ConnectionType]);
|
||||
ViewData.SetLayoutModel(new LayoutModel(nameof(ServerNavPages.Services), StringLocalizer["Core Lightning {0}", Model.ConnectionType])
|
||||
.SetCategory(WellKnownCategories.Server));
|
||||
}
|
||||
|
||||
<div class="sticky-header">
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
@model LightningWalletServices
|
||||
@{
|
||||
ViewData.SetActivePage(ServerNavPages.Services, StringLocalizer["BTCPay Server Configurator"]);
|
||||
ViewData.SetLayoutModel(new(nameof(ServerNavPages.Services), StringLocalizer["BTCPay Server Configurator"]));
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
@model CreateDictionaryViewModel
|
||||
@{
|
||||
ViewData.SetActivePage(ServerNavPages.Translations, "Create a new dictionary");
|
||||
ViewData.SetLayoutModel(new LayoutModel(nameof(ServerNavPages.Translations), "Create a new dictionary")
|
||||
.SetCategory(WellKnownCategories.Server));
|
||||
}
|
||||
<form method="post">
|
||||
<div class="sticky-header">
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
@using BTCPayServer.Controllers
|
||||
@model BTCPayServer.Controllers.UIServerController.CreateTemporaryFileUrlViewModel
|
||||
@{
|
||||
ViewData.SetActivePage(ServerNavPages.Services, StringLocalizer["Create temporary file link"]);
|
||||
ViewData.SetLayoutModel(new LayoutModel(nameof(ServerNavPages.Services), StringLocalizer["Create temporary file link"])
|
||||
.SetCategory(WellKnownCategories.Server));
|
||||
}
|
||||
|
||||
<form method="post">
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
@using Microsoft.AspNetCore.Mvc.TagHelpers
|
||||
@model BTCPayServer.Controllers.RegisterFromAdminViewModel
|
||||
@{
|
||||
ViewData.SetActivePage(ServerNavPages.Users, StringLocalizer["Create account"]);
|
||||
ViewData.SetLayoutModel(new(nameof(ServerNavPages.Users), StringLocalizer["Create account"]));
|
||||
var canSendEmail = ViewData["CanSendEmail"] is true;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
@model BTCPayServer.Models.ServerViewModels.DynamicDnsViewModel
|
||||
@{
|
||||
ViewData.SetActivePage(ServerNavPages.Services, StringLocalizer["Dynamic DNS Service"]);
|
||||
ViewData.SetLayoutModel(new LayoutModel(nameof(ServerNavPages.Services), StringLocalizer["Dynamic DNS Service"])
|
||||
.SetCategory(WellKnownCategories.Server));
|
||||
}
|
||||
|
||||
@section PageFootContent {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
@using BTCPayServer.Abstractions.Models
|
||||
@model BTCPayServer.Models.ServerViewModels.DynamicDnsViewModel[]
|
||||
@{
|
||||
ViewData.SetActivePage(ServerNavPages.Services, StringLocalizer["Dynamic DNS Settings"]);
|
||||
ViewData.SetLayoutModel(new LayoutModel(nameof(ServerNavPages.Services), StringLocalizer["Dynamic DNS Settings"])
|
||||
.SetCategory(WellKnownCategories.Server));
|
||||
}
|
||||
<div class="sticky-header">
|
||||
<nav aria-label="breadcrumb">
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
@model BTCPayServer.Storage.Services.Providers.AmazonS3Storage.Configuration.AmazonS3StorageConfiguration
|
||||
@{
|
||||
ViewData.SetActivePage(ServerNavPages.Files, StringLocalizer["Amazon S3 Storage"]);
|
||||
ViewData.SetLayoutModel(new LayoutModel(nameof(ServerNavPages.Files), StringLocalizer["Amazon S3 Storage"])
|
||||
.SetCategory(WellKnownCategories.Server));
|
||||
}
|
||||
|
||||
<div class="sticky-header">
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
@model BTCPayServer.Storage.Services.Providers.AzureBlobStorage.Configuration.AzureBlobStorageConfiguration
|
||||
@{
|
||||
ViewData.SetActivePage(ServerNavPages.Files, StringLocalizer["Azure Blob Storage"]);
|
||||
ViewData.SetLayoutModel(new LayoutModel(nameof(ServerNavPages.Files), StringLocalizer["Azure Blob Storage"])
|
||||
.SetCategory(WellKnownCategories.Server));
|
||||
}
|
||||
|
||||
<div class="sticky-header">
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
@model EditDictionaryViewModel
|
||||
@{
|
||||
ViewData.SetActivePage(ServerNavPages.Translations);
|
||||
ViewData["Title"] = Context.GetRouteValue("dictionary");
|
||||
ViewData.SetLayoutModel(new LayoutModel(nameof(ServerNavPages.Translations), Context.GetRouteValue("dictionary") as string)
|
||||
.SetCategory(WellKnownCategories.Server));
|
||||
}
|
||||
|
||||
<form method="post" class="d-flex flex-column">
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
@model BTCPayServer.Storage.Services.Providers.FileSystemStorage.Configuration.FileSystemStorageConfiguration
|
||||
@{
|
||||
ViewData.SetActivePage(ServerNavPages.Files, StringLocalizer["Local Filesystem Storage"]);
|
||||
ViewData.SetLayoutModel(new LayoutModel(nameof(ServerNavPages.Files), StringLocalizer["Local Filesystem Storage"])
|
||||
.SetCategory(WellKnownCategories.Server));
|
||||
}
|
||||
|
||||
<div class="sticky-header">
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
@model BTCPayServer.Storage.Services.Providers.GoogleCloudStorage.Configuration.GoogleCloudStorageConfiguration
|
||||
@{
|
||||
ViewData.SetActivePage(ServerNavPages.Files, StringLocalizer["Google Cloud Storage"]);
|
||||
ViewData.SetLayoutModel(new LayoutModel(nameof(ServerNavPages.Files), StringLocalizer["Google Cloud Storage"])
|
||||
.SetCategory(WellKnownCategories.Server));
|
||||
}
|
||||
|
||||
<div class="sticky-header">
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
@model ServerEmailsViewModel
|
||||
@{
|
||||
ViewData.SetActivePage(ServerNavPages.Emails, StringLocalizer["Emails"]);
|
||||
ViewData.SetLayoutModel(new LayoutModel("Server-" + nameof(ServerNavPages.Emails), StringLocalizer["Emails"]).SetCategory(WellKnownCategories.Server));
|
||||
}
|
||||
|
||||
<form method="post" autocomplete="off">
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
@model ViewFilesViewModel
|
||||
@{
|
||||
ViewData.SetActivePage(ServerNavPages.Files, StringLocalizer["File Storage"]);
|
||||
ViewData.SetLayoutModel(new LayoutModel(nameof(ServerNavPages.Files), StringLocalizer["File Storage"])
|
||||
.SetCategory(WellKnownCategories.Server));
|
||||
}
|
||||
|
||||
<div class="sticky-header">
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
@model ChargeServiceViewModel
|
||||
@{
|
||||
ViewData.SetActivePage(ServerNavPages.Services, StringLocalizer["Lightning Charge Service"]);
|
||||
ViewData.SetLayoutModel(new LayoutModel(nameof(ServerNavPages.Services), StringLocalizer["Lightning Charge Service"])
|
||||
.SetCategory(WellKnownCategories.Server));
|
||||
}
|
||||
|
||||
<div class="sticky-header">
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
@model LightningWalletServices
|
||||
@{
|
||||
ViewData.SetActivePage(ServerNavPages.Services, Model.WalletName);
|
||||
ViewData.SetLayoutModel(new LayoutModel(nameof(ServerNavPages.Services), Model.WalletName)
|
||||
.SetCategory(WellKnownCategories.Server));
|
||||
}
|
||||
|
||||
<div class="sticky-header">
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
@using BTCPayServer.Abstractions.Models
|
||||
@model ListDictionariesViewModel
|
||||
@{
|
||||
ViewData.SetActivePage(ServerNavPages.Translations, StringLocalizer["Dictionaries"]);
|
||||
ViewData.SetLayoutModel(new LayoutModel(nameof(ServerNavPages.Translations), StringLocalizer["Dictionaries"])
|
||||
.SetCategory(WellKnownCategories.Server));
|
||||
}
|
||||
|
||||
<div class="sticky-header">
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
@inject PluginService PluginService
|
||||
@{
|
||||
Layout = "_Layout";
|
||||
ViewData.SetActivePage(ServerNavPages.Plugins);
|
||||
ViewData.SetLayoutModel(new LayoutModel(nameof(ServerNavPages.Plugins), StringLocalizer["Plugins"]));
|
||||
var installed = Model.Installed;
|
||||
var availableAndNotInstalled = new List<PluginService.AvailablePlugin>();
|
||||
var availableAndNotInstalledx = Model.Available
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
@model BTCPayServer.Models.StoreViewModels.ListStoresViewModel
|
||||
@{
|
||||
Layout = "_Layout";
|
||||
ViewData.SetActivePage(ServerNavPages.Stores, StringLocalizer["Store Overview"]);
|
||||
ViewData.SetTitle(StringLocalizer["Store Overview"]);
|
||||
ViewData["StoreList"] = true;
|
||||
}
|
||||
<div class="sticky-header">
|
||||
<h2 class="my-1">@ViewData["Title"]</h2>
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
@using BTCPayServer.Abstractions.Models
|
||||
@inject BTCPayServer.Security.ContentSecurityPolicies Csp
|
||||
@model UsersViewModel
|
||||
@{
|
||||
ViewData.SetActivePage(ServerNavPages.Users, StringLocalizer["Users"]);
|
||||
ViewData.SetLayoutModel(new LayoutModel(nameof(ServerNavPages.Users), StringLocalizer["Users"])
|
||||
.SetCategory(WellKnownCategories.Server));
|
||||
var nextUserEmailSortOrder = (string)ViewData["NextUserEmailSortOrder"];
|
||||
var userEmailSortOrder = nextUserEmailSortOrder switch
|
||||
{
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
@using BTCPayServer.Abstractions.Models
|
||||
@model LndSeedBackupViewModel
|
||||
@{
|
||||
ViewData.SetActivePage(ServerNavPages.Services, StringLocalizer["LND Seed Backup"]);
|
||||
ViewData.SetLayoutModel(new LayoutModel(nameof(ServerNavPages.Services), StringLocalizer["LND Seed Backup"])
|
||||
.SetCategory(WellKnownCategories.Server));
|
||||
}
|
||||
|
||||
<div class="sticky-header">
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
@model LndServicesViewModel
|
||||
@{
|
||||
ViewData.SetActivePage(ServerNavPages.Services, StringLocalizer["LND {0}", Model.ConnectionType]);
|
||||
ViewData.SetLayoutModel(new LayoutModel(nameof(ServerNavPages.Services), StringLocalizer["LND {0}", Model.ConnectionType])
|
||||
.SetCategory(WellKnownCategories.Server));
|
||||
}
|
||||
|
||||
<div class="sticky-header">
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
@model BTCPayServer.Models.ServerViewModels.LogsViewModel
|
||||
@{
|
||||
ViewData.SetActivePage(ServerNavPages.Logs, StringLocalizer["Logs"]);
|
||||
ViewData.SetLayoutModel(new LayoutModel(nameof(ServerNavPages.Logs), StringLocalizer["Logs"])
|
||||
.SetCategory(WellKnownCategories.Server));
|
||||
}
|
||||
|
||||
<div class="sticky-header">
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
@using Microsoft.AspNetCore.Mvc.TagHelpers
|
||||
@model BTCPayServer.Models.ServerViewModels.MaintenanceViewModel
|
||||
@{
|
||||
ViewData.SetActivePage(ServerNavPages.Maintenance, StringLocalizer["Maintenance"]);
|
||||
ViewData.SetLayoutModel(new LayoutModel(nameof(ServerNavPages.Maintenance), StringLocalizer["Maintenance"])
|
||||
.SetCategory(WellKnownCategories.Server));
|
||||
}
|
||||
|
||||
<div class="sticky-header">
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
@model LightningWalletServices
|
||||
@{
|
||||
ViewData.SetActivePage(ServerNavPages.Services, Model.WalletName);
|
||||
ViewData.SetLayoutModel(new LayoutModel(nameof(ServerNavPages.Services), Model.WalletName)
|
||||
.SetCategory(WellKnownCategories.Server));
|
||||
}
|
||||
|
||||
<div class="sticky-header">
|
||||
|
||||
@@ -4,7 +4,8 @@
|
||||
@inject EmailSenderFactory EmailSenderFactory
|
||||
@inject TransactionLinkProviders TransactionLinkProviders
|
||||
@{
|
||||
ViewData.SetActivePage(ServerNavPages.Policies, StringLocalizer["Policies"]);
|
||||
ViewData.SetLayoutModel(new LayoutModel(nameof(ServerNavPages.Policies), StringLocalizer["Policies"])
|
||||
.SetCategory(WellKnownCategories.Server));
|
||||
var linkProviders = TransactionLinkProviders.ToArray();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
@model LightningWalletServices
|
||||
@{
|
||||
ViewData.SetActivePage(ServerNavPages.Services, Model.WalletName);
|
||||
ViewData.SetLayoutModel(new LayoutModel(nameof(ServerNavPages.Services), Model.WalletName)
|
||||
.SetCategory(WellKnownCategories.Server));
|
||||
}
|
||||
|
||||
<div class="sticky-header">
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
@model BTCPayServer.Controllers.ResetUserPasswordFromAdmin
|
||||
@{
|
||||
ViewData.SetActivePage(ServerNavPages.Users, StringLocalizer["Reset Password"]);
|
||||
ViewData.SetLayoutModel(new(nameof(ServerNavPages.Users), StringLocalizer["Reset Password"]));
|
||||
}
|
||||
|
||||
<form method="post" asp-action="ResetUserPassword">
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user