btcpayserver/BTCPayServer/Components/MainNav/Default.cshtml
d11n b4daa76aeb
Theme Switch: Refactor and add system option (#5473)
* Theme Switch: Refactor and add system option

Before, we had no way to reset the theme option to the system default. This introduces that option and refactors the theme switch to work in a simpler manner.

* Prevent account menu close on click inside

Context: #5476
2023-11-21 09:56:10 +01:00

293 lines
20 KiB
Text

@using BTCPayServer.Views.Server
@using BTCPayServer.Views.Stores
@using BTCPayServer.Views.Invoice
@using BTCPayServer.Views.Manage
@using BTCPayServer.Views.PaymentRequest
@using BTCPayServer.Views.Wallets
@using BTCPayServer.Client
@using BTCPayServer.Components.ThemeSwitch
@using BTCPayServer.Components.UIExtensionPoint
@using BTCPayServer.Services
@using BTCPayServer.Views.Apps
@using BTCPayServer.Views.CustodianAccounts
@inject Microsoft.AspNetCore.Http.IHttpContextAccessor HttpContext;
@inject BTCPayServerEnvironment Env
@inject SignInManager<ApplicationUser> SignInManager
@inject PoliciesSettings PoliciesSettings
@inject ThemeSettings Theme
@model BTCPayServer.Components.MainNav.MainNavViewModel
<nav id="mainNav" class="d-flex flex-column justify-content-between">
<div class="accordion px-3 px-lg-4">
@if (SignInManager.IsSignedIn(User))
{
@if (Model.Store != null)
{
<div class="accordion-item" permission="@Policies.CanModifyStoreSettings">
<div class="accordion-body">
<ul class="navbar-nav">
<li class="nav-item">
<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">
<vc:icon symbol="home"/>
<span>Dashboard</span>
</a>
</li>
<li class="nav-item">
<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">
<vc:icon symbol="settings"/>
<span>Settings</span>
</a>
</li>
</ul>
</div>
</div>
<div class="accordion-item">
<header class="accordion-header" id="Nav-Wallets-Header" permission="@Policies.CanModifyStoreSettings">
<div class="accordion-button">
Wallets
</div>
</header>
<div id="Nav-Wallets" class="accordion-collapse" aria-labelledby="Nav-Wallets-Header" permission="@Policies.CanModifyStoreSettings">
<div class="accordion-body">
<ul class="navbar-nav">
@foreach (var scheme in Model.DerivationSchemes.OrderBy(scheme => scheme.Collapsed))
{
var isSetUp = !string.IsNullOrWhiteSpace(scheme.Value);
<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}")">
<span class="me-2 btcpay-status btcpay-status--@(scheme.Enabled ? "enabled" : "pending")"></span>
<span>@(Model.AltcoinsBuild ? $"{scheme.Crypto} Wallet" : "Bitcoin")</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}")">
<span class="me-2 btcpay-status btcpay-status--@(scheme.Enabled ? "enabled" : "pending")"></span>
<span>@(Model.AltcoinsBuild ? $"{scheme.Crypto} Wallet" : "Bitcoin")</span>
</a>
}
</li>
}
@foreach (var scheme in Model.LightningNodes)
{
var isSetUp = !string.IsNullOrWhiteSpace(scheme.Address);
<li class="nav-item">
@if (isSetUp)
{
<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}")">
<span class="me-2 btcpay-status btcpay-status--@(scheme.Enabled ? "enabled" : "pending")"></span>
<span>@(Model.AltcoinsBuild ? $"{scheme.CryptoCode} " : "")Lightning</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}")">
<span class="me-2 btcpay-status btcpay-status--@(scheme.Enabled ? "enabled" : "pending")"></span>
<span>@(Model.AltcoinsBuild ? $"{scheme.CryptoCode} " : "")Lightning</span>
</a>
}
</li>
}
<vc:ui-extension-point location="store-wallets-nav" model="@Model"/>
@if (PoliciesSettings.Experimental)
{
@foreach (var custodianAccount in Model.CustodianAccounts)
{
<li class="nav-item">
<a asp-area="" asp-controller="UICustodianAccounts" asp-action="ViewCustodianAccount" asp-route-storeId="@custodianAccount.StoreId" asp-route-accountId="@custodianAccount.Id" class="nav-link @ViewData.IsActivePage(CustodianAccountsNavPages.View, custodianAccount.Id)" id="@($"StoreNav-CustodianAccount-{custodianAccount.Id}")">
@* TODO which icon should we use? *@
<span>@custodianAccount.Name</span>
<span class="badge bg-warning ms-1" style="font-size:10px;">Experimental</span>
</a>
</li>
}
<li class="nav-item">
<a asp-area="" asp-controller="UICustodianAccounts" asp-action="CreateCustodianAccount" asp-route-storeId="@Model.Store.Id" class="nav-link @ViewData.IsActivePage(CustodianAccountsNavPages.Create)" id="StoreNav-CreateCustodianAccount">
<vc:icon symbol="new"/>
<span>Add Custodian</span>
<span class="badge bg-warning ms-1" style="font-size:10px;">Experimental</span>
</a>
</li>
}
</ul>
</div>
</div>
<div class="accordion-item">
<header class="accordion-header" id="Nav-Payments-Header">
<button class="accordion-button" type="button" data-bs-toggle="collapse" data-bs-target="#Nav-Payments" aria-expanded="true" aria-controls="Nav-Payments">
Payments
<vc:icon symbol="caret-down"/>
</button>
</header>
<div id="Nav-Payments" class="accordion-collapse collapse show" aria-labelledby="Nav-Payments-Header">
<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">
<vc:icon symbol="invoice"/>
<span>Invoices</span>
</a>
</li>
<li class="nav-item" permission="@Policies.CanViewInvoices">
<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">
<vc:icon symbol="invoice" />
<span>Reporting</span>
</a>
</li>
<li class="nav-item" permission="@Policies.CanModifyStoreSettings">
<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">
<vc:icon symbol="payment-requests"/>
<span>Requests</span>
</a>
</li>
<li class="nav-item" permission="@Policies.CanViewStoreSettings">
<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">
<vc:icon symbol="pull-payments"/>
<span>Pull Payments</span>
</a>
</li>
<li class="nav-item" permission="@Policies.CanModifyStoreSettings">
<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">
<vc:icon symbol="payouts"/>
<span>Payouts</span>
</a>
</li>
</ul>
</div>
</div>
</div>
</div>
}
<div class="accordion-item">
<header class="accordion-header" id="Nav-Plugins-Header">
<button class="accordion-button" type="button" data-bs-toggle="collapse" data-bs-target="#Nav-Plugins" aria-expanded="true" aria-controls="Nav-Plugins">
Plugins
<vc:icon symbol="caret-down"/>
</button>
</header>
<div id="Nav-Plugins" class="accordion-collapse collapse show" aria-labelledby="Nav-Plugins-Header">
<div class="accordion-body">
<ul class="navbar-nav">
<vc:ui-extension-point location="header-nav" model="@Model"/>
@if (Model.Store != null)
{
<vc:ui-extension-point location="store-integrations-nav" model="@Model"/>
}
</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">
<vc:icon symbol="manage-plugins"/>
<span>Manage Plugins</span>
</a>
</li>
@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">
@Model.ArchivedAppsCount Archived App@(Model.ArchivedAppsCount == 1 ? "" : "s")
</a>
</li>
}
</ul>
</div>
</div>
</div>
<script>
(() => {
// apply collapse settings
const navCollapsed = window.localStorage.getItem('btcpay-nav-collapsed')
const collapsed = navCollapsed ? JSON.parse(navCollapsed) : []
collapsed.forEach(id => {
const el = document.getElementById(id)
const btn = el && el.previousElementSibling.querySelector(`[aria-controls="${id}"]`)
if (el && btn) {
el.classList.remove('show')
btn.classList.add('collapsed')
btn.setAttribute('aria-expanded', 'false')
}
})
// hide empty plugins drawer
const pluginsItem = document.getElementById('Nav-Plugins').closest('.accordion-item')
const pluginsContent = pluginsItem.querySelector('.navbar-nav').innerHTML.trim()
if (pluginsContent === '') {
pluginsItem.setAttribute('hidden', true)
}
})()
</script>
}
else if (Env.IsSecure(HttpContext.HttpContext))
{
<ul class="navbar-nav">
@if (!PoliciesSettings.LockSubscription)
{
<li class="nav-item">
<a asp-area="" asp-controller="UIAccount" asp-action="Register" class="nav-link" id="Nav-Register">Register</a>
</li>
}
<li class="nav-item">
<a asp-area="" asp-controller="UIAccount" asp-action="Login" class="nav-link" id="Nav-Login">Log in</a>
</li>
</ul>
}
</div>
@if (SignInManager.IsSignedIn(User))
{
<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.Theme) @ViewData.IsActivePage(ServerNavPages.Maintenance) @ViewData.IsActivePage(ServerNavPages.Logs) @ViewData.IsActivePage(ServerNavPages.Files)" id="Nav-ServerSettings">
<vc:icon symbol="server-settings"/>
<span>Server Settings</span>
</a>
</li>
<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">
<vc:icon symbol="account"/>
<span>Account</span>
</a>
<ul class="dropdown-menu py-0 w-100" aria-labelledby="Nav-Account">
<li class="p-3 border-bottom">
<strong class="d-block text-truncate" style="max-width:195px">@User.Identity.Name</strong>
@if (User.IsInRole(Roles.ServerAdmin))
{
<div class="text-secondary">Administrator</div>
}
</li>
@if (!Theme.CustomTheme)
{
<li class="py-1 px-3">
<vc:theme-switch css-class="w-100 pt-2"/>
</li>
}
<li class="py-1 px-3">
<label class="d-flex align-items-center justify-content-between gap-3 nav-link">
<span class="fw-semibold">Hide Sensitive Info</span>
<input id="HideSensitiveInfo" name="HideSensitiveInfo" type="checkbox" class="btcpay-toggle" />
</label>
<script>
document.getElementById('HideSensitiveInfo').checked = window.localStorage.getItem('btcpay-hide-sensitive-info') === 'true';
</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">
<span>Manage Account</span>
</a>
</li>
<li class="border-top py-1 px-3">
<a asp-area="" asp-controller="UIAccount" asp-action="Logout" class="nav-link text-danger" id="Nav-Logout">
<span>Logout</span>
</a>
</li>
</ul>
</li>
</ul>
}
</nav>