UI: Move section navigation to sidebar (#5744)

* UI: Move section navigation to sidebar

* Scroll active nav link into view

* Move CTAs to top right

* Server Settings: Make Policies first page

* Responsive table fixes

* Spacing fixes

* Add breadcrumb samples

* store settings fixes

* payment request fixes

* updates pull payment title

* adds invoice detail fix

* updates server settings breadcrumbs + copy fix

* Don't open Server Settings on Plugins page

* Add breadcrumbs to pull payment views

* adds breadcrumbs to account

* server and store breadcrumb fixes

* fixes access tokens

* Fix payment processor breadcrumbs

* fixes webhook 404

* Final touches

* Fix test

* Add breadcrumb for email rules page

* Design system updates

---------

Co-authored-by: dstrukt <gfxdsign@gmail.com>
This commit is contained in:
d11n
2024-06-19 15:23:10 +02:00
committed by GitHub
parent aa9e1acb91
commit 0f8da123b8
149 changed files with 2200 additions and 1794 deletions

View File

@@ -12,7 +12,7 @@ namespace BTCPayServer.Abstractions.Extensions
private const string ACTIVE_CATEGORY_KEY = "ActiveCategory";
private const string ACTIVE_PAGE_KEY = "ActivePage";
private const string ACTIVE_ID_KEY = "ActiveId";
private const string ActivePageClass = "active";
private const string ACTIVE_CLASS = "active";
public enum DateDisplayFormat
{
@@ -55,50 +55,63 @@ namespace BTCPayServer.Abstractions.Extensions
viewData[ACTIVE_CATEGORY_KEY] = activeCategory;
}
public static string IsActiveCategory<T>(this ViewDataDictionary viewData, T category, object id = null)
public static bool IsActiveCategory(this ViewDataDictionary viewData, string category, object id = null)
{
return IsActiveCategory(viewData, category.ToString(), id);
}
public static string IsActiveCategory(this ViewDataDictionary viewData, string category, object id = null)
{
if (!viewData.ContainsKey(ACTIVE_CATEGORY_KEY))
{
return null;
}
if (!viewData.ContainsKey(ACTIVE_CATEGORY_KEY)) return false;
var activeId = viewData[ACTIVE_ID_KEY];
var activeCategory = viewData[ACTIVE_CATEGORY_KEY]?.ToString();
var categoryMatch = category.Equals(activeCategory, StringComparison.InvariantCultureIgnoreCase);
var idMatch = id == null || activeId == null || id.Equals(activeId);
return categoryMatch && idMatch ? ActivePageClass : null;
return categoryMatch && idMatch;
}
public static string IsActivePage<T>(this ViewDataDictionary viewData, T page, object id = null)
where T : IConvertible
public static bool IsActiveCategory<T>(this ViewDataDictionary viewData, T category, object id = null)
{
return IsActivePage(viewData, page.ToString(), page.GetType().ToString(), id);
return IsActiveCategory(viewData, category.ToString(), id);
}
public static string IsActivePage<T>(this ViewDataDictionary viewData, IEnumerable<T> pages, object id = null)
where T : IConvertible
public static bool IsActivePage(this ViewDataDictionary viewData, string page, string category, object id = null)
{
return pages.Any(page => IsActivePage(viewData, page.ToString(), page.GetType().ToString(), id) == ActivePageClass)
? ActivePageClass
: null;
}
public static string IsActivePage(this ViewDataDictionary viewData, string page, string category, object id = null)
{
if (!viewData.ContainsKey(ACTIVE_PAGE_KEY))
{
return null;
}
if (!viewData.ContainsKey(ACTIVE_PAGE_KEY)) return false;
var activeId = viewData[ACTIVE_ID_KEY];
var activePage = viewData[ACTIVE_PAGE_KEY]?.ToString();
var activeCategory = viewData[ACTIVE_CATEGORY_KEY]?.ToString();
var categoryAndPageMatch = (category == null || activeCategory.Equals(category, StringComparison.InvariantCultureIgnoreCase)) && page.Equals(activePage, StringComparison.InvariantCultureIgnoreCase);
var categoryAndPageMatch = page.Equals(activePage, StringComparison.InvariantCultureIgnoreCase) &&
(category == null || activeCategory != null && activeCategory.Equals(category, StringComparison.InvariantCultureIgnoreCase));
var idMatch = id == null || activeId == null || id.Equals(activeId);
return categoryAndPageMatch && idMatch ? ActivePageClass : null;
return categoryAndPageMatch && idMatch;
}
public static bool IsActivePage<T>(this ViewDataDictionary viewData, IEnumerable<T> pages, object id = null)
where T : IConvertible
{
return pages.Any(page => ActivePageClass(viewData, page.ToString(), page.GetType().ToString(), id) == ACTIVE_CLASS);
}
public static string ActiveCategoryClass<T>(this ViewDataDictionary viewData, T category, object id = null)
{
return ActiveCategoryClass(viewData, category.ToString(), id);
}
public static string ActiveCategoryClass(this ViewDataDictionary viewData, string category, object id = null)
{
return IsActiveCategory(viewData, category, id) ? ACTIVE_CLASS : null;
}
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);
}
public static string ActivePageClass(this ViewDataDictionary viewData, string page, string category, object id = null)
{
return IsActivePage(viewData, page, category, id) ? ACTIVE_CLASS : null;
}
public static string ActivePageClass<T>(this ViewDataDictionary viewData, IEnumerable<T> pages, object id = null) where T : IConvertible
{
return IsActivePage(viewData, pages, id) ? ACTIVE_CLASS : null;
}
public static HtmlString ToBrowserDate(this DateTimeOffset date, string netFormat, string jsDateFormat = "short", string jsTimeFormat = "short")

View File

@@ -74,14 +74,17 @@ namespace BTCPayServer.Tests
var controller = user.GetController<UIStoresController>();
var lightningVm = (LightningNodeViewModel)Assert.IsType<ViewResult>(controller.SetupLightningNode(user.StoreId, cryptoCode)).Model;
Assert.True(lightningVm.Enabled);
var response = await controller.SetLightningNodeEnabled(user.StoreId, cryptoCode, false);
Assert.IsType<RedirectToActionResult>(response);
// Get enabled state from settings
LightningSettingsViewModel lnSettingsModel;
var response = controller.LightningSettings(user.StoreId, cryptoCode);
var lnSettingsModel = (LightningSettingsViewModel)Assert.IsType<ViewResult>(response).Model;
Assert.NotNull(lnSettingsModel?.ConnectionString);
Assert.True(lnSettingsModel.Enabled);
lnSettingsModel.Enabled = false;
response = await controller.LightningSettings(lnSettingsModel);
Assert.IsType<RedirectToActionResult>(response);
response = controller.LightningSettings(user.StoreId, cryptoCode);
lnSettingsModel = (LightningSettingsViewModel)Assert.IsType<ViewResult>(response).Model;
Assert.NotNull(lnSettingsModel?.ConnectionString);
Assert.False(lnSettingsModel.Enabled);
// Setup wallet

View File

@@ -199,8 +199,7 @@ retry:
Assert.Equal("Recommendation (Kraken)", rateSource.SelectedOption.Text);
rateSource.SelectByText("CoinGecko");
Driver.WaitForElement(By.Id("Create")).Click();
Driver.FindElement(By.Id("StoreNav-StoreSettings")).Click();
Driver.FindElement(By.Id($"SectionNav-{StoreNavPages.General.ToString()}")).Click();
Driver.FindElement(By.Id("StoreNav-General")).Click();
var storeId = Driver.WaitForElement(By.Id("Id")).GetAttribute("value");
if (keepId)
StoreId = storeId;
@@ -330,10 +329,11 @@ retry:
Assert.Contains($"{cryptoCode} Lightning node updated.", FindAlertMessage().Text);
var enabled = Driver.FindElement(By.Id($"{cryptoCode}LightningEnabled"));
if (enabled.Text == "Enable")
if (enabled.Selected == false)
{
enabled.Click();
Assert.Contains($"{cryptoCode} Lightning payments are now enabled for this store.", FindAlertMessage().Text);
Driver.FindElement(By.Id("save")).Click();
Assert.Contains($"{cryptoCode} Lightning settings successfully updated", FindAlertMessage().Text);
}
}
@@ -418,23 +418,11 @@ retry:
WalletId = new WalletId(storeId, WalletId.CryptoCode);
}
Driver.FindElement(By.Id("StoreNav-StoreSettings")).Click();
if (storeNavPage != StoreNavPages.General)
{
switch (storeNavPage)
{
case StoreNavPages.Dashboard:
case StoreNavPages.Payouts:
case StoreNavPages.PayButton:
case StoreNavPages.PullPayments:
Driver.FindElement(By.Id($"StoreNav-{storeNavPage.ToString()}")).Click();
break;
default:
Driver.FindElement(By.Id($"SectionNav-{storeNavPage.ToString()}")).Click();
break;
}
Driver.FindElement(By.Id($"StoreNav-{StoreNavPages.General}")).Click();
}
Driver.FindElement(By.Id($"StoreNav-{storeNavPage}")).Click();
}
public void GoToWalletSettings(string cryptoCode = "BTC")
@@ -450,9 +438,9 @@ retry:
{
Driver.FindElement(By.Id($"StoreNav-Lightning{cryptoCode}")).Click();
// if Lightning is already set up we need to navigate to the settings
if (Driver.PageSource.Contains("id=\"SectionNav-LightningSettings\""))
if (Driver.PageSource.Contains("id=\"StoreNav-LightningSettings\""))
{
Driver.FindElement(By.Id("SectionNav-LightningSettings")).Click();
Driver.FindElement(By.Id("StoreNav-LightningSettings")).Click();
}
}
@@ -614,10 +602,10 @@ retry:
Driver.Navigate().GoToUrl(new Uri(ServerUri, relativeUrl));
}
public void GoToServer(ServerNavPages navPages = ServerNavPages.Index)
public void GoToServer(ServerNavPages navPages = ServerNavPages.Policies)
{
Driver.FindElement(By.Id("Nav-ServerSettings")).Click();
if (navPages != ServerNavPages.Index)
if (navPages != ServerNavPages.Policies)
{
Driver.FindElement(By.Id($"SectionNav-{navPages}")).Click();
}

View File

@@ -63,9 +63,7 @@ namespace BTCPayServer.Tests
s.GoToServer();
s.Driver.AssertNoError();
s.ClickOnAllSectionLinks();
s.GoToServer();
s.Driver.FindElement(By.LinkText("Services")).Click();
s.GoToServer(ServerNavPages.Services);
TestLogs.LogInformation("Let's check if we can access the logs");
s.Driver.FindElement(By.LinkText("Logs")).Click();
s.Driver.FindElement(By.PartialLinkText(".log")).Click();
@@ -257,10 +255,8 @@ namespace BTCPayServer.Tests
await s.StartAsync();
s.RegisterNewUser(true);
s.GoToHome();
s.GoToServer();
s.GoToServer(ServerNavPages.Services);
s.Driver.AssertNoError();
s.Driver.FindElement(By.LinkText("Services")).Click();
TestLogs.LogInformation("Let's if we can access LND's seed");
Assert.Contains("server/services/lndseedbackup/BTC", s.Driver.PageSource);
s.Driver.Navigate().GoToUrl(s.Link("/server/services/lndseedbackup/BTC"));
@@ -609,6 +605,12 @@ namespace BTCPayServer.Tests
// Ensure empty server settings
s.Driver.Navigate().GoToUrl(s.Link("/server/emails"));
if (s.Driver.PageSource.Contains("id=\"ResetPassword\""))
{
s.Driver.FindElement(By.Id("ResetPassword")).Click();
Assert.Contains("Email server password reset", s.FindAlertMessage().Text);
}
s.Driver.FindElement(By.Id("Settings_Login")).Clear();
s.Driver.FindElement(By.Id("Settings_Password")).Clear();
s.Driver.FindElement(By.Id("Settings_From")).Clear();
@@ -3429,7 +3431,7 @@ retry:
Assert.DoesNotContain(guestBadges, element => element.Text.Equals("Default", StringComparison.InvariantCultureIgnoreCase));
Assert.Contains(guestBadges, element => element.Text.Equals("Server-wide", StringComparison.InvariantCultureIgnoreCase));
guestRow.FindElement(By.Id("SetDefault")).Click();
s.FindAlertMessage();
Assert.Contains("Role set default", s.FindAlertMessage().Text);
existingServerRoles = s.Driver.FindElement(By.CssSelector("table")).FindElements(By.CssSelector("tr"));
foreach (var roleItem in existingServerRoles)
@@ -3451,6 +3453,8 @@ retry:
ownerRow.FindElement(By.Id("SetDefault")).Click();
s.FindAlertMessage();
Assert.Contains("Role set default", s.FindAlertMessage().Text);
s.CreateNewStore();
s.GoToStore(StoreNavPages.Roles);
var existingStoreRoles = s.Driver.FindElement(By.CssSelector("table")).FindElements(By.CssSelector("tr"));

View File

@@ -1,9 +1,5 @@
@using BTCPayServer.Abstractions.Extensions;
@using BTCPayServer.Configuration;
@using Microsoft.AspNetCore.Hosting;
@using Microsoft.AspNetCore.Mvc.Routing;
@using Microsoft.AspNetCore.Mvc.ViewFeatures;
@using Microsoft.AspNetCore.Mvc;
@inject IFileVersionProvider FileVersionProvider
@inject BTCPayServerOptions BTCPayServerOptions

View File

@@ -1,6 +1,4 @@
@using BTCPayServer.Payments
@using BTCPayServer.Services.Invoices
@using BTCPayServer.Abstractions.Extensions
@model BTCPayServer.Components.InvoiceStatus.InvoiceStatusViewModel
@inject Dictionary<PaymentMethodId, IPaymentModelExtension> Extensions

View File

@@ -10,7 +10,9 @@
@using BTCPayServer.Plugins
@using BTCPayServer.Services
@using BTCPayServer.Views.Apps
@using BTCPayServer.Configuration
@inject Microsoft.AspNetCore.Http.IHttpContextAccessor HttpContext;
@inject BTCPayServerOptions BtcPayServerOptions
@inject BTCPayServerEnvironment Env
@inject SignInManager<ApplicationUser> SignInManager
@inject PoliciesSettings PoliciesSettings
@@ -30,17 +32,48 @@
<div class="accordion-body">
<ul class="navbar-nav">
<li class="nav-item" permission="@Policies.CanModifyStoreSettings">
<a asp-area="" asp-controller="UIStores" asp-action="Dashboard" asp-route-storeId="@Model.Store.Id" class="nav-link @ViewData.IsActivePage(StoreNavPages.Dashboard)" id="StoreNav-Dashboard">
<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)">
<vc:icon symbol="nav-dashboard"/>
<span>Dashboard</span>
</a>
</li>
<li class="nav-item" permission="@Policies.CanViewStoreSettings">
<a asp-area="" asp-controller="UIStores" asp-action="GeneralSettings" asp-route-storeId="@Model.Store.Id" class="nav-link @ViewData.IsActivePage(new [] {StoreNavPages.Rates, StoreNavPages.CheckoutAppearance, StoreNavPages.General, StoreNavPages.Tokens, StoreNavPages.Users, StoreNavPages.Webhooks, StoreNavPages.PayoutProcessors, StoreNavPages.Emails})" id="StoreNav-StoreSettings">
<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)">
<vc:icon symbol="nav-store-settings"/>
<span>Settings</span>
</a>
</li>
@if (ViewData.IsActivePage([StoreNavPages.General, StoreNavPages.Rates, StoreNavPages.CheckoutAppearance, StoreNavPages.Tokens, StoreNavPages.Users, StoreNavPages.Roles, StoreNavPages.Webhooks, StoreNavPages.PayoutProcessors, StoreNavPages.Emails, StoreNavPages.Forms]))
{
<li class="nav-item nav-item-sub" permission="@Policies.CanModifyStoreSettings">
<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">Rates</a>
</li>
<li class="nav-item nav-item-sub" permission="@Policies.CanModifyStoreSettings">
<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">Checkout Appearance</a>
</li>
<li class="nav-item nav-item-sub" permission="@Policies.CanModifyStoreSettings">
<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">Access Tokens</a>
</li>
<li class="nav-item nav-item-sub" permission="@Policies.CanModifyStoreSettings">
<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">Users</a>
</li>
<li class="nav-item nav-item-sub" permission="@Policies.CanModifyStoreSettings">
<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">Roles</a>
</li>
<li class="nav-item nav-item-sub" permission="@Policies.CanModifyStoreSettings">
<a id="StoreNav-@(nameof(StoreNavPages.Webhooks))" class="nav-link @ViewData.ActivePageClass(StoreNavPages.Webhooks)" asp-controller="UIStores" asp-action="Webhooks" asp-route-storeId="@Model.Store.Id">Webhooks</a>
</li>
<li class="nav-item nav-item-sub" permission="@Policies.CanModifyStoreSettings">
<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">Payout Processors</a>
</li>
<li class="nav-item nav-item-sub" permission="@Policies.CanModifyStoreSettings">
<a id="StoreNav-@(nameof(StoreNavPages.Emails))" class="nav-link @ViewData.ActivePageClass(StoreNavPages.Emails)" asp-controller="UIStores" asp-action="StoreEmailSettings" asp-route-storeId="@Model.Store.Id">Emails</a>
</li>
<li class="nav-item nav-item-sub" permission="@Policies.CanModifyStoreSettings">
<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">Forms</a>
</li>
}
<vc:ui-extension-point location="store-nav" model="@Model"/>
</ul>
</div>
</div>
@@ -56,22 +89,36 @@
@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">
@if (isSetUp && scheme.WalletSupported)
{
<a asp-area="" asp-controller="UIWallets" asp-action="WalletTransactions" asp-route-walletId="@scheme.WalletId" class="nav-link @ViewData.IsActiveCategory(typeof(WalletsNavPages), scheme.WalletId.ToString()) @ViewData.IsActivePage(StoreNavPages.OnchainSettings)" id="@($"StoreNav-Wallet{scheme.Crypto}")">
<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}")">
<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.IsActivePage(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" class="nav-link @ViewData.ActivePageClass(StoreNavPages.OnchainSettings)" id="@($"StoreNav-Wallet{scheme.Crypto}")">
<span class="me-2 btcpay-status btcpay-status--@(scheme.Enabled ? "enabled" : "pending")"></span>
<span>@PrettyName.PrettyName(scheme.PaymentMethodId)</span>
</a>
}
</li>
@if (ViewData.IsActiveCategory(typeof(WalletsNavPages), scheme.WalletId.ToString()) || ViewData.IsActivePage([WalletsNavPages.Settings], scheme.WalletId.ToString()) || ViewData.IsActivePage([StoreNavPages.OnchainSettings], categoryId))
{
<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">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">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">Settings</a>
</li>
<vc:ui-extension-point location="wallet-nav" model="@Model" />
}
}
@foreach (var scheme in Model.LightningNodes)
{
@@ -82,20 +129,26 @@
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.IsActivePage(StoreNavPages.Lightning) @ViewData.IsActivePage(StoreNavPages.LightningSettings)" id="@($"StoreNav-Lightning{scheme.CryptoCode}")">
<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}")">
<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.IsActivePage(StoreNavPages.LightningSettings)" id="@($"StoreNav-Lightning{scheme.CryptoCode}")">
<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}")">
<span class="me-2 btcpay-status btcpay-status--@(scheme.Enabled ? "enabled" : "pending")"></span>
<span>@PrettyName.PrettyName(scheme.PaymentMethodId)</span>
</a>
}
</li>
@if (ViewData.IsActivePage([StoreNavPages.Lightning, StoreNavPages.LightningSettings], $"{Model.Store.Id}-{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">Settings</a>
</li>
<vc:ui-extension-point location="lightning-nav" model="@Model"/>
}
}
<vc:ui-extension-point location="store-wallets-nav" model="@Model"/>
</ul>
@@ -112,25 +165,25 @@
<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.IsActiveCategory(typeof(InvoiceNavPages))" id="StoreNav-Invoices">
<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">
<vc:icon symbol="nav-invoices"/>
<span>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.IsActivePage(StoreNavPages.Reporting)" id="SectionNav-Reporting">
<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">
<vc:icon symbol="nav-reporting" />
<span>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.IsActiveCategory(typeof(PaymentRequestsNavPages))" id="StoreNav-PaymentRequests">
<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">
<vc:icon symbol="nav-payment-requests"/>
<span>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.IsActivePage(StoreNavPages.PullPayments)" id="StoreNav-PullPayments">
<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">
<vc:icon symbol="nav-pull-payments"/>
<span>Pull Payments</span>
</a>
@@ -139,7 +192,7 @@
<a asp-area=""
asp-controller="UIStorePullPayments" asp-action="Payouts"
asp-route-pullPaymentId=""
asp-route-storeId="@Model.Store.Id" class="nav-link @ViewData.IsActivePage(StoreNavPages.Payouts)" id="StoreNav-Payouts">
asp-route-storeId="@Model.Store.Id" class="nav-link @ViewData.ActivePageClass(StoreNavPages.Payouts)" id="StoreNav-Payouts">
<vc:icon symbol="nav-payouts"/>
<span>Payouts</span>
</a>
@@ -168,7 +221,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.IsActivePage(ServerNavPages.Plugins)" id="Nav-ManagePlugins">
<a asp-area="" asp-controller="UIServer" asp-action="ListPlugins" class="nav-link @ViewData.ActivePageClass(ServerNavPages.Plugins)" id="Nav-ManagePlugins">
@if (PluginService.GetDisabledPlugins().Any())
{
<span class="me-2 btcpay-status btcpay-status--disabled"></span>
@@ -183,7 +236,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.IsActivePage(AppsNavPages.Index)" id="Nav-ArchivedApps">
<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">
@Model.ArchivedAppsCount Archived App@(Model.ArchivedAppsCount == 1 ? "" : "s")
</a>
</li>
@@ -234,13 +287,44 @@
{
<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="ListUsers" class="nav-link @ViewData.IsActivePage(ServerNavPages.Users) @ViewData.IsActivePage(ServerNavPages.Emails) @ViewData.IsActivePage(ServerNavPages.Policies) @ViewData.IsActivePage(ServerNavPages.Services) @ViewData.IsActivePage(ServerNavPages.Branding) @ViewData.IsActivePage(ServerNavPages.Maintenance) @ViewData.IsActivePage(ServerNavPages.Logs) @ViewData.IsActivePage(ServerNavPages.Files)" id="Nav-ServerSettings">
<a asp-area="" asp-controller="UIServer" asp-action="Policies" class="nav-link @ViewData.ActivePageClass(ServerNavPages.Policies)" id="Nav-ServerSettings">
<vc:icon symbol="nav-server-settings"/>
<span>Server Settings</span>
</a>
</li>
@if (ViewData.IsActiveCategory(typeof(ServerNavPages)) && !ViewData.IsActivePage([ServerNavPages.Plugins]))
{
<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">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">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">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">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">Branding</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">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">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">Files</a>
</li>
}
<vc:ui-extension-point location="server-nav" model="@Model"/>
<li class="nav-item dropup">
<a class="nav-link @ViewData.IsActiveCategory(typeof(ManageNavPages))" role="button" data-bs-toggle="dropdown" data-bs-auto-close="outside" aria-expanded="false" id="Nav-Account">
<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">
<vc:icon symbol="nav-account"/>
<span>Account</span>
</a>
@@ -268,7 +352,7 @@
</script>
</li>
<li class="border-top py-1 px-3">
<a asp-area="" asp-controller="UIManage" asp-action="Index" class="nav-link @ViewData.IsActiveCategory(typeof(ManageNavPages))" id="Nav-ManageAccount">
<a asp-area="" asp-controller="UIManage" asp-action="Index" class="nav-link" id="Nav-ManageAccount">
<span>Manage Account</span>
</a>
</li>
@@ -279,6 +363,25 @@
</li>
</ul>
</li>
@if (ViewData.IsActiveCategory(typeof(ManageNavPages)) || ViewData.IsActivePage([ManageNavPages.ChangePassword]))
{
<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">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">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">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">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">Login Codes</a>
</li>
<vc:ui-extension-point location="user-nav" model="@Model" />
}
@if (!string.IsNullOrWhiteSpace(Model.ContactUrl))
{
<li class="nav-item">
@@ -291,3 +394,9 @@
</ul>
}
</nav>
<script>
(function () {
const activeEl = document.querySelector('#mainNav .nav-link.active')
if (activeEl) activeEl.scrollIntoView({ block: 'center', inline: 'center' })
})()
</script>

View File

@@ -1,9 +1,7 @@
@using BTCPayServer.Abstractions.Extensions
@using BTCPayServer.Client.Models
@using BTCPayServer.Services
@using BTCPayServer.Services.Invoices
@inject DisplayFormatter DisplayFormatter
@inject PaymentMethodHandlerDictionary PaymentMethodHandlerDictionary
@model BTCPayServer.Components.StoreRecentInvoices.StoreRecentInvoicesViewModel
<div class="widget store-recent-invoices" id="StoreRecentInvoices-@Model.Store.Id">

View File

@@ -1,4 +1,3 @@
@using BTCPayServer.Abstractions.Extensions
@using BTCPayServer.Services
@inject DisplayFormatter DisplayFormatter
@model BTCPayServer.Components.StoreRecentTransactions.StoreRecentTransactionsViewModel

View File

@@ -51,22 +51,22 @@ 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.IsActivePage(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.ActivePageClass(ServerNavPages.Stores) != "active" ? " active" : "")" 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.IsActivePage(StoreNavPages.Create)" id="StoreSelectorCreate">Create Store</a></li>
<li><a asp-controller="UIUserStores" asp-action="CreateStore" class="dropdown-item @ViewData.ActivePageClass(StoreNavPages.Create)" id="StoreSelectorCreate">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.IsActivePage(StoreNavPages.Index)" id="StoreSelectorArchived">@Model.ArchivedCount Archived Store@(Model.ArchivedCount == 1 ? "" : "s")</a></li>
<li><a asp-controller="UIUserStores" asp-action="ListStores" asp-route-archived="true" class="dropdown-item @ViewData.ActivePageClass(StoreNavPages.Index)" id="StoreSelectorArchived">@Model.ArchivedCount Archived Store@(Model.ArchivedCount == 1 ? "" : "s")</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.IsActivePage(ServerNavPages.Stores)" id="StoreSelectorAdminStores">Admin Store Overview</a></li>
<li permission="@Policies.CanModifyServerSettings"><a asp-controller="UIServer" asp-action="ListStores" class="dropdown-item @ViewData.ActivePageClass(ServerNavPages.Stores)" id="StoreSelectorAdminStores">Admin Store Overview</a></li>
*@
</ul>
</div>

View File

@@ -1,13 +1,9 @@
@using BTCPayServer.Services;
@using BTCPayServer.Views.Stores
@using BTCPayServer.Client
@using BTCPayServer.Views.Wallets
@using BTCPayServer.Services
@inject DisplayFormatter DisplayFormatter
@model BTCPayServer.Components.WalletNav.WalletNavViewModel
<div class="d-sm-flex align-items-center justify-content-between">
<a asp-controller="UIWallets" asp-action="WalletTransactions" asp-route-walletId="@Model.WalletId" class="unobtrusive-link">
<h2 class="mb-1">@Model.Label</h2>
<h2 class="my-1">@Model.Label</h2>
<div class="text-muted fw-semibold" data-sensitive>
@DisplayFormatter.Currency(Model.Balance, Model.Network.CryptoCode)
@if (!string.IsNullOrEmpty(Model.BalanceDefaultCurrency))
@@ -16,16 +12,3 @@
}
</div>
</a>
<div class="d-flex gap-3 mt-3 mt-sm-0" permission="@Policies.CanModifyStoreSettings">
@if (!Model.Network.ReadonlyWallet)
{
<a class="btn btn-primary" asp-controller="UIWallets" asp-action="WalletSend" asp-route-walletId="@Model.WalletId" id="WalletNav-Send">Send</a>
}
<a class="btn btn-primary" asp-controller="UIWallets" asp-action="WalletReceive" asp-route-walletId="@Model.WalletId" id="WalletNav-Receive">Receive</a>
<a class="btn btn-secondary @ViewData.IsActivePage(WalletsNavPages.Settings) @ViewData.IsActivePage(StoreNavPages.OnchainSettings)" asp-controller="UIStores" asp-action="WalletSettings" asp-route-cryptoCode="@Model.WalletId.CryptoCode" asp-route-storeId="@Model.WalletId.StoreId" title="Settings" id="WalletNav-Settings">
<vc:icon symbol="settings"/>
</a>
</div>
</div>
<vc:ui-extension-point location="wallet-nav" model="@Model"/>

View File

@@ -5,7 +5,6 @@ using BTCPayServer.Abstractions.Extensions;
using BTCPayServer.Abstractions.Models;
using BTCPayServer.Client;
using BTCPayServer.Data;
using BTCPayServer.Models;
using LNURL;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;

View File

@@ -60,6 +60,7 @@ namespace BTCPayServer.Controllers
Role = roleData.Role
});
}
[HttpPost("server/roles/{role}")]
public async Task<IActionResult> CreateOrEditRole([FromRoute] string role, UpdateRoleViewModel viewModel)
{

View File

@@ -246,16 +246,27 @@ public partial class UIStoresController
}
var network = _explorerProvider.GetNetwork(vm.CryptoCode);
var lnId = PaymentTypes.LN.GetPaymentMethodId(network.CryptoCode);
var lnurlId = PaymentTypes.LNURL.GetPaymentMethodId(network.CryptoCode);
var lightning = GetConfig<LightningPaymentMethodConfig>(lnId, store);
if (lightning == null)
return NotFound();
var needUpdate = false;
var blob = store.GetStoreBlob();
blob.LightningDescriptionTemplate = vm.LightningDescriptionTemplate ?? string.Empty;
blob.LightningAmountInSatoshi = vm.LightningAmountInSatoshi;
blob.LightningPrivateRouteHints = vm.LightningPrivateRouteHints;
blob.OnChainWithLnInvoiceFallback = vm.OnChainWithLnInvoiceFallback;
var lnurlId = PaymentTypes.LNURL.GetPaymentMethodId(vm.CryptoCode);
blob.SetExcluded(lnurlId, !vm.LNURLEnabled);
var lnurl = GetConfig<LNURLPaymentMethodConfig>(PaymentTypes.LNURL.GetPaymentMethodId(vm.CryptoCode), store);
// Lightning
blob.SetExcluded(lnId, !vm.Enabled);
// LNURL
blob.SetExcluded(lnurlId, !vm.LNURLEnabled || !vm.Enabled);
var lnurl = GetConfig<LNURLPaymentMethodConfig>(lnurlId, store);
if (lnurl is null || (
lnurl.UseBech32Scheme != vm.LNURLBech32Mode ||
lnurl.LUD12Enabled != vm.LUD12Enabled))
@@ -284,36 +295,6 @@ public partial class UIStoresController
return RedirectToAction(nameof(LightningSettings), new { vm.StoreId, vm.CryptoCode });
}
[HttpPost("{storeId}/lightning/{cryptoCode}/status")]
[Authorize(Policy = Policies.CanModifyStoreSettings, AuthenticationSchemes = AuthenticationSchemes.Cookie)]
public async Task<IActionResult> SetLightningNodeEnabled(string storeId, string cryptoCode, bool enabled)
{
var store = HttpContext.GetStoreData();
if (store == null)
return NotFound();
var network = _explorerProvider.GetNetwork(cryptoCode);
if (network == null)
return NotFound();
var lightning = GetConfig<LightningPaymentMethodConfig>(PaymentTypes.LN.GetPaymentMethodId(cryptoCode), store);
if (lightning == null)
return NotFound();
var paymentMethodId = PaymentTypes.LN.GetPaymentMethodId(network.CryptoCode);
var storeBlob = store.GetStoreBlob();
storeBlob.SetExcluded(paymentMethodId, !enabled);
if (!enabled)
{
storeBlob.SetExcluded(PaymentTypes.LNURL.GetPaymentMethodId(network.CryptoCode), true);
}
store.SetStoreBlob(storeBlob);
await _storeRepo.UpdateStore(store);
TempData[WellKnownTempData.SuccessMessage] = $"{network.CryptoCode} Lightning payments are now {(enabled ? "enabled" : "disabled")} for this store.";
return RedirectToAction(nameof(LightningSettings), new { storeId, cryptoCode });
}
private bool CanUseInternalLightning(string cryptoCode)
{
return _lightningNetworkOptions.InternalLightningByCryptoCode.ContainsKey(cryptoCode.ToUpperInvariant()) && (User.IsInRole(Roles.ServerAdmin) || _policiesSettings.AllowLightningInternalNodeForAll);

View File

@@ -78,7 +78,6 @@ public partial class UIStoresController
var model = new CreateTokenViewModel();
ViewBag.HidePublicKey = storeId == null;
ViewBag.ShowStores = storeId == null;
ViewBag.ShowMenu = storeId != null;
model.StoreId = storeId;
return View(model);
}
@@ -143,7 +142,6 @@ public partial class UIStoresController
var model = new CreateTokenViewModel();
ViewBag.HidePublicKey = true;
ViewBag.ShowStores = true;
ViewBag.ShowMenu = false;
var stores = (await _storeRepo.GetStoresByUserId(userId)).Where(data => data.HasPermission(userId, Policies.CanModifyStoreSettings)).ToArray();
model.Stores = new SelectList(stores, nameof(CurrentStore.Id), nameof(CurrentStore.StoreName));

View File

@@ -1,6 +1,8 @@
using System.Threading.Tasks;
using BTCPayServer.Abstractions.Constants;
using BTCPayServer.Abstractions.Extensions;
using BTCPayServer.Abstractions.Models;
using BTCPayServer.Client;
using BTCPayServer.Data;
using BTCPayServer.Fido2.Models;
using BTCPayServer.Models;
@@ -13,7 +15,7 @@ using Newtonsoft.Json.Linq;
namespace BTCPayServer.Fido2
{
[Route("fido2")]
[Authorize]
[Authorize(AuthenticationSchemes = AuthenticationSchemes.Cookie, Policy = Policies.CanViewProfile)]
public class UIFido2Controller : Controller
{
private readonly UserManager<ApplicationUser> _userManager;

View File

@@ -1,13 +1,11 @@
@using BTCPayServer.Client
@using BTCPayServer.Views.Server
@using Microsoft.AspNetCore.Mvc.TagHelpers
@using BTCPayServer.Abstractions.Extensions
@using BTCPayServer.Abstractions.TagHelpers
@using BTCPayServer.Controllers
@using BTCPayServer.Views.Stores
@model UpdateRoleViewModel
@{
Layout = "_NavLayout.cshtml";
var role = Context.GetRouteValue("role") as string;
if (role == "create")
@@ -15,23 +13,34 @@
var storeId = Context.GetRouteValue("storeId") as string;
if (storeId is null)
ViewData.SetActivePage(ServerNavPages.Roles, role is null ? "Create role" : "Update role");
ViewData.SetActivePage(ServerNavPages.Roles, role is null ? "Create role" : "Update Role");
else
{
ViewData.SetActivePage(StoreNavPages.Roles, role is null ? "Create role" : "Update role");
ViewData.SetActivePage(StoreNavPages.Roles, role is null ? "Create role" : "Update Role");
}
var storePolicies = Policies.AllPolicies.Where(Policies.IsStorePolicy).ToArray();
}
<h3 class="mb-4">@ViewData["Title"]</h3>
<form method="post">
<div class="sticky-header">
<nav aria-label="breadcrumb">
<ol class="breadcrumb">
<li class="breadcrumb-item">
<a asp-action="ListRoles" asp-route-storeId="@storeId">Roles</a>
</li>
<li class="breadcrumb-item active" aria-current="page">@ViewData["Title"]</li>
</ol>
<h2>@ViewData["Title"]</h2>
</nav>
<button id="Save" type="submit" class="btn btn-primary" name="command" value="Save">Save</button>
</div>
<div class="row">
<div class="col-xxl-constrain">
<form method="post">
@if (!ViewContext.ModelState.IsValid)
{
<div asp-validation-summary="ModelOnly"></div>
}
<div class="form-group" style="max-width:320px">
<label asp-for="Role" class="form-label"></label>
@if (role == null)
@@ -64,10 +73,9 @@
}
</div>
<span asp-validation-for="Policies" class="text-danger"></span>
<button id="Save" type="submit" class="btn btn-primary" name="command" value="Save">Save</button>
</div>
</div>
</form>
</div>
</div>
@{
void RenderTree(KeyValuePair<string, HashSet<string>> policy, KeyValuePair<string, HashSet<string>>[] storePolicyMap, bool isChecked)

View File

@@ -3,7 +3,7 @@
@using BTCPayServer.Views.Apps
@using BTCPayServer.Plugins.Crowdfund
@using BTCPayServer.Services.Apps
@inject AppService AppService;
@inject AppService AppService
@model BTCPayServer.Components.MainNav.MainNavViewModel
@{
var store = Context.GetStoreData();
@@ -14,7 +14,7 @@
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.IsActivePage(AppsNavPages.Create, appType.Type)" id="@($"StoreNav-Create{appType.Type}")">
<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}")">
<vc:icon symbol="nav-crowdfund" />
<span>@appType.Description</span>
</a>
@@ -31,7 +31,7 @@
@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.IsActivePage(AppsNavPages.Update, app.Id)" id="@($"StoreNav-App-{app.Id}")">
<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}")">
<span>@app.AppName</span>
</a>
</li>

View File

@@ -1,5 +1,4 @@
@using System.Globalization
@using BTCPayServer.Abstractions.Extensions
@using BTCPayServer.Abstractions.Models
@using BTCPayServer.Client
@using BTCPayServer.TagHelpers
@@ -27,9 +26,9 @@
}
<form method="post" permissioned="@Policies.CanModifyStoreSettings">
<div class="sticky-header d-sm-flex align-items-center justify-content-between">
<h2 class="mb-0">@ViewData["Title"]</h2>
<div class="d-flex gap-3 mt-3 mt-sm-0">
<div class="sticky-header">
<h2>@ViewData["Title"]</h2>
<div>
<button type="submit" class="btn btn-primary order-sm-1" id="SaveSettings">Save</button>
@if (Model.Archived)
{
@@ -46,8 +45,11 @@
<input type="hidden" asp-for="StoreId" />
<input type="hidden" asp-for="Archived" />
<div asp-validation-summary="ModelOnly"></div>
@if (!ViewContext.ModelState.IsValid)
{
<div asp-validation-summary="ModelOnly"></div>
}
<div class="row">
<div class="col-sm-10 col-md-9 col-xl-7 col-xxl-6">
<div class="row">

View File

@@ -76,7 +76,6 @@
</div>
</div>
</div>
<button type="submit" class="btn btn-primary mt-2" name="command" value="Save" id="Save">Save</button>
</div>
</div>

View File

@@ -1,6 +1,6 @@
@model BTCPayServer.Models.EmailsViewModel
<h3 class="mt-5 mb-3">Testing</h3>
<h3 class="my-3">Testing</h3>
<div class="row">
<div class="col-xl-10 col-xxl-constrain">
<div class="form-group">

View File

@@ -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.IsActivePage("LightningAddress", nameof(StoreNavPages))" id="StoreNav-LightningAddress">
<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">
<vc:icon symbol="nav-lightning-address "/>
<span>Lightning Address</span>
</a>

View File

@@ -4,7 +4,6 @@
@using BTCPayServer.Client
@model BTCPayServer.Models.ServerViewModels.RolesViewModel
@{
Layout = "_NavLayout.cshtml";
var storeId = Context.GetRouteValue("storeId") as string;
var controller = ViewContext.RouteData.Values["controller"].ToString().TrimEnd("Controller", StringComparison.InvariantCultureIgnoreCase);
if (string.IsNullOrEmpty(storeId))
@@ -25,10 +24,11 @@
var showInUseColumn = !Model.Roles.Any(r => r.IsUsed is null);
}
<div class="d-flex align-items-center justify-content-between mb-3">
<h3 class="mb-0">@ViewData["Title"]</h3>
<div class="sticky-header">
<h2>@ViewData["Title"]</h2>
<a class="btn btn-primary" role="button" id="CreateRole" asp-controller="@controller" asp-action="CreateOrEditRole" asp-route-role="create" asp-route-storeId="@storeId" permission="@permission">Add Role</a>
</div>
<partial name="_StatusMessage" />
<div class="table-responsive">
<table class="table table-hover">
@@ -50,7 +50,7 @@
<th>Permissions</th>
@if (showInUseColumn)
{
<th class="text-center">In use</th>
<th class="text-center w-75px">In use</th>
}
<th class="actions-col" permission="@permission">Actions</th>
</tr>

View File

@@ -3,8 +3,11 @@
ViewData.SetActivePage(StoreNavPages.PayButton, "Pay Button", Context.GetStoreData().Id);
}
<div class="sticky-header">
<h2 class="my-1">@ViewData["Title"]</h2>
</div>
<partial name="_StatusMessage" />
<h2 class="mt-1 mb-4">@ViewData["Title"]</h2>
<div class="row">
<div class="col-xl-8 col-xxl-constrain">

View File

@@ -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.IsActivePage(StoreNavPages.PayButton)" id="StoreNav-PayButton">
<a asp-area="" asp-controller="UIPayButton" asp-action="PayButton" asp-route-storeId="@store.Id" class="nav-link @ViewData.ActivePageClass(StoreNavPages.PayButton)" id="StoreNav-PayButton">
<vc:icon symbol="nav-pay-button"/>
<span>Pay Button</span>
</a>

View File

@@ -174,9 +174,12 @@
</script>
}
<div class="sticky-header">
<h2 class="my-1">@ViewData["Title"]</h2>
</div>
<partial name="_StatusMessage" />
<h2 class="mt-1 mb-4">@ViewData["Title"]</h2>
<div id="payButtonCtrl">
<div class="row">
<div class="col-xl-8">

View File

@@ -3,7 +3,7 @@
@using BTCPayServer.Views.Apps
@using BTCPayServer.Plugins.PointOfSale
@using BTCPayServer.Services.Apps
@inject AppService AppService;
@inject AppService AppService
@model BTCPayServer.Components.MainNav.MainNavViewModel
@{
var store = Context.GetStoreData();
@@ -14,7 +14,7 @@
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.IsActivePage(AppsNavPages.Create, appType.Type)" id="@($"StoreNav-Create{appType.Type}")">
<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}")">
<vc:icon symbol="nav-pointofsale" />
<span>@appType.Description</span>
</a>
@@ -31,7 +31,7 @@
@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.IsActivePage(AppsNavPages.Update, app.Id)" id="@($"StoreNav-App-{app.Id}")">
<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}")">
<span>@app.AppName</span>
</a>
</li>

View File

@@ -34,9 +34,9 @@
}
<form method="post" permissioned="@Policies.CanModifyStoreSettings">
<div class="sticky-header d-sm-flex align-items-center justify-content-between">
<h2 class="mb-0">@ViewData["Title"]</h2>
<div class="d-flex gap-3 mt-3 mt-sm-0">
<div class="sticky-header">
<h2>@ViewData["Title"]</h2>
<div>
<button type="submit" class="btn btn-primary order-sm-1" id="SaveSettings">Save</button>
@if (Model.Archived)
{
@@ -58,8 +58,11 @@
<input type="hidden" asp-for="StoreId" />
<input type="hidden" asp-for="Archived" />
<div asp-validation-summary="ModelOnly"></div>
@if (!ViewContext.ModelState.IsValid)
{
<div asp-validation-summary="ModelOnly"></div>
}
<div class="row">
<div class="col-sm-10 col-md-9 col-xl-7 col-xxl-6">
<div class="row">

View File

@@ -1,5 +1,4 @@
@using BTCPayServer.Client
@using BTCPayServer.Abstractions.Extensions
@using BTCPayServer.Views.Stores
@model BTCPayServer.Components.MainNav.MainNavViewModel
@{
@@ -9,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.IsActivePage("shopify", nameof(StoreNavPages))" id="StoreNav-Shopify">
<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">
<vc:icon symbol="logo-shopify" />
<span>Shopify</span>
</a>

View File

@@ -1,4 +1,3 @@
@using BTCPayServer.Abstractions.Extensions
@inject BTCPayServer.Services.BTCPayServerEnvironment _env
<footer class="btcpay-footer d-print-none">

View File

@@ -1,32 +0,0 @@
@using NBitcoin
@{
Layout = "/Views/Shared/_Layout.cshtml";
ViewBag.ShowMenu = ViewBag.ShowMenu ?? true;
if (!ViewData.ContainsKey("NavPartialName"))
{
ViewData["NavPartialName"] = "_Nav";
}
}
@section PageHeadContent {
@await RenderSectionAsync("PageHeadContent", false)
}
@section PageFootContent {
@await RenderSectionAsync("PageFootContent", false)
}
@if (ViewBag.ShowMenu)
{
<partial name="@ViewData["NavPartialName"].ToString()" />
<script>
(function () {
const activeEl = document.querySelector('#SectionNav .nav .active')
if (activeEl) activeEl.scrollIntoView({ block: 'end', inline: 'center' })
})()
</script>
}
<partial name="_StatusMessage" />
@RenderBody()

View File

@@ -10,7 +10,10 @@
</p>
<form asp-action="ForgotPassword" method="post">
@if (!ViewContext.ModelState.IsValid)
{
<div asp-validation-summary="All" class="@(ViewContext.ModelState.ErrorCount.Equals(1) ? "no-marker" : "")"></div>
}
<div class="form-group">
<label asp-for="Email" class="form-label"></label>
<input asp-for="Email" class="form-control" />

View File

@@ -9,7 +9,10 @@
<form asp-route-returnurl="@ViewData["ReturnUrl"]" method="post" id="login-form" asp-action="Login">
<fieldset disabled="@(ViewData.ContainsKey("disabled") ? "disabled" : null)">
@if (!ViewContext.ModelState.IsValid)
{
<div asp-validation-summary="ModelOnly" class="@(ViewContext.ModelState.ErrorCount.Equals(1) ? "no-marker" : "")"></div>
}
<div class="form-group">
<label asp-for="Email" class="form-label"></label>
<input asp-for="Email" class="form-control" required autofocus />

View File

@@ -3,7 +3,10 @@
<div class="twoFaBox">
<h2 class="h3 mb-3">Two-Factor Authentication</h2>
<form method="post" asp-route-returnUrl="@ViewData["ReturnUrl"]" asp-action="LoginWith2fa">
@if (!ViewContext.ModelState.IsValid)
{
<div asp-validation-summary="ModelOnly"></div>
}
<input asp-for="RememberMe" type="hidden"/>
<div class="form-group">
<label asp-for="TwoFactorCode" class="form-label"></label>

View File

@@ -8,7 +8,10 @@
<form asp-route-returnUrl="@ViewData["ReturnUrl"]" asp-route-logon="true" method="post">
<fieldset disabled="@(ViewData.ContainsKey("disabled") ? "disabled" : null)" >
@if (!ViewContext.ModelState.IsValid)
{
<div asp-validation-summary="ModelOnly" class="@(ViewContext.ModelState.ErrorCount.Equals(1) ? "no-marker" : "")"></div>
}
<div class="form-group">
<label asp-for="Email" class="form-label"></label>
<input asp-for="Email" class="form-control" required autofocus />

View File

@@ -6,7 +6,10 @@
}
<form method="post" asp-action="SetPassword">
@if (!ViewContext.ModelState.IsValid)
{
<div asp-validation-summary="All" class="@(ViewContext.ModelState.ErrorCount.Equals(1) ? "no-marker" : "")"></div>
}
<input asp-for="Code" type="hidden" />
<input asp-for="EmailSetInternally" type="hidden" />
@if (Model.EmailSetInternally)

View File

@@ -7,14 +7,19 @@
<partial name="_ValidationScriptsPartial" />
}
<form asp-action="CreateApp" asp-route-appType="@Model.AppType">
<div class="sticky-header">
<h2>@ViewData["Title"]</h2>
<input type="submit" value="Create" class="btn btn-primary" id="Create" />
</div>
<partial name="_StatusMessage" />
<h2 class="mt-1 mb-4">@ViewData["Title"]</h2>
<div class="row">
<div class="col-xl-8 col-xxl-constrain">
<form asp-action="CreateApp" asp-route-appType="@Model.AppType">
@if (!ViewContext.ModelState.IsValid)
{
<div asp-validation-summary="ModelOnly"></div>
}
@if (string.IsNullOrEmpty(Model.AppType))
{
<div class="form-group">
@@ -27,9 +32,6 @@
<input asp-for="AppName" class="form-control" required />
<span asp-validation-for="AppName" class="text-danger"></span>
</div>
<div class="form-group mt-4">
<input type="submit" value="Create" class="btn btn-primary" id="Create" />
</div>
</div>
</form>
</div>
</div>

View File

@@ -32,8 +32,8 @@
<partial name="_StatusMessage" />
<div class="d-sm-flex align-items-center justify-content-between mb-2">
<h2 class="mb-0">
<div class="sticky-header">
<h2>
@ViewData["Title"]
<small>
<a href="https://docs.btcpayserver.org/Apps/" target="_blank" rel="noreferrer noopener" title="More information...">
@@ -41,14 +41,13 @@
</a>
</small>
</h2>
<a asp-action="CreateApp" asp-route-storeId="@Context.GetStoreData().Id" class="btn btn-primary mt-3 mt-sm-0" role="button" id="CreateNewApp">Create a new app</a>
<a asp-action="CreateApp" asp-route-storeId="@Context.GetStoreData().Id" class="btn btn-primary" role="button" id="CreateNewApp">Create a new app</a>
</div>
<div class="row">
<div class="col-lg-12">
<div class="table-responsive-md">
@if (Model.Apps.Any())
{
<table class="table table-hover table-responsive-md">
<table class="table table-hover">
<thead>
<tr>
<th>
@@ -136,6 +135,5 @@
</p>
}
</div>
</div>
<partial name="_Confirm" model="@(new ConfirmModel("Delete app", "This app will be removed from this store.", "Delete"))" />

View File

@@ -3,7 +3,18 @@
ViewData.SetActivePage(ManageNavPages.TwoFactorAuthentication, "Register your security device");
}
<h3 class="mb-3">@ViewData["Title"]</h3>
<div class="sticky-header">
<nav aria-label="breadcrumb">
<ol class="breadcrumb">
<li class="breadcrumb-item">
<a asp-controller="UIManage" asp-action="TwoFactorAuthentication">Two Factor Authentication</a>
</li>
<li class="breadcrumb-item active" aria-current="page">Register Device</li>
</ol>
<h2>@ViewData["Title"]</h2>
</nav>
</div>
<partial name="_StatusMessage" />
<p>Insert your security device and proceed.</p>

View File

@@ -1,4 +0,0 @@
@{
Layout = "../Shared/_NavLayout.cshtml";
ViewData["NavPartialName"] = "../UIManage/_Nav";
}

View File

@@ -3,28 +3,28 @@
@using BTCPayServer.Client
@model List<BTCPayServer.Data.FormData>
@{
Layout = "../Shared/_NavLayout.cshtml";
ViewData["NavPartialName"] = "../UIStores/_Nav";
ViewData.SetActivePage(StoreNavPages.Forms, "Forms");
var storeId = Context.GetCurrentStoreId();
}
<div class="row">
<div class="col-xxl-constrain col-xl-10">
<div class="d-flex align-items-center justify-content-between mb-3">
<h3 class="mb-0">
<div class="sticky-header">
<h2>
<span>@ViewData["Title"]</span>
<a href="https://docs.btcpayserver.org/Forms" target="_blank" rel="noreferrer noopener" title="More information...">
<vc:icon symbol="info" />
</a>
</h3>
</h2>
<a asp-action="Create" asp-route-storeId="@storeId" class="btn btn-primary mt-3 mt-sm-0" role="button" id="CreateForm" permission="@Policies.CanModifyStoreSettings">
Create Form
</a>
</div>
<div class="row">
<div class="col-xxl-constrain col-xl-10">
@if (Model.Any())
{
<table class="table table-hover table-responsive-md">
<div class="table-responsive-md mt-0">
<table class="table table-hover">
<thead>
<tr>
<th>Name</th>
@@ -47,10 +47,11 @@
}
</tbody>
</table>
</div>
}
else
{
<p class="text-secondary mt-3">
<p class="text-secondary">
There are no forms yet.
</p>
}

View File

@@ -6,8 +6,6 @@
Csp.UnsafeEval();
var formId = Context.GetRouteValue("id");
var isNew = formId is null;
Layout = "../Shared/_NavLayout.cshtml";
ViewData["NavPartialName"] = "../UIStores/_Nav";
ViewData.SetActivePage(StoreNavPages.Forms, $"{(isNew ? "Create" : "Edit")} Form", Model.Name);
var storeId = Context.GetCurrentStoreId();
}
@@ -194,16 +192,22 @@
}
<form method="post" asp-action="Modify" asp-route-id="@formId" asp-route-storeId="@storeId">
<div class="row mb-4">
<div class="col-12">
<div class="d-flex align-items-center justify-content-between mb-3">
<h3 class="mb-0">
<span>@ViewData["Title"]</span>
<div class="sticky-header">
<nav aria-label="breadcrumb">
<ol class="breadcrumb">
<li class="breadcrumb-item">
<a asp-controller="UIForms" asp-action="FormsList" asp-route-storeId="@storeId">Forms</a>
</li>
<li class="breadcrumb-item active" aria-current="page">@ViewData["Title"]</li>
</ol>
<h2>
@ViewData["Title"]
<a href="https://docs.btcpayserver.org/Forms" target="_blank" rel="noreferrer noopener" title="More information...">
<vc:icon symbol="info" />
</a>
</h3>
<div class="d-flex gap-3 mt-3 mt-sm-0">
</h2>
</nav>
<div>
<button type="submit" class="btn btn-primary order-sm-1" id="SaveButton">Save</button>
@if (!isNew)
{
@@ -211,7 +215,12 @@
}
</div>
</div>
<div class="row mb-4">
<div class="col-12">
@if (!ViewContext.ModelState.IsValid)
{
<div asp-validation-summary="All"></div>
}
<div class="form-group" style="max-width: 27rem;">
<label asp-for="Name" class="form-label" data-required></label>
<input asp-for="Name" class="form-control" required />

View File

@@ -1,5 +1,4 @@
@model BTCPayServer.Models.InvoicingModels.CreateInvoiceModel
@using BTCPayServer.Services.Apps
@using BTCPayServer.TagHelpers
@using Microsoft.AspNetCore.Mvc.TagHelpers
@using BTCPayServer.Abstractions.TagHelpers
@@ -29,8 +28,16 @@
}
<form asp-action="CreateInvoice" method="post" id="create-invoice-form">
<div class="sticky-header d-flex align-items-center justify-content-between">
<h2 class="mb-0">@ViewData["Title"]</h2>
<div class="sticky-header">
<nav aria-label="breadcrumb">
<ol class="breadcrumb">
<li class="breadcrumb-item">
<a asp-action="ListInvoices" asp-route-storeId="@Model.StoreId">Invoices</a>
</li>
<li class="breadcrumb-item active" aria-current="page">@ViewData["Title"]</li>
</ol>
<h2>@ViewData["Title"]</h2>
</nav>
<input type="submit" value="Create" class="btn btn-primary" id="Create" />
</div>
@@ -38,7 +45,10 @@
<div class="row">
<div class="col-xl-8 col-xxl-constrain">
@if (!ViewContext.ModelState.IsValid)
{
<div asp-validation-summary="ModelOnly"></div>
}
@if (Model.StoreId != null)
{
<input type="hidden" asp-for="StoreId" />

View File

@@ -169,9 +169,17 @@
</div>
}
<div class="sticky-header d-flex flex-wrap gap-3 align-items-center justify-content-between">
<h2 class="mb-0 text-break">@ViewData["Title"]</h2>
<div class="d-flex flex-wrap gap-3 d-print-none">
<div class="sticky-header">
<nav aria-label="breadcrumb">
<ol class="breadcrumb">
<li class="breadcrumb-item">
<a asp-action="ListInvoices" asp-route-storeId="@Model.StoreId">Invoices</a>
</li>
<li class="breadcrumb-item active" aria-current="page">Invoice</li>
</ol>
<h2>@ViewData["Title"]</h2>
</nav>
<div>
@if (Model.ShowCheckout)
{
<a asp-action="Checkout" class="invoice-checkout-link btn btn-primary text-nowrap" asp-route-invoiceId="@Model.Id">Checkout</a>

View File

@@ -100,8 +100,8 @@
@Html.HiddenFor(a => a.Count)
<div class="sticky-header d-sm-flex align-items-center justify-content-between">
<h2 class="mb-0">
<div class="sticky-header">
<h2>
@ViewData["Title"]
<a href="#descriptor" data-bs-toggle="collapse">
<vc:icon symbol="info" />

View File

@@ -1,5 +1,4 @@
@using BTCPayServer.Views.Stores
@using BTCPayServer.Abstractions.Extensions
@using BTCPayServer.Abstractions.Models
@model UILNURLController.EditLightningAddressVM
@{
@@ -26,6 +25,13 @@
</script>
}
<div class="sticky-header">
<h2>@ViewData["Title"]</h2>
<a data-bs-toggle="collapse" data-bs-target="#AddAddress" class="btn btn-primary" role="button">
Add Address
</a>
</div>
<partial name="_StatusMessage" />
@if (Context.Request.PathBase.ToString() != string.Empty)
@@ -37,13 +43,6 @@
</div>
}
<div class="d-flex align-items-center justify-content-between mb-2">
<h2 class="mb-0">@ViewData["Title"]</h2>
<a data-bs-toggle="collapse" data-bs-target="#AddAddress" class="btn btn-primary" role="button">
Add Address
</a>
</div>
<form asp-action="EditLightningAddress" method="post">
@{
var showAddForm = !ViewContext.ViewData.ModelState.IsValid || !string.IsNullOrEmpty(Model.Add?.Username) || Model.Add?.Max != null || Model.Add?.Min != null || !string.IsNullOrEmpty(Model.Add?.CurrencyCode);
@@ -51,7 +50,7 @@
}
<div class="collapse @(showAddForm ? "show": "")" id="AddAddress">
<div class="form-group pt-2">
<div class="form-group">
<label asp-for="Add.Username" class="form-label"></label>
<div class="input-group">
<input asp-for="Add.Username" class="form-control"/>
@@ -106,8 +105,6 @@
@if (Model.Items.Any())
{
<div class="row">
<div class="col">
<table class="table table-hover">
<thead>
<tr>
@@ -154,8 +151,7 @@
}
</td>
<td class="text-end">
<button type="submit" title="Remove" name="command" value="@($"remove:{Model.Items[index].Username}")"
class="btn btn-link px-0 remove" data-bs-toggle="modal" data-bs-target="#ConfirmModal" data-description="The Lightning Address <strong>@Html.Encode(address)</strong> will be removed." data-confirm-input="REMOVE">
<button type="submit" title="Remove" name="command" value="@($"remove:{Model.Items[index].Username}")" class="btn btn-link px-0 remove" data-bs-toggle="modal" data-bs-target="#ConfirmModal" data-description="The Lightning Address <strong>@Html.Encode(address)</strong> will be removed." data-confirm-input="REMOVE">
Remove
</button>
</td>
@@ -163,12 +159,10 @@
}
</tbody>
</table>
</div>
</div>
}
else
{
<p class="text-secondary mt-3">
<p class="text-secondary">
There are no Lightning Addresses yet.
</p>
}

View File

@@ -2,19 +2,20 @@
@model Uri
@{
ViewData.SetActivePage(ManageNavPages.TwoFactorAuthentication, "Register your Lightning node for LNURL Auth");
Dictionary<string, string> formats = new Dictionary<string, string>()
var formats = new Dictionary<string, string>
{
{ "Bech32", LNURL.EncodeUri(Model, "login", true).ToString().ToUpperInvariant() },
{ "URI", LNURL.EncodeUri(Model, "login", false).ToString().ToUpperInvariant() }
};
}
<h3 class="mb-3">@ViewData["Title"]</h3>
<h2 class="mb-2 mb-lg-3">@ViewData["Title"]</h2>
<partial name="_StatusMessage" />
<p>Scan the QR code with your Lightning wallet to link it to your user account.</p>
<div id="info-message" class="d-inline-block">
<ul class="nav justify-content-center my-2">
<ul class="nav justify-content-center btcpay-pills align-items-center gap-2 my-2">
@for (int i = 0; i < formats.Count; i++)
{
var mode = formats.ElementAt(i);

View File

@@ -1,6 +0,0 @@
@{
Layout = "../Shared/_NavLayout.cshtml";
ViewBag.MainTitle = "Manage your account";
ViewData["NavPartialName"] = "../UIManage/_Nav";
}

View File

@@ -1,10 +0,0 @@
@using BTCPayServer.Client
@using BTCPayServer.Views.Stores
@using BTCPayServer.Abstractions.Extensions
<nav id="SectionNav">
<div class="nav">
<a class="nav-link @ViewData.IsActivePage(StoreNavPages.Lightning)" asp-controller="UIStores" asp-action="Lightning" asp-route-storeId="@Context.GetRouteValue("storeId")" asp-route-cryptoCode="@Context.GetRouteValue("cryptoCode")" id="SectionNav-Lightning" permission="@Policies.CanModifyStoreSettings">Lightning</a>
<a class="nav-link @ViewData.IsActivePage(StoreNavPages.LightningSettings)" asp-controller="UIStores" asp-action="LightningSettings" asp-route-storeId="@Context.GetRouteValue("storeId")" asp-route-cryptoCode="@Context.GetRouteValue("cryptoCode")" id="SectionNav-LightningSettings" permission="@Policies.CanModifyStoreSettings">Settings</a>
<vc:ui-extension-point location="lightning-nav" model="@Model"/>
</div>
</nav>

View File

@@ -3,21 +3,31 @@
@using Microsoft.AspNetCore.Mvc.TagHelpers
@model BTCPayServer.PayoutProcessors.Lightning.UILightningAutomatedPayoutProcessorsController.LightningTransferViewModel
@{
ViewData["NavPartialName"] = "../UIStores/_Nav";
Layout = "../Shared/_NavLayout.cshtml";
ViewData.SetActivePage(StoreNavPages.PayoutProcessors, "Lightning Payout Processor", Context.GetStoreData().Id);
var storeId = Context.GetStoreData().Id;
ViewData.SetActivePage(StoreNavPages.PayoutProcessors, "Lightning Payout Processor", storeId);
}
<form method="post" permissioned="@Policies.CanModifyStoreSettings">
<div class="sticky-header">
<nav aria-label="breadcrumb">
<ol class="breadcrumb">
<li class="breadcrumb-item">
<a asp-controller="UIPayoutProcessors" asp-action="ConfigureStorePayoutProcessors" asp-route-storeId="@storeId">Payout Processors</a>
</li>
<li class="breadcrumb-item active" aria-current="page">@ViewData["Title"]</li>
</ol>
<h2>@ViewData["Title"]</h2>
</nav>
<button name="command" type="submit" class="btn btn-primary" value="Save" id="Save">Save</button>
</div>
<partial name="_StatusMessage" />
<div class="row">
<div class="col-xl-8 col-xxl-constrain">
<div class="d-flex align-items-center justify-content-between mb-3">
<h3 class="mb-0">@ViewData["Title"]</h3>
</div>
<p>Set a schedule for automated Lightning Network Payouts.</p>
@if (!ViewContext.ModelState.IsValid)
{
<div asp-validation-summary="All"></div>
}
<form method="post" permissioned="@Policies.CanModifyStoreSettings">
<div class="d-flex my-3">
<input asp-for="ProcessNewPayoutsInstantly" type="checkbox" class="btcpay-toggle me-3" />
<label asp-for="ProcessNewPayoutsInstantly" class="form-check-label">Process approved payouts instantly</label>
@@ -40,11 +50,9 @@
</div>
<div class="form-text">If a payout fails this many times, it will be cancelled.</div>
</div>
<button name="command" type="submit" class="btn btn-primary mt-2" value="Save" id="Save">Save</button>
</div>
</div>
</form>
</div>
</div>
@section PageFootContent {
<partial name="_ValidationScriptsPartial" />

View File

@@ -7,14 +7,15 @@
Csp.UnsafeEval();
}
<div class="row">
<div class="col-xl-10 col-xxl-constrain">
<div class="d-flex align-items-center justify-content-between mb-3">
<h3 class="mb-0">@ViewData["Title"]</h3>
<div class="sticky-header">
<h2>@ViewData["Title"]</h2>
<a class="btn btn-primary" asp-action="AddApiKey" id="AddApiKey">
Generate Key
</a>
</div>
<partial name="_StatusMessage" />
<div class="row">
<div class="col-xl-10 col-xxl-constrain">
<p>
The <a asp-controller="UIHome" asp-action="SwaggerDocs" target="_blank">BTCPay Server Greenfield API</a> offers programmatic access to your instance. You can manage your BTCPay
Server (e.g. stores, invoices, users) as well as automate workflows and integrations (see <a href="https://docs.btcpayserver.org/Development/GreenFieldExample/" rel="noreferrer noopener">use case examples</a>).

View File

@@ -25,15 +25,26 @@
</script>
}
<h3 class="mb-3">@ViewData["Title"]</h3>
<form method="post" asp-action="AddApiKey" id="Permissions">
<div class="sticky-header">
<nav aria-label="breadcrumb">
<ol class="breadcrumb">
<li class="breadcrumb-item">
<a asp-action="APIKeys">API Keys</a>
</li>
<li class="breadcrumb-item active" aria-current="page">@ViewData["Title"]</li>
</ol>
<h2>@ViewData["Title"]</h2>
</nav>
<button type="submit" class="btn btn-primary" id="Generate">Generate API Key</button>
</div>
<p>Generate a new api key to use BTCPay through its API.</p>
<div class="row">
<div class="col-xl-10 col-xxl-constrain">
<p>Generate a new api key to use BTCPay through its API.</p>
<form method="post" asp-action="AddApiKey" id="Permissions">
@if (!ViewContext.ModelState.IsValid)
{
<div asp-validation-summary="All"></div>
}
<div class="form-group">
<label asp-for="Label" class="form-label"></label>
<input asp-for="Label" class="form-control"/>
@@ -133,8 +144,6 @@
}
}
</div>
<button type="submit" class="btn btn-primary" id="Generate">Generate API Key</button>
</div>
</div>
</form>
</div>
</div>

View File

@@ -43,7 +43,10 @@
<h1>@ViewData["Title"]</h1>
<p class="lead text-secondary mt-3">@(displayName ?? "An application") is requesting access to your BTCPay Server account.</p>
</header>
@if (!ViewContext.ModelState.IsValid)
{
<div asp-validation-summary="All"></div>
}
@if (Model.NeedsStorePermission && store == null)
{

View File

@@ -2,14 +2,19 @@
@{
ViewData.SetActivePage(ManageNavPages.ChangePassword, "Change your password");
}
<h3 class="mb-4">@ViewData["Title"]</h3>
<form method="post">
<div class="sticky-header">
<h2>@ViewData["Title"]</h2>
<button type="submit" class="btn btn-primary" id="UpdatePassword">Update Password</button>
</div>
<partial name="_StatusMessage" />
<div class="row">
<div class="col-xl-8 col-xxl-constrain">
@if (!ViewContext.ModelState.IsValid)
{
<div asp-validation-summary="All"></div>
}
<form method="post">
<div class="form-group">
<label asp-for="OldPassword" class="form-label" data-required></label>
<input asp-for="OldPassword" class="form-control"/>
@@ -25,10 +30,9 @@
<input asp-for="ConfirmPassword" class="form-control"/>
<span asp-validation-for="ConfirmPassword" class="text-danger"></span>
</div>
<button type="submit" class="btn btn-primary mt-2" id="UpdatePassword">Update Password</button>
</div>
</div>
</form>
</div>
</div>
@section PageFootContent {
<partial name="_ValidationScriptsPartial" />

View File

@@ -1,11 +1,21 @@
@model EnableAuthenticatorViewModel
@{
ViewData.SetActivePage(ManageNavPages.TwoFactorAuthentication, "Enable authenticator app");
ViewData.SetActivePage(ManageNavPages.TwoFactorAuthentication, "Enable Authenticator App");
}
<div class="col-xl-8 col-xxl-constrain">
<h3>Enable Authenticator</h3>
<div class="sticky-header">
<nav aria-label="breadcrumb">
<ol class="breadcrumb">
<li class="breadcrumb-item">
<a asp-action="TwoFactorAuthentication">Two Factor Authentication</a>
</li>
<li class="breadcrumb-item active" aria-current="page">@ViewData["Title"]</li>
</ol>
<h2>@ViewData["Title"]</h2>
</nav>
</div>
<partial name="_StatusMessage" />
<p class="my-3">To use an authenticator app go through the following steps:</p>
<div class="col-xl-8 col-xxl-constrain">
<ol class="ps-3">
<li class="mb-5">
<div class="mb-2">Download a two-factor authenticator app like …</div>

View File

@@ -3,6 +3,9 @@
ViewData.SetActivePage(ManageNavPages.TwoFactorAuthentication, "Recovery codes");
}
<h2 class="mb-2 mb-lg-3">@ViewData["Title"]</h2>
<partial name="_StatusMessage" />
<div class="alert alert-warning" role="alert">
<h5>
<vc:icon symbol="warning" />
@@ -14,7 +17,7 @@
</div>
<div class="row">
<div class="col-md-12">
@for(var row = 0; row < Model.RecoveryCodes.Count(); row += 2)
@for(var row = 0; row < Model.RecoveryCodes.Length; row += 2)
{
<code>@Model.RecoveryCodes[row]</code><text>&nbsp;</text><code>@Model.RecoveryCodes[row + 1]</code><br />
}

View File

@@ -3,10 +3,15 @@
@{
ViewData.SetActivePage(ManageNavPages.Index, "Update your account");
}
<h3 class="mb-4">@ViewData["Title"]</h3>
<div class="col-xxl-constrain col-xl-8">
<form method="post">
<div class="sticky-header">
<h2>@ViewData["Title"]</h2>
<button type="submit" id="save" class="btn btn-primary">Save</button>
</div>
<partial name="_StatusMessage" />
<div class="col-xxl-constrain col-xl-8">
@if (!ViewContext.ModelState.IsValid)
{
<div asp-validation-summary="All"></div>
@@ -37,14 +42,12 @@
}
</div>
</div>
<button type="submit" id="save" class="btn btn-primary mt-2">Save</button>
<h3 class="mt-5 mb-4">Delete Account</h3>
<div id="danger-zone">
<a id="delete-user" class="btn btn-outline-danger mb-5" data-confirm-input="DELETE" data-bs-toggle="modal" data-bs-target="#ConfirmModal" asp-action="DeleteUserPost" data-description="This action will also delete all stores, invoices, apps and data associated with the user.">Delete Account</a>
</div>
</form>
</div>
</form>
<partial name="_Confirm"
model="@(new ConfirmModel("Delete user", "The user will be permanently deleted. This action will also delete all stores, invoices, apps and data associated with your user.", "Delete", actionName: nameof(BTCPayServer.Controllers.UIManageController.DeleteUserPost)))"/>

View File

@@ -2,7 +2,12 @@
@{
ViewData.SetActivePage(ManageNavPages.LoginCodes, "Login Codes");
}
<h3 class="mb-3">@ViewData["Title"]</h3>
<div class="sticky-header">
<h2>@ViewData["Title"]</h2>
<a class="btn btn-primary" id="regeneratecode" asp-action="LoginCodes">Regenerate code</a>
</div>
<partial name="_StatusMessage" />
<p>Easily log into BTCPay Server on another device using a simple login code from an already authenticated device.</p>
<div class="d-inline-flex flex-column" style="width:256px">
<div class="qr-container mb-2">
@@ -13,7 +18,6 @@
<div class="progress only-for-js" data-bs-toggle="tooltip" data-bs-placement="top">
<div class="progress-bar progress-bar-striped progress-bar-animated" role="progressbar" style="width:100%" id="progressbar"></div>
</div>
<a class="btn btn-secondary mt-3" id="regeneratecode" asp-action="LoginCodes">Regenerate code</a>
</div>
@section PageFootContent

View File

@@ -2,11 +2,15 @@
@{
ViewData.SetActivePage(ManageNavPages.Notifications, "Notification Settings");
}
<h3 class="mb-3">@ViewData["Title"]</h3>
<form method="post" asp-action="NotificationSettings">
<div class="sticky-header">
<h2>@ViewData["Title"]</h2>
<button type="submit" class="btn btn-primary" name="command" value="update">Save</button>
</div>
<partial name="_StatusMessage" />
<div class="row">
<div class="col-xl-8 col-xxl-constrain">
<form method="post" asp-action="NotificationSettings">
@if (Model.All)
{
<p>All notifications are disabled.</p>
@@ -27,13 +31,12 @@
</div>
}
<div class="mt-4">
<button type="submit" class="btn btn-primary" name="command" value="update">Save</button>
<button type="submit" class="btn btn-secondary ms-3" name="command" value="disable-all">Disable all notifications</button>
<button type="submit" class="btn btn-secondary" name="command" value="disable-all">Disable all notifications</button>
</div>
}
</div>
</div>
</form>
</div>
</div>
<script>
function toggleAllCheckboxes(checkbox) {

View File

@@ -1,9 +1,14 @@
@model BTCPayServer.Models.ManageViewModels.SetPasswordViewModel
@{
ViewData.SetActivePage(ManageNavPages.ChangePassword, "Set password");
ViewData.SetActivePage(ManageNavPages.ChangePassword, "Set your password");
}
<h3>Set your password</h3>
<form method="post">
<div class="sticky-header">
<h2>@ViewData["Title"]</h2>
<button type="submit" class="btn btn-primary">Set Password</button>
</div>
<partial name="_StatusMessage" />
<p class="text-info">
You do not have a local username/password for this site. Add a local
@@ -11,8 +16,10 @@
</p>
<div class="row">
<div class="col-md-6">
<form method="post">
@if (!ViewContext.ModelState.IsValid)
{
<div asp-validation-summary="All"></div>
}
<div class="form-group">
<label asp-for="NewPassword" class="form-label"></label>
<input asp-for="NewPassword" class="form-control" />
@@ -23,10 +30,9 @@
<input asp-for="ConfirmPassword" class="form-control" />
<span asp-validation-for="ConfirmPassword" class="text-danger"></span>
</div>
<button type="submit" class="btn btn-primary">Set Password</button>
</div>
</div>
</form>
</div>
</div>
@section PageFootContent {
<partial name="_ValidationScriptsPartial" />

View File

@@ -1,11 +1,12 @@
@using Fido2NetLib
@using BTCPayServer.Abstractions.Models
@model TwoFactorAuthenticationViewModel
@{
ViewData.SetActivePage(ManageNavPages.TwoFactorAuthentication, "Two-Factor Authentication");
}
<h3 class="mb-3">@ViewData["Title"]</h3>
<div class="sticky-header">
<h2 class="my-1">@ViewData["Title"]</h2>
</div>
<partial name="_StatusMessage" />
<div class="row">
<div class="col-xl-8 col-xxl-constrain">
<p>

View File

@@ -1,16 +0,0 @@
@inject SignInManager<ApplicationUser> SignInManager
<div class="sticky-header mb-l">
<h2 class="mt-1 mb-2 mb-lg-4">Account Settings</h2>
<nav id="SectionNav">
<div class="nav">
<a id="SectionNav-@ManageNavPages.Index.ToString()" class="nav-link @ViewData.IsActivePage(ManageNavPages.Index)" asp-controller="UIManage" asp-action="Index">Account</a>
<a id="SectionNav-@ManageNavPages.ChangePassword.ToString()" class="nav-link @ViewData.IsActivePage(ManageNavPages.ChangePassword)" asp-controller="UIManage" asp-action="ChangePassword">Password</a>
<a id="SectionNav-@ManageNavPages.TwoFactorAuthentication.ToString()" class="nav-link @ViewData.IsActivePage(ManageNavPages.TwoFactorAuthentication)" asp-controller="UIManage" asp-action="TwoFactorAuthentication">Two-Factor Authentication</a>
<a id="SectionNav-@ManageNavPages.APIKeys.ToString()" class="nav-link @ViewData.IsActivePage(ManageNavPages.APIKeys)" asp-controller="UIManage" asp-action="APIKeys">API Keys</a>
<a id="SectionNav-@ManageNavPages.Notifications.ToString()" class="nav-link @ViewData.IsActivePage(ManageNavPages.Notifications)" asp-controller="UIManage" asp-action="NotificationSettings">Notifications</a>
<a id="SectionNav-@ManageNavPages.LoginCodes.ToString()" class="nav-link @ViewData.IsActivePage(ManageNavPages.LoginCodes)" asp-controller="UIManage" asp-action="LoginCodes">Login Codes</a>
<vc:ui-extension-point location="user-nav" model="@Model"/>
</div>
</nav>
</div>

View File

@@ -2,6 +2,5 @@
@using BTCPayServer.Views
@using BTCPayServer.Views.Manage
@{
Layout = "../Shared/_NavLayout.cshtml";
ViewData.SetActiveCategory(typeof(ManageNavPages));
}

View File

@@ -1,18 +1,17 @@
@using BTCPayServer.Views.Stores
@using BTCPayServer.Abstractions.Extensions
@using MoneroLikePaymentMethodViewModel = BTCPayServer.Services.Altcoins.Monero.UI.UIMoneroLikeStoreController.MoneroLikePaymentMethodViewModel
@using MoneroLikeSettlementThresholdChoice = BTCPayServer.Services.Altcoins.Monero.UI.UIMoneroLikeStoreController.MoneroLikeSettlementThresholdChoice;
@model MoneroLikePaymentMethodViewModel
@{
Layout = "../Shared/_NavLayout.cshtml";
ViewData["NavPartialName"] = "../UIStores/_Nav";
ViewData.SetActivePage(Model.CryptoCode, $"{Model.CryptoCode} Settings", Model.CryptoCode);
}
<div class="row">
<div class="col-md-8">
@if (!ViewContext.ModelState.IsValid)
{
<div asp-validation-summary="All"></div>
}
@if (Model.Summary != null)
{
<div class="card">

View File

@@ -1,18 +1,18 @@
@using BTCPayServer.Views.Stores
@using BTCPayServer.Abstractions.Extensions
@model BTCPayServer.Services.Altcoins.Monero.UI.UIMoneroLikeStoreController.MoneroLikePaymentMethodListViewModel
@{
Layout = "../Shared/_NavLayout.cshtml";
ViewData.SetActivePage("Monero Settings", "Monero Settings", "Monero Settings");
ViewData["NavPartialName"] = "../UIStores/_Nav";
}
<div class="row">
<div class="col-md-8">
<div asp-validation-summary="All" class="text-danger"></div>
<div class="form-group">
<table class="table table-hover table-responsive-md">
@if (!ViewContext.ModelState.IsValid)
{
<div asp-validation-summary="All"></div>
}
<div class="table-responsive-md">
<table class="table table-hover">
<thead>
<tr>
<th>Crypto</th>

View File

@@ -3,22 +3,32 @@
@using Microsoft.AspNetCore.Mvc.TagHelpers
@model BTCPayServer.PayoutProcessors.OnChain.UIOnChainAutomatedPayoutProcessorsController.OnChainTransferViewModel
@{
ViewData["NavPartialName"] = "../UIStores/_Nav";
Layout = "../Shared/_NavLayout.cshtml";
ViewData.SetActivePage(StoreNavPages.PayoutProcessors, "On-Chain Payout Processor", Context.GetStoreData().Id);
var storeId = Context.GetStoreData().Id;
var cryptoCode = Context.GetRouteValue("cryptocode")?.ToString();
ViewData.SetActivePage(StoreNavPages.PayoutProcessors, "On-Chain Payout Processor", storeId);
}
<form method="post" permissioned="@Policies.CanModifyStoreSettings">
<div class="sticky-header">
<nav aria-label="breadcrumb">
<ol class="breadcrumb">
<li class="breadcrumb-item">
<a asp-controller="UIPayoutProcessors" asp-action="ConfigureStorePayoutProcessors" asp-route-storeId="@storeId">Payout Processors</a>
</li>
<li class="breadcrumb-item active" aria-current="page">@ViewData["Title"]</li>
</ol>
<h2>@ViewData["Title"]</h2>
</nav>
<button name="command" type="submit" class="btn btn-primary" value="Save" id="Save">Save</button>
</div>
<partial name="_StatusMessage" />
<div class="row">
<div class="col-xl-8 col-xxl-constrain">
<div class="d-flex align-items-center justify-content-between mb-3">
<h3 class="mb-0">@ViewData["Title"]</h3>
</div>
<p>Set a schedule for automated On-Chain Bitcoin Payouts. </p>
@if (!ViewContext.ModelState.IsValid)
{
<div asp-validation-summary="All"></div>
}
<form method="post" permissioned="@Policies.CanModifyStoreSettings">
<div class="d-flex my-3">
<input asp-for="ProcessNewPayoutsInstantly" type="checkbox" class="btcpay-toggle me-3" />
<label asp-for="ProcessNewPayoutsInstantly" class="form-check-label">Process approved payouts instantly</label>
@@ -49,10 +59,9 @@
</div>
<div class="form-text">Only process payouts when this payout sum is reached.</div>
</div>
<button name="command" type="submit" class="btn btn-primary mt-2" value="Save" id="Save">Save</button>
</div>
</div>
</form>
</div>
</div>
@section PageFootContent {
<partial name="_ValidationScriptsPartial" />

View File

@@ -22,9 +22,17 @@
}
<form method="post" action="@Url.Action("EditPaymentRequest", "UIPaymentRequest", new { storeId = Model.StoreId, payReqId = Model.Id }, Context.Request.Scheme)">
<div class="sticky-header d-sm-flex align-items-center justify-content-between">
<h2 class="mb-0">@ViewData["Title"]</h2>
<div class="d-flex gap-3 mt-3 mt-sm-0">
<div class="sticky-header">
<nav aria-label="breadcrumb">
<ol class="breadcrumb">
<li class="breadcrumb-item">
<a asp-action="GetPaymentRequests" asp-route-storeId="@Model.StoreId">Requests</a>
</li>
<li class="breadcrumb-item active" aria-current="page">@ViewData["Title"]</li>
</ol>
<h2>@ViewData["Title"]</h2>
</nav>
<div>
@if (string.IsNullOrEmpty(Model.Id))
{
<button type="submit" class="btn btn-primary" id="SaveButton" permission="@Policies.CanModifyPaymentRequests">Create</button>
@@ -41,7 +49,10 @@
<div class="row">
<div class="col-xl-8 col-xxl-constrain">
@if (!ViewContext.ModelState.IsValid)
{
<div asp-validation-summary="ModelOnly"></div>
}
<div class="form-group">
<label asp-for="Title" class="form-label" data-required></label>
<input asp-for="Title" class="form-control" required />

View File

@@ -23,8 +23,8 @@
Model.Search.ContainsFilter(key) && Model.Search.GetFilterBool(key) is true;
}
<div class="sticky-header d-sm-flex align-items-center justify-content-between">
<h2 class="mb-0">
<div class="sticky-header">
<h2>
@ViewData["Title"]
<a href="#descriptor" data-bs-toggle="collapse">
<vc:icon symbol="info" />

View File

@@ -1,22 +1,19 @@
@using BTCPayServer.Views.Stores
@using Microsoft.AspNetCore.Mvc.TagHelpers
@using BTCPayServer.Abstractions.Extensions
@using BTCPayServer.Abstractions.Models
@using BTCPayServer.Client
@model List<BTCPayServer.PayoutProcessors.UIPayoutProcessorsController.StorePayoutProcessorsView>
@{
ViewData["NavPartialName"] = "../UIStores/_Nav";
Layout = "../Shared/_NavLayout.cshtml";
var storeId = Context.GetStoreData().Id;
ViewData.SetActivePage(StoreNavPages.PayoutProcessors, "Payout Processors", storeId);
}
<div class="row">
<div class="col-xl-8 col-xxl-constrain">
<div class="d-flex align-items-center justify-content-between mb-3">
<h3 class="mb-0">@ViewData["Title"]</h3>
<div class="sticky-header">
<h2 class="my-1">@ViewData["Title"]</h2>
</div>
<p>Payout Processors allow BTCPay Server to handle payouts in an automated way.</p>
<div class="row">
<div class="col-xl-8 col-xxl-constrain">
@if (Model.Any())
{
foreach (var processorsView in Model)

View File

@@ -1,7 +1,7 @@
@using BTCPayServer.Views.Stores
@model BTCPayServer.Models.WalletViewModels.UpdatePullPaymentModel
@{
var storeId = Context.GetStoreData().Id;
ViewData.SetActivePage(StoreNavPages.Create, "Edit Pull Payment", Model.Id);
}
@@ -14,10 +14,18 @@
<script src="~/vendor/summernote/summernote-bs5.js" asp-append-version="true"></script>
}
<form method="post" asp-action="EditPullPayment" asp-route-storeId="@Context.GetRouteValue("storeId")" asp-route-pullPaymentId="@Model.Id">
<div class="sticky-header d-sm-flex align-items-center justify-content-between">
<h2 class="mb-0">@ViewData["Title"]</h2>
<div class="d-flex gap-3 mt-3 mt-sm-0">
<form method="post" asp-action="EditPullPayment" asp-route-storeId="@storeId" asp-route-pullPaymentId="@Model.Id">
<div class="sticky-header">
<nav aria-label="breadcrumb">
<ol class="breadcrumb">
<li class="breadcrumb-item">
<a asp-controller="UIStorePullPayments" asp-action="PullPayments" asp-route-storeId="@storeId">Pull Payments</a>
</li>
<li class="breadcrumb-item active" aria-current="page">@ViewData["Title"]</li>
</ol>
<h2>@ViewData["Title"]</h2>
</nav>
<div>
@if (string.IsNullOrEmpty(Model.Id))
{
<button type="submit" class="btn btn-primary" id="SaveButton">Create</button>
@@ -34,7 +42,10 @@
<div class="row">
<div class="col-xl-8 col-xxl-constrain">
@if (!ViewContext.ModelState.IsValid)
{
<div asp-validation-summary="ModelOnly"></div>
}
<div class="form-group">
<label asp-for="Name" class="form-label" data-required></label>
<input asp-for="Name" class="form-control" required />

View File

@@ -19,19 +19,17 @@
}
<div class="sticky-header">
<div class="d-flex flex-wrap align-items-center justify-content-between gap-3">
<h2 class="mb-0">
<h2>
@ViewData["Title"]
<a href="https://docs.btcpayserver.org/Accounting/" target="_blank" rel="noreferrer noopener" title="More information...">
<vc:icon symbol="info" />
</a>
</h2>
<div class="d-flex flex-wrap gap-3">
<div>
<a cheat-mode="true" class="btn btn-outline-info text-nowrap" asp-action="StoreReports" asp-route-fakeData="true" asp-route-viewName="@Model.Request?.ViewName">Create fake data</a>
<button id="exportCSV" class="btn btn-primary text-nowrap" type="button">Export</button>
</div>
</div>
</div>
<div class="d-flex flex-column flex-sm-row align-items-center gap-3 mb-l">
<div class="dropdown" v-pre>
<button id="ViewNameToggle" class="btn btn-secondary dropdown-toggle dropdown-toggle-custom-caret" type="button" data-bs-toggle="dropdown" aria-expanded="false">@Model.Request.ViewName</button>

View File

@@ -13,11 +13,15 @@
<partial name="_ValidationScriptsPartial" />
}
<h3 class="mb-4">@ViewData["Title"]</h3>
<form method="post" enctype="multipart/form-data">
<div class="sticky-header">
<h2>@ViewData["Title"]</h2>
<button type="submit" class="btn btn-primary" name="command" value="Save">Save</button>
</div>
<partial name="_StatusMessage" />
<div class="row">
<div class="col-xl-8 col-xxl-constrain">
<form method="post" enctype="multipart/form-data">
<div class="form-group">
<label asp-for="ServerName" class="form-label"></label>
<input asp-for="ServerName" class="form-control" />
@@ -107,8 +111,6 @@
}
</div>
</div>
<button type="submit" class="btn btn-primary mt-2" name="command" value="Save">Save</button>
</div>
</div>
</form>
</div>
</div>

View File

@@ -3,7 +3,18 @@
ViewData.SetActivePage(ServerNavPages.Services, $"C-Lightning {Model.ConnectionType}");
}
<h2 class="mt-1 mb-4">@ViewData["Title"]</h2>
<div class="sticky-header">
<nav aria-label="breadcrumb">
<ol class="breadcrumb">
<li class="breadcrumb-item">
<a asp-action="Services">Services</a>
</li>
<li class="breadcrumb-item active" aria-current="page">@ViewData["Title"]</li>
</ol>
<h2>@ViewData["Title"]</h2>
</nav>
</div>
<partial name="_StatusMessage" />
@if (!ViewContext.ModelState.IsValid)
{

View File

@@ -3,13 +3,25 @@
ViewData.SetActivePage(ServerNavPages.Services, "BTCPay Server Configurator");
}
<h3 class="mb-4">@ViewData["Title"]</h3>
<div class="row">
<div class="col-md-6">
<div class="sticky-header">
<nav aria-label="breadcrumb">
<ol class="breadcrumb">
<li class="breadcrumb-item">
<a asp-action="Services">Services</a>
</li>
<li class="breadcrumb-item active" aria-current="page">@ViewData["Title"]</li>
</ol>
<h2>@ViewData["Title"]</h2>
</nav>
</div>
<partial name="_StatusMessage" />
@if (!ViewContext.ModelState.IsValid)
{
<div asp-validation-summary="All"></div>
</div>
</div>
}
<div class="row">
<div class="col-md-8">

View File

@@ -4,7 +4,12 @@
ViewData.SetActivePage(ServerNavPages.Services, $"Create temporary file link");
}
<h3 class="mb-4">@ViewData["Title"]</h3>
<form method="post">
<div class="sticky-header">
<h2>@ViewData["Title"]</h2>
<button type="submit" class="btn btn-primary" name="command" value="Generate">Generate</button>
</div>
<partial name="_StatusMessage" />
<div class="row">
<div class="col-xl-8 col-xxl-constrain">
@@ -12,7 +17,6 @@
{
<div asp-validation-summary="All"></div>
}
<form method="post">
<div class="form-group form-check">
<input type="checkbox" class="form-check-input" asp-for="IsDownload"/>
<label asp-for="IsDownload" class="form-check-label"></label>
@@ -28,10 +32,9 @@
<span asp-validation-for="TimeAmount" class="text-danger"></span>
<span asp-validation-for="TimeType" class="text-danger"></span>
</div>
<button type="submit" class="btn btn-primary mt-2" name="command" value="Generate">Generate</button>
</div>
</div>
</form>
</div>
</div>
@section PageFootContent {
<partial name="_ValidationScriptsPartial" />

View File

@@ -3,31 +3,42 @@
ViewData.SetActivePage(ServerNavPages.Users, "Create account");
}
<h3 class="mb-4">@ViewData["Title"]</h3>
<form method="post" asp-action="CreateUser">
<div class="sticky-header">
<nav aria-label="breadcrumb">
<ol class="breadcrumb">
<li class="breadcrumb-item">
<a asp-action="ListUsers">Users</a>
</li>
<li class="breadcrumb-item active" aria-current="page">@ViewData["Title"]</li>
</ol>
<h2>@ViewData["Title"]</h2>
</nav>
<button id="Save" type="submit" class="btn btn-primary" name="command" value="Save">Create Account</button>
</div>
<partial name="_StatusMessage" />
<div class="row">
<div class="col-xl-6 col-xxl-constrain">
<form method="post" asp-action="CreateUser">
@if (!ViewContext.ModelState.IsValid)
{
<div asp-validation-summary="ModelOnly"></div>
}
<div class="form-group">
<label asp-for="Email" class="form-label"></label>
<input asp-for="Email" required="required" class="form-control"/>
<span asp-validation-for="Email" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Password" class="form-label"></label>
<input asp-for="Password" class="form-control"/>
<span asp-validation-for="Password" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="ConfirmPassword" class="form-label"></label>
<input asp-for="ConfirmPassword" class="form-control"/>
<span asp-validation-for="ConfirmPassword" class="text-danger"></span>
</div>
@if (ViewData["AllowIsAdmin"] is true)
{
<div class="form-group form-check">
@@ -44,9 +55,10 @@
<span asp-validation-for="EmailConfirmed" class="text-danger"></span>
</div>
}
<button id="Save" type="submit" class="btn btn-primary mt-2" name="command" value="Save">Create account</button>
</div>
</div>
</form>
</div>
</div>
@section PageFootContent {
<partial name="_ValidationScriptsPartial" />
}

View File

@@ -10,8 +10,30 @@
});
</script>
}
<h3 class="mb-4">@ViewData["Title"]</h3>
<form method="post">
<div class="sticky-header">
<nav aria-label="breadcrumb">
<ol class="breadcrumb">
<li class="breadcrumb-item">
<a asp-action="Services">Services</a>
</li>
<li class="breadcrumb-item">
<a asp-action="DynamicDnsService">Dynamic DNS Settings</a>
</li>
<li class="breadcrumb-item active" aria-current="page">@ViewData["Title"]</li>
</ol>
<h2>
<span>@ViewData["Title"]</span>
<small>
<a href="https://docs.btcpayserver.org/Apps/" target="_blank" rel="noreferrer noopener" title="More information...">
<vc:icon symbol="info" />
</a>
</small>
</h2>
</nav>
<button name="command" class="btn btn-primary" type="submit" value="Save">Save</button>
</div>
<partial name="_StatusMessage" />
<div class="row">
<div class="col-md-8">
@@ -19,7 +41,6 @@
{
<div asp-validation-summary="All"></div>
}
<form method="post">
<div class="form-group">
<input type="hidden" asp-for="Modify"/>
<div class="form-group">
@@ -68,8 +89,7 @@
<input asp-for="Settings.Enabled" disabled type="checkbox" class="btcpay-toggle ms-2" />
</div>
}
<button name="command" class="btn btn-primary mt-2" type="submit" value="Save">Save</button>
</div>
</div>
</div>
</form>
</div>
</div>

View File

@@ -3,23 +3,32 @@
@{
ViewData.SetActivePage(ServerNavPages.Services, "Dynamic DNS Settings");
}
<div class="row">
<div class="col-md-8">
<div class="d-sm-flex align-items-center justify-content-between mb-3">
<h3 class="mb-0">
@ViewData["Title"]
<div class="sticky-header">
<nav aria-label="breadcrumb">
<ol class="breadcrumb">
<li class="breadcrumb-item">
<a asp-action="Services">Services</a>
</li>
<li class="breadcrumb-item active" aria-current="page">@ViewData["Title"]</li>
</ol>
<h2>
<span>@ViewData["Title"]</span>
<small>
<a href="https://docs.btcpayserver.org/Apps/" target="_blank" rel="noreferrer noopener" title="More information...">
<vc:icon symbol="info" />
</a>
</small>
</h3>
</h2>
</nav>
<div>
<form method="post" asp-action="DynamicDnsService">
<button id="AddDynamicDNS" class="btn btn-primary mt-2" type="submit">Add service</button>
<button id="AddDynamicDNS" class="btn btn-primary mt-2" type="submit">Add Service</button>
</form>
</div>
</div>
<partial name="_StatusMessage" />
<div class="row">
<div class="col-md-8">
<div class="form-group">
<p>
Dynamic DNS allows you to have a stable DNS name pointing to your server, even if your IP address changes regulary.
@@ -33,7 +42,8 @@
@if (Model.Any())
{
<table class="table table-sm table-responsive-md">
<div class="table-responsive-md">
<table class="table table-sm">
<thead>
<tr>
<th>Hostname</th>
@@ -67,6 +77,7 @@
}
</tbody>
</table>
</div>
}
else
{

View File

@@ -3,7 +3,21 @@
ViewData.SetActivePage(ServerNavPages.Files, "Amazon S3 Storage");
}
<h3 class="mb-4">@ViewData["Title"]</h3>
<div class="sticky-header">
<nav aria-label="breadcrumb">
<ol class="breadcrumb">
<li class="breadcrumb-item">
<a asp-action="Files">Files</a>
</li>
<li class="breadcrumb-item">
<a asp-action="Storage">Storage Provider</a>
</li>
<li class="breadcrumb-item active" aria-current="page">Provider</li>
</ol>
<h2>@ViewData["Title"]</h2>
</nav>
</div>
<partial name="_StatusMessage" />
<div class="row">
<div class="col-xl-10 col-xxl-constrain">

View File

@@ -3,7 +3,21 @@
ViewData.SetActivePage(ServerNavPages.Files, "Azure Blob Storage");
}
<h3 class="mb-4">@ViewData["Title"]</h3>
<div class="sticky-header">
<nav aria-label="breadcrumb">
<ol class="breadcrumb">
<li class="breadcrumb-item">
<a asp-action="Files">Files</a>
</li>
<li class="breadcrumb-item">
<a asp-action="Storage">Storage Provider</a>
</li>
<li class="breadcrumb-item active" aria-current="page">Provider</li>
</ol>
<h2>@ViewData["Title"]</h2>
</nav>
</div>
<partial name="_StatusMessage" />
<div class="row">
<div class="col-xl-10 col-xxl-constrain">

View File

@@ -3,7 +3,21 @@
ViewData.SetActivePage(ServerNavPages.Files, $"Local Filesystem Storage");
}
<h3 class="mb-4">@ViewData["Title"]</h3>
<div class="sticky-header">
<nav aria-label="breadcrumb">
<ol class="breadcrumb">
<li class="breadcrumb-item">
<a asp-action="Files">Files</a>
</li>
<li class="breadcrumb-item">
<a asp-action="Storage">Storage Provider</a>
</li>
<li class="breadcrumb-item active" aria-current="page">Provider</li>
</ol>
<h2>@ViewData["Title"]</h2>
</nav>
</div>
<partial name="_StatusMessage" />
<p>Any uploaded files are being saved on the same machine that hosts BTCPay; please pay attention to your storage space.</p>
<div class="row">

View File

@@ -3,7 +3,21 @@
ViewData.SetActivePage(ServerNavPages.Files, "Google Cloud Storage");
}
<h3 class="mb-4">@ViewData["Title"]</h3>
<div class="sticky-header">
<nav aria-label="breadcrumb">
<ol class="breadcrumb">
<li class="breadcrumb-item">
<a asp-action="Files">Files</a>
</li>
<li class="breadcrumb-item">
<a asp-action="Storage">Storage Provider</a>
</li>
<li class="breadcrumb-item active" aria-current="page">Provider</li>
</ol>
<h2>@ViewData["Title"]</h2>
</nav>
</div>
<partial name="_StatusMessage" />
<div class="row">
<div class="col-xl-10 col-xxl-constrain">

View File

@@ -3,9 +3,13 @@
ViewData.SetActivePage(ServerNavPages.Emails, "Emails");
}
<h3 class="mb-4">Email Server</h3>
<form method="post" autocomplete="off">
<div class="form-group" style="margin:1rem 0 2rem">
<div class="sticky-header">
<h2>@ViewData["Title"]</h2>
<button type="submit" class="btn btn-primary" name="command" value="Save" id="Save">Save</button>
</div>
<partial name="_StatusMessage" />
<div class="form-group mb-4">
<div class="d-flex align-items-center">
<input asp-for="EnableStoresToUseServerEmailSettings" type="checkbox" class="btcpay-toggle me-3"/>
<div>

View File

@@ -3,15 +3,14 @@
ViewData.SetActivePage(ServerNavPages.Files, "File Storage");
}
<div class="row">
<div class="col">
<div class="d-flex align-items-center justify-content-between mt-n1 mb-4">
<h3 class="mb-0">@ViewData["Title"]</h3>
<div class="sticky-header">
<h2>@ViewData["Title"]</h2>
<a asp-action="storage" asp-route-forceChoice="true" asp-route-returnurl="@ViewData["ReturnUrl"]" class="btn btn-secondary d-flex align-items-center">
<vc:icon symbol="settings" />
<span class="ms-1">Settings</span>
</a>
</div>
<partial name="_StatusMessage" />
@if (!Model.StorageConfigured)
{
@@ -31,17 +30,6 @@
<vc:icon symbol="info" />
</a>
</p>
@if (Model.StorageConfigured)
{
<form asp-action="CreateFiles" method="post" enctype="multipart/form-data">
<div class="d-flex">
<input multiple type="file" class="form-control mb-3" name="files" id="files" required>
<button class="btn btn-primary mb-3 ms-3" role="button">Upload</button>
</div>
</form>
}
@if (Model.DirectUrlByFiles is { Count: > 0 })
{
foreach (var fileUrlPair in Model.DirectUrlByFiles)
@@ -84,6 +72,9 @@
</button>
</div>
</div>
<button type="button" class="btn btn-link" data-clipboard="@url">
<vc:icon symbol="copy" />
</button>
</div>
</div>
}
@@ -97,7 +88,7 @@
<tr>
<th>Name</th>
<th>Timestamp</th>
<th>User</th>
<th>Uploaded By</th>
<th class="text-end">Actions</th>
</tr>
</thead>
@@ -125,5 +116,3 @@
<p class="text-secondary mt-3">There are no files yet.</p>
}
}
</div>
</div>

View File

@@ -1,9 +1,20 @@
@model ChargeServiceViewModel
@{
ViewData.SetActivePage(ServerNavPages.Services, "Lightning charge service");
ViewData.SetActivePage(ServerNavPages.Services, "Lightning Charge Service");
}
<h3 class="mb-4">@ViewData["Title"]</h3>
<div class="sticky-header">
<nav aria-label="breadcrumb">
<ol class="breadcrumb">
<li class="breadcrumb-item">
<a asp-action="Services">Services</a>
</li>
<li class="breadcrumb-item active" aria-current="page">@ViewData["Title"]</li>
</ol>
<h2>@ViewData["Title"]</h2>
</nav>
</div>
<partial name="_StatusMessage" />
<div class="row">
<div class="col-md-8">

View File

@@ -3,7 +3,18 @@
ViewData.SetActivePage(ServerNavPages.Services, Model.WalletName);
}
<h3 class="mb-4">@ViewData["Title"]</h3>
<div class="sticky-header">
<nav aria-label="breadcrumb">
<ol class="breadcrumb">
<li class="breadcrumb-item">
<a asp-action="Services">Services</a>
</li>
<li class="breadcrumb-item active" aria-current="page">@ViewData["Title"]</li>
</ol>
<h2>@ViewData["Title"]</h2>
</nav>
</div>
<partial name="_StatusMessage" />
@if (Model.ShowQR)
{

View File

@@ -3,14 +3,11 @@
Layout = "_Layout";
ViewData.SetActivePage(ServerNavPages.Stores, "Store Overview");
}
<div class="sticky-header">
<h2 class="my-1">@ViewData["Title"]</h2>
</div>
<partial name="_StatusMessage" />
<div class="d-sm-flex justify-content-between mb-2">
<h2 class="mb-0">
@ViewData["Title"]
</h2>
</div>
@if (Model.Stores.Any())
{
<table class="table table-hover">

View File

@@ -13,12 +13,13 @@
const string sortByDesc = "Sort by email descending...";
const string sortByAsc = "Sort by email ascending...";
}
<div class="d-flex align-items-center justify-content-between mb-3">
<h3 class="mb-0">@ViewData["Title"]</h3>
<div class="sticky-header">
<h2>@ViewData["Title"]</h2>
<a asp-action="CreateUser" class="btn btn-primary" role="button" id="CreateUser">
Add User
</a>
</div>
<partial name="_StatusMessage" />
<form asp-action="ListUsers" asp-route-sortOrder="@(userEmailSortOrder)" style="max-width:640px" method="get">
<input asp-for="SearchTerm" class="form-control" placeholder="Search by email..." />

View File

@@ -4,7 +4,18 @@
ViewData.SetActivePage(ServerNavPages.Services, "LND Seed Backup");
}
<h3 class="mb-4">@ViewData["Title"]</h3>
<div class="sticky-header">
<nav aria-label="breadcrumb">
<ol class="breadcrumb">
<li class="breadcrumb-item">
<a asp-action="Services">Services</a>
</li>
<li class="breadcrumb-item active" aria-current="page">@ViewData["Title"]</li>
</ol>
<h2>@ViewData["Title"]</h2>
</nav>
</div>
<partial name="_StatusMessage" />
@if (Model.IsWalletUnlockPresent)
{

View File

@@ -3,7 +3,18 @@
ViewData.SetActivePage(ServerNavPages.Services, $"LND {Model.ConnectionType}");
}
<h3 class="mb-4">@ViewData["Title"]</h3>
<div class="sticky-header">
<nav aria-label="breadcrumb">
<ol class="breadcrumb">
<li class="breadcrumb-item">
<a asp-action="Services">Services</a>
</li>
<li class="breadcrumb-item active" aria-current="page">@ViewData["Title"]</li>
</ol>
<h2>@ViewData["Title"]</h2>
</nav>
</div>
<partial name="_StatusMessage" />
<p>
BTCPay exposes LND's @Model.ConnectionType service for outside consumption, you will find connection information here.
</p>

View File

@@ -3,7 +3,10 @@
ViewData.SetActivePage(ServerNavPages.Logs, "Logs");
}
<h3 class="mb-4">@ViewData["Title"]</h3>
<div class="sticky-header">
<h2 class="my-1">@ViewData["Title"]</h2>
</div>
<partial name="_StatusMessage" />
<ul class="list-unstyled">
@foreach (var file in Model.LogFiles)

View File

@@ -3,7 +3,10 @@
ViewData.SetActivePage(ServerNavPages.Maintenance, "Maintenance");
}
<h3 class="mb-3">@ViewData["Title"]</h3>
<div class="sticky-header">
<h2 class="my-1">@ViewData["Title"]</h2>
</div>
<partial name="_StatusMessage" />
<form method="post">
<div class="row mb-5">

View File

@@ -3,7 +3,18 @@
ViewData.SetActivePage(ServerNavPages.Services, Model.WalletName);
}
<h3 class="mb-4">@ViewData["Title"]</h3>
<div class="sticky-header">
<nav aria-label="breadcrumb">
<ol class="breadcrumb">
<li class="breadcrumb-item">
<a asp-action="Services">Services</a>
</li>
<li class="breadcrumb-item active" aria-current="page">@ViewData["Title"]</li>
</ol>
<h2>@ViewData["Title"]</h2>
</nav>
</div>
<partial name="_StatusMessage" />
@if (Model.ShowQR)
{

View File

@@ -1,11 +1,8 @@
@using BTCPayServer.Payments;
@using BTCPayServer.Services
@using BTCPayServer.Services.Invoices
@using BTCPayServer.Services.Mails;
@model BTCPayServer.Services.PoliciesSettings
@inject SettingsRepository _SettingsRepository
@inject TransactionLinkProviders TransactionLinkProviders
@inject PaymentMethodHandlerDictionary _handlers;
@{
ViewData.SetActivePage(ServerNavPages.Policies);
var linkProviders = TransactionLinkProviders.ToArray();
@@ -21,7 +18,12 @@
</style>
}
<h3 class="mb-4">@ViewData["Title"]</h3>
<form method="post">
<div class="sticky-header">
<h2>@ViewData["Title"]</h2>
<button id="SaveButton" type="submit" class="btn btn-primary" name="command" value="Save">Save</button>
</div>
<partial name="_StatusMessage" />
@if (!ViewContext.ModelState.IsValid)
{
@@ -30,7 +32,7 @@
<div class="row">
<div class="col-xl-10 col-xxl-constrain">
<form method="post" class="d-flex flex-column">
<div class="d-flex flex-column">
<div class="form-group mb-5">
<h4 class="mb-3">Registration</h4>
<div class="d-flex gap-3">
@@ -178,12 +180,6 @@
<label asp-for="PluginPreReleases" class="form-check-label"></label>
</div>
@* To handle the multiple submit buttons on this page: Give this button
a specific order to put it last, but keep it first in the markup *@
<div class="order-1">
<button id="SaveButton" type="submit" class="btn btn-primary" name="command" value="Save">Save</button>
</div>
<h4 class="mt-5">Customization</h4>
<div class="form-group mb-3">
<label asp-for="DefaultCurrency" class="form-label"></label>
@@ -214,7 +210,7 @@
<div class="d-flex align-items-center justify-content-between">
<label asp-for="DomainToAppMapping[index].Domain" class="form-label"></label>
<button type="submit" title="Remove domain mapping" name="command" value="@($"remove-domain:{index}")" class="d-inline-block ms-2 btn text-danger btn-link p-0 mb-2">
<vc:icon symbol="cross" /> Remove Mapping
<span class="fa fa-times"></span> Remove Mapping
</button>
</div>
<input asp-for="DomainToAppMapping[index].Domain" class="form-control"/>
@@ -259,9 +255,10 @@
<input type="text" class="form-control block-explorer-link" asp-for="BlockExplorerLinks[i].Link" value="@linkValue" rel="noreferrer noopener" />
</div>
}
</div>
</div>
</div>
</form>
</div>
</div>
@section PageFootContent {
<script>

View File

@@ -3,7 +3,18 @@
ViewData.SetActivePage(ServerNavPages.Services, Model.WalletName);
}
<h3 class="mb-4">@ViewData["Title"]</h3>
<div class="sticky-header">
<nav aria-label="breadcrumb">
<ol class="breadcrumb">
<li class="breadcrumb-item">
<a asp-action="Services">Services</a>
</li>
<li class="breadcrumb-item active" aria-current="page">@ViewData["Title"]</li>
</ol>
<h2>@ViewData["Title"]</h2>
</nav>
</div>
<partial name="_StatusMessage" />
@if (Model.ShowQR)
{

View File

@@ -4,15 +4,21 @@
ViewData.SetActivePage(ServerNavPages.Services, "SSH settings");
}
<h3 class="mb-4">@ViewData["Title"]</h3>
<div class="sticky-header">
<nav aria-label="breadcrumb">
<ol class="breadcrumb">
<li class="breadcrumb-item">
<a asp-action="Services">Services</a>
</li>
<li class="breadcrumb-item active" aria-current="page">@ViewData["Title"]</li>
</ol>
<h2>@ViewData["Title"]</h2>
</nav>
</div>
<partial name="_StatusMessage" />
<p>SSH services are used by the maintenance operations.</p>
<div class="row">
<div class="col-md-8">
<div class="form-group">
<p>
<span>SSH services are used by the maintenance operations<br /></span>
</p>
</div>
@if (!ViewContext.ModelState.IsValid)
{
<div asp-validation-summary="All"></div>
@@ -44,15 +50,9 @@
@if (Model.SSHKeyFileContent != null)
{
<h4>Authorized keys</h4>
<p>You can enter here SSH public keys authorized to connect to your server.</p>
<div class="row">
<div class="col-md-8">
<div class="form-group">
<p>
<span>You can enter here SSH public keys authorized to connect to your server.<br /></span>
</p>
</div>
<form method="post">
<div class="form-group">
<textarea asp-for="SSHKeyFileContent" rows="20" cols="80" class="form-control"></textarea>
@@ -65,20 +65,14 @@
}
<h4 class="mt-5 mb-3">Other actions</h4>
<p>Increase the security of your instance by disabling the ability to change the SSH settings in this BTCPay Server instance's user interface.</p>
<div class="row">
<div class="col-md-8">
<div class="form-group">
<p>
<span>Increase the security of your instance by disabling the ability to change the SSH settings in this BTCPay Server instance's user interface.<br /></span>
</p>
</div>
<div>
<form method="post">
<button name="command" id="disable" type="submit" class="btn btn-outline-danger mb-5" value="disable" data-bs-toggle="modal" data-bs-target="#ConfirmModal" data-confirm-input="DISABLE">Disable</button>
</form>
</div>
</div>
</div>
<partial name="_Confirm" model="@(new ConfirmModel("Disable modification of SSH settings", "This action is permanent and will remove the ability to change the SSH settings via the BTCPay Server user interface.", "Disable"))"/>

View File

@@ -2,7 +2,7 @@ namespace BTCPayServer.Views.Server
{
public enum ServerNavPages
{
Index, Users, Emails, Policies, Branding, Services, Maintenance, Logs, Files, Plugins,
Users, Emails, Policies, Branding, Services, Maintenance, Logs, Files, Plugins,
Roles,
Stores
}

View File

@@ -3,7 +3,10 @@
ViewData.SetActivePage(ServerNavPages.Services, "Services");
}
<h3 class="mb-4">@ViewData["Title"]</h3>
<div class="sticky-header">
<h2 class="my-1">@ViewData["Title"]</h2>
</div>
<partial name="_StatusMessage" />
<div class="mb-5">
<h4 class="mb-3">Crypto services exposed by your server</h4>
@@ -64,7 +67,7 @@
<tr>
<td>@s.Name</td>
<td style="text-align: right">
<a href="@s.Link" target="_blank" rel="noreferrer noopener">See information</a>
<a href="@s.Link" rel="noreferrer noopener">See information</a>
</td>
</tr>
}

View File

@@ -1,9 +1,22 @@
@model BTCPayServer.Storage.ViewModels.ChooseStorageViewModel
@{
ViewData.SetActivePage(ServerNavPages.Files, "Storage");
ViewData.SetActivePage(ServerNavPages.Files, "Storage Provider");
}
<h3 class="mb-4">@ViewData["Title"]</h3>
<form method="post">
<div class="sticky-header">
<nav aria-label="breadcrumb">
<ol class="breadcrumb">
<li class="breadcrumb-item">
<a asp-action="Files">Files</a>
</li>
<li class="breadcrumb-item active" aria-current="page">@ViewData["Title"]</li>
</ol>
<h2>@ViewData["Title"]</h2>
</nav>
<button type="submit" class="btn btn-primary" name="command" value="Save">Next</button>
</div>
<partial name="_StatusMessage" />
<div class="row">
<div class="col-xl-10 col-xxl-constrain">
@@ -13,7 +26,6 @@
If you change your configured storage provider, your current files will become inaccessible.
</div>
}
<form method="post">
@if (!ViewContext.ModelState.IsValid)
{
<div asp-validation-summary="All"></div>
@@ -22,10 +34,9 @@
<label asp-for="Provider" class="form-label"></label>
<select asp-for="Provider" asp-items="@Model.ProvidersList" class="form-select w-auto"></select>
</div>
<button type="submit" class="btn btn-primary mt-2" name="command" value="Save">Next</button>
</div>
</div>
</form>
</div>
</div>
@section PageFootContent {
<partial name="_ValidationScriptsPartial" />

View File

@@ -3,16 +3,27 @@
ViewData.SetActivePage(ServerNavPages.Users, Model.Email);
}
<h3 class="mb-4">@ViewData["Title"]</h3>
<form method="post">
<div class="form-check my-3">
<div class="sticky-header">
<nav aria-label="breadcrumb">
<ol class="breadcrumb">
<li class="breadcrumb-item">
<a asp-action="ListUsers">Users</a>
</li>
<li class="breadcrumb-item active" aria-current="page">User</li>
</ol>
<h2>@ViewData["Title"]</h2>
</nav>
<button name="command" type="submit" class="btn btn-primary" value="Save" id="SaveUser">Save</button>
</div>
<partial name="_StatusMessage" />
<div class="form-check">
<input asp-for="IsAdmin" type="checkbox" class="form-check-input" />
<label asp-for="IsAdmin" class="form-check-label">User is admin</label>
</div>
@if (Model.Approved.HasValue)
{
<div class="form-check my-3">
<div class="form-check">
<input id="Approved" name="Approved" type="checkbox" value="true" class="form-check-input" @(Model.Approved.Value ? "checked" : "") />
<label for="Approved" class="form-check-label">User is approved</label>
</div>
@@ -20,11 +31,10 @@
}
@if (Model.EmailConfirmed.HasValue)
{
<div class="form-check my-3">
<div class="form-check">
<input id="EmailConfirmed" name="EmailConfirmed" value="true" type="checkbox" class="form-check-input" @(Model.EmailConfirmed.Value ? "checked" : "") />
<label for="EmailConfirmed" class="form-check-label">Email address is confirmed</label>
</div>
<input name="EmailConfirmed" type="hidden" value="false">
}
<button name="command" type="submit" class="btn btn-primary mt-3" value="Save" id="SaveUser">Save</button>
</form>

Some files were not shown because too many files have changed in this diff Show More