btcpayserver/BTCPayServer/Views/UIServer/Theme.cshtml
d11n 6972e8a3db
UI: Theme extensions (#4398)
* Theme extensions

Adds the ability to choose the themeing strategy: Extend one of the existing themes (light or dark) or go fully custom. The latter was the only option up to now, which isn't ideal:

- One had to provide a full-blown theme file overriding all variables
- Tedious, error prone and hard to maintain, because one has to keep track of updates

This PR makes it so that one can choose light or dark as base theme and do modifications on top.

Benefit: You can specify a limited set of variables and might get away with 5-20 lines of CSS.

* Ensure custom theme is present

* Update checkout test
2022-12-14 13:37:31 +09:00

110 lines
6 KiB
Text

@using BTCPayServer.Abstractions.Contracts
@using BTCPayServer.Services
@model BTCPayServer.Services.ThemeSettings
@inject IFileService FileService
@{
ViewData.SetActivePage(ServerNavPages.Theme, "Theme");
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()));
}
@section PageFootContent {
<partial name="_ValidationScriptsPartial" />
}
<h3 class="mb-4">@ViewData["Title"]</h3>
<div class="row">
<div class="col-xl-8 col-xxl-constrain">
<form method="post" enctype="multipart/form-data">
<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">
<input asp-for="CustomTheme" type="checkbox" class="btcpay-toggle me-3" data-bs-toggle="collapse" data-bs-target="#CustomThemeSettings" aria-expanded="@(Model.CustomTheme)" aria-controls="CustomThemeSettings" />
<div>
<label asp-for="CustomTheme" class="form-label"></label>
<div class="text-muted">
<a href="https://docs.btcpayserver.org/Development/Theme/#1-custom-themes" target="_blank" rel="noreferrer noopener">Adjust the design</a>
of your BTCPay Server instance to your needs.
</div>
</div>
</div>
<div class="collapse @(Model.CustomTheme ? "show" : "")" id="CustomThemeSettings">
@if (!string.IsNullOrEmpty(Model.CustomThemeCssUri))
{
<div class="form-group mb-0 pt-2">
<label asp-for="CustomThemeCssUri" class="form-label" data-required></label>
<input asp-for="CustomThemeCssUri" class="form-control"/>
<span asp-validation-for="CustomThemeCssUri" class="text-danger"></span>
</div>
}
else
{
<div class="form-group pt-2">
<label asp-for="CustomThemeExtension" class="form-label" data-required></label>
<select asp-for="CustomThemeExtension" asp-items="@themeExtension" class="form-select w-auto"></select>
</div>
<div class="form-group mb-0">
<div class="d-flex align-items-center justify-content-between gap-2">
<label asp-for="CustomThemeFile" class="form-label" data-required></label>
@if (!string.IsNullOrEmpty(Model.CustomThemeFileId))
{
<button type="submit" class="btn btn-link p-0 text-danger" name="RemoveCustomThemeFile" 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="CustomThemeFile" type="file" class="form-control flex-grow">
@if (!string.IsNullOrEmpty(Model.CustomThemeFileId))
{
<a href="@(await FileService.GetFileUrl(Context.Request.GetAbsoluteRootUri(), Model.CustomThemeFileId))" target="_blank" rel="noreferrer noopener" class="text-nowrap">Custom CSS</a>
}
</div>
<span asp-validation-for="CustomThemeFile" class="text-danger"></span>
}
else
{
<input asp-for="CustomThemeFile" type="file" class="form-control" disabled>
<p class="form-text text-muted">In order to upload a theme file, a <a asp-controller="UIServer" asp-action="Files">file storage</a> must be configured.</p>
}
</div>
}
</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>
</div>