2022-07-15 05:38:33 +02:00
@using BTCPayServer.Abstractions.Models
2022-07-18 20:51:53 +02:00
@using BTCPayServer.Views.Apps
2024-03-14 10:25:40 +01:00
@using BTCPayServer.Client
2023-03-17 03:56:32 +01:00
@using BTCPayServer.Plugins.PointOfSale
2023-02-20 11:35:54 +01:00
@using BTCPayServer.Forms
2024-03-14 10:25:40 +01:00
@using BTCPayServer.TagHelpers
@using Microsoft.AspNetCore.Mvc.TagHelpers
2023-02-20 11:35:54 +01:00
@inject FormDataService FormDataService
2023-03-08 17:57:36 +09:00
@inject BTCPayServer.Security.ContentSecurityPolicies Csp
2022-07-18 20:51:53 +02:00
@model BTCPayServer.Plugins.PointOfSale.Models.UpdatePointOfSaleViewModel
2018-04-03 11:50:41 +09:00
@{
2022-01-24 18:07:52 -08:00
ViewData.SetActivePage(AppsNavPages.Update, "Update Point of Sale", Model.Id);
2023-03-08 17:57:36 +09:00
Csp.UnsafeEval();
2023-02-20 11:35:54 +01:00
var checkoutFormOptions = await FormDataService.GetSelect(Model.StoreId, Model.FormId);
2024-09-26 12:10:14 +02:00
var posPath = Url.Action("ViewPointOfSale", "UIPointOfSale", new { appId = Model.Id });
2018-04-03 11:50:41 +09:00
}
2021-04-08 15:32:42 +02:00
2023-11-02 19:58:03 +01:00
@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" />
2024-03-14 08:52:33 +01:00
<link href="~/vendor/vue-qrcode-reader/vue-qrcode-reader.css" rel="stylesheet" asp-append-version="true" />
2023-11-02 19:58:03 +01:00
}
@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>
}
2024-03-19 14:58:33 +01:00
<form method="post" permissioned="@Policies.CanModifyStoreSettings">
2024-06-19 15:23:10 +02:00
<div class="sticky-header">
2024-07-25 22:46:02 +09:00
<h2 text-translate="true">@ViewData["Title"]</h2>
2024-06-19 15:23:10 +02:00
<div>
2024-07-25 15:23:28 +09:00
<button id="page-primary" type="submit" class="btn btn-primary order-sm-1">Save</button>
2023-09-11 02:59:17 +02:00
@if (Model.Archived)
{
2024-03-19 14:58:33 +01:00
<button type="submit" class="btn btn-outline-secondary" name="Archived" value="False">Unarchive</button>
2023-09-11 02:59:17 +02:00
}
else
{
2024-03-14 08:52:33 +01:00
<div class="btn-group" role="group" aria-label="View Point of Sale">
<a class="btn btn-secondary" asp-controller="UIPointOfSale" asp-action="ViewPointOfSale" asp-route-appId="@Model.Id" id="ViewApp" target="_blank">View</a>
2024-09-26 12:10:14 +02:00
<button type="button" class="btn btn-secondary px-3 d-inline-flex align-items-center" data-bs-toggle="modal" data-bs-target="#OpenPosModal">
2024-03-14 08:52:33 +01:00
<vc:icon symbol="qr-code" />
</button>
</div>
2023-09-11 02:59:17 +02:00
}
2022-02-07 10:37:45 +01:00
</div>
2022-02-21 03:05:42 +01:00
</div>
2021-04-08 15:32:42 +02:00
2022-02-07 10:37:45 +01:00
<partial name="_StatusMessage" />
2021-07-23 03:57:19 -07:00
2021-12-11 04:32:23 +01:00
<input type="hidden" asp-for="StoreId" />
2023-09-11 02:59:17 +02:00
<input type="hidden" asp-for="Archived" />
2021-12-11 04:32:23 +01:00
2024-06-19 15:23:10 +02:00
@if (!ViewContext.ModelState.IsValid)
{
2024-09-26 08:52:16 +02:00
<div asp-validation-summary="All" class="@(ViewContext.ModelState.ErrorCount.Equals(1) ? "no-marker" : "")"></div>
2024-06-19 15:23:10 +02:00
}
2021-12-11 04:32:23 +01:00
<div class="row">
2023-01-26 01:27:31 +01:00
<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>
2021-12-11 04:32:23 +01:00
</div>
<div class="form-group">
2023-01-26 01:27:31 +01:00
<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>
2021-12-11 04:32:23 +01:00
</div>
2023-01-26 01:27:31 +01:00
<div class="form-group mb-0">
2021-12-11 04:32:23 +01:00
<label asp-for="Currency" class="form-label"></label>
2022-09-26 03:26:13 +02:00
<input asp-for="Currency" class="form-control w-auto" currency-selection />
2022-12-04 10:01:38 +01:00
<div class="form-text">Uses the store's default currency (@Model.StoreDefaultCurrency) if empty.</div>
2021-12-11 04:32:23 +01:00
<span asp-validation-for="Currency" class="text-danger"></span>
</div>
</div>
2022-01-28 08:45:56 +01:00
</div>
2023-01-26 01:27:31 +01:00
<div id="description" class="row mt-4">
2022-01-27 03:56:46 +01:00
<div class="col-xl-10 col-xxl-constrain">
2022-01-28 08:45:56 +01:00
<div class="form-group mb-0">
2021-12-11 04:32:23 +01:00
<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>
2022-01-28 08:45:56 +01:00
</div>
2023-11-09 10:27:33 +01:00
<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>
2022-01-28 08:45:56 +01:00
</div>
2023-01-26 01:27:31 +01:00
<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>
2024-03-14 11:11:54 +01:00
<fieldset id="keypad-display" class="mt-2">
<legend class="h5 mb-3 fw-semibold">Keypad</legend>
<div class="form-group d-flex align-items-center pt-2">
<input asp-for="ShowItems" type="checkbox" class="btcpay-toggle me-3" />
<label asp-for="ShowItems" class="form-label mb-0"></label>
<span asp-validation-for="ShowItems" class="text-danger"></span>
</div>
</fieldset>
2023-11-13 13:59:14 +01:00
<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" />
2024-03-14 15:16:48 +01:00
<label asp-for="ShowSearch" class="form-check-label"></label>
2023-11-13 13:59:14 +01:00
<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" />
2024-03-14 15:16:48 +01:00
<label asp-for="ShowCategories" class="form-check-label"></label>
2023-11-13 13:59:14 +01:00
<span asp-validation-for="ShowCategories" class="text-danger"></span>
</div>
</fieldset>
2023-01-26 01:27:31 +01:00
<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" />
2024-03-14 15:16:48 +01:00
<label asp-for="EnableTips" class="form-check-label"></label>
2023-01-26 01:27:31 +01:00
<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>
2022-07-20 22:29:31 -07:00
<div class="form-group d-flex align-items-center">
<input asp-for="ShowDiscount" type="checkbox" class="btcpay-toggle me-3" />
2022-07-21 13:38:33 +02:00
<div>
2024-03-14 15:16:48 +01:00
<label asp-for="ShowDiscount" class="form-check-label"></label>
2022-07-21 13:38:33 +02:00
<div class="text-muted">Not recommended for customer self-checkout.</div>
</div>
2021-12-11 04:32:23 +01:00
<span asp-validation-for="ShowDiscount" class="text-danger"></span>
2022-07-20 22:29:31 -07:00
</div>
2023-01-26 01:27:31 +01:00
</fieldset>
<fieldset id="custom-payments" class="mt-2">
<legend class="h5 mb-3 fw-semibold">Custom Payments</legend>
2021-12-11 04:32:23 +01:00
<div class="form-group mb-4 d-flex align-items-center">
2022-04-13 21:09:37 -07:00
<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"/>
2024-03-14 15:16:48 +01:00
<label asp-for="ShowCustomAmount" class="form-check-label"></label>
2021-12-11 04:32:23 +01:00
<span asp-validation-for="ShowCustomAmount" class="text-danger"></span>
</div>
<div class="collapse @(Model.ShowCustomAmount ? "show" : "")" id="CustomAmountSettings">
2023-01-26 01:27:31 +01:00
<div class="form-group">
2021-12-11 04:32:23 +01:00
<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>
2018-11-17 12:43:11 +09:00
</div>
2021-07-23 03:57:19 -07:00
</div>
2023-01-26 01:27:31 +01:00
</fieldset>
2021-12-11 04:32:23 +01:00
</div>
2022-01-28 08:45:56 +01:00
</div>
2023-01-26 01:27:31 +01:00
<div class="row" style="margin-top:2.25rem;">
2022-01-27 03:56:46 +01:00
<div class="col-xl-8 col-xxl-constrain">
2023-01-26 01:27:31 +01:00
<h3 class="mb-2">Additional Options</h3>
2021-12-11 04:32:23 +01:00
<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>
2022-01-27 03:56:46 +01:00
<pre class="p-3">@Model.Example1</pre>
2021-12-11 04:32:23 +01:00
}
@if (Model.Example2 != null)
{
<span>For a specific item of your template</span>
2022-01-27 03:56:46 +01:00
<pre class="p-3">@Model.Example2</pre>
2021-12-11 04:32:23 +01:00
}
2021-10-25 03:06:32 -07:00
</div>
2020-01-23 20:01:49 -06:00
</div>
2021-12-11 04:32:23 +01:00
</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.
@{
2022-07-22 15:41:14 +02:00
var iframe = $"<iframe src='{Url.Action("ViewPointOfSale", "UIPointOfSale", new { appId = Model.Id }, Context.Request.Scheme)}' style='max-width: 100%; border: 0;'></iframe>";
2021-12-11 04:32:23 +01:00
}
2022-01-27 03:56:46 +01:00
<pre class="p-3">@iframe</pre>
2021-10-25 03:06:32 -07:00
</div>
</div>
2021-12-11 04:32:23 +01:00
</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>
2019-01-31 08:56:21 +01:00
</div>
2021-12-11 04:32:23 +01:00
<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>
2019-01-31 08:56:21 +01:00
</div>
</div>
2021-12-11 04:32:23 +01:00
</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>
2021-07-23 03:57:19 -07:00
</div>
2022-06-06 02:58:32 -07:00
<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>
2022-01-27 03:56:46 +01:00
<pre class="p-3">@Model.ExampleCallback</pre>
2021-12-11 04:32:23 +01:00
<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>
2022-02-07 10:37:45 +01:00
<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>
2021-07-23 03:57:19 -07:00
</div>
2021-12-11 04:32:23 +01:00
</div>
</div>
2021-09-24 07:13:38 +02:00
</div>
2021-12-11 04:32:23 +01:00
</div>
</div>
2022-01-28 08:45:56 +01:00
</div>
2021-12-11 04:32:23 +01:00
</form>
2021-05-19 04:39:27 +02:00
2023-11-09 10:27:33 +01:00
<div class="d-grid d-sm-flex flex-wrap gap-3 mt-3">
2022-06-28 07:05:02 +02:00
<a class="btn btn-secondary" asp-action="ListInvoices" asp-controller="UIInvoice" asp-route-storeId="@Model.StoreId" asp-route-searchterm="@Model.SearchTerm">Invoices</a>
2023-09-11 02:59:17 +02:00
<form method="post" asp-controller="UIApps" asp-action="ToggleArchive" asp-route-appId="@Model.Id">
2024-03-14 10:25:40 +01:00
<button type="submit" class="w-100 btn btn-outline-secondary" id="btn-archive-toggle" permission="@Policies.CanModifyStoreSettings">
2023-09-11 02:59:17 +02:00
@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>
2024-03-14 10:25:40 +01:00
<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" permission="@Policies.CanModifyStoreSettings">Delete this app</a>
2021-12-19 05:05:10 +01:00
</div>
2024-03-14 10:25:40 +01:00
<partial name="_Confirm" model="@(new ConfirmModel("Delete app", "This app will be removed from this store.", "Delete"))" permission="@Policies.CanModifyStoreSettings" />
2024-03-14 08:52:33 +01:00
2024-09-26 12:10:14 +02:00
<div class="modal fade" id="OpenPosModal" tabindex="-1" aria-labelledby="ConfirmTitle" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Scan the QR code to open the Point of Sale</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close">
<vc:icon symbol="close"/>
</button>
</div>
<div class="modal-body pt-0">
<component type="typeof(BTCPayServer.Blazor.PosLoginCode)" render-mode="ServerPrerendered" param-Users="@Model.StoreUsers" param-PosPath="@posPath" />
</div>
</div>
</div>
</div>