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
33 changed files with 138 additions and 140 deletions

View File

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

View File

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

View File

@@ -5,6 +5,7 @@ using BTCPayServer.Data;
using BTCPayServer.Filters; using BTCPayServer.Filters;
using BTCPayServer.Lightning; using BTCPayServer.Lightning;
using BTCPayServer.Logging; using BTCPayServer.Logging;
using BTCPayServer.Models;
using BTCPayServer.Payments; using BTCPayServer.Payments;
using BTCPayServer.Payments.Lightning; using BTCPayServer.Payments.Lightning;
using BTCPayServer.Services.Stores; using BTCPayServer.Services.Stores;
@@ -42,9 +43,7 @@ namespace BTCPayServer.Controllers
{ {
CryptoCode = cryptoCode, CryptoCode = cryptoCode,
StoreName = store.StoreName, StoreName = store.StoreName,
BrandColor = storeBlob.BrandColor, StoreBranding = new StoreBrandingViewModel(storeBlob)
LogoFileId = storeBlob.LogoFileId,
CssFileId = storeBlob.CssFileId
}; };
try try
{ {
@@ -74,7 +73,6 @@ namespace BTCPayServer.Controllers
return existing; return existing;
} }
private string GetImage(PaymentMethodId paymentMethodId, BTCPayNetwork network) private string GetImage(PaymentMethodId paymentMethodId, BTCPayNetwork network)
{ {
var res = paymentMethodId.PaymentType == PaymentTypes.BTCLike var res = paymentMethodId.PaymentType == PaymentTypes.BTCLike
@@ -84,7 +82,6 @@ namespace BTCPayServer.Controllers
} }
} }
public class ShowLightningNodeInfoViewModel public class ShowLightningNodeInfoViewModel
{ {
public class NodeData public class NodeData
@@ -103,13 +100,11 @@ namespace BTCPayServer.Controllers
return _connection; return _connection;
} }
} }
public StoreBrandingViewModel StoreBranding { get; set; }
public NodeData[] NodeInfo { get; set; } public NodeData[] NodeInfo { get; set; }
public bool Available { get; set; } public bool Available { get; set; }
public string CryptoCode { get; set; } public string CryptoCode { get; set; }
public string CryptoImage { get; set; } public string CryptoImage { get; set; }
public string StoreName { 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) ViewPullPaymentModel vm = new(pp, DateTimeOffset.UtcNow)
{ {
BrandColor = storeBlob.BrandColor,
CssFileId = storeBlob.CssFileId,
AmountCollected = totalPaid, AmountCollected = totalPaid,
AmountDue = amountDue, AmountDue = amountDue,
ClaimedAmount = amountDue, ClaimedAmount = amountDue,
@@ -105,6 +103,11 @@ namespace BTCPayServer.Controllers
}).ToList() }).ToList()
}; };
vm.IsPending &= vm.AmountDue > 0.0m; vm.IsPending &= vm.AmountDue > 0.0m;
vm.StoreBranding = new StoreBrandingViewModel(storeBlob)
{
EmbeddedCSS = blob.View.EmbeddedCSS,
CustomCSSLink = blob.View.CustomCSSLink
};
if (_pullPaymentHostedService.SupportsLNURL(blob)) if (_pullPaymentHostedService.SupportsLNURL(blob))
{ {

View File

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

View File

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

View File

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

View File

@@ -9,13 +9,11 @@ namespace BTCPayServer.Models.InvoicingModels
public class InvoiceReceiptViewModel public class InvoiceReceiptViewModel
{ {
public InvoiceStatus Status { get; set; } public InvoiceStatus Status { get; set; }
public StoreBrandingViewModel StoreBranding { get; set; }
public string InvoiceId { get; set; } public string InvoiceId { get; set; }
public string OrderId { get; set; } public string OrderId { get; set; }
public string Currency { get; set; } public string Currency { get; set; }
public string StoreName { 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 decimal Amount { get; set; }
public DateTimeOffset Timestamp { get; set; } public DateTimeOffset Timestamp { get; set; }
public Dictionary<string, object> AdditionalData { 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 string CryptoCode { get; set; }
public bool Displayed { get; set; } public bool Displayed { get; set; }
} }
public StoreBrandingViewModel StoreBranding { get; set; }
public string CustomCSSLink { get; set; } public string CustomCSSLink { get; set; }
public string CustomLogoLink { get; set; } public string CustomLogoLink { get; set; }
public string CssFileId { get; set; }
public string LogoFileId { get; set; }
public string PaymentSoundUrl { get; set; } public string PaymentSoundUrl { get; set; }
public string NfcReadSoundUrl { get; set; } public string NfcReadSoundUrl { get; set; }
public string ErrorSoundUrl { get; set; } public string ErrorSoundUrl { get; set; }

View File

@@ -118,8 +118,6 @@ namespace BTCPayServer.Models.PaymentRequestViewModels
EmbeddedCSS = blob.EmbeddedCSS; EmbeddedCSS = blob.EmbeddedCSS;
CustomCSSLink = blob.CustomCSSLink; CustomCSSLink = blob.CustomCSSLink;
AllowCustomPaymentAmounts = blob.AllowCustomPaymentAmounts; AllowCustomPaymentAmounts = blob.AllowCustomPaymentAmounts;
if (!string.IsNullOrEmpty(EmbeddedCSS))
EmbeddedCSS = $"<style>{EmbeddedCSS}</style>";
switch (data.Status) switch (data.Status)
{ {
case Client.Models.PaymentRequestData.PaymentRequestStatus.Pending: case Client.Models.PaymentRequestData.PaymentRequestStatus.Pending:
@@ -139,7 +137,7 @@ namespace BTCPayServer.Models.PaymentRequestViewModels
throw new ArgumentOutOfRangeException(); throw new ArgumentOutOfRangeException();
} }
} }
public StoreBrandingViewModel StoreBranding { get; set; }
public bool AllowCustomPaymentAmounts { get; set; } public bool AllowCustomPaymentAmounts { get; set; }
public string Email { get; set; } public string Email { get; set; }
public string Status { get; set; } public string Status { get; set; }
@@ -154,9 +152,6 @@ namespace BTCPayServer.Models.PaymentRequestViewModels
public DateTime? ExpiryDate { get; set; } public DateTime? ExpiryDate { get; set; }
public string Title { get; set; } public string Title { get; set; }
public string Description { 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 StoreName { get; set; }
public string StoreWebsite { get; set; } public string StoreWebsite { get; set; }
public string EmbeddedCSS { 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; ExpiryDate = data.EndDate is DateTimeOffset dt ? (DateTime?)dt.UtcDateTime : null;
Email = blob.View.Email; Email = blob.View.Email;
MinimumClaim = blob.MinimumClaim; MinimumClaim = blob.MinimumClaim;
EmbeddedCSS = blob.View.EmbeddedCSS;
CustomCSSLink = blob.View.CustomCSSLink;
if (!string.IsNullOrEmpty(EmbeddedCSS))
EmbeddedCSS = $"<style>{EmbeddedCSS}</style>";
IsPending = !data.IsExpired(); IsPending = !data.IsExpired();
var period = data.GetPeriod(now); var period = data.GetPeriod(now);
if (data.Archived) if (data.Archived)
@@ -91,15 +87,12 @@ namespace BTCPayServer.Models
public DateTime? ExpiryDate { get; set; } public DateTime? ExpiryDate { get; set; }
public string Title { get; set; } public string Title { get; set; }
public string Description { 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 List<PayoutLine> Payouts { get; set; } = new();
public DateTimeOffset StartDate { get; set; } public DateTimeOffset StartDate { get; set; }
public DateTime LastRefreshed { get; set; } public DateTime LastRefreshed { get; set; }
public CurrencyData CurrencyData { get; set; } public CurrencyData CurrencyData { get; set; }
public Uri LnurlEndpoint { get; set; } public Uri LnurlEndpoint { get; set; }
public StoreBrandingViewModel StoreBranding { get; set; }
public bool Archived { get; set; } public bool Archived { get; set; }
public bool AutoApprove { get; set; } public bool AutoApprove { get; set; }

View File

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

View File

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

View File

@@ -1,6 +1,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
using BTCPayServer.Models;
using BTCPayServer.Plugins.PointOfSale.Models; using BTCPayServer.Plugins.PointOfSale.Models;
using BTCPayServer.Services.Rates; using BTCPayServer.Services.Rates;
@@ -14,12 +15,7 @@ namespace BTCPayServer.Plugins.Crowdfund.Models
public string Title { get; set; } public string Title { get; set; }
public string Description { get; set; } public string Description { get; set; }
public string MainImageUrl { get; set; } public string MainImageUrl { get; set; }
public string CssFileId { get; set; }
public string LogoFileId { get; set; }
public string StoreName { 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? StartDate { get; set; }
public DateTime? EndDate { get; set; } public DateTime? EndDate { get; set; }
@@ -29,6 +25,7 @@ namespace BTCPayServer.Plugins.Crowdfund.Models
public CrowdfundInfo Info { get; set; } public CrowdfundInfo Info { get; set; }
public string Tagline { get; set; } public string Tagline { get; set; }
public StoreBrandingViewModel StoreBranding { get; set; }
public ViewPointOfSaleViewModel.Item[] Perks { get; set; } public ViewPointOfSaleViewModel.Item[] Perks { get; set; }
public bool SimpleDisplay { get; set; } public bool SimpleDisplay { get; set; }
public bool DisqusEnabled { 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 store = await _appService.GetStore(app);
var storeBlob = store.GetStoreBlob(); var storeBlob = store.GetStoreBlob();
var storeBranding = new StoreBrandingViewModel(storeBlob)
{
EmbeddedCSS = settings.EmbeddedCSS,
CustomCSSLink = settings.CustomCSSLink
};
return View($"PointOfSale/Public/{viewType}", new ViewPointOfSaleViewModel return View($"PointOfSale/Public/{viewType}", new ViewPointOfSaleViewModel
{ {
Title = settings.Title, Title = settings.Title,
StoreName = store.StoreName, StoreName = store.StoreName,
BrandColor = storeBlob.BrandColor, StoreBranding = storeBranding,
CssFileId = storeBlob.CssFileId,
LogoFileId = storeBlob.LogoFileId,
Step = step.ToString(CultureInfo.InvariantCulture), Step = step.ToString(CultureInfo.InvariantCulture),
ViewType = (PosViewType)viewType, ViewType = (PosViewType)viewType,
ShowCustomAmount = settings.ShowCustomAmount, ShowCustomAmount = settings.ShowCustomAmount,
@@ -117,12 +121,9 @@ namespace BTCPayServer.Plugins.PointOfSale.Controllers
CustomButtonText = settings.CustomButtonText, CustomButtonText = settings.CustomButtonText,
CustomTipText = settings.CustomTipText, CustomTipText = settings.CustomTipText,
CustomTipPercentages = settings.CustomTipPercentages, CustomTipPercentages = settings.CustomTipPercentages,
CustomCSSLink = settings.CustomCSSLink,
CustomLogoLink = storeBlob.CustomLogo,
AppId = appId, AppId = appId,
StoreId = store.Id, StoreId = store.Id,
Description = settings.Description, Description = settings.Description,
EmbeddedCSS = settings.EmbeddedCSS,
RequiresRefundEmail = settings.RequiresRefundEmail RequiresRefundEmail = settings.RequiresRefundEmail
}); });
} }
@@ -458,9 +459,7 @@ namespace BTCPayServer.Plugins.PointOfSale.Controllers
var vm = new FormViewModel var vm = new FormViewModel
{ {
StoreName = store.StoreName, StoreName = store.StoreName,
BrandColor = storeBlob.BrandColor, StoreBranding = new StoreBrandingViewModel(storeBlob),
CssFileId = storeBlob.CssFileId,
LogoFileId = storeBlob.LogoFileId,
FormName = formData.Name, FormName = formData.Name,
Form = form, Form = form,
AspController = controller, AspController = controller,

View File

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

View File

@@ -4,6 +4,7 @@
@inject BTCPayServer.Security.ContentSecurityPolicies Csp @inject BTCPayServer.Security.ContentSecurityPolicies Csp
@{ @{
ViewData["Title"] = Model.Title; ViewData["Title"] = Model.Title;
ViewData["StoreBranding"] = Model.StoreBranding;
Layout = null; Layout = null;
Csp.UnsafeEval(); Csp.UnsafeEval();
if (!string.IsNullOrEmpty(Model.DisqusShortname)) if (!string.IsNullOrEmpty(Model.DisqusShortname))
@@ -16,18 +17,8 @@
<html class="h-100" @(Env.IsDeveloping ? " data-devenv" : "")> <html class="h-100" @(Env.IsDeveloping ? " data-devenv" : "")>
<head> <head>
<partial name="LayoutHead"/> <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="~/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"/>
<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>")
}
<style> <style>
#app { --wrap-max-width: 1320px; } #app { --wrap-max-width: 1320px; }
#crowdfund-main-image { #crowdfund-main-image {
@@ -44,7 +35,7 @@
object-fit: scale-down; object-fit: scale-down;
} }
</style> </style>
<vc:ui-extension-point location="crowdfund-head" model="@Model"></vc:ui-extension-point> <vc:ui-extension-point location="crowdfund-head" model="@Model"/>
</head> </head>
<body class="min-vh-100 p-2"> <body class="min-vh-100 p-2">
@if (!Model.Enabled) @if (!Model.Enabled)

View File

@@ -1,7 +1,6 @@
@inject BTCPayServer.Services.PoliciesSettings PoliciesSettings @inject BTCPayServer.Services.PoliciesSettings PoliciesSettings
<meta charset="utf-8" /> <meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="icon" href="~/favicon.ico" type="image/x-icon">
@if (PoliciesSettings.DiscourageSearchEngines) @if (PoliciesSettings.DiscourageSearchEngines)
{ {
<meta name="robots" content="noindex"> <meta name="robots" content="noindex">
@@ -16,6 +15,17 @@
<link href="~/main/site.css" asp-append-version="true" rel="stylesheet" /> <link href="~/main/site.css" asp-append-version="true" rel="stylesheet" />
<partial name="LayoutHeadTheme" /> <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 *@ @* Non-JS *@
<noscript> <noscript>
<style> <style>

View File

@@ -1,9 +1,10 @@
@model (string BrandColor, string CssFileId, string CustomCSSLink, string EmbeddedCSS) @model StoreBrandingViewModel
@using BTCPayServer.Abstractions.Extensions
@using Microsoft.AspNetCore.Mvc.TagHelpers
@using BTCPayServer.Abstractions.Contracts @using BTCPayServer.Abstractions.Contracts
@inject IFileService FileService @inject IFileService FileService
@{ @{
var logoUrl = !string.IsNullOrEmpty(Model.LogoFileId)
? await FileService.GetFileUrl(Context.Request.GetAbsoluteRootUri(), Model.LogoFileId)
: null;
var cssUrl = !string.IsNullOrEmpty(Model.CssFileId) var cssUrl = !string.IsNullOrEmpty(Model.CssFileId)
? await FileService.GetFileUrl(Context.Request.GetAbsoluteRootUri(), Model.CssFileId) ? await FileService.GetFileUrl(Context.Request.GetAbsoluteRootUri(), Model.CssFileId)
: null; : null;
@@ -36,6 +37,7 @@
color: var(--btcpay-body-link-accent); color: var(--btcpay-body-link-accent);
} }
</style> </style>
<meta name="theme-color" content="@brand">
} }
@if (!string.IsNullOrEmpty(cssUrl)) @if (!string.IsNullOrEmpty(cssUrl))
{ {
@@ -52,3 +54,8 @@
@Safe.Raw(Model.EmbeddedCSS) @Safe.Raw(Model.EmbeddedCSS)
</style> </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"> <div id="PosKeypad" class="public-page-wrap">
<partial name="_StatusMessage" /> <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")) @if (Context.Request.Query.ContainsKey("simple"))
{ {
<partial name="PointOfSale/Public/MinimalLight" model="Model" /> <partial name="PointOfSale/Public/MinimalLight" model="Model" />

View File

@@ -44,7 +44,7 @@ else
} }
<div id="PosPrint" class="public-page-wrap"> <div id="PosPrint" class="public-page-wrap">
<partial name="_StatusMessage" /> <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)) @if (!string.IsNullOrEmpty(Model.Description))
{ {
<div class="lead text-center">@Safe.Raw(Model.Description)</div> <div class="lead text-center">@Safe.Raw(Model.Description)</div>

View File

@@ -17,7 +17,7 @@
} }
<div id="PosStatic" class="public-page-wrap"> <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> <main>
<partial name="_StatusMessage" /> <partial name="_StatusMessage" />
@if (!string.IsNullOrEmpty(Model.Description)) @if (!string.IsNullOrEmpty(Model.Description))

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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