mirror of
https://github.com/btcpayserver/btcpayserver.git
synced 2025-02-26 15:41:29 +01:00
* UI: Deprecate the custom CSS options As discussed with @pavlenex we are deprecating the custom CSS options for particular entities (payemnt request, pull payment, POS, crowdfund) in favor of the store branding approach. This displays the custom CSS section only if these values are set already. * Add IDs to html element This will allow styling of individual entities.
322 lines
20 KiB
Text
322 lines
20 KiB
Text
@using BTCPayServer.Abstractions.Models
|
|
@using BTCPayServer.Views.Apps
|
|
@using BTCPayServer.Abstractions.Extensions
|
|
@using BTCPayServer.Plugins.PointOfSale
|
|
@using BTCPayServer.Forms
|
|
@inject FormDataService FormDataService
|
|
@inject BTCPayServer.Security.ContentSecurityPolicies Csp
|
|
@model BTCPayServer.Plugins.PointOfSale.Models.UpdatePointOfSaleViewModel
|
|
@{
|
|
ViewData.SetActivePage(AppsNavPages.Update, "Update Point of Sale", Model.Id);
|
|
Csp.UnsafeEval();
|
|
var checkoutFormOptions = await FormDataService.GetSelect(Model.StoreId, Model.FormId);
|
|
}
|
|
|
|
@section PageHeadContent {
|
|
<link href="~/vendor/highlightjs/default.min.css" rel="stylesheet" asp-append-version="true">
|
|
<link href="~/vendor/summernote/summernote-bs5.css" rel="stylesheet" asp-append-version="true" />
|
|
}
|
|
|
|
@section PageFootContent {
|
|
<partial name="_ValidationScriptsPartial" />
|
|
<script src="~/vendor/summernote/summernote-bs5.js" asp-append-version="true"></script>
|
|
<script src="~/pos/admin.js" asp-append-version="true"></script>
|
|
}
|
|
|
|
<form method="post">
|
|
<div class="sticky-header d-sm-flex align-items-center justify-content-between">
|
|
<h2 class="mb-0">@ViewData["Title"]</h2>
|
|
<div class="d-flex gap-3 mt-3 mt-sm-0">
|
|
<button type="submit" class="btn btn-primary order-sm-1" id="SaveSettings">Save</button>
|
|
@if (Model.Archived)
|
|
{
|
|
<button type="submit" class="btn btn-outline-secondary" name="Archived" value="False">Unarchive</button>
|
|
}
|
|
else
|
|
{
|
|
<a class="btn btn-secondary" asp-controller="UIPointOfSale" asp-action="ViewPointOfSale" asp-route-appId="@Model.Id" id="ViewApp" target="_blank">View</a>
|
|
}
|
|
</div>
|
|
</div>
|
|
|
|
<partial name="_StatusMessage" />
|
|
|
|
<input type="hidden" asp-for="StoreId" />
|
|
<input type="hidden" asp-for="Archived" />
|
|
<div asp-validation-summary="ModelOnly"></div>
|
|
|
|
<div class="row">
|
|
<div class="col-sm-10 col-md-9 col-xl-7 col-xxl-6">
|
|
<div class="row">
|
|
<div class="col-sm-6">
|
|
<div class="form-group">
|
|
<label asp-for="AppName" class="form-label" data-required></label>
|
|
<input asp-for="AppName" class="form-control" required />
|
|
<span asp-validation-for="AppName" class="text-danger"></span>
|
|
</div>
|
|
</div>
|
|
<div class="col-sm-6">
|
|
<div class="form-group">
|
|
<label asp-for="Title" class="form-label" data-required></label>
|
|
<input asp-for="Title" class="form-control" required />
|
|
<span asp-validation-for="Title" class="text-danger"></span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="form-group">
|
|
<label asp-for="DefaultView" class="form-label" data-required>Choose Point of Sale Style</label>
|
|
<div class="btcpay-list-select">
|
|
@foreach (var type in Enum.GetValues<PosViewType>())
|
|
{
|
|
<input type="radio" asp-for="DefaultView" value="@type" id="DefaultView_@type">
|
|
<label for="DefaultView_@type" class="btcpay-list-select-item">
|
|
<vc:icon symbol="pos-@type.ToString().ToLowerInvariant()" />
|
|
@typeof(PosViewType).DisplayName(type.ToString())
|
|
</label>
|
|
}
|
|
</div>
|
|
</div>
|
|
<div class="form-group mb-0">
|
|
<label asp-for="Currency" class="form-label"></label>
|
|
<input asp-for="Currency" class="form-control w-auto" currency-selection />
|
|
<div class="form-text">Uses the store's default currency (@Model.StoreDefaultCurrency) if empty.</div>
|
|
<span asp-validation-for="Currency" class="text-danger"></span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div id="description" class="row mt-4">
|
|
<div class="col-xl-10 col-xxl-constrain">
|
|
<div class="form-group mb-0">
|
|
<label asp-for="Description" class="form-label"></label>
|
|
<textarea asp-for="Description" rows="10" cols="40" class="form-control richtext"></textarea>
|
|
<span asp-validation-for="Description" class="text-danger"></span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div id="products" class="row">
|
|
<div class="col-xxl-constrain">
|
|
<partial name="TemplateEditor" model="@(nameof(Model.Template), Model.Template, "Products", Model.Currency ?? Model.StoreDefaultCurrency)" />
|
|
</div>
|
|
</div>
|
|
<div class="row mt-5">
|
|
<div class="col-sm-10 col-md-9 col-xl-7 col-xxl-6">
|
|
<h3 class="mb-4">Checkout</h3>
|
|
<fieldset>
|
|
<div class="form-group" id="button-price-text">
|
|
<label asp-for="ButtonText" class="form-label" data-required></label>
|
|
<input asp-for="ButtonText" class="form-control" required />
|
|
<span asp-validation-for="ButtonText" class="text-danger"></span>
|
|
</div>
|
|
<div class="form-group">
|
|
<label asp-for="FormId" class="form-label"></label>
|
|
<select asp-for="FormId" class="form-select w-auto" asp-items="@checkoutFormOptions"></select>
|
|
<span asp-validation-for="FormId" class="text-danger"></span>
|
|
</div>
|
|
</fieldset>
|
|
<fieldset id="cart-display" class="mt-2">
|
|
<legend class="h5 mb-3 fw-semibold">Cart</legend>
|
|
<div class="form-group d-flex align-items-center pt-2">
|
|
<input asp-for="ShowSearch" type="checkbox" class="btcpay-toggle me-3" />
|
|
<label asp-for="ShowSearch" class="form-label mb-0"></label>
|
|
<span asp-validation-for="ShowSearch" class="text-danger"></span>
|
|
</div>
|
|
<div class="form-group d-flex align-items-center">
|
|
<input asp-for="ShowCategories" type="checkbox" class="btcpay-toggle me-3" />
|
|
<label asp-for="ShowCategories" class="form-label mb-0"></label>
|
|
<span asp-validation-for="ShowCategories" class="text-danger"></span>
|
|
</div>
|
|
</fieldset>
|
|
<fieldset id="tips" class="mt-2">
|
|
<legend class="h5 mb-3 fw-semibold">Tips</legend>
|
|
<div class="form-group d-flex align-items-center pt-2">
|
|
<input asp-for="EnableTips" type="checkbox" class="btcpay-toggle me-3" data-bs-toggle="collapse" data-bs-target="#CustomTipsSettings" aria-expanded="@Model.EnableTips" aria-controls="CustomTipsSettings" />
|
|
<label asp-for="EnableTips" class="form-label mb-0"></label>
|
|
<span asp-validation-for="EnableTips" class="text-danger"></span>
|
|
</div>
|
|
<div class="collapse @(Model.EnableTips ? "show" : "")" id="CustomTipsSettings">
|
|
<div class="form-group">
|
|
<label asp-for="CustomTipText" class="form-label" data-required></label>
|
|
<input asp-for="CustomTipText" class="form-control" required />
|
|
<span asp-validation-for="CustomTipText" class="text-danger"></span>
|
|
</div>
|
|
<div class="form-group">
|
|
<label asp-for="CustomTipPercentages" class="form-label"></label>
|
|
<input asp-for="CustomTipPercentages" class="form-control" />
|
|
<span asp-validation-for="CustomTipPercentages" class="text-danger"></span>
|
|
</div>
|
|
</div>
|
|
</fieldset>
|
|
<fieldset id="discounts" class="mt-2">
|
|
<legend class="h5 mb-3 fw-semibold">Discounts</legend>
|
|
<div class="form-group d-flex align-items-center">
|
|
<input asp-for="ShowDiscount" type="checkbox" class="btcpay-toggle me-3" />
|
|
<div>
|
|
<label asp-for="ShowDiscount" class="form-label mb-0"></label>
|
|
<div class="text-muted">Not recommended for customer self-checkout.</div>
|
|
</div>
|
|
<span asp-validation-for="ShowDiscount" class="text-danger"></span>
|
|
</div>
|
|
</fieldset>
|
|
<fieldset id="custom-payments" class="mt-2">
|
|
<legend class="h5 mb-3 fw-semibold">Custom Payments</legend>
|
|
<div class="form-group mb-4 d-flex align-items-center">
|
|
<input asp-for="ShowCustomAmount" type="checkbox" class="btcpay-toggle me-3" data-bs-toggle="collapse" data-bs-target="#CustomAmountSettings" aria-expanded="@Model.ShowCustomAmount" aria-controls="CustomAmountSettings"/>
|
|
<label asp-for="ShowCustomAmount" class="form-label mb-0"></label>
|
|
<span asp-validation-for="ShowCustomAmount" class="text-danger"></span>
|
|
</div>
|
|
<div class="collapse @(Model.ShowCustomAmount ? "show" : "")" id="CustomAmountSettings">
|
|
<div class="form-group">
|
|
<label asp-for="CustomButtonText" class="form-label" data-required></label>
|
|
<input asp-for="CustomButtonText" class="form-control" required />
|
|
<span asp-validation-for="CustomButtonText" class="text-danger"></span>
|
|
</div>
|
|
</div>
|
|
</fieldset>
|
|
</div>
|
|
</div>
|
|
<div class="row" style="margin-top:2.25rem;">
|
|
<div class="col-xl-8 col-xxl-constrain">
|
|
<h3 class="mb-2">Additional Options</h3>
|
|
<div class="form-group">
|
|
<div class="accordion" id="additional">
|
|
<div class="accordion-item">
|
|
<h2 class="accordion-header" id="additional-embed-payment-button-header">
|
|
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#additional-embed-payment-button" aria-expanded="false" aria-controls="additional-embed-payment-button">
|
|
Embed a payment button linking to POS item
|
|
<vc:icon symbol="caret-down" />
|
|
</button>
|
|
</h2>
|
|
<div id="additional-embed-payment-button" class="accordion-collapse collapse" aria-labelledby="additional-embed-payment-button-header">
|
|
<div class="accordion-body">
|
|
<p>You can host point of sale buttons in an external website with the following code.</p>
|
|
@if (Model.Example1 != null)
|
|
{
|
|
<span>For anything with a custom amount</span>
|
|
<pre class="p-3">@Model.Example1</pre>
|
|
}
|
|
@if (Model.Example2 != null)
|
|
{
|
|
<span>For a specific item of your template</span>
|
|
<pre class="p-3">@Model.Example2</pre>
|
|
}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="accordion-item">
|
|
<h2 class="accordion-header" id="additional-embed-pos-iframe-header">
|
|
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#additional-embed-pos-iframe" aria-expanded="false" aria-controls="additional-embed-pos-iframe">
|
|
Embed Point of Sale via Iframe
|
|
<vc:icon symbol="caret-down" />
|
|
</button>
|
|
</h2>
|
|
<div id="additional-embed-pos-iframe" class="accordion-collapse collapse" aria-labelledby="additional-embed-pos-iframe-header">
|
|
<div class="accordion-body">
|
|
You can embed this POS via an iframe.
|
|
@{
|
|
var iframe = $"<iframe src='{Url.Action("ViewPointOfSale", "UIPointOfSale", new { appId = Model.Id }, Context.Request.Scheme)}' style='max-width: 100%; border: 0;'></iframe>";
|
|
}
|
|
<pre class="p-3">@iframe</pre>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="accordion-item">
|
|
<h2 class="accordion-header" id="additional-redirect-header">
|
|
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#additional-redirect" aria-expanded="false" aria-controls="additional-redirect">
|
|
Redirects
|
|
<vc:icon symbol="caret-down" />
|
|
</button>
|
|
</h2>
|
|
<div id="additional-redirect" class="accordion-collapse collapse" aria-labelledby="additional-redirect-header">
|
|
<div class="accordion-body">
|
|
<div class="form-group">
|
|
<label asp-for="RedirectUrl" class="form-label"></label>
|
|
<input asp-for="RedirectUrl" class="form-control" />
|
|
<span asp-validation-for="RedirectUrl" class="text-danger"></span>
|
|
</div>
|
|
<div class="form-group">
|
|
<label asp-for="RedirectAutomatically" class="form-label"></label>
|
|
<select asp-for="RedirectAutomatically" asp-items="Model.RedirectAutomaticallySelectList" class="form-select"></select>
|
|
<span asp-validation-for="RedirectAutomatically" class="text-danger"></span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="accordion-item">
|
|
<h2 class="accordion-header" id="additional-notification-header">
|
|
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#additional-notification" aria-expanded="false" aria-controls="additional-notification">
|
|
Notification URL Callbacks
|
|
<vc:icon symbol="caret-down" />
|
|
</button>
|
|
</h2>
|
|
<div id="additional-notification" class="accordion-collapse collapse" aria-labelledby="additional-notification-header">
|
|
<div class="accordion-body">
|
|
<div class="form-group">
|
|
<label asp-for="NotificationUrl" class="form-label"></label>
|
|
<input asp-for="NotificationUrl" class="form-control" />
|
|
<span asp-validation-for="NotificationUrl" class="text-danger"></span>
|
|
</div>
|
|
<p>A <code>POST</code> callback will be sent to the specified <code>notificationUrl</code> (for on-chain transactions when there are sufficient confirmations):</p>
|
|
<pre class="p-3">@Model.ExampleCallback</pre>
|
|
<p><strong>Never</strong> trust anything but <code>id</code>, <strong>ignore</strong> the other fields completely, an attacker can spoof those, they are present only for backward compatibility reason:</p>
|
|
<ul>
|
|
<li>Send a <code>GET</code> request to <code>https://btcpay.example.com/invoices/{invoiceId}</code> with <code>Content-Type: application/json; Authorization: Basic YourLegacyAPIkey"</code>, Legacy API key can be created with Access Tokens in Store settings</li>
|
|
<li>Verify that the <code>orderId</code> is from your backend, that the <code>price</code> is correct and that <code>status</code> is <code>settled</code></li>
|
|
<li>You can then ship your order</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
@* We are deprecating the custom CSS options in favor of the store branding approach.
|
|
Display this section only if these values are set. *@
|
|
@if (!string.IsNullOrWhiteSpace(Model.CustomCSSLink) || !string.IsNullOrWhiteSpace(Model.EmbeddedCSS))
|
|
{
|
|
<div class="accordion-item">
|
|
<h2 class="accordion-header" id="additional-custom-css-header">
|
|
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#additional-custom-css" aria-expanded="false" aria-controls="additional-custom-css">
|
|
Custom CSS
|
|
<vc:icon symbol="caret-down" />
|
|
</button>
|
|
</h2>
|
|
<div id="additional-custom-css" class="accordion-collapse collapse" aria-labelledby="additional-custom-css-header">
|
|
<div class="accordion-body">
|
|
<div class="form-group">
|
|
<label asp-for="CustomCSSLink" class="form-label"></label>
|
|
<a href="https://docs.btcpayserver.org/Development/Theme/#2-bootstrap-themes" target="_blank" rel="noreferrer noopener" title="More information...">
|
|
<vc:icon symbol="info" />
|
|
</a>
|
|
<input asp-for="CustomCSSLink" class="form-control" />
|
|
<span asp-validation-for="CustomCSSLink" class="text-danger"></span>
|
|
</div>
|
|
<div class="form-group">
|
|
<label asp-for="EmbeddedCSS" class="form-label"></label>
|
|
<textarea asp-for="EmbeddedCSS" rows="10" cols="40" class="form-control"></textarea>
|
|
<span asp-validation-for="EmbeddedCSS" class="text-danger"></span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</form>
|
|
|
|
<div class="d-grid d-sm-flex flex-wrap gap-3 mt-3">
|
|
<a class="btn btn-secondary" asp-action="ListInvoices" asp-controller="UIInvoice" asp-route-storeId="@Model.StoreId" asp-route-searchterm="@Model.SearchTerm">Invoices</a>
|
|
<form method="post" asp-controller="UIApps" asp-action="ToggleArchive" asp-route-appId="@Model.Id">
|
|
<button type="submit" class="w-100 btn btn-outline-secondary" id="btn-archive-toggle">
|
|
@if (Model.Archived)
|
|
{
|
|
<span class="text-nowrap">Unarchive this app</span>
|
|
}
|
|
else
|
|
{
|
|
<span class="text-nowrap" data-bs-toggle="tooltip" title="Archive this app so that it does not appear in the apps list by default">Archive this app</span>
|
|
}
|
|
</button>
|
|
</form>
|
|
<a id="DeleteApp" class="btn btn-outline-danger" asp-controller="UIApps" asp-action="DeleteApp" asp-route-appId="@Model.Id" data-bs-toggle="modal" data-bs-target="#ConfirmModal" data-description="The app <strong>@Html.Encode(Model.AppName)</strong> and its settings will be permanently deleted." data-confirm-input="DELETE">Delete this app</a>
|
|
</div>
|
|
|
|
<partial name="_Confirm" model="@(new ConfirmModel("Delete app", "This app will be removed from this store.", "Delete"))" />
|