Store Branding: Refactoring and logo as favicon (#5519)

* Store Branding: Refactoring and logo as favicon

- Encapsulates store branding properties into their own view model
- Uses the logo as favicon on public pages

* Refactorings

* Updates
This commit is contained in:
d11n 2023-12-01 16:13:44 +01:00 committed by GitHub
parent afed3a0899
commit 44b7ed0e6e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
33 changed files with 138 additions and 140 deletions

View File

@ -223,9 +223,7 @@ namespace BTCPayServer.Controllers
Currency = i.Currency,
Timestamp = i.InvoiceTime,
StoreName = store.StoreName,
BrandColor = storeBlob.BrandColor,
LogoFileId = storeBlob.LogoFileId,
CssFileId = storeBlob.CssFileId,
StoreBranding = new StoreBrandingViewModel(storeBlob),
ReceiptOptions = receipt
};
@ -858,11 +856,11 @@ namespace BTCPayServer.Controllers
DefaultLang = lang ?? invoice.DefaultLanguage ?? storeBlob.DefaultLang ?? "en",
ShowPayInWalletButton = storeBlob.ShowPayInWalletButton,
ShowStoreHeader = storeBlob.ShowStoreHeader,
CustomCSSLink = storeBlob.CustomCSS,
StoreBranding = new StoreBrandingViewModel(storeBlob)
{
CustomCSSLink = storeBlob.CustomCSS
},
CustomLogoLink = storeBlob.CustomLogo,
LogoFileId = storeBlob.LogoFileId,
CssFileId = storeBlob.CssFileId,
BrandColor = storeBlob.BrandColor,
CheckoutType = invoice.CheckoutType ?? storeBlob.CheckoutType,
HtmlTitle = storeBlob.HtmlTitle ?? "BTCPay Invoice",
CelebratePayment = storeBlob.CelebratePayment,

View File

@ -10,6 +10,7 @@ using BTCPayServer.Data;
using BTCPayServer.Filters;
using BTCPayServer.Forms;
using BTCPayServer.Forms.Models;
using BTCPayServer.Models;
using BTCPayServer.Models.PaymentRequestViewModels;
using BTCPayServer.PaymentRequest;
using BTCPayServer.Services;
@ -209,12 +210,14 @@ namespace BTCPayServer.Controllers
}
var storeBlob = store.GetStoreBlob();
vm.HubPath = PaymentRequestHub.GetHubPath(Request);
vm.StoreName = store.StoreName;
vm.StoreWebsite = store.StoreWebsite;
vm.BrandColor = storeBlob.BrandColor;
vm.LogoFileId = storeBlob.LogoFileId;
vm.CssFileId = storeBlob.CssFileId;
vm.HubPath = PaymentRequestHub.GetHubPath(Request);
vm.StoreBranding = new StoreBrandingViewModel(storeBlob)
{
EmbeddedCSS = vm.EmbeddedCSS,
CustomCSSLink = vm.CustomCSSLink
};
return View(vm);
}
@ -240,7 +243,6 @@ namespace BTCPayServer.Controllers
var formData = await FormDataService.GetForm(prFormId);
if (formData is null)
{
return RedirectToAction("PayPaymentRequest", new { payReqId });
}
@ -266,8 +268,14 @@ namespace BTCPayServer.Controllers
}
viewModel.FormName = formData.Name;
viewModel.Form = form;
var storeBlob = result.StoreData.GetStoreBlob();
viewModel.StoreBranding = new StoreBrandingViewModel(storeBlob)
{
EmbeddedCSS = prBlob.EmbeddedCSS,
CustomCSSLink = prBlob.CustomCSSLink
};
return View("Views/UIForms/View", viewModel);
}
[HttpGet("{payReqId}/pay")]

View File

@ -5,6 +5,7 @@ using BTCPayServer.Data;
using BTCPayServer.Filters;
using BTCPayServer.Lightning;
using BTCPayServer.Logging;
using BTCPayServer.Models;
using BTCPayServer.Payments;
using BTCPayServer.Payments.Lightning;
using BTCPayServer.Services.Stores;
@ -42,9 +43,7 @@ namespace BTCPayServer.Controllers
{
CryptoCode = cryptoCode,
StoreName = store.StoreName,
BrandColor = storeBlob.BrandColor,
LogoFileId = storeBlob.LogoFileId,
CssFileId = storeBlob.CssFileId
StoreBranding = new StoreBrandingViewModel(storeBlob)
};
try
{
@ -74,7 +73,6 @@ namespace BTCPayServer.Controllers
return existing;
}
private string GetImage(PaymentMethodId paymentMethodId, BTCPayNetwork network)
{
var res = paymentMethodId.PaymentType == PaymentTypes.BTCLike
@ -84,7 +82,6 @@ namespace BTCPayServer.Controllers
}
}
public class ShowLightningNodeInfoViewModel
{
public class NodeData
@ -103,13 +100,11 @@ namespace BTCPayServer.Controllers
return _connection;
}
}
public StoreBrandingViewModel StoreBranding { get; set; }
public NodeData[] NodeInfo { get; set; }
public bool Available { get; set; }
public string CryptoCode { get; set; }
public string CryptoImage { get; set; }
public string StoreName { get; set; }
public string LogoFileId { get; set; }
public string CssFileId { get; set; }
public string BrandColor { get; set; }
}
}

View File

@ -83,8 +83,6 @@ namespace BTCPayServer.Controllers
ViewPullPaymentModel vm = new(pp, DateTimeOffset.UtcNow)
{
BrandColor = storeBlob.BrandColor,
CssFileId = storeBlob.CssFileId,
AmountCollected = totalPaid,
AmountDue = amountDue,
ClaimedAmount = amountDue,
@ -105,6 +103,11 @@ namespace BTCPayServer.Controllers
}).ToList()
};
vm.IsPending &= vm.AmountDue > 0.0m;
vm.StoreBranding = new StoreBrandingViewModel(storeBlob)
{
EmbeddedCSS = blob.View.EmbeddedCSS,
CustomCSSLink = blob.View.CustomCSSLink
};
if (_pullPaymentHostedService.SupportsLNURL(blob))
{

View File

@ -139,9 +139,10 @@ namespace BTCPayServer.Controllers
public async Task<IActionResult> Index(string storeId)
{
var userId = _UserManager.GetUserId(User);
if(userId is null)
if (string.IsNullOrEmpty(userId))
return Forbid();
var store = await _Repo.FindStore(storeId, _UserManager.GetUserId(User));
var store = await _Repo.FindStore(storeId, userId);
if (store is null)
{
return Forbid();
@ -158,12 +159,10 @@ namespace BTCPayServer.Controllers
return View();
}
[HttpGet]
[Route("{storeId}/users")]
[HttpGet("{storeId}/users")]
public async Task<IActionResult> StoreUsers()
{
StoreUsersViewModel vm = new StoreUsersViewModel();
vm.Role = StoreRoleId.Guest.Role;
var vm = new StoreUsersViewModel { Role = StoreRoleId.Guest.Role };
await FillUsers(vm);
return View(vm);
}
@ -182,8 +181,7 @@ namespace BTCPayServer.Controllers
public StoreData CurrentStore => HttpContext.GetStoreData();
[HttpPost]
[Route("{storeId}/users")]
[HttpPost("{storeId}/users")]
public async Task<IActionResult> StoreUsers(string storeId, StoreUsersViewModel vm)
{
await FillUsers(vm);

View File

@ -1,13 +1,11 @@
using System.Collections.Generic;
using BTCPayServer.Abstractions.Form;
using BTCPayServer.Models;
namespace BTCPayServer.Forms.Models;
public class FormViewModel
{
public string LogoFileId { get; set; }
public string CssFileId { get; set; }
public string BrandColor { get; set; }
public string StoreName { get; set; }
public string FormName { get; set; }
public Form Form { get; set; }
@ -15,5 +13,6 @@ public class FormViewModel
public string AspAction { get; set; }
public Dictionary<string, string> RouteParameters { get; set; } = new();
public MultiValueDictionary<string, string> FormParameters { get; set; } = new();
public StoreBrandingViewModel StoreBranding { get; set; }
public string FormParameterPrefix { get; set; }
}

View File

@ -13,6 +13,7 @@ using BTCPayServer.Controllers;
using BTCPayServer.Data;
using BTCPayServer.Filters;
using BTCPayServer.Forms.Models;
using BTCPayServer.Models;
using BTCPayServer.Services.Stores;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
@ -164,9 +165,7 @@ public class UIFormsController : Controller
FormName = formData.Name,
Form = form,
StoreName = store?.StoreName,
BrandColor = storeBlob?.BrandColor,
CssFileId = storeBlob?.CssFileId,
LogoFileId = storeBlob?.LogoFileId,
StoreBranding = new StoreBrandingViewModel(storeBlob)
});
}

View File

@ -9,13 +9,11 @@ namespace BTCPayServer.Models.InvoicingModels
public class InvoiceReceiptViewModel
{
public InvoiceStatus Status { get; set; }
public StoreBrandingViewModel StoreBranding { get; set; }
public string InvoiceId { get; set; }
public string OrderId { get; set; }
public string Currency { get; set; }
public string StoreName { get; set; }
public string BrandColor { get; set; }
public string LogoFileId { get; set; }
public string CssFileId { get; set; }
public decimal Amount { get; set; }
public DateTimeOffset Timestamp { get; set; }
public Dictionary<string, object> AdditionalData { get; set; }

View File

@ -23,10 +23,9 @@ namespace BTCPayServer.Models.InvoicingModels
public string CryptoCode { get; set; }
public bool Displayed { get; set; }
}
public StoreBrandingViewModel StoreBranding { get; set; }
public string CustomCSSLink { get; set; }
public string CustomLogoLink { get; set; }
public string CssFileId { get; set; }
public string LogoFileId { get; set; }
public string PaymentSoundUrl { get; set; }
public string NfcReadSoundUrl { get; set; }
public string ErrorSoundUrl { get; set; }

View File

@ -118,8 +118,6 @@ namespace BTCPayServer.Models.PaymentRequestViewModels
EmbeddedCSS = blob.EmbeddedCSS;
CustomCSSLink = blob.CustomCSSLink;
AllowCustomPaymentAmounts = blob.AllowCustomPaymentAmounts;
if (!string.IsNullOrEmpty(EmbeddedCSS))
EmbeddedCSS = $"<style>{EmbeddedCSS}</style>";
switch (data.Status)
{
case Client.Models.PaymentRequestData.PaymentRequestStatus.Pending:
@ -139,7 +137,7 @@ namespace BTCPayServer.Models.PaymentRequestViewModels
throw new ArgumentOutOfRangeException();
}
}
public StoreBrandingViewModel StoreBranding { get; set; }
public bool AllowCustomPaymentAmounts { get; set; }
public string Email { get; set; }
public string Status { get; set; }
@ -154,9 +152,6 @@ namespace BTCPayServer.Models.PaymentRequestViewModels
public DateTime? ExpiryDate { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public string LogoFileId { get; set; }
public string CssFileId { get; set; }
public string BrandColor { get; set; }
public string StoreName { get; set; }
public string StoreWebsite { get; set; }
public string EmbeddedCSS { get; set; }

View File

@ -0,0 +1,24 @@
using BTCPayServer.Data;
namespace BTCPayServer.Models;
public class StoreBrandingViewModel
{
public string BrandColor { get; set; }
public string LogoFileId { get; set; }
public string CssFileId { get; set; }
public string CustomCSSLink { get; set; }
public string EmbeddedCSS { get; set; }
public StoreBrandingViewModel()
{
}
public StoreBrandingViewModel(StoreBlob storeBlob)
{
if (storeBlob == null) return;
BrandColor = storeBlob.BrandColor;
LogoFileId = storeBlob.LogoFileId;
CssFileId = storeBlob.CssFileId;
}
}

View File

@ -34,10 +34,6 @@ namespace BTCPayServer.Models
ExpiryDate = data.EndDate is DateTimeOffset dt ? (DateTime?)dt.UtcDateTime : null;
Email = blob.View.Email;
MinimumClaim = blob.MinimumClaim;
EmbeddedCSS = blob.View.EmbeddedCSS;
CustomCSSLink = blob.View.CustomCSSLink;
if (!string.IsNullOrEmpty(EmbeddedCSS))
EmbeddedCSS = $"<style>{EmbeddedCSS}</style>";
IsPending = !data.IsExpired();
var period = data.GetPeriod(now);
if (data.Archived)
@ -91,15 +87,12 @@ namespace BTCPayServer.Models
public DateTime? ExpiryDate { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public string BrandColor { get; set; }
public string CssFileId { get; set; }
public string EmbeddedCSS { get; set; }
public string CustomCSSLink { get; set; }
public List<PayoutLine> Payouts { get; set; } = new();
public DateTimeOffset StartDate { get; set; }
public DateTime LastRefreshed { get; set; }
public CurrencyData CurrencyData { get; set; }
public Uri LnurlEndpoint { get; set; }
public StoreBrandingViewModel StoreBranding { get; set; }
public bool Archived { get; set; }
public bool AutoApprove { get; set; }

View File

@ -94,7 +94,6 @@ namespace BTCPayServer.PaymentRequest
}
var blob = pr.GetBlob();
var invoices = await _paymentRequestRepository.GetInvoicesForPaymentRequest(id);
var paymentStats = _invoiceRepository.GetContributionsByPaymentMethodId(blob.Currency, invoices, true);
var amountDue = blob.Amount - paymentStats.TotalCurrency;

View File

@ -8,6 +8,7 @@ using BTCPayServer.Abstractions.Models;
using BTCPayServer.Abstractions.Services;
using BTCPayServer.Configuration;
using BTCPayServer.Data;
using BTCPayServer.Models;
using BTCPayServer.Plugins.Crowdfund.Controllers;
using BTCPayServer.Plugins.Crowdfund.Models;
using BTCPayServer.Plugins.PointOfSale;
@ -177,19 +178,19 @@ namespace BTCPayServer.Plugins.Crowdfund
var store = appData.StoreData;
var storeBlob = store.GetStoreBlob();
var storeBranding = new StoreBrandingViewModel(storeBlob)
{
CustomCSSLink = settings.CustomCSSLink,
EmbeddedCSS = settings.EmbeddedCSS
};
return new ViewCrowdfundViewModel
{
Title = settings.Title,
Tagline = settings.Tagline,
Description = settings.Description,
CustomCSSLink = settings.CustomCSSLink,
MainImageUrl = settings.MainImageUrl,
EmbeddedCSS = settings.EmbeddedCSS,
StoreName = store.StoreName,
CssFileId = storeBlob.CssFileId,
LogoFileId = storeBlob.LogoFileId,
BrandColor = storeBlob.BrandColor,
StoreBranding = storeBranding,
StoreId = appData.StoreDataId,
AppId = appData.Id,
StartDate = settings.StartDate?.ToUniversalTime(),

View File

@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using BTCPayServer.Models;
using BTCPayServer.Plugins.PointOfSale.Models;
using BTCPayServer.Services.Rates;
@ -14,12 +15,7 @@ namespace BTCPayServer.Plugins.Crowdfund.Models
public string Title { get; set; }
public string Description { get; set; }
public string MainImageUrl { get; set; }
public string CssFileId { get; set; }
public string LogoFileId { get; set; }
public string StoreName { get; set; }
public string BrandColor { get; set; }
public string EmbeddedCSS { get; set; }
public string CustomCSSLink { get; set; }
public DateTime? StartDate { get; set; }
public DateTime? EndDate { get; set; }
@ -29,6 +25,7 @@ namespace BTCPayServer.Plugins.Crowdfund.Models
public CrowdfundInfo Info { get; set; }
public string Tagline { get; set; }
public StoreBrandingViewModel StoreBranding { get; set; }
public ViewPointOfSaleViewModel.Item[] Perks { get; set; }
public bool SimpleDisplay { get; set; }
public bool DisqusEnabled { get; set; }

View File

@ -87,13 +87,17 @@ namespace BTCPayServer.Plugins.PointOfSale.Controllers
var store = await _appService.GetStore(app);
var storeBlob = store.GetStoreBlob();
var storeBranding = new StoreBrandingViewModel(storeBlob)
{
EmbeddedCSS = settings.EmbeddedCSS,
CustomCSSLink = settings.CustomCSSLink
};
return View($"PointOfSale/Public/{viewType}", new ViewPointOfSaleViewModel
{
Title = settings.Title,
StoreName = store.StoreName,
BrandColor = storeBlob.BrandColor,
CssFileId = storeBlob.CssFileId,
LogoFileId = storeBlob.LogoFileId,
StoreBranding = storeBranding,
Step = step.ToString(CultureInfo.InvariantCulture),
ViewType = (PosViewType)viewType,
ShowCustomAmount = settings.ShowCustomAmount,
@ -117,12 +121,9 @@ namespace BTCPayServer.Plugins.PointOfSale.Controllers
CustomButtonText = settings.CustomButtonText,
CustomTipText = settings.CustomTipText,
CustomTipPercentages = settings.CustomTipPercentages,
CustomCSSLink = settings.CustomCSSLink,
CustomLogoLink = storeBlob.CustomLogo,
AppId = appId,
StoreId = store.Id,
Description = settings.Description,
EmbeddedCSS = settings.EmbeddedCSS,
RequiresRefundEmail = settings.RequiresRefundEmail
});
}
@ -458,9 +459,7 @@ namespace BTCPayServer.Plugins.PointOfSale.Controllers
var vm = new FormViewModel
{
StoreName = store.StoreName,
BrandColor = storeBlob.BrandColor,
CssFileId = storeBlob.CssFileId,
LogoFileId = storeBlob.LogoFileId,
StoreBranding = new StoreBrandingViewModel(storeBlob),
FormName = formData.Name,
Form = form,
AspController = controller,

View File

@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using BTCPayServer.JsonConverters;
using BTCPayServer.Models;
using BTCPayServer.Services.Apps;
using Microsoft.AspNetCore.Mvc.Rendering;
using Newtonsoft.Json;
@ -57,9 +58,7 @@ namespace BTCPayServer.Plugins.PointOfSale.Models
public bool SymbolSpace { get; set; }
}
public string LogoFileId { get; set; }
public string CssFileId { get; set; }
public string BrandColor { get; set; }
public StoreBrandingViewModel StoreBranding { get; set; }
public string StoreName { get; set; }
public CurrencyInfoData CurrencyInfo { get; set; }
public PosViewType ViewType { get; set; }
@ -106,14 +105,9 @@ namespace BTCPayServer.Plugins.PointOfSale.Models
public string CustomButtonText { get; set; }
public string CustomTipText { get; set; }
public int[] CustomTipPercentages { get; set; }
[Display(Name = "Custom CSS URL")]
public string CustomCSSLink { get; set; }
public string CustomLogoLink { get; set; }
public string Description { get; set; }
public SelectList AllCategories { get; set; }
[Display(Name = "Custom CSS Code")]
public string EmbeddedCSS { get; set; }
public RequiresRefundEmail RequiresRefundEmail { get; set; } = RequiresRefundEmail.InheritFromStore;
public string StoreId { get; set; }
}

View File

@ -4,6 +4,7 @@
@inject BTCPayServer.Security.ContentSecurityPolicies Csp
@{
ViewData["Title"] = Model.Title;
ViewData["StoreBranding"] = Model.StoreBranding;
Layout = null;
Csp.UnsafeEval();
if (!string.IsNullOrEmpty(Model.DisqusShortname))
@ -16,18 +17,8 @@
<html class="h-100" @(Env.IsDeveloping ? " data-devenv" : "")>
<head>
<partial name="LayoutHead"/>
<partial name="LayoutHeadStoreBranding" model="@(Model.BrandColor, Model.CssFileId, Model.CustomCSSLink, Model.EmbeddedCSS)" />
<link href="~/vendor/bootstrap-vue/bootstrap-vue.min.css" asp-append-version="true" rel="stylesheet" />
<link href="~/crowdfund/styles/main.css" asp-append-version="true" rel="stylesheet" />
@if (!string.IsNullOrEmpty(Model.CustomCSSLink))
{
<link href="@Model.CustomCSSLink" rel="stylesheet" asp-append-version="true"/>
}
@if (!string.IsNullOrEmpty(Model.EmbeddedCSS))
{
@Safe.Raw($"<style>{Model.EmbeddedCSS}</style>")
}
<link href="~/vendor/bootstrap-vue/bootstrap-vue.min.css" asp-append-version="true" rel="stylesheet"/>
<link href="~/crowdfund/styles/main.css" asp-append-version="true" rel="stylesheet"/>
<style>
#app { --wrap-max-width: 1320px; }
#crowdfund-main-image {
@ -44,7 +35,7 @@
object-fit: scale-down;
}
</style>
<vc:ui-extension-point location="crowdfund-head" model="@Model"></vc:ui-extension-point>
<vc:ui-extension-point location="crowdfund-head" model="@Model"/>
</head>
<body class="min-vh-100 p-2">
@if (!Model.Enabled)

View File

@ -1,7 +1,6 @@
@inject BTCPayServer.Services.PoliciesSettings PoliciesSettings
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="icon" href="~/favicon.ico" type="image/x-icon">
@if (PoliciesSettings.DiscourageSearchEngines)
{
<meta name="robots" content="noindex">
@ -16,6 +15,17 @@
<link href="~/main/site.css" asp-append-version="true" rel="stylesheet" />
<partial name="LayoutHeadTheme" />
@if (ViewData.TryGetValue("StoreBranding", out var storeBranding))
{
<partial name="LayoutHeadStoreBranding" model="storeBranding" />
}
else
{
<meta name="theme-color" content="#51B13E">
<link rel="icon" href="~/favicon.ico">
<link rel="apple-touch-icon" href="~/img/icons/icon-512x512.png">
<link rel="apple-touch-startup-image" href="~/img/splash.png">
}
@* Non-JS *@
<noscript>
<style>

View File

@ -1,9 +1,10 @@
@model (string BrandColor, string CssFileId, string CustomCSSLink, string EmbeddedCSS)
@using BTCPayServer.Abstractions.Extensions
@using Microsoft.AspNetCore.Mvc.TagHelpers
@model StoreBrandingViewModel
@using BTCPayServer.Abstractions.Contracts
@inject IFileService FileService
@{
var logoUrl = !string.IsNullOrEmpty(Model.LogoFileId)
? await FileService.GetFileUrl(Context.Request.GetAbsoluteRootUri(), Model.LogoFileId)
: null;
var cssUrl = !string.IsNullOrEmpty(Model.CssFileId)
? await FileService.GetFileUrl(Context.Request.GetAbsoluteRootUri(), Model.CssFileId)
: null;
@ -36,6 +37,7 @@
color: var(--btcpay-body-link-accent);
}
</style>
<meta name="theme-color" content="@brand">
}
@if (!string.IsNullOrEmpty(cssUrl))
{
@ -52,3 +54,8 @@
@Safe.Raw(Model.EmbeddedCSS)
</style>
}
@if (!string.IsNullOrEmpty(logoUrl))
{
<link rel="icon" href="@logoUrl">
<link rel="apple-touch-icon" href="@logoUrl">
}

View File

@ -15,7 +15,7 @@
}
<div id="PosKeypad" class="public-page-wrap">
<partial name="_StatusMessage" />
<partial name="_StoreHeader" model="(string.IsNullOrEmpty(Model.Title) ? Model.StoreName : Model.Title, Model.LogoFileId)" />
<partial name="_StoreHeader" model="(string.IsNullOrEmpty(Model.Title) ? Model.StoreName : Model.Title, Model.StoreBranding)" />
@if (Context.Request.Query.ContainsKey("simple"))
{
<partial name="PointOfSale/Public/MinimalLight" model="Model" />

View File

@ -44,7 +44,7 @@ else
}
<div id="PosPrint" class="public-page-wrap">
<partial name="_StatusMessage" />
<partial name="_StoreHeader" model="(string.IsNullOrEmpty(Model.Title) ? Model.StoreName : Model.Title, Model.LogoFileId)" />
<partial name="_StoreHeader" model="(string.IsNullOrEmpty(Model.Title) ? Model.StoreName : Model.Title, Model.StoreBranding)" />
@if (!string.IsNullOrEmpty(Model.Description))
{
<div class="lead text-center">@Safe.Raw(Model.Description)</div>

View File

@ -17,7 +17,7 @@
}
<div id="PosStatic" class="public-page-wrap">
<partial name="_StoreHeader" model="(string.IsNullOrEmpty(Model.Title) ? Model.StoreName : Model.Title, Model.LogoFileId)" />
<partial name="_StoreHeader" model="(string.IsNullOrEmpty(Model.Title) ? Model.StoreName : Model.Title, Model.StoreBranding)" />
<main>
<partial name="_StatusMessage" />
@if (!string.IsNullOrEmpty(Model.Description))

View File

@ -1,6 +1,4 @@
@using BTCPayServer.Abstractions.Extensions
@using Microsoft.AspNetCore.Hosting
@using Microsoft.AspNetCore.Mvc.TagHelpers
@using Newtonsoft.Json.Linq
@using System.IO
@using BTCPayServer.Services
@ -9,6 +7,7 @@
@model BTCPayServer.Plugins.PointOfSale.Models.ViewPointOfSaleViewModel
@{
ViewData["Title"] = string.IsNullOrEmpty(Model.Title) ? Model.StoreName : Model.Title;
ViewData["StoreBranding"] = Model.StoreBranding;
Layout = null;
async Task<string> GetDynamicManifest(string title)
@ -33,10 +32,8 @@
<!DOCTYPE html>
<html class="h-100" lang="en" @(Env.IsDeveloping ? " data-devenv" : "")>
<head>
<partial name="LayoutHead"/>
<partial name="LayoutHeadStoreBranding" model="@(Model.BrandColor, Model.CssFileId, Model.CustomCSSLink, Model.EmbeddedCSS)" />
<partial name="LayoutHead" />
<meta name="apple-mobile-web-app-capable" content="yes">
<link rel="apple-touch-icon" href="~/img/icons/icon-512x512.png">
<link rel="apple-touch-startup-image" href="~/img/splash.png">
<link rel="manifest" href="@(await GetDynamicManifest(ViewData["Title"]!.ToString()))">
<link href="~/pos/common.css" asp-append-version="true" rel="stylesheet" />

View File

@ -16,8 +16,7 @@
.account-form h4 {
margin-bottom: 1.5rem;
}
.main-logo { height: 4rem; width: 18rem; }
.main-logo.main-logo-btcpay { height: 4.5rem; width: 2.5rem; }
.main-logo { height: 4.5rem; max-width: 18rem; }
.main-logo-btcpay .main-logo-btcpay--large { display: none; }
</style>
@await RenderSectionAsync("PageHeadContent", false)

View File

@ -1,10 +1,9 @@
@inject IFileService FileService
@using BTCPayServer.Abstractions.Contracts
@using BTCPayServer.Abstractions.Extensions
@model (string Title, string LogoFileId)
@model (string Title, StoreBrandingViewModel StoreBranding)
@{
var logoUrl = !string.IsNullOrEmpty(Model.LogoFileId)
? await FileService.GetFileUrl(Context.Request.GetAbsoluteRootUri(), Model.LogoFileId)
var logoUrl = !string.IsNullOrEmpty(Model.StoreBranding.LogoFileId)
? await FileService.GetFileUrl(Context.Request.GetAbsoluteRootUri(), Model.StoreBranding.LogoFileId)
: null;
}
<header class="store-header" v-pre>

View File

@ -3,21 +3,21 @@
@{
Layout = null;
ViewData["Title"] = Model.FormName;
ViewData["StoreBranding"] = Model.StoreBranding;
}
<!DOCTYPE html>
<html lang="en" @(Env.IsDeveloping ? " data-devenv" : "")>
<head>
<partial name="LayoutHead" />
<partial name="LayoutHeadStoreBranding" model="@(Model.BrandColor, Model.CssFileId, "", "")" />
<meta name="robots" content="noindex,nofollow">
<style>#FormView { --wrap-max-width: 576px; }</style>
</head>
<body class="min-vh-100">
<div id="FormView" class="public-page-wrap">
<partial name="_StatusMessage" model="@(new ViewDataDictionary(ViewData) { { "Margin", "mb-4" } })" />
@if (!string.IsNullOrEmpty(Model.StoreName) || !string.IsNullOrEmpty(Model.LogoFileId))
@if (!string.IsNullOrEmpty(Model.StoreName) || !string.IsNullOrEmpty(Model.StoreBranding.LogoFileId))
{
<partial name="_StoreHeader" model="(Model.StoreName, Model.LogoFileId)" />
<partial name="_StoreHeader" model="(Model.StoreName, Model.StoreBranding)" />
}
else
{

View File

@ -1,7 +1,5 @@
@using BTCPayServer.Services
@using BTCPayServer.Abstractions.Contracts
@using Microsoft.AspNetCore.Mvc.TagHelpers
@using Microsoft.EntityFrameworkCore.Diagnostics
@inject LanguageService LangService
@inject BTCPayServerEnvironment Env
@inject IEnumerable<IUIExtension> UiExtensions
@ -11,6 +9,7 @@
@{
Layout = null;
ViewData["Title"] = Model.HtmlTitle;
ViewData["StoreBranding"] = Model.StoreBranding;
Csp.UnsafeEval();
var hasPaymentPlugins = UiExtensions.Any(extension => extension.Location == "checkout-payment-method");
var displayedPaymentMethods = Model.AvailableCryptos.Where(c => c.Displayed).ToList();
@ -27,7 +26,6 @@
<partial name="LayoutHead"/>
<meta name="robots" content="noindex,nofollow">
<link href="~/checkout-v2/checkout.css" asp-append-version="true" rel="stylesheet" />
<partial name="LayoutHeadStoreBranding" model="@(Model.BrandColor, Model.CssFileId, "", "")" />
@if (!string.IsNullOrEmpty(Model.PaymentSoundUrl))
{
<link rel="preload" href="@Model.PaymentSoundUrl" as="audio" />
@ -45,7 +43,7 @@
<div id="Checkout-v2" class="public-page-wrap" v-cloak>
@if (Model.ShowStoreHeader)
{
<partial name="_StoreHeader" model="(Model.StoreName, Model.LogoFileId)" />
<partial name="_StoreHeader" model="(Model.StoreName, Model.StoreBranding)" />
}
<main class="tile">
<nav v-if="isModal">

View File

@ -8,6 +8,7 @@
@{
Layout = null;
ViewData["Title"] = $"Receipt from {Model.StoreName}";
ViewData["StoreBranding"] = Model.StoreBranding;
var isProcessing = Model.Status == InvoiceStatus.Processing;
var isFreeInvoice = (Model.Status == InvoiceStatus.New && Model.Amount == 0);
var isSettled = Model.Status == InvoiceStatus.Settled;
@ -15,8 +16,7 @@
<!DOCTYPE html>
<html lang="en" @(Env.IsDeveloping ? " data-devenv" : "")>
<head>
<partial name="LayoutHead" />
<partial name="LayoutHeadStoreBranding" model="@(Model.BrandColor, Model.CssFileId, "", "")" />
<partial name="LayoutHead"/>
<meta name="robots" content="noindex,nofollow">
@if (isProcessing)
{
@ -43,7 +43,7 @@
<div id="InvoiceReceipt" class="public-page-wrap">
<main class="flex-grow-1">
<div class="d-flex flex-column justify-content-center gap-4">
<partial name="_StoreHeader" model="(Model.StoreName, Model.LogoFileId)" />
<partial name="_StoreHeader" model="(Model.StoreName, Model.StoreBranding)" />
<partial name="_StatusMessage" model="@(new ViewDataDictionary(ViewData) { { "Margin", "mb-4" } })"/>
<div id="InvoiceSummary" class="tile d-flex flex-wrap align-items-center justify-content-center">
@if (isProcessing)

View File

@ -74,7 +74,7 @@
<body class="m-0 p-0 bg-white">
<center>
<partial name="_StoreHeader" model="(Model.StoreName, Model.LogoFileId)" />
<partial name="_StoreHeader" model="(Model.StoreName, Model.StoreBranding)" />
<div id="InvoiceSummary" style="max-width:600px">
@if (isProcessing)
{

View File

@ -6,6 +6,7 @@
@inject BTCPayServer.Security.ContentSecurityPolicies Csp
@{
ViewData["Title"] = Model.Title;
ViewData["StoreBranding"] = Model.StoreBranding;
Csp.UnsafeEval();
Layout = null;
string StatusClass(InvoiceState state)
@ -33,9 +34,8 @@
<!DOCTYPE html>
<html lang="en" @(Env.IsDeveloping ? " data-devenv" : "")>
<head>
<partial name="LayoutHead" />
<partial name="LayoutHeadStoreBranding" model="@(Model.BrandColor, Model.CssFileId, Model.CustomCSSLink, Model.EmbeddedCSS)" />
<link href="~/vendor/bootstrap-vue/bootstrap-vue.min.css" asp-append-version="true" rel="stylesheet" />
<partial name="LayoutHead"/>
<link href="~/vendor/bootstrap-vue/bootstrap-vue.min.css" asp-append-version="true" rel="stylesheet"/>
<script>var srvModel = @Safe.Json(Model);</script>
<script src="~/vendor/vuejs/vue.min.js" asp-append-version="true"></script>
<script src="~/vendor/vue-toasted/vue-toasted.min.js" asp-append-version="true"></script>
@ -63,7 +63,7 @@
<div id="app" class="public-page-wrap">
<main class="flex-grow-1">
<div class="d-flex flex-column justify-content-center gap-4">
<partial name="_StoreHeader" model="(Model.Title, Model.LogoFileId)" />
<partial name="_StoreHeader" model="(Model.Title, Model.StoreBranding)" />
<div class="text-center mt-n3">
Invoice from
@if (!string.IsNullOrEmpty(Model.StoreWebsite))

View File

@ -3,20 +3,20 @@
@{
Layout = null;
ViewData["Title"] = $"{Model.StoreName} {Model.CryptoCode} Lightning Node";
ViewData["StoreBranding"] = Model.StoreBranding;
}
<!DOCTYPE html>
<html lang="en" @(Env.IsDeveloping ? " data-devenv" : "")>
<head>
<partial name="LayoutHead" />
<partial name="LayoutHeadStoreBranding" model="@(Model.BrandColor, Model.CssFileId, "", "")" />
<link href="~/main/qrcode.css" rel="stylesheet" asp-append-version="true" />
<partial name="LayoutHead"/>
<link href="~/main/qrcode.css" rel="stylesheet" asp-append-version="true"/>
<style>#app { --wrap-max-width: 400px; }</style>
</head>
<body class="min-vh-100">
<div id="app" class="public-page-wrap">
<main class="flex-grow-1">
<div class="d-flex flex-column justify-content-center gap-4">
<partial name="_StoreHeader" model="(Model.StoreName, Model.LogoFileId)" />
<partial name="_StoreHeader" model="(Model.StoreName, Model.StoreBranding)" />
<section class="tile">
<h2 class="h4 card-subtitle text-center text-secondary mt-1 mb-3">
<span>@Model.CryptoCode</span>

View File

@ -1,13 +1,12 @@
@using BTCPayServer.Client
@using BTCPayServer.Services
@using Microsoft.AspNetCore.Mvc.TagHelpers
@using BTCPayServer.Abstractions.TagHelpers
@inject BTCPayServer.Security.ContentSecurityPolicies Csp
@inject BTCPayServerEnvironment Env
@inject DisplayFormatter DisplayFormatter
@model BTCPayServer.Models.ViewPullPaymentModel
@{
ViewData["Title"] = Model.Title;
ViewData["StoreBranding"] = Model.StoreBranding;
Csp.UnsafeEval();
Layout = null;
string StatusTextClass(string status)
@ -28,9 +27,8 @@
<!DOCTYPE html>
<html lang="en" @(Env.IsDeveloping ? " data-devenv" : "")>
<head>
<partial name="LayoutHead" />
<partial name="LayoutHeadStoreBranding" model="@(Model.BrandColor, Model.CssFileId, Model.CustomCSSLink, Model.EmbeddedCSS)" />
<link href="~/vendor/bootstrap-vue/bootstrap-vue.min.css" asp-append-version="true" rel="stylesheet" />
<partial name="LayoutHead"/>
<link href="~/vendor/bootstrap-vue/bootstrap-vue.min.css" asp-append-version="true" rel="stylesheet"/>
<link href="~/vendor/vue-qrcode-reader/vue-qrcode-reader.css" rel="stylesheet" asp-append-version="true"/>
<style>
.no-marker > ul { list-style-type: none; }