mirror of
https://github.com/aljazceru/btcpayserver.git
synced 2025-12-17 14:04:26 +01:00
* Update layout structure and header * Implement store selector * Simplify homepage * Update layout * Use dropdown for store selector * Hide global nav in store context * Horizontal section nav * Remove outer section and container from content views * Update nav * Set store context for invoice and payment request lists * Test fixes * Persist menu collapse state on client-side * MainNav as view component * Update app routes to incorporate store context * Test fixes * Display ticker for altcoins build only * Plugins nav * Incorporate category for active page as well * Update invoice icon * Add apps list to nav * Add store context to app type controllers * Incorporate id for active page as well * Test fixes * AppsController cleanup * Nav: Display only apps for the current store * Remove leftover from merge * Nav styles optimization * Left-align content container * Increase sidebar padding on desktop * Use min-width for store selector menu * Store settings nav update * Update app and payment request routes * Test fixes * Refactor MainNav component to use StoresController * Set store context for invoice actions * Cleanups * Remove CurrentStore checks The response will be "Access denied" in case the CookieAuthorizationHandler cannot resolve the store. * Remove unnecessary store context setters * Test fix
110 lines
4.2 KiB
C#
110 lines
4.2 KiB
C#
using System;
|
|
using System.Globalization;
|
|
using Microsoft.AspNetCore.Html;
|
|
using Microsoft.AspNetCore.Mvc.ViewFeatures;
|
|
|
|
namespace BTCPayServer.Abstractions.Extensions
|
|
{
|
|
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";
|
|
|
|
public static void SetActivePageAndTitle<T>(this ViewDataDictionary viewData, T activePage, string title = null, string mainTitle = null)
|
|
where T : IConvertible
|
|
{
|
|
// Browser Title
|
|
viewData["Title"] = title ?? activePage.ToString();
|
|
// Breadcrumb
|
|
viewData["MainTitle"] = mainTitle;
|
|
viewData["PageTitle"] = title;
|
|
// Navigation
|
|
viewData[ACTIVE_PAGE_KEY] = activePage;
|
|
SetActiveCategory(viewData, activePage.GetType());
|
|
}
|
|
|
|
public static void SetActiveCategory<T>(this ViewDataDictionary viewData, T activeCategory)
|
|
{
|
|
viewData[ACTIVE_CATEGORY_KEY] = activeCategory;
|
|
}
|
|
|
|
// TODO: Refactor this and merge it with SetActivePage
|
|
public static void SetActiveId<T>(this ViewDataDictionary viewData, T activeId)
|
|
{
|
|
viewData[ACTIVE_ID_KEY] = activeId;
|
|
}
|
|
|
|
public static string IsActiveCategory<T>(this ViewDataDictionary viewData, T category, object id = null)
|
|
{
|
|
if (!viewData.ContainsKey(ACTIVE_CATEGORY_KEY))
|
|
{
|
|
return null;
|
|
}
|
|
var activeId = viewData[ACTIVE_ID_KEY];
|
|
var activeCategory = (T)viewData[ACTIVE_CATEGORY_KEY];
|
|
var categoryMatch = category.Equals(activeCategory);
|
|
var idMatch = id == null || activeId == null || id.Equals(activeId);
|
|
return categoryMatch && idMatch ? "active" : null;
|
|
}
|
|
|
|
public static string IsActivePage<T>(this ViewDataDictionary viewData, T page, object id = null)
|
|
where T : IConvertible
|
|
{
|
|
if (!viewData.ContainsKey(ACTIVE_PAGE_KEY))
|
|
{
|
|
return null;
|
|
}
|
|
var activeId = viewData[ACTIVE_ID_KEY];
|
|
var activePage = (T)viewData[ACTIVE_PAGE_KEY];
|
|
var activeCategory = viewData[ACTIVE_CATEGORY_KEY];
|
|
var categoryAndPageMatch = activeCategory.Equals(activePage.GetType()) && page.Equals(activePage);
|
|
var idMatch = id == null || activeId == null || id.Equals(activeId);
|
|
return categoryAndPageMatch && idMatch ? "active" : null;
|
|
}
|
|
|
|
public static HtmlString ToBrowserDate(this DateTimeOffset date)
|
|
{
|
|
var displayDate = date.ToString("o", CultureInfo.InvariantCulture);
|
|
return new HtmlString($"<span class='localizeDate'>{displayDate}</span>");
|
|
}
|
|
|
|
public static HtmlString ToBrowserDate(this DateTime date)
|
|
{
|
|
var displayDate = date.ToString("o", CultureInfo.InvariantCulture);
|
|
return new HtmlString($"<span class='localizeDate'>{displayDate}</span>");
|
|
}
|
|
|
|
public static string ToTimeAgo(this DateTimeOffset date)
|
|
{
|
|
var diff = DateTimeOffset.UtcNow - date;
|
|
var formatted = diff.Seconds > 0
|
|
? $"{diff.TimeString()} ago"
|
|
: $"in {diff.Negate().TimeString()}";
|
|
return formatted;
|
|
}
|
|
|
|
public static string TimeString(this TimeSpan timeSpan)
|
|
{
|
|
if (timeSpan.TotalMinutes < 1)
|
|
{
|
|
return $"{(int)timeSpan.TotalSeconds} second{Plural((int)timeSpan.TotalSeconds)}";
|
|
}
|
|
if (timeSpan.TotalHours < 1)
|
|
{
|
|
return $"{(int)timeSpan.TotalMinutes} minute{Plural((int)timeSpan.TotalMinutes)}";
|
|
}
|
|
if (timeSpan.Days < 1)
|
|
{
|
|
return $"{(int)timeSpan.TotalHours} hour{Plural((int)timeSpan.TotalHours)}";
|
|
}
|
|
return $"{(int)timeSpan.TotalDays} day{Plural((int)timeSpan.TotalDays)}";
|
|
}
|
|
|
|
private static string Plural(int totalDays)
|
|
{
|
|
return totalDays > 1 ? "s" : string.Empty;
|
|
}
|
|
}
|
|
}
|