mirror of
https://github.com/btcpayserver/btcpayserver.git
synced 2025-02-20 13:34:37 +01:00
Server Settings: Customize instance name and add contact URL (#5718)
* Server Settings: Customize instance name and add contact URL - The custom instance name would improve #5563 - Added contact URL closes #4806 * Fix custom logo display
This commit is contained in:
parent
147c6c4548
commit
4ae1046571
14 changed files with 206 additions and 102 deletions
|
@ -252,7 +252,7 @@
|
|||
{
|
||||
<ul id="mainNavSettings" class="navbar-nav border-top p-3 px-lg-4">
|
||||
<li class="nav-item" permission="@Policies.CanModifyServerSettings">
|
||||
<a asp-area="" asp-controller="UIServer" asp-action="ListUsers" class="nav-link @ViewData.IsActivePage(ServerNavPages.Users) @ViewData.IsActivePage(ServerNavPages.Emails) @ViewData.IsActivePage(ServerNavPages.Policies) @ViewData.IsActivePage(ServerNavPages.Services) @ViewData.IsActivePage(ServerNavPages.Theme) @ViewData.IsActivePage(ServerNavPages.Maintenance) @ViewData.IsActivePage(ServerNavPages.Logs) @ViewData.IsActivePage(ServerNavPages.Files)" id="Nav-ServerSettings">
|
||||
<a asp-area="" asp-controller="UIServer" asp-action="ListUsers" class="nav-link @ViewData.IsActivePage(ServerNavPages.Users) @ViewData.IsActivePage(ServerNavPages.Emails) @ViewData.IsActivePage(ServerNavPages.Policies) @ViewData.IsActivePage(ServerNavPages.Services) @ViewData.IsActivePage(ServerNavPages.Branding) @ViewData.IsActivePage(ServerNavPages.Maintenance) @ViewData.IsActivePage(ServerNavPages.Logs) @ViewData.IsActivePage(ServerNavPages.Files)" id="Nav-ServerSettings">
|
||||
<vc:icon symbol="server-settings"/>
|
||||
<span>Server Settings</span>
|
||||
</a>
|
||||
|
|
|
@ -150,6 +150,7 @@ namespace BTCPayServer.Controllers
|
|||
}
|
||||
if (!ModelState.IsValid)
|
||||
return View(vm);
|
||||
|
||||
if (command == "changedomain")
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(vm.DNSDomain))
|
||||
|
@ -995,143 +996,167 @@ namespace BTCPayServer.Controllers
|
|||
return RedirectToAction(nameof(Services));
|
||||
}
|
||||
|
||||
[HttpGet("server/theme")]
|
||||
public async Task<IActionResult> Theme()
|
||||
[HttpGet("server/branding")]
|
||||
public async Task<IActionResult> Branding()
|
||||
{
|
||||
var data = await _SettingsRepository.GetSettingAsync<ThemeSettings>() ?? new ThemeSettings();
|
||||
return View(data);
|
||||
var server = await _SettingsRepository.GetSettingAsync<ServerSettings>() ?? new ServerSettings();
|
||||
var theme = await _SettingsRepository.GetSettingAsync<ThemeSettings>() ?? new ThemeSettings();
|
||||
|
||||
var vm = new BrandingViewModel
|
||||
{
|
||||
ServerName = server.ServerName,
|
||||
ContactUrl = server.ContactUrl,
|
||||
CustomTheme = theme.CustomTheme,
|
||||
CustomThemeExtension = theme.CustomThemeExtension,
|
||||
CustomThemeCssUri = theme.CustomThemeCssUri,
|
||||
CustomThemeFileId = theme.CustomThemeFileId,
|
||||
LogoFileId = theme.LogoFileId
|
||||
};
|
||||
return View(vm);
|
||||
}
|
||||
|
||||
[HttpPost("server/theme")]
|
||||
public async Task<IActionResult> Theme(
|
||||
ThemeSettings model,
|
||||
[HttpPost("server/branding")]
|
||||
public async Task<IActionResult> Branding(
|
||||
BrandingViewModel vm,
|
||||
[FromForm] bool RemoveLogoFile,
|
||||
[FromForm] bool RemoveCustomThemeFile)
|
||||
{
|
||||
var settingsChanged = false;
|
||||
var settings = await _SettingsRepository.GetSettingAsync<ThemeSettings>() ?? new ThemeSettings();
|
||||
var server = await _SettingsRepository.GetSettingAsync<ServerSettings>() ?? new ServerSettings();
|
||||
var theme = await _SettingsRepository.GetSettingAsync<ThemeSettings>() ?? new ThemeSettings();
|
||||
|
||||
var userId = GetUserId();
|
||||
if (userId is null)
|
||||
return NotFound();
|
||||
|
||||
if (model.CustomThemeFile != null)
|
||||
vm.LogoFileId = theme.LogoFileId;
|
||||
vm.CustomThemeFileId = theme.CustomThemeFileId;
|
||||
|
||||
if (server.ServerName != vm.ServerName || server.ContactUrl != vm.ContactUrl)
|
||||
{
|
||||
if (model.CustomThemeFile.ContentType.Equals("text/css", StringComparison.InvariantCulture))
|
||||
server.ServerName = vm.ServerName;
|
||||
server.ContactUrl = vm.ContactUrl;
|
||||
settingsChanged = true;
|
||||
await _SettingsRepository.UpdateSetting(server);
|
||||
}
|
||||
|
||||
if (vm.CustomThemeFile != null)
|
||||
{
|
||||
if (vm.CustomThemeFile.ContentType.Equals("text/css", StringComparison.InvariantCulture))
|
||||
{
|
||||
// delete existing file
|
||||
if (!string.IsNullOrEmpty(settings.CustomThemeFileId))
|
||||
if (!string.IsNullOrEmpty(theme.CustomThemeFileId))
|
||||
{
|
||||
await _fileService.RemoveFile(settings.CustomThemeFileId, userId);
|
||||
await _fileService.RemoveFile(theme.CustomThemeFileId, userId);
|
||||
}
|
||||
|
||||
// add new file
|
||||
try
|
||||
{
|
||||
var storedFile = await _fileService.AddFile(model.CustomThemeFile, userId);
|
||||
settings.CustomThemeFileId = storedFile.Id;
|
||||
var storedFile = await _fileService.AddFile(vm.CustomThemeFile, userId);
|
||||
vm.CustomThemeFileId = theme.CustomThemeFileId = storedFile.Id;
|
||||
settingsChanged = true;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
ModelState.AddModelError(nameof(settings.CustomThemeFile), $"Could not save theme file: {e.Message}");
|
||||
ModelState.AddModelError(nameof(vm.CustomThemeFile), $"Could not save theme file: {e.Message}");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ModelState.AddModelError(nameof(settings.CustomThemeFile), "The uploaded theme file needs to be a CSS file");
|
||||
ModelState.AddModelError(nameof(vm.CustomThemeFile), "The uploaded theme file needs to be a CSS file");
|
||||
}
|
||||
}
|
||||
else if (RemoveCustomThemeFile && !string.IsNullOrEmpty(settings.CustomThemeFileId))
|
||||
else if (RemoveCustomThemeFile && !string.IsNullOrEmpty(theme.CustomThemeFileId))
|
||||
{
|
||||
await _fileService.RemoveFile(settings.CustomThemeFileId, userId);
|
||||
settings.CustomThemeFileId = null;
|
||||
await _fileService.RemoveFile(theme.CustomThemeFileId, userId);
|
||||
vm.CustomThemeFileId = theme.CustomThemeFileId = null;
|
||||
settingsChanged = true;
|
||||
}
|
||||
|
||||
if (model.LogoFile != null)
|
||||
if (vm.LogoFile != null)
|
||||
{
|
||||
if (model.LogoFile.Length > 1_000_000)
|
||||
if (vm.LogoFile.Length > 1_000_000)
|
||||
{
|
||||
ModelState.AddModelError(nameof(model.LogoFile), "The uploaded logo file should be less than 1MB");
|
||||
ModelState.AddModelError(nameof(vm.LogoFile), "The uploaded logo file should be less than 1MB");
|
||||
}
|
||||
else if (!model.LogoFile.ContentType.StartsWith("image/", StringComparison.InvariantCulture))
|
||||
else if (!vm.LogoFile.ContentType.StartsWith("image/", StringComparison.InvariantCulture))
|
||||
{
|
||||
ModelState.AddModelError(nameof(model.LogoFile), "The uploaded logo file needs to be an image");
|
||||
ModelState.AddModelError(nameof(vm.LogoFile), "The uploaded logo file needs to be an image");
|
||||
}
|
||||
else
|
||||
{
|
||||
var formFile = await model.LogoFile.Bufferize();
|
||||
var formFile = await vm.LogoFile.Bufferize();
|
||||
if (!FileTypeDetector.IsPicture(formFile.Buffer, formFile.FileName))
|
||||
{
|
||||
ModelState.AddModelError(nameof(model.LogoFile), "The uploaded logo file needs to be an image");
|
||||
ModelState.AddModelError(nameof(vm.LogoFile), "The uploaded logo file needs to be an image");
|
||||
}
|
||||
else
|
||||
{
|
||||
model.LogoFile = formFile;
|
||||
vm.LogoFile = formFile;
|
||||
// delete existing file
|
||||
if (!string.IsNullOrEmpty(settings.LogoFileId))
|
||||
if (!string.IsNullOrEmpty(theme.LogoFileId))
|
||||
{
|
||||
await _fileService.RemoveFile(settings.LogoFileId, userId);
|
||||
await _fileService.RemoveFile(theme.LogoFileId, userId);
|
||||
}
|
||||
// add new file
|
||||
try
|
||||
{
|
||||
var storedFile = await _fileService.AddFile(model.LogoFile, userId);
|
||||
settings.LogoFileId = storedFile.Id;
|
||||
var storedFile = await _fileService.AddFile(vm.LogoFile, userId);
|
||||
vm.LogoFileId = theme.LogoFileId = storedFile.Id;
|
||||
settingsChanged = true;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
ModelState.AddModelError(nameof(settings.LogoFile), $"Could not save logo: {e.Message}");
|
||||
ModelState.AddModelError(nameof(vm.LogoFile), $"Could not save logo: {e.Message}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (RemoveLogoFile && !string.IsNullOrEmpty(settings.LogoFileId))
|
||||
else if (RemoveLogoFile && !string.IsNullOrEmpty(theme.LogoFileId))
|
||||
{
|
||||
await _fileService.RemoveFile(settings.LogoFileId, userId);
|
||||
settings.LogoFileId = null;
|
||||
await _fileService.RemoveFile(theme.LogoFileId, userId);
|
||||
vm.LogoFileId = theme.LogoFileId = null;
|
||||
settingsChanged = true;
|
||||
}
|
||||
|
||||
if (model.CustomTheme && !string.IsNullOrEmpty(model.CustomThemeCssUri) && !Uri.IsWellFormedUriString(model.CustomThemeCssUri, UriKind.RelativeOrAbsolute))
|
||||
if (vm.CustomTheme && !string.IsNullOrEmpty(vm.CustomThemeCssUri) && !Uri.IsWellFormedUriString(vm.CustomThemeCssUri, UriKind.RelativeOrAbsolute))
|
||||
{
|
||||
ModelState.AddModelError(nameof(settings.CustomThemeCssUri), "Please provide a non-empty theme URI");
|
||||
ModelState.AddModelError(nameof(theme.CustomThemeCssUri), "Please provide a non-empty theme URI");
|
||||
}
|
||||
else if (settings.CustomThemeCssUri != model.CustomThemeCssUri)
|
||||
else if (theme.CustomThemeCssUri != vm.CustomThemeCssUri)
|
||||
{
|
||||
settings.CustomThemeCssUri = model.CustomThemeCssUri;
|
||||
theme.CustomThemeCssUri = vm.CustomThemeCssUri;
|
||||
settingsChanged = true;
|
||||
}
|
||||
|
||||
if (settings.CustomThemeExtension != model.CustomThemeExtension)
|
||||
if (theme.CustomThemeExtension != vm.CustomThemeExtension)
|
||||
{
|
||||
// Require a custom theme to be defined in that case
|
||||
if (string.IsNullOrEmpty(model.CustomThemeCssUri) && string.IsNullOrEmpty(settings.CustomThemeFileId))
|
||||
if (string.IsNullOrEmpty(vm.CustomThemeCssUri) && string.IsNullOrEmpty(theme.CustomThemeFileId))
|
||||
{
|
||||
ModelState.AddModelError(nameof(settings.CustomThemeFile), "Please provide a custom theme");
|
||||
ModelState.AddModelError(nameof(vm.CustomThemeFile), "Please provide a custom theme");
|
||||
}
|
||||
else
|
||||
{
|
||||
settings.CustomThemeExtension = model.CustomThemeExtension;
|
||||
theme.CustomThemeExtension = vm.CustomThemeExtension;
|
||||
settingsChanged = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (settings.CustomTheme != model.CustomTheme)
|
||||
if (theme.CustomTheme != vm.CustomTheme)
|
||||
{
|
||||
settings.CustomTheme = model.CustomTheme;
|
||||
theme.CustomTheme = vm.CustomTheme;
|
||||
settingsChanged = true;
|
||||
}
|
||||
|
||||
if (settingsChanged)
|
||||
{
|
||||
await _SettingsRepository.UpdateSetting(settings);
|
||||
TempData[WellKnownTempData.SuccessMessage] = "Theme settings updated successfully";
|
||||
await _SettingsRepository.UpdateSetting(theme);
|
||||
TempData[WellKnownTempData.SuccessMessage] = "Settings updated successfully";
|
||||
}
|
||||
|
||||
return View(settings);
|
||||
return View(vm);
|
||||
}
|
||||
|
||||
[Route("server/emails")]
|
||||
|
|
40
BTCPayServer/Models/ServerViewModels/BrandingViewModel.cs
Normal file
40
BTCPayServer/Models/ServerViewModels/BrandingViewModel.cs
Normal file
|
@ -0,0 +1,40 @@
|
|||
using System.ComponentModel.DataAnnotations;
|
||||
using BTCPayServer.Services;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace BTCPayServer.Models.ServerViewModels;
|
||||
|
||||
public class BrandingViewModel
|
||||
{
|
||||
// Server
|
||||
[Display(Name = "Server Name")]
|
||||
public string ServerName { get; set; }
|
||||
|
||||
[Display(Name = "Contact URL")]
|
||||
public string ContactUrl { get; set; }
|
||||
|
||||
// Theme
|
||||
[Display(Name = "Use custom theme")]
|
||||
public bool CustomTheme { get; set; }
|
||||
|
||||
[Display(Name = "Custom Theme Extension Type")]
|
||||
public ThemeExtension CustomThemeExtension { get; set; }
|
||||
|
||||
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Populate)]
|
||||
[MaxLength(500)]
|
||||
[Display(Name = "Custom Theme CSS URL")]
|
||||
public string CustomThemeCssUri { get; set; }
|
||||
|
||||
[Display(Name = "Custom Theme File")]
|
||||
[JsonIgnore]
|
||||
public IFormFile CustomThemeFile { get; set; }
|
||||
|
||||
public string CustomThemeFileId { get; set; }
|
||||
|
||||
[Display(Name = "Logo")]
|
||||
[JsonIgnore]
|
||||
public IFormFile LogoFile { get; set; }
|
||||
|
||||
public string LogoFileId { get; set; }
|
||||
}
|
14
BTCPayServer/Services/ServerSettings.cs
Normal file
14
BTCPayServer/Services/ServerSettings.cs
Normal file
|
@ -0,0 +1,14 @@
|
|||
using System.ComponentModel.DataAnnotations;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace BTCPayServer.Services;
|
||||
|
||||
public class ServerSettings
|
||||
{
|
||||
[Display(Name = "Server Name")]
|
||||
public string ServerName { get; set; }
|
||||
|
||||
[Display(Name = "Contact URL")]
|
||||
public string ContactUrl { get; set; }
|
||||
}
|
|
@ -1,5 +1,4 @@
|
|||
using System.ComponentModel.DataAnnotations;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace BTCPayServer.Services;
|
||||
|
@ -27,16 +26,8 @@ public class ThemeSettings
|
|||
[Display(Name = "Custom Theme CSS URL")]
|
||||
public string CustomThemeCssUri { get; set; }
|
||||
|
||||
[Display(Name = "Custom Theme File")]
|
||||
[JsonIgnore]
|
||||
public IFormFile CustomThemeFile { get; set; }
|
||||
|
||||
public string CustomThemeFileId { get; set; }
|
||||
|
||||
[Display(Name = "Logo")]
|
||||
[JsonIgnore]
|
||||
public IFormFile LogoFile { get; set; }
|
||||
|
||||
public string LogoFileId { get; set; }
|
||||
|
||||
public bool FirstRun { get; set; }
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
@using System.IO
|
||||
@using BTCPayServer.Services
|
||||
@inject IWebHostEnvironment WebHostEnvironment
|
||||
@inject SettingsRepository SettingsRepository
|
||||
@inject BTCPayServerEnvironment Env
|
||||
@model BTCPayServer.Plugins.PointOfSale.Models.ViewPointOfSaleViewModel
|
||||
@{
|
||||
|
@ -12,6 +13,7 @@
|
|||
|
||||
async Task<string> GetDynamicManifest(string title)
|
||||
{
|
||||
var settings = await SettingsRepository.GetSettingAsync<ServerSettings>() ?? new ServerSettings();
|
||||
var manifest = WebHostEnvironment.WebRootFileProvider.GetFileInfo("manifest.json");
|
||||
if (!manifest.Exists)
|
||||
{
|
||||
|
@ -19,8 +21,9 @@
|
|||
}
|
||||
using var reader = new StreamReader(manifest.CreateReadStream());
|
||||
var jObject = JObject.Parse(await reader.ReadToEndAsync());
|
||||
var serverName = string.IsNullOrWhiteSpace(settings.ServerName) ? "BTCPay Server" : settings.ServerName;
|
||||
jObject["short_name"] = title;
|
||||
jObject["name"] = $"BTCPay Server: {title}";
|
||||
jObject["name"] = $"{serverName}: {title}";
|
||||
foreach (var jToken in jObject["icons"]!)
|
||||
{
|
||||
var icon = (JObject)jToken;
|
||||
|
|
|
@ -1,7 +1,13 @@
|
|||
@using BTCPayServer.Services
|
||||
@using Microsoft.AspNetCore.Mvc.TagHelpers
|
||||
@using BTCPayServer.Components.MainLogo
|
||||
@inject SettingsRepository SettingsRepository
|
||||
@{
|
||||
Layout = "_LayoutSimple";
|
||||
ViewBag.ShowTitle ??= true;
|
||||
ViewBag.ShowLeadText ??= false;
|
||||
|
||||
var settings = await SettingsRepository.GetSettingAsync<ServerSettings>() ?? new ServerSettings();
|
||||
}
|
||||
|
||||
@section PageHeadContent {
|
||||
|
@ -33,7 +39,7 @@
|
|||
<vc:main-logo />
|
||||
</a>
|
||||
|
||||
<h1 class="h2 mb-3">Welcome to your BTCPay Server</h1>
|
||||
<h1 class="h2 mb-3">Welcome to @(string.IsNullOrWhiteSpace(settings.ServerName) ? "your BTCPay\u00a0Server" : settings.ServerName)</h1>
|
||||
@if (ViewBag.ShowLeadText)
|
||||
{
|
||||
<p class="lead">
|
||||
|
@ -49,11 +55,18 @@
|
|||
<div class="account-form">
|
||||
@if (ViewBag.ShowTitle)
|
||||
{
|
||||
<h4 v-pre>@ViewData["Title"]</h4>
|
||||
<h4 v-pre>@ViewData["Title"]</h4>
|
||||
}
|
||||
@RenderBody()
|
||||
</div>
|
||||
|
||||
@if (!string.IsNullOrWhiteSpace(settings.ContactUrl))
|
||||
{
|
||||
<p class="text-center mt-n5 mb-5 pt-2">
|
||||
<a class="text-secondary" href="@settings.ContactUrl" id="ContactLink">Contact Us</a>
|
||||
</p>
|
||||
}
|
||||
|
||||
<div class="row justify-content-center mt-5">
|
||||
<div class="col">
|
||||
<partial name="_BTCPaySupporters"/>
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
}
|
||||
|
||||
<style>
|
||||
.main-logo { height: 4rem; width: 18rem; }
|
||||
.main-logo { height: 4.5rem; max-width: 18rem; }
|
||||
.main-logo-btcpay .main-logo-btcpay--small { display: none; }
|
||||
.lead img { max-width: 100%; }
|
||||
</style>
|
||||
|
|
|
@ -1,11 +1,15 @@
|
|||
@using BTCPayServer.Services
|
||||
@using Microsoft.AspNetCore.Mvc.TagHelpers
|
||||
@model HomeViewModel;
|
||||
@inject SettingsRepository SettingsRepository
|
||||
@{
|
||||
ViewData["Title"] = "BTCPay Server";
|
||||
var settings = await SettingsRepository.GetSettingAsync<ServerSettings>() ?? new ServerSettings();
|
||||
ViewData["Title"] = string.IsNullOrWhiteSpace(settings.ServerName) ? "BTCPay Server" : settings.ServerName;
|
||||
}
|
||||
|
||||
<partial name="_StatusMessage" />
|
||||
|
||||
<h2>Welcome to your BTCPay Server</h2>
|
||||
<h2>Welcome to @(string.IsNullOrWhiteSpace(settings.ServerName) ? "your BTCPay\u00a0Server" : settings.ServerName)</h2>
|
||||
|
||||
@if (!Model.HasStore)
|
||||
{
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
@using BTCPayServer.Abstractions.Contracts
|
||||
@using BTCPayServer.Services
|
||||
@model BTCPayServer.Services.ThemeSettings
|
||||
@model BrandingViewModel;
|
||||
@inject IFileService FileService
|
||||
@{
|
||||
ViewData.SetActivePage(ServerNavPages.Theme, "Theme");
|
||||
ViewData.SetActivePage(ServerNavPages.Branding, "Branding");
|
||||
var canUpload = await FileService.IsAvailable();
|
||||
var themeExtension = ((ThemeExtension[])Enum.GetValues(typeof(ThemeExtension))).Select(t =>
|
||||
new SelectListItem(typeof(ThemeExtension).DisplayName(t.ToString()), t == ThemeExtension.Custom ? null : t.ToString()));
|
||||
|
@ -18,6 +18,51 @@
|
|||
<div class="row">
|
||||
<div class="col-xl-8 col-xxl-constrain">
|
||||
<form method="post" enctype="multipart/form-data">
|
||||
<div class="form-group">
|
||||
<label asp-for="ServerName" class="form-label"></label>
|
||||
<input asp-for="ServerName" class="form-control" />
|
||||
<div class="form-text">You can give this server a custom name, which will appear on public facing pages.</div>
|
||||
<span asp-validation-for="ServerName" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label asp-for="ContactUrl" class="form-label"></label>
|
||||
<input asp-for="ContactUrl" class="form-control" />
|
||||
<div class="form-text">
|
||||
Contact link for support requests related to this BTCPay Server instance.
|
||||
This link will appear on public facing pages.
|
||||
Can be any valid URI, such as a website, email, and Nostr.
|
||||
</div>
|
||||
<span asp-validation-for="ContactUrl" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="d-flex align-items-center justify-content-between gap-2">
|
||||
<label asp-for="LogoFile" class="form-label"></label>
|
||||
@if (!string.IsNullOrEmpty(Model.LogoFileId))
|
||||
{
|
||||
<button type="submit" class="btn btn-link p-0 text-danger" name="RemoveLogoFile" value="true">
|
||||
<span class="fa fa-times"></span> Remove
|
||||
</button>
|
||||
}
|
||||
</div>
|
||||
@if (canUpload)
|
||||
{
|
||||
<div class="d-flex align-items-center gap-3">
|
||||
<input asp-for="LogoFile" type="file" class="form-control flex-grow">
|
||||
@if (!string.IsNullOrEmpty(Model.LogoFileId))
|
||||
{
|
||||
<img src="@(await FileService.GetFileUrl(Context.Request.GetAbsoluteRootUri(), Model.LogoFileId))" alt="Logo" style="height:2.1rem;max-width:10.5rem;"/>
|
||||
}
|
||||
</div>
|
||||
<span asp-validation-for="LogoFile" class="text-danger"></span>
|
||||
}
|
||||
else
|
||||
{
|
||||
<input asp-for="LogoFile" type="file" class="form-control" disabled>
|
||||
<div class="form-text">In order to upload a logo, a <a asp-controller="UIServer" asp-action="Files">file storage</a> must be configured.</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
<h3 class="mt-5 mb-3">Theme</h3>
|
||||
<p>Use the default Light or Dark Themes, or provide a custom CSS theme file below.</p>
|
||||
|
||||
<div class="d-flex align-items-center mb-3">
|
||||
|
@ -75,35 +120,6 @@
|
|||
}
|
||||
</div>
|
||||
|
||||
<h3 class="mt-5 mb-3">Branding</h3>
|
||||
<div class="form-group">
|
||||
<div class="d-flex align-items-center justify-content-between gap-2">
|
||||
<label asp-for="LogoFile" class="form-label"></label>
|
||||
@if (!string.IsNullOrEmpty(Model.LogoFileId))
|
||||
{
|
||||
<button type="submit" class="btn btn-link p-0 text-danger" name="RemoveLogoFile" value="true">
|
||||
<span class="fa fa-times"></span> Remove
|
||||
</button>
|
||||
}
|
||||
</div>
|
||||
@if (canUpload)
|
||||
{
|
||||
<div class="d-flex align-items-center gap-3">
|
||||
<input asp-for="LogoFile" type="file" class="form-control flex-grow">
|
||||
@if (!string.IsNullOrEmpty(Model.LogoFileId))
|
||||
{
|
||||
<img src="@(await FileService.GetFileUrl(Context.Request.GetAbsoluteRootUri(), Model.LogoFileId))" alt="Logo" style="height:2.1rem;max-width:10.5rem;"/>
|
||||
}
|
||||
</div>
|
||||
<span asp-validation-for="LogoFile" class="text-danger"></span>
|
||||
}
|
||||
else
|
||||
{
|
||||
<input asp-for="LogoFile" type="file" class="form-control" disabled>
|
||||
<div class="form-text">In order to upload a logo, a <a asp-controller="UIServer" asp-action="Files">file storage</a> must be configured.</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
<button type="submit" class="btn btn-primary mt-2" name="command" value="Save">Save</button>
|
||||
</form>
|
||||
</div>
|
|
@ -13,10 +13,8 @@
|
|||
<input asp-for="DNSDomain" class="form-control" disabled="@(Model.CanUseSSH ? null : "disabled")" />
|
||||
<div class="form-text">You can change the domain name of your server by following <a href="https://docs.btcpayserver.org/FAQ/Deployment/#how-to-change-your-btcpay-server-domain-name" target="_blank" rel="noreferrer noopener">this guide</a>.</div>
|
||||
<span asp-validation-for="DNSDomain" class="text-danger"></span>
|
||||
<button name="command" type="submit" class="btn btn-secondary mt-3" value="changedomain" title="Change domain" disabled="@(Model.CanUseSSH ? null : "disabled")">
|
||||
Confirm
|
||||
</button>
|
||||
</div>
|
||||
<button name="command" type="submit" class="btn btn-secondary" value="changedomain" title="Change domain" disabled="@(Model.CanUseSSH ? null : "disabled")">Change Domain</button>
|
||||
|
||||
<h4 class="mt-5 mb-2">Restart</h4>
|
||||
<p>Restart BTCPay Server and related services.</p>
|
||||
|
|
|
@ -2,7 +2,7 @@ namespace BTCPayServer.Views.Server
|
|||
{
|
||||
public enum ServerNavPages
|
||||
{
|
||||
Index, Users, Emails, Policies, Theme, Services, Maintenance, Logs, Files, Plugins,
|
||||
Index, Users, Emails, Policies, Branding, Services, Maintenance, Logs, Files, Plugins,
|
||||
Roles
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
<a asp-controller="UIServer" id="SectionNav-@ServerNavPages.Emails" class="nav-link @ViewData.IsActivePage(ServerNavPages.Emails)" asp-action="Emails">Email</a>
|
||||
<a asp-controller="UIServer" id="SectionNav-@ServerNavPages.Policies" class="nav-link @ViewData.IsActivePage(ServerNavPages.Policies)" asp-action="Policies">Policies</a>
|
||||
<a asp-controller="UIServer" id="SectionNav-@ServerNavPages.Services" class="nav-link @ViewData.IsActivePage(ServerNavPages.Services)" asp-action="Services">Services</a>
|
||||
<a asp-controller="UIServer" id="SectionNav-@ServerNavPages.Theme" class="nav-link @ViewData.IsActivePage(ServerNavPages.Theme)" asp-action="Theme">Theme</a>
|
||||
<a asp-controller="UIServer" id="SectionNav-@ServerNavPages.Branding" class="nav-link @ViewData.IsActivePage(ServerNavPages.Branding)" asp-action="Branding">Branding</a>
|
||||
@if (_btcPayServerOptions.DockerDeployment)
|
||||
{
|
||||
<a asp-controller="UIServer" id="SectionNav-@ServerNavPages.Maintenance" class="nav-link @ViewData.IsActivePage(ServerNavPages.Maintenance)" asp-action="Maintenance">Maintenance</a>
|
||||
|
|
|
@ -29,8 +29,8 @@
|
|||
@section PageHeadContent {
|
||||
<style>
|
||||
#FirstStore { max-width: 27rem; margin: 0 auto; text-align: center; }
|
||||
#FirstStore .main-logo { height: 4rem; width: 18rem; }
|
||||
#FirstStore .main-logo.main-logo-btcpay { height: 4.5rem; width: 2.5rem; }
|
||||
#FirstStore .main-logo { height: 4.5rem; max-width: 18rem; }
|
||||
#FirstStore .main-logo.main-logo-btcpay { width: 2.5rem; }
|
||||
#FirstStore .main-logo-btcpay .main-logo-btcpay--large { display: none; }
|
||||
#FirstStore .form-control, #FirstStore .form-select { width: 100%; }
|
||||
#FirstStore .form-text { font-size: var(--btcpay-font-size-s); }
|
||||
|
|
Loading…
Add table
Reference in a new issue