Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

UI: Move section navigation to sidebar #5744

Open
wants to merge 23 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
67 changes: 40 additions & 27 deletions BTCPayServer.Abstractions/Extensions/ViewsRazor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ public static class ViewsRazor
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
{
Expand Down Expand Up @@ -55,50 +55,63 @@ public static void SetActiveCategory(this ViewDataDictionary viewData, string ac
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)
{
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;
}

public static bool IsActiveCategory<T>(this ViewDataDictionary viewData, T category, object id = null)
{
return IsActiveCategory(viewData, category.ToString(), id);
}

public static string IsActiveCategory(this ViewDataDictionary viewData, string category, object id = null)
public static bool IsActivePage(this ViewDataDictionary viewData, string page, string category, object id = null)
{
if (!viewData.ContainsKey(ACTIVE_CATEGORY_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 categoryMatch = category.Equals(activeCategory, 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 categoryMatch && idMatch ? ActivePageClass : null;
return categoryAndPageMatch && idMatch;
}

public static string IsActivePage<T>(this ViewDataDictionary viewData, T page, object id = null)
public static bool IsActivePage<T>(this ViewDataDictionary viewData, IEnumerable<T> pages, object id = null)
where T : IConvertible
{
return IsActivePage(viewData, page.ToString(), page.GetType().ToString(), id);
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 IsActivePage<T>(this ViewDataDictionary viewData, IEnumerable<T> pages, object id = null)
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 pages.Any(page => IsActivePage(viewData, page.ToString(), page.GetType().ToString(), id) == ActivePageClass)
? ActivePageClass
: null;
return ActivePageClass(viewData, page.ToString(), page.GetType().ToString(), id);
}

public static string IsActivePage(this ViewDataDictionary viewData, string page, string category, object id = null)
public static string ActivePageClass(this ViewDataDictionary viewData, string page, string category, object id = null)
{
if (!viewData.ContainsKey(ACTIVE_PAGE_KEY))
{
return null;
}
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 idMatch = id == null || activeId == null || id.Equals(activeId);
return categoryAndPageMatch && idMatch ? ActivePageClass : 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")
Expand Down
11 changes: 7 additions & 4 deletions BTCPayServer.Tests/AltcoinTests/AltcoinTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -74,14 +74,17 @@ public async Task CanSetupWallet()
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
Expand Down
32 changes: 10 additions & 22 deletions BTCPayServer.Tests/SeleniumTester.cs
Original file line number Diff line number Diff line change
Expand Up @@ -199,8 +199,7 @@ public TestAccount AsTestAccount()
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;
Expand Down Expand Up @@ -330,10 +329,11 @@ public void AddLightningNode(string connectionType = null, bool test = true)
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);
}
}

Expand Down Expand Up @@ -418,23 +418,11 @@ public void GoToStore(string storeId, StoreNavPages storeNavPage = StoreNavPages
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")
Expand All @@ -450,9 +438,9 @@ public void GoToLightningSettings(string cryptoCode = "BTC")
{
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();
}
}

Expand Down Expand Up @@ -614,10 +602,10 @@ public void GoToUrl(string relativeUrl)
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();
}
Expand Down
18 changes: 11 additions & 7 deletions BTCPayServer.Tests/SeleniumTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -63,9 +63,7 @@ public async Task CanNavigateServerSettings()
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();
Expand Down Expand Up @@ -257,10 +255,8 @@ public async Task CanUseLndSeedBackup()
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"));
Expand Down Expand Up @@ -609,6 +605,12 @@ public async Task CanSetupEmailServer()

// 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();
Expand Down Expand Up @@ -3429,7 +3431,7 @@ public async Task CanUseRoleManager()
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)
Expand All @@ -3451,6 +3453,8 @@ public async Task CanUseRoleManager()
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"));
Expand Down
4 changes: 0 additions & 4 deletions BTCPayServer/Blazor/Icon.razor
Original file line number Diff line number Diff line change
@@ -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

Expand Down
2 changes: 0 additions & 2 deletions BTCPayServer/Components/InvoiceStatus/Default.cshtml
Original file line number Diff line number Diff line change
@@ -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

Expand Down