mirror of
https://github.com/btcpayserver/btcpayserver.git
synced 2024-11-19 01:43:50 +01:00
More Translations (#6318)
* Store selector * Footer * Notifications * Checkout Appearance * Users list * Forms * Emails * Pay Button * Edit Dictionary * Remove newlines, fix typos * Forms * Pull payments and payouts * Various pages * Use local docs link * Fix * Even more translations * Fixes #6325 * Account pages * Notifications * Placeholders * Various pages and components * Add more
This commit is contained in:
parent
e5611f9165
commit
a962e60de9
@ -360,7 +360,9 @@ retry:
|
||||
{
|
||||
await tester.StartAsync();
|
||||
var engine = tester.PayTester.GetService<RazorProjectEngine>();
|
||||
foreach (var file in soldir.EnumerateFiles("*.cshtml", SearchOption.AllDirectories))
|
||||
var files = soldir.EnumerateFiles("*.cshtml", SearchOption.AllDirectories)
|
||||
.Union(soldir.EnumerateFiles("*.razor", SearchOption.AllDirectories));
|
||||
foreach (var file in files)
|
||||
{
|
||||
var filePath = file.FullName;
|
||||
var txt = File.ReadAllText(file.FullName);
|
||||
|
@ -4,10 +4,12 @@
|
||||
@using BTCPayServer.Services.Notifications;
|
||||
@using Microsoft.AspNetCore.Identity;
|
||||
@using Microsoft.AspNetCore.Routing;
|
||||
@using Microsoft.Extensions.Localization
|
||||
@implements IDisposable
|
||||
@inject AuthenticationStateProvider _AuthenticationStateProvider
|
||||
@inject NotificationManager _NotificationManager
|
||||
@inject UserManager<ApplicationUser> _UserManager
|
||||
@inject IStringLocalizer StringLocalizer
|
||||
@inject IJSRuntime _JSRuntime
|
||||
@inject LinkGenerator _LinkGenerator
|
||||
@inject BTCPayServerOptions _BTCPayServerOptions
|
||||
@ -16,13 +18,13 @@
|
||||
<div id="Notifications">
|
||||
@if (UnseenCount == "0")
|
||||
{
|
||||
<a href="@NotificationsUrl" id="NotificationsHandle" class="mainMenuButton" title="Notifications">
|
||||
<a href="@NotificationsUrl" id="NotificationsHandle" class="mainMenuButton" title="@StringLocalizer["Notifications"]">
|
||||
<Icon Symbol="nav-notifications" />
|
||||
</a>
|
||||
}
|
||||
else
|
||||
{
|
||||
<button id="NotificationsHandle" class="mainMenuButton" title="Notifications" type="button" data-bs-toggle="dropdown">
|
||||
<button id="NotificationsHandle" class="mainMenuButton" title="@StringLocalizer["Notifications"]" type="button" data-bs-toggle="dropdown">
|
||||
<Icon Symbol="nav-notifications" />
|
||||
<span class="badge rounded-pill bg-danger p-1 ms-1" id="NotificationsBadge">@UnseenCount</span>
|
||||
</button>
|
||||
@ -31,8 +33,8 @@
|
||||
{
|
||||
<div class="dropdown-menu text-center" id="NotificationsDropdown" aria-labelledby="NotificationsHandle">
|
||||
<div class="d-flex gap-3 align-items-center justify-content-between py-3 px-4 border-bottom border-light">
|
||||
<h5 class="m-0">Notifications</h5>
|
||||
<a class="btn btn-link p-0" @onclick="MarkAllAsSeen" id="NotificationsMarkAllAsSeen">Mark all as seen</a>
|
||||
<h5 class="m-0" text-translate="true">Notifications</h5>
|
||||
<a class="btn btn-link p-0" @onclick="MarkAllAsSeen" id="NotificationsMarkAllAsSeen" text-translate="true">Mark all as seen</a>
|
||||
</div>
|
||||
<div id="NotificationsList" v-pre>
|
||||
@foreach (var n in Last5)
|
||||
@ -54,7 +56,7 @@
|
||||
</div>
|
||||
|
||||
<div class="p-3">
|
||||
<a href="@NotificationsUrl">View all</a>
|
||||
<a href="@NotificationsUrl" text-translate="true">View all</a>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
@ -1,13 +1,13 @@
|
||||
@using Microsoft.AspNetCore.Http
|
||||
|
||||
@inject IHttpContextAccessor HttpContextAccessor;
|
||||
@inject IHttpContextAccessor HttpContextAccessor
|
||||
|
||||
@if (Users?.Any() is true)
|
||||
{
|
||||
<div @attributes="Attrs" class="@CssClass">
|
||||
<label for="SignedInUser" class="form-label">Signed in user</label>
|
||||
<label for="SignedInUser" class="form-label" text-translate="true">Signed in user</label>
|
||||
<select id="SignedInUser" class="form-select" value="@_userId" @onchange="@(e => _userId = e.Value?.ToString())">
|
||||
<option value="">None, just open the URL</option>
|
||||
<option value="" text-translate="true">None, just open the URL</option>
|
||||
@foreach (var u in Users)
|
||||
{
|
||||
<option value="@u.Key">@u.Value</option>
|
||||
|
@ -5,11 +5,13 @@
|
||||
@using Microsoft.AspNetCore.Identity
|
||||
@using Microsoft.AspNetCore.Mvc
|
||||
@using Microsoft.AspNetCore.Routing
|
||||
@using Microsoft.Extensions.Localization
|
||||
@inject AuthenticationStateProvider AuthenticationStateProvider
|
||||
@inject UserManager<ApplicationUser> UserManager;
|
||||
@inject UserLoginCodeService UserLoginCodeService;
|
||||
@inject LinkGenerator LinkGenerator;
|
||||
@inject IHttpContextAccessor HttpContextAccessor;
|
||||
@inject UserManager<ApplicationUser> UserManager
|
||||
@inject UserLoginCodeService UserLoginCodeService
|
||||
@inject LinkGenerator LinkGenerator
|
||||
@inject IHttpContextAccessor HttpContextAccessor
|
||||
@inject IStringLocalizer StringLocalizer
|
||||
@implements IDisposable
|
||||
|
||||
@if (!string.IsNullOrEmpty(_data))
|
||||
@ -18,7 +20,7 @@
|
||||
<div class="qr-container mb-2">
|
||||
<QrCode Data="@_data" Size="Size"/>
|
||||
</div>
|
||||
<p class="text-center text-muted mb-1" id="progress">Valid for @_seconds seconds</p>
|
||||
<p class="text-center text-muted mb-1" id="progress">@StringLocalizer["Valid for {0} seconds", _seconds]</p>
|
||||
<div class="progress only-for-js" data-bs-toggle="tooltip" data-bs-placement="top">
|
||||
<div class="progress-bar progress-bar-striped progress-bar-animated @(Percent < 15 ? "bg-warning" : null)" role="progressbar" style="width:@Percent%" id="progressbar"></div>
|
||||
</div>
|
||||
|
@ -17,9 +17,9 @@
|
||||
<small class="badge bg-warning rounded-pill ms-1 ms-sm-0" title="@type">@displayType</small>
|
||||
}
|
||||
}
|
||||
private static string StoreName(string title)
|
||||
private string StoreName(string title)
|
||||
{
|
||||
return string.IsNullOrEmpty(title) ? "Unnamed Store" : title;
|
||||
return string.IsNullOrEmpty(title) ? StringLocalizer["Unnamed Store"] : title;
|
||||
}
|
||||
#pragma warning restore 1998
|
||||
}
|
||||
@ -44,7 +44,7 @@ else
|
||||
{
|
||||
<vc:icon symbol="nav-store"/>
|
||||
}
|
||||
<span>@(Model.CurrentStoreId == null ? "Select Store" : Model.CurrentDisplayName)</span>
|
||||
<span>@(Model.CurrentStoreId == null ? StringLocalizer["Select Store"] : Model.CurrentDisplayName)</span>
|
||||
<vc:icon symbol="caret-down"/>
|
||||
</button>
|
||||
<ul id="StoreSelectorMenu" class="dropdown-menu" aria-labelledby="StoreSelectorToggle">
|
||||
@ -58,15 +58,15 @@ else
|
||||
{
|
||||
<li><hr class="dropdown-divider"></li>
|
||||
}
|
||||
<li><a asp-controller="UIUserStores" asp-action="CreateStore" class="dropdown-item @ViewData.ActivePageClass(StoreNavPages.Create)" id="StoreSelectorCreate">Create Store</a></li>
|
||||
<li><a asp-controller="UIUserStores" asp-action="CreateStore" class="dropdown-item @ViewData.ActivePageClass(StoreNavPages.Create)" id="StoreSelectorCreate" text-translate="true">Create Store</a></li>
|
||||
@if (Model.ArchivedCount > 0)
|
||||
{
|
||||
<li><hr class="dropdown-divider"></li>
|
||||
<li><a asp-controller="UIUserStores" asp-action="ListStores" asp-route-archived="true" class="dropdown-item @ViewData.ActivePageClass(StoreNavPages.Index)" id="StoreSelectorArchived">@Model.ArchivedCount Archived Store@(Model.ArchivedCount == 1 ? "" : "s")</a></li>
|
||||
<li><a asp-controller="UIUserStores" asp-action="ListStores" asp-route-archived="true" class="dropdown-item @ViewData.ActivePageClass(StoreNavPages.Index)" id="StoreSelectorArchived">@(Model.ArchivedCount == 1 ? StringLocalizer["{0} Archived Store", Model.ArchivedCount] : StringLocalizer["{0} Archived Stores", Model.ArchivedCount])</a></li>
|
||||
}
|
||||
@*
|
||||
<li permission="@Policies.CanModifyServerSettings"><hr class="dropdown-divider"></li>
|
||||
<li permission="@Policies.CanModifyServerSettings"><a asp-controller="UIServer" asp-action="ListStores" class="dropdown-item @ViewData.ActivePageClass(ServerNavPages.Stores)" id="StoreSelectorAdminStores">Admin Store Overview</a></li>
|
||||
<li permission="@Policies.CanModifyServerSettings"><a asp-controller="UIServer" asp-action="ListStores" class="dropdown-item @ViewData.ActivePageClass(ServerNavPages.Stores)" id="StoreSelectorAdminStores" text-translate="true">Admin Store Overview</a></li>
|
||||
*@
|
||||
</ul>
|
||||
</div>
|
||||
|
@ -3,8 +3,8 @@
|
||||
<div class="btcpay-theme-switch @Model.CssClass">
|
||||
<span class="btcpay-theme-switch-label" text-translate="true">Theme</span>
|
||||
<div class="btcpay-theme-switch-themes">
|
||||
<button type="button" title="System" data-theme="system"><vc:icon symbol="themes-system"/></button>
|
||||
<button type="button" title="Light" data-theme="light"><vc:icon symbol="themes-light"/></button>
|
||||
<button type="button" title="Dark" data-theme="dark"><vc:icon symbol="themes-dark"/></button>
|
||||
<button type="button" title="@StringLocalizer["System"]" data-theme="system"><vc:icon symbol="themes-system"/></button>
|
||||
<button type="button" title="@StringLocalizer["Light"]" data-theme="light"><vc:icon symbol="themes-light"/></button>
|
||||
<button type="button" title="@StringLocalizer["Dark"]" data-theme="dark"><vc:icon symbol="themes-dark"/></button>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -1,27 +1,15 @@
|
||||
#nullable enable
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using BTCPayServer.Controllers;
|
||||
using BTCPayServer.Data;
|
||||
using BTCPayServer.Models.StoreViewModels;
|
||||
using BTCPayServer.Payments;
|
||||
using BTCPayServer.Payments.Lightning;
|
||||
using BTCPayServer.Services;
|
||||
using BTCPayServer.Services.Apps;
|
||||
using BTCPayServer.Services.Invoices;
|
||||
using BTCPayServer.Services.Rates;
|
||||
using BTCPayServer.Services.Stores;
|
||||
using BTCPayServer.Services.Wallets;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.Rendering;
|
||||
using Microsoft.AspNetCore.Mvc.ViewComponents;
|
||||
using Microsoft.AspNetCore.Mvc.ViewFeatures;
|
||||
using NBitcoin;
|
||||
using NBitcoin.Secp256k1;
|
||||
using Microsoft.Extensions.Localization;
|
||||
|
||||
namespace BTCPayServer.Components.WalletNav
|
||||
{
|
||||
@ -33,6 +21,7 @@ namespace BTCPayServer.Components.WalletNav
|
||||
private readonly CurrencyNameTable _currencies;
|
||||
private readonly DefaultRulesCollection _defaultRules;
|
||||
private readonly RateFetcher _rateFetcher;
|
||||
private IStringLocalizer StringLocalizer { get; }
|
||||
|
||||
public WalletNav(
|
||||
BTCPayWalletProvider walletProvider,
|
||||
@ -40,6 +29,7 @@ namespace BTCPayServer.Components.WalletNav
|
||||
UIWalletsController walletsController,
|
||||
CurrencyNameTable currencies,
|
||||
DefaultRulesCollection defaultRules,
|
||||
IStringLocalizer stringLocalizer,
|
||||
RateFetcher rateFetcher)
|
||||
{
|
||||
_walletProvider = walletProvider;
|
||||
@ -48,6 +38,7 @@ namespace BTCPayServer.Components.WalletNav
|
||||
_currencies = currencies;
|
||||
_defaultRules = defaultRules;
|
||||
_rateFetcher = rateFetcher;
|
||||
StringLocalizer = stringLocalizer;
|
||||
}
|
||||
|
||||
public async Task<IViewComponentResult> InvokeAsync(WalletId walletId)
|
||||
@ -71,7 +62,7 @@ namespace BTCPayServer.Components.WalletNav
|
||||
Network = network,
|
||||
Balance = balance.ShowMoney(network),
|
||||
DefaultCurrency = defaultCurrency,
|
||||
Label = derivation?.Label ?? $"{store.StoreName} {walletId.CryptoCode} Wallet"
|
||||
Label = derivation?.Label ?? $"{store.StoreName} {StringLocalizer["{0} Wallet", walletId.CryptoCode]}"
|
||||
};
|
||||
|
||||
if (defaultCurrency != network.CryptoCode)
|
||||
|
@ -9,6 +9,7 @@ using System;
|
||||
using System.Net.WebSockets;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Html;
|
||||
using static BTCPayServer.BoltcardDataExtensions;
|
||||
|
||||
namespace BTCPayServer.Controllers
|
||||
@ -71,7 +72,7 @@ next:
|
||||
var permission = await vaultClient.AskPermission(VaultServices.NFC, cts.Token);
|
||||
if (permission is null)
|
||||
{
|
||||
await vaultClient.Show(VaultMessageType.Error, "BTCPay Server Vault does not seem to be running, you can download it on <a target=\"_blank\" href=\"https://github.com/btcpayserver/BTCPayServer.Vault/releases/latest\">Github</a>.", cts.Token);
|
||||
await vaultClient.Show(VaultMessageType.Error, StringLocalizer["BTCPay Server Vault does not seem to be running, you can download it on {0}.", new HtmlString("<a href=\"https://github.com/btcpayserver/BTCPayServer.Vault/releases/latest/\" class=\"alert-link\" target=\"_blank\" rel=\"noreferrer noopener\">GitHub</a>")], cts.Token);
|
||||
goto next;
|
||||
}
|
||||
await vaultClient.Show(VaultMessageType.Ok, StringLocalizer["BTCPayServer successfully connected to the vault."], cts.Token);
|
||||
|
@ -88,6 +88,9 @@ namespace BTCPayServer.Controllers
|
||||
foreach (var prop in jobj.Properties())
|
||||
{
|
||||
prop.Value = "OK";
|
||||
if (prop.Name.Contains("{0}")) prop.Value += " {0}";
|
||||
if (prop.Name.Contains("{1}")) prop.Value += " {1}";
|
||||
if (prop.Name.Contains("{2}")) prop.Value += " {2}";
|
||||
}
|
||||
viewModel.Translations = Translations.CreateFromJson(jobj.ToString()).ToJsonFormat();
|
||||
}
|
||||
|
@ -331,8 +331,8 @@ namespace BTCPayServer.Controllers
|
||||
}
|
||||
|
||||
return View("Confirm", new ConfirmModel(StringLocalizer["Delete admin"],
|
||||
$"The admin <strong>{Html.Encode(user.Email)}</strong> will be permanently deleted. This action will also delete all accounts, users and data associated with the server account. Are you sure?",
|
||||
"Delete"));
|
||||
StringLocalizer["The admin {0} will be permanently deleted. This action will also delete all accounts, users and data associated with the server account. Are you sure?", Html.Encode(user.Email)],
|
||||
StringLocalizer["Delete"]));
|
||||
}
|
||||
|
||||
return View("Confirm", new ConfirmModel(StringLocalizer["Delete user"], $"The user <strong>{Html.Encode(user.Email)}</strong> will be permanently deleted. Are you sure?", "Delete"));
|
||||
|
@ -4,6 +4,7 @@ namespace BTCPayServer.Forms;
|
||||
|
||||
public class ModifyForm
|
||||
{
|
||||
[DisplayName("Name")]
|
||||
public string Name { get; set; }
|
||||
|
||||
[DisplayName("Form configuration (JSON)")]
|
||||
|
@ -89,8 +89,7 @@ public class UIFormsController : Controller
|
||||
|
||||
if (!_formDataService.IsFormSchemaValid(modifyForm.FormConfig, out var form, out var error))
|
||||
{
|
||||
ModelState.AddModelError(nameof(modifyForm.FormConfig),
|
||||
$"Form config was invalid: {error})");
|
||||
ModelState.AddModelError(nameof(modifyForm.FormConfig), StringLocalizer["Form config was invalid: {0}", error!]);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -117,7 +116,9 @@ public class UIFormsController : Controller
|
||||
TempData.SetStatusMessageModel(new StatusMessageModel
|
||||
{
|
||||
Severity = StatusMessageModel.StatusSeverity.Success,
|
||||
Message = $"Form {(isNew ? "created" : "updated")} successfully."
|
||||
Message = isNew
|
||||
? StringLocalizer["Form created successfully."].Value
|
||||
: StringLocalizer["Form updated successfully."].Value
|
||||
});
|
||||
if (isNew)
|
||||
{
|
||||
@ -126,7 +127,7 @@ public class UIFormsController : Controller
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
ModelState.AddModelError("", $"An error occurred while saving: {e.Message}");
|
||||
ModelState.AddModelError("", StringLocalizer["An error occurred while saving: {0}", e.Message]);
|
||||
}
|
||||
|
||||
return View(modifyForm);
|
||||
@ -216,14 +217,13 @@ public class UIFormsController : Controller
|
||||
|
||||
try
|
||||
{
|
||||
|
||||
var request = _formDataService.GenerateInvoiceParametersFromForm(form);
|
||||
var inv = await invoiceController.CreateInvoiceCoreRaw(request, store, Request.GetAbsoluteRoot());
|
||||
if (inv.Price == 0 && inv.Type == InvoiceType.Standard && inv.ReceiptOptions?.Enabled is not false)
|
||||
{
|
||||
return RedirectToAction("InvoiceReceipt", "UIInvoice", new { invoiceId = inv.Id });
|
||||
}
|
||||
return RedirectToAction("Checkout", "UIInvoice", new { invoiceId = inv.Id });
|
||||
var request = _formDataService.GenerateInvoiceParametersFromForm(form);
|
||||
var inv = await invoiceController.CreateInvoiceCoreRaw(request, store, Request.GetAbsoluteRoot());
|
||||
if (inv.Price == 0 && inv.Type == InvoiceType.Standard && inv.ReceiptOptions?.Enabled is not false)
|
||||
{
|
||||
return RedirectToAction("InvoiceReceipt", "UIInvoice", new { invoiceId = inv.Id });
|
||||
}
|
||||
return RedirectToAction("Checkout", "UIInvoice", new { invoiceId = inv.Id });
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
@ -13,6 +13,7 @@ using BTCPayServer.Services;
|
||||
using BTCPayServer.Services.Notifications;
|
||||
using BTCPayServer.Services.Notifications.Blobs;
|
||||
using Microsoft.AspNetCore.Routing;
|
||||
using Microsoft.Extensions.Localization;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
@ -22,15 +23,17 @@ namespace BTCPayServer.HostedServices
|
||||
{
|
||||
private const string TYPE = "pluginupdate";
|
||||
|
||||
internal class Handler(LinkGenerator linkGenerator, BTCPayServerOptions options) : NotificationHandler<PluginUpdateNotification>
|
||||
internal class Handler(LinkGenerator linkGenerator, BTCPayServerOptions options, IStringLocalizer stringLocalizer) : NotificationHandler<PluginUpdateNotification>
|
||||
{
|
||||
private IStringLocalizer StringLocalizer { get; } = stringLocalizer;
|
||||
|
||||
public override string NotificationType => TYPE;
|
||||
|
||||
public override (string identifier, string name)[] Meta
|
||||
{
|
||||
get
|
||||
{
|
||||
return new (string identifier, string name)[] {(TYPE, "Plugin update")};
|
||||
return new (string identifier, string name)[] {(TYPE, StringLocalizer["Plugin update"])};
|
||||
}
|
||||
}
|
||||
|
||||
@ -38,7 +41,7 @@ namespace BTCPayServer.HostedServices
|
||||
{
|
||||
vm.Identifier = notification.Identifier;
|
||||
vm.Type = notification.NotificationType;
|
||||
vm.Body = $"New {notification.Name} plugin version {notification.Version} released!";
|
||||
vm.Body = StringLocalizer["New {0} plugin version {1} released!", notification.Name, notification.Version];
|
||||
vm.ActionLink = linkGenerator.GetPathByAction(nameof(UIServerController.ListPlugins),
|
||||
"UIServer",
|
||||
new {plugin = notification.PluginIdentifier}, options.RootPath);
|
||||
|
@ -1,9 +1,11 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using BTCPayServer.Services;
|
||||
|
||||
namespace BTCPayServer.Models.ServerViewModels;
|
||||
|
||||
public class EditDictionaryViewModel
|
||||
{
|
||||
[Display(Name = "Translations")]
|
||||
public string Translations { get; set; }
|
||||
public int Lines { get; set; }
|
||||
public string Command { get; set; }
|
||||
|
@ -107,18 +107,5 @@ namespace BTCPayServer.Models.StoreViewModels
|
||||
GreaterThan,
|
||||
LessThan
|
||||
}
|
||||
public static string ToString(CriteriaType type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case CriteriaType.GreaterThan:
|
||||
return "Greater than";
|
||||
case CriteriaType.LessThan:
|
||||
return "Less than";
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException(nameof(type), type, null);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -10,6 +10,7 @@ namespace BTCPayServer.Models.StoreViewModels
|
||||
[Required]
|
||||
[MaxLength(50)]
|
||||
[MinLength(1)]
|
||||
[Display(Name = "Name")]
|
||||
public string Name { get; set; }
|
||||
|
||||
[Required]
|
||||
|
@ -15,6 +15,8 @@ namespace BTCPayServer.Models.StoreViewModels
|
||||
public string CryptoCode { get; set; }
|
||||
public bool CanUseInternalNode { get; set; }
|
||||
public bool SkipPortTest { get; set; }
|
||||
|
||||
[Display(Name = "Enabled")]
|
||||
public bool Enabled { get; set; } = true;
|
||||
|
||||
[Display(Name = "Connection string")]
|
||||
|
@ -9,12 +9,15 @@ namespace BTCPayServer.Models.StoreViewModels
|
||||
public WalletId WalletId { get; set; }
|
||||
public string StoreId { get; set; }
|
||||
public bool IsHotWallet { get; set; }
|
||||
|
||||
[Display(Name = "Enabled")]
|
||||
public bool Enabled { get; set; }
|
||||
public bool CanUsePayJoin { get; set; }
|
||||
|
||||
[Display(Name = "Enable Payjoin/P2EP")]
|
||||
public bool PayJoinEnabled { get; set; }
|
||||
|
||||
[Display(Name = "Label")]
|
||||
public string Label { get; set; }
|
||||
|
||||
public string DerivationSchemeInput { get; set; }
|
||||
|
@ -43,15 +43,19 @@ namespace BTCPayServer.Models.WalletViewModels
|
||||
public class NewPullPaymentModel
|
||||
{
|
||||
[MaxLength(30)]
|
||||
[Display(Name = "Name")]
|
||||
public string Name { get; set; }
|
||||
|
||||
[Display(Name = "Description")]
|
||||
public string Description { get; set; }
|
||||
|
||||
[Required]
|
||||
public decimal Amount
|
||||
{
|
||||
get; set;
|
||||
}
|
||||
[Display(Name = "Amount")]
|
||||
public decimal Amount { get; set; }
|
||||
|
||||
[Required]
|
||||
[ReadOnly(true)]
|
||||
[Display(Name = "Currency")]
|
||||
public string Currency { get; set; }
|
||||
|
||||
[Display(Name = "Payout Methods")]
|
||||
@ -61,12 +65,12 @@ namespace BTCPayServer.Models.WalletViewModels
|
||||
[Range(0, 365 * 10)]
|
||||
public long BOLT11Expiration { get; set; } = 30;
|
||||
[Display(Name = "Automatically approve claims")]
|
||||
public bool AutoApproveClaims { get; set; } = false;
|
||||
public bool AutoApproveClaims { get; set; }
|
||||
}
|
||||
|
||||
public class UpdatePullPaymentModel
|
||||
{
|
||||
|
||||
[Display(Name = "Id")]
|
||||
public string Id { get; set; }
|
||||
|
||||
public UpdatePullPaymentModel()
|
||||
@ -87,6 +91,7 @@ namespace BTCPayServer.Models.WalletViewModels
|
||||
}
|
||||
|
||||
[MaxLength(30)]
|
||||
[Display(Name = "Name")]
|
||||
public string Name { get; set; }
|
||||
|
||||
[Display(Name = "Memo")]
|
||||
|
@ -10,6 +10,7 @@ using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Routing;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Microsoft.Extensions.Localization;
|
||||
|
||||
namespace BTCPayServer.PayoutProcessors.Lightning;
|
||||
|
||||
@ -19,19 +20,22 @@ public class LightningAutomatedPayoutSenderFactory : IPayoutProcessorFactory
|
||||
private readonly IServiceProvider _serviceProvider;
|
||||
private readonly LinkGenerator _linkGenerator;
|
||||
private readonly PayoutMethodId[] _supportedPayoutMethods;
|
||||
private IStringLocalizer StringLocalizer { get; }
|
||||
|
||||
public LightningAutomatedPayoutSenderFactory(
|
||||
PayoutMethodHandlerDictionary handlers,
|
||||
IServiceProvider serviceProvider,
|
||||
IStringLocalizer stringLocalizer,
|
||||
LinkGenerator linkGenerator)
|
||||
{
|
||||
_handlers = handlers;
|
||||
_serviceProvider = serviceProvider;
|
||||
_linkGenerator = linkGenerator;
|
||||
_supportedPayoutMethods = _handlers.OfType<LightningLikePayoutHandler>().Select(n => n.PayoutMethodId).ToArray();
|
||||
StringLocalizer = stringLocalizer;
|
||||
}
|
||||
|
||||
public string FriendlyName { get; } = "Automated Lightning Sender";
|
||||
public string FriendlyName => StringLocalizer["Automated Lightning Sender"];
|
||||
|
||||
public string ConfigureLink(string storeId, PayoutMethodId payoutMethodId, HttpRequest request)
|
||||
{
|
||||
|
@ -10,6 +10,7 @@ using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Routing;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Microsoft.Extensions.Localization;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace BTCPayServer.PayoutProcessors.OnChain;
|
||||
@ -20,18 +21,21 @@ public class OnChainAutomatedPayoutSenderFactory : EventHostedServiceBase, IPayo
|
||||
private readonly IServiceProvider _serviceProvider;
|
||||
private readonly LinkGenerator _linkGenerator;
|
||||
private readonly PayoutMethodId[] _supportedPayoutMethods;
|
||||
private IStringLocalizer StringLocalizer { get; }
|
||||
|
||||
public string FriendlyName { get; } = "Automated Bitcoin Sender";
|
||||
public string FriendlyName => StringLocalizer["Automated Bitcoin Sender"];
|
||||
public OnChainAutomatedPayoutSenderFactory(
|
||||
PayoutMethodHandlerDictionary handlers,
|
||||
EventAggregator eventAggregator,
|
||||
ILogger<OnChainAutomatedPayoutSenderFactory> logger,
|
||||
IStringLocalizer stringLocalizer,
|
||||
IServiceProvider serviceProvider, LinkGenerator linkGenerator) : base(eventAggregator, logger)
|
||||
{
|
||||
_handlers = handlers;
|
||||
_serviceProvider = serviceProvider;
|
||||
_linkGenerator = linkGenerator;
|
||||
_supportedPayoutMethods = _handlers.OfType<BitcoinLikePayoutHandler>().Select(c => c.PayoutMethodId).ToArray();
|
||||
StringLocalizer = stringLocalizer;
|
||||
}
|
||||
|
||||
public string Processor => ProcessorName;
|
||||
|
@ -22,7 +22,9 @@ namespace BTCPayServer.Plugins.PointOfSale.Models
|
||||
[Display(Name = "Display Title")]
|
||||
public string Title { get; set; }
|
||||
[MaxLength(5)]
|
||||
[Display(Name = "Currency")]
|
||||
public string Currency { get; set; }
|
||||
[Display(Name = "Template")]
|
||||
public string Template { get; set; }
|
||||
|
||||
[Display(Name = "Point of Sale Style")]
|
||||
@ -77,23 +79,11 @@ namespace BTCPayServer.Plugins.PointOfSale.Models
|
||||
public string SearchTerm { get; set; }
|
||||
|
||||
public SelectList RedirectAutomaticallySelectList =>
|
||||
new SelectList(new List<SelectListItem>()
|
||||
new(new List<SelectListItem>
|
||||
{
|
||||
new SelectListItem()
|
||||
{
|
||||
Text = "Yes",
|
||||
Value = "true"
|
||||
},
|
||||
new SelectListItem()
|
||||
{
|
||||
Text = "No",
|
||||
Value = "false"
|
||||
},
|
||||
new SelectListItem()
|
||||
{
|
||||
Text = "Use Store Settings",
|
||||
Value = ""
|
||||
}
|
||||
new() { Text = "Yes", Value = "true" },
|
||||
new() { Text = "No", Value = "false" },
|
||||
new() { Text = "Use Store Settings", Value = "" }
|
||||
}, nameof(SelectListItem.Value), nameof(SelectListItem.Text), RedirectAutomatically);
|
||||
|
||||
public string Description { get; set; }
|
||||
|
@ -3,6 +3,7 @@ using BTCPayServer.Client.Models;
|
||||
using BTCPayServer.Configuration;
|
||||
using BTCPayServer.Controllers;
|
||||
using Microsoft.AspNetCore.Routing;
|
||||
using Microsoft.Extensions.Localization;
|
||||
|
||||
namespace BTCPayServer.Services.Notifications.Blobs
|
||||
{
|
||||
@ -14,11 +15,13 @@ namespace BTCPayServer.Services.Notifications.Blobs
|
||||
{
|
||||
private readonly LinkGenerator _linkGenerator;
|
||||
private readonly BTCPayServerOptions _options;
|
||||
private IStringLocalizer StringLocalizer { get; }
|
||||
|
||||
public Handler(LinkGenerator linkGenerator, BTCPayServerOptions options)
|
||||
public Handler(LinkGenerator linkGenerator, BTCPayServerOptions options, IStringLocalizer stringLocalizer)
|
||||
{
|
||||
_linkGenerator = linkGenerator;
|
||||
_options = options;
|
||||
StringLocalizer = stringLocalizer;
|
||||
}
|
||||
|
||||
public override string NotificationType => TYPE;
|
||||
@ -27,7 +30,7 @@ namespace BTCPayServer.Services.Notifications.Blobs
|
||||
{
|
||||
get
|
||||
{
|
||||
return new (string identifier, string name)[] { (TYPE, "External payout approval") };
|
||||
return new (string identifier, string name)[] { (TYPE, StringLocalizer["External payout approval"]) };
|
||||
}
|
||||
}
|
||||
|
||||
@ -38,7 +41,7 @@ namespace BTCPayServer.Services.Notifications.Blobs
|
||||
vm.Type = notification.NotificationType;
|
||||
vm.StoreId = notification.StoreId;
|
||||
vm.Body =
|
||||
"A payment that was made to an approved payout by an external wallet is waiting for your confirmation.";
|
||||
StringLocalizer["A payment that was made to an approved payout by an external wallet is waiting for your confirmation."];
|
||||
vm.ActionLink = _linkGenerator.GetPathByAction(nameof(UIStorePullPaymentsController.Payouts),
|
||||
"UIStorePullPayments",
|
||||
new
|
||||
|
@ -3,6 +3,7 @@ using BTCPayServer.Configuration;
|
||||
using BTCPayServer.Controllers;
|
||||
using BTCPayServer.Data;
|
||||
using Microsoft.AspNetCore.Routing;
|
||||
using Microsoft.Extensions.Localization;
|
||||
|
||||
namespace BTCPayServer.Services.Notifications.Blobs;
|
||||
|
||||
@ -28,15 +29,16 @@ internal class InviteAcceptedNotification : BaseNotification
|
||||
StoreName = store.StoreName;
|
||||
}
|
||||
|
||||
internal class Handler(LinkGenerator linkGenerator, BTCPayServerOptions options)
|
||||
internal class Handler(LinkGenerator linkGenerator, BTCPayServerOptions options, IStringLocalizer stringLocalizer)
|
||||
: NotificationHandler<InviteAcceptedNotification>
|
||||
{
|
||||
private IStringLocalizer StringLocalizer { get; } = stringLocalizer;
|
||||
public override string NotificationType => TYPE;
|
||||
public override (string identifier, string name)[] Meta
|
||||
{
|
||||
get
|
||||
{
|
||||
return [(TYPE, "User accepted invitation")];
|
||||
return [(TYPE, StringLocalizer["User accepted invitation"])];
|
||||
}
|
||||
}
|
||||
|
||||
@ -45,7 +47,7 @@ internal class InviteAcceptedNotification : BaseNotification
|
||||
vm.Identifier = notification.Identifier;
|
||||
vm.Type = notification.NotificationType;
|
||||
vm.StoreId = notification.StoreId;
|
||||
vm.Body = $"User {notification.UserEmail} accepted the invite to {notification.StoreName}.";
|
||||
vm.Body = StringLocalizer["User {0} accepted the invite to {1}.", notification.UserEmail, notification.StoreName];
|
||||
vm.ActionLink = linkGenerator.GetPathByAction(nameof(UIStoresController.StoreUsers),
|
||||
"UIStores",
|
||||
new { storeId = notification.StoreId }, options.RootPath);
|
||||
|
@ -6,6 +6,7 @@ using BTCPayServer.Controllers;
|
||||
using BTCPayServer.Events;
|
||||
using ExchangeSharp;
|
||||
using Microsoft.AspNetCore.Routing;
|
||||
using Microsoft.Extensions.Localization;
|
||||
|
||||
namespace BTCPayServer.Services.Notifications.Blobs
|
||||
{
|
||||
@ -16,11 +17,13 @@ namespace BTCPayServer.Services.Notifications.Blobs
|
||||
{
|
||||
private readonly LinkGenerator _linkGenerator;
|
||||
private readonly BTCPayServerOptions _options;
|
||||
private IStringLocalizer StringLocalizer { get; }
|
||||
|
||||
public Handler(LinkGenerator linkGenerator, BTCPayServerOptions options)
|
||||
public Handler(LinkGenerator linkGenerator, BTCPayServerOptions options, IStringLocalizer stringLocalizer)
|
||||
{
|
||||
_linkGenerator = linkGenerator;
|
||||
_options = options;
|
||||
StringLocalizer = stringLocalizer;
|
||||
}
|
||||
|
||||
public override string NotificationType => TYPE;
|
||||
@ -29,25 +32,25 @@ namespace BTCPayServer.Services.Notifications.Blobs
|
||||
{
|
||||
get
|
||||
{
|
||||
return new (string identifier, string name)[] { (TYPE, "All invoice updates"), }
|
||||
.Concat(TextMapping.Select(pair => ($"{TYPE}_{pair.Key}", $"Invoice {pair.Value}"))).ToArray();
|
||||
return new (string identifier, string name)[] { (TYPE, StringLocalizer["All invoice updates"]), }
|
||||
.Concat(TextMapping.Select(pair => ($"{TYPE}_{pair.Key}", StringLocalizer["Invoice {0}", pair.Value].Value))).ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
internal static Dictionary<string, string> TextMapping = new Dictionary<string, string>()
|
||||
private Dictionary<string, string> TextMapping => new()
|
||||
{
|
||||
// {InvoiceEvent.PaidInFull, "was fully paid"},
|
||||
{InvoiceEvent.PaidAfterExpiration, "was paid after expiration"},
|
||||
{InvoiceEvent.ExpiredPaidPartial, "expired with partial payments"},
|
||||
{InvoiceEvent.FailedToConfirm, "has payments that failed to confirm on time"},
|
||||
// {InvoiceEvent.ReceivedPayment, "received a payment"},
|
||||
{InvoiceEvent.Confirmed, "is settled"}
|
||||
// {InvoiceEvent.PaidInFull, StringLocalizer["was fully paid"},
|
||||
{InvoiceEvent.PaidAfterExpiration, StringLocalizer["was paid after expiration"]},
|
||||
{InvoiceEvent.ExpiredPaidPartial, StringLocalizer["expired with partial payments"]},
|
||||
{InvoiceEvent.FailedToConfirm, StringLocalizer["has payments that failed to confirm on time"]},
|
||||
// {InvoiceEvent.ReceivedPayment, StringLocalizer["received a payment"},
|
||||
{InvoiceEvent.Confirmed, StringLocalizer["is settled"]}
|
||||
};
|
||||
|
||||
protected override void FillViewModel(InvoiceEventNotification notification,
|
||||
NotificationViewModel vm)
|
||||
{
|
||||
var baseStr = $"Invoice {notification.InvoiceId.Substring(0, 5)}..";
|
||||
var baseStr = StringLocalizer["Invoice {0}..", notification.InvoiceId.Substring(0, 5)];
|
||||
if (TextMapping.ContainsKey(notification.Event))
|
||||
{
|
||||
vm.Body = $"{baseStr} {TextMapping[notification.Event]}";
|
||||
@ -74,7 +77,12 @@ namespace BTCPayServer.Services.Notifications.Blobs
|
||||
|
||||
public static bool HandlesEvent(string invoiceEvent)
|
||||
{
|
||||
return Handler.TextMapping.Keys.Any(s => s == invoiceEvent);
|
||||
return ((string[])[
|
||||
InvoiceEvent.PaidAfterExpiration,
|
||||
InvoiceEvent.ExpiredPaidPartial,
|
||||
InvoiceEvent.FailedToConfirm,
|
||||
InvoiceEvent.Confirmed])
|
||||
.Any(s => s == invoiceEvent);
|
||||
}
|
||||
|
||||
public string InvoiceId { get; set; }
|
||||
|
@ -3,6 +3,7 @@ using BTCPayServer.Configuration;
|
||||
using BTCPayServer.Controllers;
|
||||
using BTCPayServer.Data;
|
||||
using Microsoft.AspNetCore.Routing;
|
||||
using Microsoft.Extensions.Localization;
|
||||
|
||||
namespace BTCPayServer.Services.Notifications.Blobs;
|
||||
|
||||
@ -28,11 +29,13 @@ internal class NewUserRequiresApprovalNotification : BaseNotification
|
||||
{
|
||||
private readonly LinkGenerator _linkGenerator;
|
||||
private readonly BTCPayServerOptions _options;
|
||||
private IStringLocalizer StringLocalizer { get; }
|
||||
|
||||
public Handler(LinkGenerator linkGenerator, BTCPayServerOptions options)
|
||||
public Handler(LinkGenerator linkGenerator, BTCPayServerOptions options, IStringLocalizer stringLocalizer)
|
||||
{
|
||||
_linkGenerator = linkGenerator;
|
||||
_options = options;
|
||||
StringLocalizer = stringLocalizer;
|
||||
}
|
||||
|
||||
public override string NotificationType => TYPE;
|
||||
@ -40,7 +43,7 @@ internal class NewUserRequiresApprovalNotification : BaseNotification
|
||||
{
|
||||
get
|
||||
{
|
||||
return [(TYPE, "New user requires approval")];
|
||||
return [(TYPE, StringLocalizer["New user requires approval"])];
|
||||
}
|
||||
}
|
||||
|
||||
@ -48,7 +51,7 @@ internal class NewUserRequiresApprovalNotification : BaseNotification
|
||||
{
|
||||
vm.Identifier = notification.Identifier;
|
||||
vm.Type = notification.NotificationType;
|
||||
vm.Body = $"New user {notification.UserEmail} requires approval.";
|
||||
vm.Body = StringLocalizer["New user {0} requires approval.", notification.UserEmail];
|
||||
vm.ActionLink = _linkGenerator.GetPathByAction(nameof(UIServerController.User),
|
||||
"UIServer",
|
||||
new { userId = notification.UserId }, _options.RootPath);
|
||||
|
@ -1,19 +1,20 @@
|
||||
using BTCPayServer.Abstractions.Contracts;
|
||||
using BTCPayServer.Models.NotificationViewModels;
|
||||
using Microsoft.Extensions.Localization;
|
||||
|
||||
namespace BTCPayServer.Services.Notifications.Blobs
|
||||
{
|
||||
internal class NewVersionNotification : BaseNotification
|
||||
{
|
||||
private const string TYPE = "newversion";
|
||||
internal class Handler : NotificationHandler<NewVersionNotification>
|
||||
internal class Handler(IStringLocalizer stringLocalizer) : NotificationHandler<NewVersionNotification>
|
||||
{
|
||||
private IStringLocalizer StringLocalizer { get; } = stringLocalizer;
|
||||
public override string NotificationType => TYPE;
|
||||
public override (string identifier, string name)[] Meta
|
||||
{
|
||||
get
|
||||
{
|
||||
return new (string identifier, string name)[] { (TYPE, "New version") };
|
||||
return [(TYPE, StringLocalizer["New version"])];
|
||||
}
|
||||
}
|
||||
|
||||
@ -21,7 +22,7 @@ namespace BTCPayServer.Services.Notifications.Blobs
|
||||
{
|
||||
vm.Identifier = notification.Identifier;
|
||||
vm.Type = notification.NotificationType;
|
||||
vm.Body = $"New version {notification.Version} released!";
|
||||
vm.Body = StringLocalizer["New version {0} released!", notification.Version];
|
||||
vm.ActionLink = $"https://github.com/btcpayserver/btcpayserver/releases/tag/v{notification.Version}";
|
||||
}
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ using BTCPayServer.Configuration;
|
||||
using BTCPayServer.Controllers;
|
||||
using ExchangeSharp;
|
||||
using Microsoft.AspNetCore.Routing;
|
||||
using Microsoft.Extensions.Localization;
|
||||
|
||||
namespace BTCPayServer.Services.Notifications.Blobs
|
||||
{
|
||||
@ -16,11 +17,13 @@ namespace BTCPayServer.Services.Notifications.Blobs
|
||||
{
|
||||
private readonly LinkGenerator _linkGenerator;
|
||||
private readonly BTCPayServerOptions _options;
|
||||
private IStringLocalizer StringLocalizer { get; }
|
||||
|
||||
public Handler(LinkGenerator linkGenerator, BTCPayServerOptions options)
|
||||
public Handler(LinkGenerator linkGenerator, BTCPayServerOptions options, IStringLocalizer stringLocalizer)
|
||||
{
|
||||
_linkGenerator = linkGenerator;
|
||||
_options = options;
|
||||
StringLocalizer = stringLocalizer;
|
||||
}
|
||||
|
||||
public override string NotificationType => TYPE;
|
||||
@ -28,7 +31,7 @@ namespace BTCPayServer.Services.Notifications.Blobs
|
||||
{
|
||||
get
|
||||
{
|
||||
return new (string identifier, string name)[] { (TYPE, "Payouts") };
|
||||
return [(TYPE, StringLocalizer["Payouts"])];
|
||||
}
|
||||
}
|
||||
|
||||
@ -39,8 +42,8 @@ namespace BTCPayServer.Services.Notifications.Blobs
|
||||
vm.StoreId = notification.StoreId;
|
||||
vm.Body = (notification.Status ?? PayoutState.AwaitingApproval) switch
|
||||
{
|
||||
PayoutState.AwaitingApproval => "A new payout is awaiting for approval",
|
||||
PayoutState.AwaitingPayment => "A new payout is approved and awaiting payment",
|
||||
PayoutState.AwaitingApproval => StringLocalizer["A new payout is awaiting for approval"],
|
||||
PayoutState.AwaitingPayment => StringLocalizer["A new payout is approved and awaiting payment"],
|
||||
_ => throw new ArgumentOutOfRangeException()
|
||||
};
|
||||
vm.ActionLink = _linkGenerator.GetPathByAction(nameof(UIStorePullPaymentsController.Payouts),
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -67,7 +67,7 @@
|
||||
{
|
||||
<th class="text-end">
|
||||
<span text-translate="true">Network Fee</span>
|
||||
<a href="https://docs.btcpayserver.org/FAQ/Stores/#allow-anyone-to-create-invoice" target="_blank" rel="noreferrer noopener" title="More information...">
|
||||
<a href="https://docs.btcpayserver.org/FAQ/Stores/#allow-anyone-to-create-invoice" target="_blank" rel="noreferrer noopener" title="@StringLocalizer["More information..."]">
|
||||
<vc:icon symbol="info" />
|
||||
</a>
|
||||
</th>
|
||||
|
@ -11,7 +11,7 @@
|
||||
<h5 class="modal-title">
|
||||
{{title}}
|
||||
</h5>
|
||||
<button type="button" class="btn-close" aria-label="Close" v-on:click="close">
|
||||
<button type="button" class="btn-close" aria-label="@StringLocalizer["Close"]" v-on:click="close">
|
||||
<vc:icon symbol="close"/>
|
||||
</button>
|
||||
</div>
|
||||
@ -255,15 +255,15 @@ function initCameraScanningApp(title, onDataSubmit, modalId, submitOnScan = fals
|
||||
if (error.name === 'StreamApiNotSupportedError') {
|
||||
this.noStreamApiSupport = true;
|
||||
} else if (error.name === 'NotAllowedError') {
|
||||
this.errorMessage = 'A permission to the camera is needed to scan the QR code. Please grant the browser access and then retry.'
|
||||
this.errorMessage = @StringLocalizer["A permission to the camera is needed to scan the QR code. Please grant the browser access and then retry."]
|
||||
} else if (error.name === 'NotFoundError') {
|
||||
this.errorMessage = 'A camera was not detected on your device.'
|
||||
this.errorMessage = @StringLocalizer["A camera was not detected on your device."]
|
||||
} else if (error.name === 'NotSupportedError') {
|
||||
this.errorMessage = 'This page is served in non-secure context (HTTPS, localhost or file://)'
|
||||
this.errorMessage = @StringLocalizer["This page is served in non-secure context (HTTPS, localhost or file://)"]
|
||||
} else if (error.name === 'NotReadableError') {
|
||||
this.errorMessage = 'Couldn\'t access your camera. Is it already in use?'
|
||||
this.errorMessage = @StringLocalizer["Could not access your camera. Is it already in use?"]
|
||||
} else if (error.name === 'OverconstrainedError') {
|
||||
this.errorMessage = 'Constraints don\'t match any installed camera.'
|
||||
this.errorMessage = @StringLocalizer["Constraints do not match any installed camera."]
|
||||
} else {
|
||||
this.errorMessage = 'UNKNOWN ERROR: ' + error.message
|
||||
}
|
||||
|
@ -4,15 +4,15 @@
|
||||
string actionUrl = null;
|
||||
if (Model.ActionName is not null)
|
||||
{
|
||||
var controllerName = Model.ControllerName ?? ((Microsoft.AspNetCore.Mvc.Controllers.ControllerActionDescriptor)this.Url.ActionContext.ActionDescriptor).ControllerName;
|
||||
actionUrl = linkGenerator.GetPathByAction(Model.ActionName, controllerName, pathBase: this.Context.Request.PathBase);
|
||||
var controllerName = Model.ControllerName ?? ((Microsoft.AspNetCore.Mvc.Controllers.ControllerActionDescriptor)Url.ActionContext.ActionDescriptor).ControllerName;
|
||||
actionUrl = linkGenerator.GetPathByAction(Model.ActionName, controllerName, pathBase: Context.Request.PathBase);
|
||||
}
|
||||
}
|
||||
<div class="modal-dialog modal-dialog-centered">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h4 class="modal-title" id="ConfirmTitle">@Model.Title</h4>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close">
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="@StringLocalizer["Close"]">
|
||||
<vc:icon symbol="close" />
|
||||
</button>
|
||||
</div>
|
||||
|
@ -249,7 +249,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</noscript>
|
||||
<b-modal title="Contribute" v-model="contributeModalOpen" size="lg" ok-only="true" ok-variant="secondary" ok-title="Close" ref="modalContribute">
|
||||
<b-modal title="Contribute" v-model="contributeModalOpen" size="lg" ok-only="true" ok-variant="secondary" ok-title="@StringLocalizer["Close"]" ref="modalContribute">
|
||||
<contribute v-if="contributeModalOpen"
|
||||
:target-currency="srvModel.targetCurrency"
|
||||
:active="active"
|
||||
@ -330,7 +330,7 @@
|
||||
:readonly="perk.priceType === 'Fixed'"
|
||||
:min="perk.price"
|
||||
step="any"
|
||||
placeholder="Contribution Amount"
|
||||
placeholder="@StringLocalizer["Contribution Amount"]"
|
||||
required>
|
||||
<span class="input-group-text">{{targetCurrency}}</span>
|
||||
</template>
|
||||
|
@ -11,7 +11,7 @@
|
||||
@inject BTCPayServer.Security.ContentSecurityPolicies Csp
|
||||
@model BTCPayServer.Plugins.Crowdfund.Models.UpdateCrowdfundViewModel
|
||||
@{
|
||||
ViewData.SetActivePage(AppsNavPages.Update, "Update Crowdfund", Model.AppId);
|
||||
ViewData.SetActivePage(AppsNavPages.Update, StringLocalizer["Update Crowdfund"], Model.AppId);
|
||||
Csp.UnsafeEval();
|
||||
var canUpload = await FileService.IsAvailable();
|
||||
var checkoutFormOptions = await FormDataService.GetSelect(Model.StoreId, Model.FormId);
|
||||
@ -35,11 +35,11 @@
|
||||
<button id="page-primary" type="submit" class="btn btn-primary order-sm-1">Save</button>
|
||||
@if (Model.Archived)
|
||||
{
|
||||
<button type="submit" class="btn btn-outline-secondary" name="Archived" value="False">Unarchive</button>
|
||||
<button type="submit" class="btn btn-outline-secondary" name="Archived" value="False" text-translate="true">Unarchive</button>
|
||||
}
|
||||
else if (Model.ModelWithMinimumData)
|
||||
{
|
||||
<a class="btn btn-secondary" asp-controller="UICrowdfund" asp-action="ViewCrowdfund" asp-route-appId="@Model.AppId" id="ViewApp" target="_blank">View</a>
|
||||
<a class="btn btn-secondary" asp-controller="UICrowdfund" asp-action="ViewCrowdfund" asp-route-appId="@Model.AppId" id="ViewApp" target="_blank" text-translate="true">View</a>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
@ -82,7 +82,7 @@
|
||||
@if (!string.IsNullOrEmpty(Model.MainImageUrl))
|
||||
{
|
||||
<button type="submit" class="btn btn-link p-0 text-danger" name="RemoveLogoFile" value="true">
|
||||
<vc:icon symbol="cross" /> Remove
|
||||
<vc:icon symbol="cross" /> <span text-translate="true">Remove</span>
|
||||
</button>
|
||||
}
|
||||
</div>
|
||||
@ -100,7 +100,7 @@
|
||||
else
|
||||
{
|
||||
<input asp-for="MainImageFile" type="file" class="form-control" disabled>
|
||||
<div class="form-text">In order to upload an image, a <a asp-controller="UIServer" asp-action="Files">file storage</a> must be configured.</div>
|
||||
<div class="form-text">@ViewLocalizer["In order to upload, a {0} must be configured.", Html.ActionLink(StringLocalizer["file storage"], "Files", "UIServer")]</div>
|
||||
}
|
||||
</div>
|
||||
<div class="form-group">
|
||||
@ -136,7 +136,7 @@
|
||||
<div class="form-group">
|
||||
<label asp-for="TargetCurrency" class="form-label"></label>
|
||||
<input asp-for="TargetCurrency" class="form-control w-auto" currency-selection />
|
||||
<div class="form-text">Uses the store's default currency (@Model.StoreDefaultCurrency) if empty.</div>
|
||||
<div class="form-text">@StringLocalizer["Uses the store's default currency ({0}) if empty.", @Model.StoreDefaultCurrency]</div>
|
||||
<span asp-validation-for="TargetCurrency" class="text-danger"></span>
|
||||
</div>
|
||||
</div>
|
||||
@ -147,7 +147,7 @@
|
||||
<input type="datetime-local" asp-for="StartDate"
|
||||
value="@(Model.StartDate?.ToString("u", CultureInfo.InvariantCulture))"
|
||||
class="form-control flatdtpicker"
|
||||
placeholder="No start date has been set" />
|
||||
placeholder="@StringLocalizer["No start date has been set"]" />
|
||||
<button class="btn btn-secondary input-group-clear px-3" type="button" title="Clear">
|
||||
<vc:icon symbol="close"/>
|
||||
</button>
|
||||
@ -159,7 +159,7 @@
|
||||
<input type="datetime-local" asp-for="EndDate"
|
||||
value="@(Model.EndDate?.ToString("u", CultureInfo.InvariantCulture))"
|
||||
class="form-control flatdtpicker"
|
||||
placeholder="No end date has been set" />
|
||||
placeholder="@StringLocalizer["No end date has been set"]" />
|
||||
<button class="btn btn-secondary input-group-clear px-3" type="button" title="Clear">
|
||||
<vc:icon symbol="close"/>
|
||||
</button>
|
||||
@ -183,7 +183,7 @@
|
||||
<div class="form-group mb-0 pt-2 w-250px">
|
||||
<label asp-for="ResetEveryAmount" class="form-label"></label>
|
||||
<div class="d-flex align-items-center">
|
||||
<input type="number" inputmode="numeric" asp-for="ResetEveryAmount" placeholder="Amount" class="form-control me-3" min="0">
|
||||
<input type="number" inputmode="numeric" asp-for="ResetEveryAmount" placeholder="@StringLocalizer["Amount"]" class="form-control me-3" min="0">
|
||||
<select class="form-select w-auto" asp-for="ResetEvery">
|
||||
@foreach (var opt in Model.ResetEveryValues)
|
||||
{
|
||||
|
@ -36,7 +36,7 @@
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label asp-for="Settings.From" class="form-label" text-translate="true">Sender's Email Address</label>
|
||||
<input asp-for="Settings.From" class="form-control" placeholder="Firstname Lastname <email@example.com>" />
|
||||
<input asp-for="Settings.From" class="form-control" placeholder="@StringLocalizer["Firstname Lastname <email@example.com>"]" />
|
||||
<span asp-validation-for="Settings.From" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
@ -55,8 +55,8 @@
|
||||
else
|
||||
{
|
||||
<div class="input-group">
|
||||
<input value="Configured" type="text" readonly class="form-control"/>
|
||||
<button type="submit" class="btn btn-danger" name="command" value="ResetPassword" id="ResetPassword">Reset</button>
|
||||
<input value="@StringLocalizer["Configured"]" type="text" readonly class="form-control"/>
|
||||
<button type="submit" class="btn btn-danger" name="command" value="ResetPassword" id="ResetPassword" text-translate="true">Reset</button>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
@ -5,7 +5,7 @@
|
||||
<div class="col-xl-10 col-xxl-constrain">
|
||||
<div class="form-group">
|
||||
<label asp-for="TestEmail" class="form-label" text-translate="true">To test your settings, enter an email address</label>
|
||||
<input asp-for="TestEmail" placeholder="Firstname Lastname <email@example.com>" class="form-control" />
|
||||
<input asp-for="TestEmail" placeholder="@StringLocalizer["Firstname Lastname <email@example.com>"]" class="form-control" />
|
||||
<span asp-validation-for="TestEmail" class="text-danger"></span>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-secondary mt-2" name="command" value="Test" id="Test" text-translate="true">Send Test Email</button>
|
||||
|
@ -7,9 +7,9 @@
|
||||
var storeId = Context.GetRouteValue("storeId") as string;
|
||||
var controller = ViewContext.RouteData.Values["controller"].ToString().TrimEnd("Controller", StringComparison.InvariantCultureIgnoreCase);
|
||||
if (string.IsNullOrEmpty(storeId))
|
||||
ViewData.SetActivePage(ServerNavPages.Roles);
|
||||
ViewData.SetActivePage(ServerNavPages.Roles, StringLocalizer["Roles"]);
|
||||
else
|
||||
ViewData.SetActivePage(StoreNavPages.Roles);
|
||||
ViewData.SetActivePage(StoreNavPages.Roles, StringLocalizer["Roles"]);
|
||||
var permission = string.IsNullOrEmpty(storeId) ? Policies.CanModifyServerSettings : Policies.CanModifyStoreSettings;
|
||||
var nextRoleSortOrder = (string) ViewData["NextRoleSortOrder"];
|
||||
var roleSortOrder = nextRoleSortOrder switch
|
||||
@ -19,8 +19,8 @@
|
||||
_ => null
|
||||
};
|
||||
|
||||
const string sortByDesc = "Sort by name descending...";
|
||||
const string sortByAsc = "Sort by name ascending...";
|
||||
var sortByDesc = StringLocalizer["Sort by name descending..."];
|
||||
var sortByAsc = StringLocalizer["Sort by name ascending..."];
|
||||
var showInUseColumn = !Model.Roles.Any(r => r.IsUsed is null);
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
<div id="walletAlert" class="alert alert-warning alert-dismissible my-4" style="display:none;" role="alert">
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close">
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="@StringLocalizer["Close"]">
|
||||
<vc:icon symbol="close" />
|
||||
</button>
|
||||
<span id="alertMessage"></span>
|
||||
|
@ -1,6 +1,7 @@
|
||||
<div class="alert alert-warning alert-dismissible">
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close">
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="@StringLocalizer["Close"]">
|
||||
<vc:icon symbol="close" />
|
||||
</button>
|
||||
The Email settings have not been configured on this server or store yet. Setting this field will not send emails until then. <a asp-action="StoreEmailSettings" asp-controller="UIStores" asp-route-storeId="@Model" class="alert-link">Configure store email settings</a>
|
||||
<span text-translate="true">The Email settings have not been configured on this server or store yet. Setting this field will not send emails until then.</span>
|
||||
<a asp-action="StoreEmailSettings" asp-controller="UIStores" asp-route-storeId="@Model" class="alert-link" text-translate="true">Configure store email settings</a>
|
||||
</div>
|
||||
|
@ -1,4 +1,7 @@
|
||||
@using BTCPayServer.TagHelpers
|
||||
@using BTCPayServer.Views.Stores
|
||||
@using Microsoft.AspNetCore.Html
|
||||
@using Microsoft.AspNetCore.Mvc.TagHelpers
|
||||
@{
|
||||
ViewData.SetActivePage(StoreNavPages.PayButton, "Pay Button", Context.GetStoreData().Id);
|
||||
}
|
||||
@ -12,25 +15,20 @@
|
||||
<div class="row">
|
||||
<div class="col-xl-8 col-xxl-constrain">
|
||||
<div class="alert alert-warning alert-dismissible mb-4" role="alert">
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close">
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="@StringLocalizer["Close"]">
|
||||
<vc:icon symbol="close" />
|
||||
</button>
|
||||
<h5 class="alert-heading">Warning: Payment button should only be used for tips and donations</h5>
|
||||
<h5 class="alert-heading" text-translate="true">Warning: Payment button should only be used for tips and donations</h5>
|
||||
<p>
|
||||
Using the payment button for e-commerce integrations is not recommended since order relevant information can be modified by the user.
|
||||
For e-commerce, you should use our
|
||||
<a href="https://docs.btcpayserver.org/API/Greenfield/v1/" class="alert-link" target="_blank" rel="noreferrer noopener">Greenfield API</a>.
|
||||
If this store process commercial transactions, we advise you to
|
||||
<a asp-controller="UIUserStores" asp-action="CreateStore" class="alert-link">create a separate store</a> before using the payment button.
|
||||
@ViewLocalizer["Using the payment button for e-commerce integrations is not recommended since order relevant information can be modified by the user. For e-commerce, you should use our {0}. If this store process commercial transactions, we advise you to {1} before using the payment button.",
|
||||
Html.ActionLink(StringLocalizer["Greenfield API"], "SwaggerDocs", "UIHome", new { }, new { @class = "alert-link" }),
|
||||
Html.ActionLink(StringLocalizer["create a separate store"], "CreateStore", "UIUserStores", new { }, new { @class = "alert-link" })]
|
||||
</p>
|
||||
</div>
|
||||
<p>
|
||||
To start using Pay Button, you need to enable this feature explicitly.
|
||||
Once you do so, anyone could create an invoice on your store (via API, for example).
|
||||
</p>
|
||||
<p text-translate="true">To start using Pay Button, you need to enable this feature explicitly. Once you do so, anyone could create an invoice on your store (via API, for example).</p>
|
||||
<form method="post">
|
||||
@Html.Hidden("EnableStore", true)
|
||||
<button name="command" id="enable-pay-button" type="submit" value="save" class="btn btn-primary">
|
||||
<button name="command" id="enable-pay-button" type="submit" value="save" class="btn btn-primary" text-translate="true">
|
||||
Enable
|
||||
</button>
|
||||
</form>
|
||||
|
@ -1,4 +1,5 @@
|
||||
@using BTCPayServer.Views.Stores
|
||||
@using Microsoft.AspNetCore.Html
|
||||
@inject Security.ContentSecurityPolicies Csp
|
||||
@inject BTCPayNetworkProvider NetworkProvider
|
||||
@model BTCPayServer.Plugins.PayButton.Models.PayButtonViewModel
|
||||
@ -184,77 +185,75 @@
|
||||
<div class="row">
|
||||
<div class="col-xl-8">
|
||||
<div class="alert alert-warning alert-dismissible mb-4" role="alert">
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close">
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="@StringLocalizer["Close"]">
|
||||
<vc:icon symbol="close" />
|
||||
</button>
|
||||
<h5 class="alert-heading">Warning: Payment button should only be used for tips and donations</h5>
|
||||
<h5 class="alert-heading" text-translate="true">Warning: Payment button should only be used for tips and donations</h5>
|
||||
<p>
|
||||
Using the payment button for e-commerce integrations is not recommended since order relevant information can be modified by the user.
|
||||
For e-commerce, you should use our
|
||||
<a href="https://docs.btcpayserver.org/API/Greenfield/v1/" class="alert-link" target="_blank" rel="noreferrer noopener">Greenfield API</a>.
|
||||
If this store process commercial transactions, we advise you to
|
||||
<a asp-controller="UIUserStores" asp-action="CreateStore" class="alert-link">create a separate store</a> before using the payment button.
|
||||
@ViewLocalizer["Using the payment button for e-commerce integrations is not recommended since order relevant information can be modified by the user. For e-commerce, you should use our {0}. If this store process commercial transactions, we advise you to {1} before using the payment button.",
|
||||
Html.ActionLink(StringLocalizer["Greenfield API"], "SwaggerDocs", "UIHome", new { }, new { @class = "alert-link" }),
|
||||
Html.ActionLink(StringLocalizer["create a separate store"], "CreateStore", "UIUserStores", new { }, new { @class = "alert-link" })]
|
||||
</p>
|
||||
<form asp-action="DisableAnyoneCanCreateInvoice" asp-route-storeId="@Context.GetRouteValue("storeId")" method="post">
|
||||
<button name="command" id="disable-pay-button" type="submit" class="btn btn-danger mt-0" value="Save">Disable payment button</button>
|
||||
<button name="command" id="disable-pay-button" type="submit" class="btn btn-danger mt-0" value="Save" text-translate="true">Disable payment button</button>
|
||||
</form>
|
||||
</div>
|
||||
<p>Configure your Pay Button, and the generated code will be displayed at the bottom of the page to copy into your project.</p>
|
||||
<h4 class="mt-3 mb-3">General Settings</h4>
|
||||
<p text-translate="true">Configure your Pay Button, and the generated code will be displayed at the bottom of the page to copy into your project.</p>
|
||||
<h4 class="mt-3 mb-3" text-translate="true">General Settings</h4>
|
||||
<div class="form-group col-md-8">
|
||||
<label class="form-label" for="price">Price</label>
|
||||
<label class="form-label" for="price" text-translate="true">Price</label>
|
||||
<input name="price" type="text" class="form-control" id="price" inputmode="decimal"
|
||||
v-model="srvModel.price" v-on:change="inputChanges"
|
||||
v-validate="'decimal|min_value:0'" :class="{'is-invalid': errors.has('price') }">
|
||||
<small class="text-danger">{{ errors.first('price') }}</small>
|
||||
</div>
|
||||
<div class="form-group col-md-4" v-if="!srvModel.appIdEndpoint">
|
||||
<label class="form-label" for="Currency">Currency</label>
|
||||
<label class="form-label" for="Currency" text-translate="true">Currency</label>
|
||||
<input asp-for="Currency" name="currency" class="form-control w-auto" currency-selection
|
||||
v-model="srvModel.currency" v-on:change="inputChanges"
|
||||
:class="{'is-invalid': errors.has('currency') }" />
|
||||
</div>
|
||||
<div class="form-group col-md-4" v-if="!srvModel.appIdEndpoint">
|
||||
<label class="form-label" for="defaultPaymentMethod">Default Payment Method</label>
|
||||
<label class="form-label" for="defaultPaymentMethod" text-translate="true">Default Payment Method</label>
|
||||
<select v-model="srvModel.defaultPaymentMethod" v-on:change="inputChanges" class="form-select" id="default-payment-method">
|
||||
<option value="" selected>Use the store’s default</option>
|
||||
<option value="" selected text-translate="true">Use the store’s default</option>
|
||||
<option v-for="pm in srvModel.paymentMethods" v-bind:value="pm.value">{{pm.name}}</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group" v-if="!srvModel.appIdEndpoint">
|
||||
<label class="form-label" for="description">Checkout Description</label>
|
||||
<label class="form-label" for="description" text-translate="true">Checkout Description</label>
|
||||
<input name="checkoutDesc" type="text" class="form-control" id="description"
|
||||
v-model="srvModel.checkoutDesc" v-on:change="inputChanges">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="form-label" for="order-id">Order ID</label>
|
||||
<label class="form-label" for="order-id" text-translate="true">Order ID</label>
|
||||
<input name="orderId" type="text" class="form-control" id="order-id"
|
||||
v-model="srvModel.orderId" v-on:change="inputChanges">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h4 class="mt-5 mb-3">Display Options</h4>
|
||||
<h4 class="mt-5 mb-3" text-translate="true">Display Options</h4>
|
||||
<div class="row">
|
||||
<div class="col-xl-8 col-xxl-constrain">
|
||||
<div class="form-group">
|
||||
<div class="form-check" v-if="!srvModel.appIdEndpoint">
|
||||
<input id="useModal" type="checkbox" v-model="srvModel.useModal" v-on:change="inputChanges" class="form-check-input"/>
|
||||
<label for="useModal" class="form-check-label">Use Modal</label>
|
||||
<label for="useModal" class="form-check-label" text-translate="true">Use Modal</label>
|
||||
</div>
|
||||
<div class="form-check">
|
||||
<input id="buttonInlineTextMode" type="checkbox" v-model="buttonInlineTextMode" v-on:change="inputChanges" class="form-check-input"/>
|
||||
<label for="buttonInlineTextMode" class="form-check-label">Customize Pay Button Text</label>
|
||||
<label for="buttonInlineTextMode" class="form-check-label" text-translate="true">Customize Pay Button Text</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group" v-show="buttonInlineTextMode">
|
||||
<label class="form-label" for="pb-text">Pay Button Text</label>
|
||||
<label class="form-label" for="pb-text" text-translate="true">Pay Button Text</label>
|
||||
<input name="payButtonText" type="text" class="form-control" id="pb-text"
|
||||
v-model="srvModel.payButtonText" v-on:change="inputChanges">
|
||||
</div>
|
||||
<div class="form-group mb-4">
|
||||
<label class="form-label" for="pb-image-url">Pay Button Image Url</label>
|
||||
<label class="form-label" for="pb-image-url" text-translate="true">Pay Button Image Url</label>
|
||||
<input name="payButtonImageUrl" type="text" class="form-control" id="pb-image-url"
|
||||
v-model="srvModel.payButtonImageUrl" v-on:change="inputChanges"
|
||||
v-validate="{ required: this.imageUrlRequired, url: {require_tld:false} }"
|
||||
@ -262,7 +261,7 @@
|
||||
<small class="text-danger">{{ errors.first('payButtonImageUrl') }}</small>
|
||||
</div>
|
||||
<div class="form-group mb-4">
|
||||
<label class="form-label">Image Size</label>
|
||||
<label class="form-label" text-translate="true">Image Size</label>
|
||||
<div class="btn-group d-flex" role="group">
|
||||
<button type="button" class="btn btn-outline-secondary"
|
||||
v-on:click="inputChanges($event, 0)">146 x 40 px</button>
|
||||
@ -273,37 +272,37 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="form-label">Button Type</label>
|
||||
<label class="form-label" text-translate="true">Button Type</label>
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="radio" name="button-type" id="btn-fixed" value="0" v-model="srvModel.buttonType" v-on:change="inputChanges" checked/>
|
||||
<label for="btn-fixed" class="form-check-label">Fixed amount</label>
|
||||
<label for="btn-fixed" class="form-check-label" text-translate="true">Fixed amount</label>
|
||||
</div>
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="radio" name="button-type" id="btn-custom" value="1" v-model="srvModel.buttonType" v-on:change="inputChanges"/>
|
||||
<label for="btn-custom" class="form-check-label">Custom amount</label>
|
||||
<label for="btn-custom" class="form-check-label" text-translate="true">Custom amount</label>
|
||||
</div>
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="radio" name="button-type" id="btn-slider" value="2" v-model="srvModel.buttonType" v-on:change="inputChanges"/>
|
||||
<label for="btn-slider" class="form-check-label">Slider</label>
|
||||
<label for="btn-slider" class="form-check-label" text-translate="true">Slider</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row" v-if="srvModel.buttonType === '1' ||srvModel.buttonType === '2'">
|
||||
<div class="form-group col-md-4">
|
||||
<label class="form-label" for="pb-min">Min</label>
|
||||
<label class="form-label" for="pb-min" text-translate="true">Min</label>
|
||||
<input name="min" type="text" class="form-control" id="pb-min"
|
||||
v-model="srvModel.min" v-on:change="inputChanges"
|
||||
v-validate="'required|decimal|min_value:0'" :class="{'is-invalid': errors.has('min') }">
|
||||
<small class="text-danger">{{ errors.first('min') }}</small>
|
||||
</div>
|
||||
<div class="form-group col-md-4">
|
||||
<label class="form-label" for="pb-max">Max</label>
|
||||
<label class="form-label" for="pb-max" text-translate="true">Max</label>
|
||||
<input name="max" type="text" class="form-control" id="pb-max"
|
||||
v-model="srvModel.max" v-on:change="inputChanges"
|
||||
v-validate="'required|decimal'" :class="{'is-invalid': errors.has('max') }">
|
||||
<small class="text-danger">{{ errors.first('max') }}</small>
|
||||
</div>
|
||||
<div class="form-group col-md-4">
|
||||
<label class="form-label" for="pb-step">Step</label>
|
||||
<label class="form-label" for="pb-step" text-translate="true">Step</label>
|
||||
<input name="step" type="text" class="form-control" id="pb-step"
|
||||
v-model="srvModel.step" v-on:change="inputChanges"
|
||||
v-validate="'required'" :class="{'is-invalid': errors.has('step') }">
|
||||
@ -319,7 +318,7 @@
|
||||
v-model="srvModel.simpleInput"
|
||||
v-on:change="inputChanges"
|
||||
:class="{'is-invalid': errors.has('simpleInput') }">
|
||||
<label class="form-check-label" for="simpleInput">Use a simple input style</label>
|
||||
<label class="form-check-label" for="simpleInput" text-translate="true">Use a simple input style</label>
|
||||
<small class="text-danger">{{ errors.first('simpleInput') }}</small>
|
||||
</div>
|
||||
<div class="form-check">
|
||||
@ -330,57 +329,54 @@
|
||||
v-model="srvModel.fitButtonInline"
|
||||
v-on:change="inputChanges"
|
||||
:class="{'is-invalid': errors.has('fitButtonInline') }">
|
||||
<label class="form-check-label" for="fitButtonInline">Fit button inline</label>
|
||||
<label class="form-check-label" for="fitButtonInline" text-translate="true">Fit button inline</label>
|
||||
<small class="text-danger">{{ errors.first('fitButtonInline') }}</small>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
<div class="col-xl-4 mt-4 mt-xl-0">
|
||||
<h5 class="mb-3">Preview</h5>
|
||||
<h5 class="mb-3" text-translate="true">Preview</h5>
|
||||
<div id="preview"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h4 class="mt-5 mb-3">Payment Notifications</h4>
|
||||
<h4 class="mt-5 mb-3" text-translate="true">Payment Notifications</h4>
|
||||
<div class="row">
|
||||
<div class="col-xl-8 col-xxl-constrain">
|
||||
<div class="form-group">
|
||||
<label class="form-label" for="server-ipn">Server IPN</label>
|
||||
<label class="form-label" for="server-ipn" text-translate="true">Server IPN</label>
|
||||
<input name="serverIpn" type="text" class="form-control" id="server-ipn"
|
||||
v-model="srvModel.serverIpn" v-on:change="inputChanges"
|
||||
v-validate="'url'" :class="{'is-invalid': errors.has('serverIpn') }">
|
||||
<small class="text-danger">{{ errors.first('serverIpn') }}</small>
|
||||
<div class="form-text">The URL to post purchase data.</div>
|
||||
<div class="form-text" text-translate="true">The URL to post purchase data.</div>
|
||||
</div>
|
||||
<div class="form-group" v-if="!srvModel.appIdEndpoint">
|
||||
<label class="form-label" for="email-notifications">Email Notifications</label>
|
||||
<label class="form-label" for="email-notifications" text-translate="true">Email Notifications</label>
|
||||
<input name="notifyEmail" type="text" class="form-control" id="email-notifications"
|
||||
placeholder="name@domain.com"
|
||||
placeholder="@StringLocalizer["user@example.com"]"
|
||||
v-model="srvModel.notifyEmail" v-on:change="inputChanges"
|
||||
v-validate="'email'" :class="{'is-invalid': errors.has('notifyEmail') }">
|
||||
<small class="text-danger">{{ errors.first('notifyEmail') }}</small>
|
||||
<div class="form-text">Receive email notification updates.</div>
|
||||
<div class="form-text" text-translate="true">Receive email notification updates.</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="form-label" for="browser-redirect">Browser Redirect</label>
|
||||
<label class="form-label" for="browser-redirect" text-translate="true">Browser Redirect</label>
|
||||
<input name="browserRedirect" type="text" class="form-control" id="browser-redirect"
|
||||
v-model="srvModel.browserRedirect" v-on:change="inputChanges"
|
||||
v-validate="'url'" :class="{'is-invalid': errors.has('browserRedirect') }">
|
||||
<small class="text-danger">{{ errors.first('browserRedirect') }}</small>
|
||||
<div class="form-text">Where to redirect the customer after payment is complete</div>
|
||||
<div class="form-text" text-translate="true">Where to redirect the customer after payment is complete</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h4 class="mt-5 mb-3">Advanced Options</h4>
|
||||
<h4 class="mt-5 mb-3" text-translate="true">Advanced Options</h4>
|
||||
<div class="row" v-if="!srvModel.appIdEndpoint">
|
||||
<div class="col-xl-8 col-xxl-constrain">
|
||||
<p>
|
||||
Specify additional query string parameters that should be appended to the checkout page once the invoice is created.
|
||||
For example, <code>lang=da-DK</code> would load the checkout page in Danish by default.
|
||||
</p>
|
||||
<p>@ViewLocalizer["Specify additional query string parameters that should be appended to the checkout page once the invoice is created. For example, <code>lang=da-DK</code> would load the checkout page in Danish by default."]</p>
|
||||
<div class="form-group">
|
||||
<label class="form-label" for="query-string">Checkout Additional Query String</label>
|
||||
<label class="form-label" for="query-string" text-translate="true">Checkout Additional Query String</label>
|
||||
<input name="checkoutQueryString" type="text" class="form-control" id="query-string"
|
||||
v-model="srvModel.checkoutQueryString" v-on:change="inputChanges"
|
||||
:class="{'is-invalid': errors.has('checkoutQueryString') }">
|
||||
@ -391,17 +387,17 @@
|
||||
|
||||
<div class="row">
|
||||
<div class="col-xl-8 col-xxl-constrain">
|
||||
<p>Link this Pay Button to an app instead. Some features are disabled due to the different endpoint capabilities. You can set which perk/item this button should be targeting.</p>
|
||||
<p text-translate="true">Link this Pay Button to an app instead. Some features are disabled due to the different endpoint capabilities. You can set which perk/item this button should be targeting.</p>
|
||||
<div class="form-group">
|
||||
<label class="form-label" for="app-as-endpoint">Use App As Endpoint</label>
|
||||
<label class="form-label" for="app-as-endpoint" text-translate="true">Use App As Endpoint</label>
|
||||
<select v-model="srvModel.appIdEndpoint" v-on:change="inputChanges" class="form-select" id="app-as-endpoint">
|
||||
<option value="">Use default pay button endpoint</option>
|
||||
<option value="" text-translate="true">Use default pay button endpoint</option>
|
||||
<option v-for="app in srvModel.apps" v-bind:value="app.id" >{{app.appName}} ({{app.appType}})</option>
|
||||
</select>
|
||||
<small class="text-danger">{{ errors.first('appIdEndpoint') }}</small>
|
||||
</div>
|
||||
<div class="form-group" v-if="srvModel.appIdEndpoint">
|
||||
<label class="form-label" for="app-item">App Item/Perk</label>
|
||||
<label class="form-label" for="app-item" text-translate="true">App Item/Perk</label>
|
||||
<input name="appChoiceKey" type="text" class="form-control" id="app-item"
|
||||
v-model="srvModel.appChoiceKey" v-on:change="inputChanges"
|
||||
:class="{'is-invalid': errors.has('appChoiceKey') }">
|
||||
@ -410,57 +406,61 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h4 class="mt-5 mb-3">Generated Code</h4>
|
||||
<h4 class="mt-5 mb-3" text-translate="true">Generated Code</h4>
|
||||
<div class="row" v-show="!errors.any()">
|
||||
<div class="col-xxl-8">
|
||||
<pre><code id="mainCode" class="html"></code></pre>
|
||||
<button class="btn btn-outline-secondary" data-clipboard-target="#mainCode">
|
||||
<vc:icon symbol="actions-copy"/> Copy Code
|
||||
<vc:icon symbol="actions-copy"/> <span text-translate="true">Copy Code</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row" v-show="errors.any()">
|
||||
<div class="col-xl-8 col-xxl-constrain text-danger">
|
||||
<div class="col-xl-8 col-xxl-constrain text-danger" text-translate="true">
|
||||
Please fix errors shown in order for code generation to successfully execute.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="!srvModel.appIdEndpoint && (previewLink || lnurlLink)">
|
||||
<h4 class="mt-4 mb-3">Alternatives</h4>
|
||||
<p>You can also share the link/LNURL or encode it in a QR code.</p>
|
||||
<h4 class="mt-5 mb-3" text-translate="true">Alternatives</h4>
|
||||
<p text-translate="true">You can also share the link/LNURL or encode it in a QR code.</p>
|
||||
<div class="align-items-center" style="width:256px">
|
||||
<ul class="nav my-3 btcpay-pills align-items-center gap-2">
|
||||
<li class="nav-item" v-if="previewLink">
|
||||
<a class="btcpay-pill" :class="{ active: alternativeMode === 'link' }" data-bs-toggle="tab" data-bs-target="#Alternative-Link" role="tab" href="#Alternative-Link">
|
||||
<a class="btcpay-pill" :class="{ active: alternativeMode === 'link' }" data-bs-toggle="tab" data-bs-target="#Alternative-Link" role="tab" href="#Alternative-Link" text-translate="true">
|
||||
Link
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item" v-if="previewLink">
|
||||
<a class="btcpay-pill" :class="{ active: alternativeMode === 'lnurl' }" data-bs-toggle="tab" data-bs-target="#Alternative-LNURL" role="tab" href="#Alternative-LNURL">
|
||||
<a class="btcpay-pill" :class="{ active: alternativeMode === 'lnurl' }" data-bs-toggle="tab" data-bs-target="#Alternative-LNURL" role="tab" href="#Alternative-LNURL" text-translate="true">
|
||||
LNURL
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="tab-content">
|
||||
<div class="tab-pane" :class="{ active: alternativeMode === 'link' }" id="Alternative-Link" role="tabpanel">
|
||||
<a class="qr-container d-inline-block" :class="{ active: true }" :href="previewLink">
|
||||
<qrcode :value="previewLink" :options="qrOptions" tag="img"></qrcode>
|
||||
</a>
|
||||
<div class="input-group mt-3">
|
||||
<div class="form-floating">
|
||||
<vc:truncate-center text="previewLink" is-vue="true" padding="15" elastic="true" classes="form-control-plaintext" />
|
||||
<label>Link URL</label>
|
||||
<div class="payment-box">
|
||||
<a class="qr-container d-inline-block" :class="{ active: true }" :href="previewLink">
|
||||
<qrcode :value="previewLink" :options="qrOptions" tag="img"></qrcode>
|
||||
</a>
|
||||
<div class="input-group mt-3">
|
||||
<div class="form-floating">
|
||||
<vc:truncate-center text="previewLink" is-vue="true" padding="15" elastic="true" classes="form-control-plaintext" />
|
||||
<label text-translate="true">Link URL</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tab-pane" :class="{ active: alternativeMode === 'lnurl' }" id="Alternative-LNURL" role="tabpanel">
|
||||
<a class="qr-container d-inline-block" :href="lnurlLink">
|
||||
<qrcode :value="lnurlLink" :options="qrOptions" tag="img"></qrcode>
|
||||
</a>
|
||||
<div class="input-group mt-3">
|
||||
<div class="form-floating">
|
||||
<vc:truncate-center text="lnurlLink" is-vue="true" padding="15" elastic="true" classes="form-control-plaintext" />
|
||||
<label>LNURL</label>
|
||||
<div class="payment-box">
|
||||
<a class="qr-container d-inline-block" :href="lnurlLink">
|
||||
<qrcode :value="lnurlLink" :options="qrOptions" tag="img"></qrcode>
|
||||
</a>
|
||||
<div class="input-group mt-3">
|
||||
<div class="form-floating">
|
||||
<vc:truncate-center text="lnurlLink" is-vue="true" padding="15" elastic="true" classes="form-control-plaintext" />
|
||||
<label text-translate="true">LNURL</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -46,7 +46,7 @@
|
||||
</div>
|
||||
@if (Model.ShowSearch)
|
||||
{
|
||||
<input id="SearchTerm" class="form-control rounded-pill" placeholder="Search…" v-model="searchTerm" v-if="showSearch">
|
||||
<input id="SearchTerm" class="form-control rounded-pill" placeholder="@StringLocalizer["Search…"]" v-model="searchTerm" v-if="showSearch">
|
||||
}
|
||||
@if (Model.ShowCategories)
|
||||
{
|
||||
@ -97,7 +97,14 @@
|
||||
@if (item.Inventory.HasValue)
|
||||
{
|
||||
<span class="badge text-bg-warning inventory" v-text="inventoryText(@index)">
|
||||
@(item.Inventory > 0 ? $"{item.Inventory} left" : "Sold out")
|
||||
@if (item.Inventory > 0)
|
||||
{
|
||||
<span>@ViewLocalizer["{0} left", item.Inventory.ToString()]</span>
|
||||
}
|
||||
else
|
||||
{
|
||||
<span text-translate="true">Sold out</span>
|
||||
}
|
||||
</span>
|
||||
}
|
||||
</div>
|
||||
@ -113,7 +120,7 @@
|
||||
{
|
||||
<div class="input-group mb-2">
|
||||
<span class="input-group-text">@Model.CurrencySymbol</span>
|
||||
<input class="form-control" type="number" min="@(item.Price ?? 0)" step="@Model.Step" name="amount" placeholder="Amount" value="@item.Price" required v-on:click.stop>
|
||||
<input class="form-control" type="number" min="@(item.Price ?? 0)" step="@Model.Step" name="amount" placeholder="@StringLocalizer["Amount"]" value="@item.Price" required v-on:click.stop>
|
||||
</div>
|
||||
}
|
||||
<button type="button" class="btn btn-primary w-100" :disabled="!inStock(@index)">
|
||||
@ -138,10 +145,10 @@
|
||||
<div class="public-page-wrap" v-cloak>
|
||||
<header class="sticky-top bg-tile offcanvas-header py-3 py-lg-4 d-flex align-items-baseline justify-content-center gap-3 px-5 pe-lg-0">
|
||||
<h1 class="mb-0" id="cartLabel">Cart</h1>
|
||||
<button id="CartClear" type="reset" v-on:click="clear" class="btn btn-text text-primary p-1" v-if="cartCount > 0">
|
||||
<button id="CartClear" type="reset" v-on:click="clear" class="btn btn-text text-primary p-1" v-if="cartCount > 0" text-translate="true">
|
||||
Empty
|
||||
</button>
|
||||
<button id="CartClose" type="button" class="cart-toggle-btn" v-on:click="toggleCart" aria-controls="cart" aria-label="Close">
|
||||
<button id="CartClose" type="button" class="cart-toggle-btn" v-on:click="toggleCart" aria-controls="cart" aria-label="@StringLocalizer["Close"]">
|
||||
<vc:icon symbol="cross" />
|
||||
</button>
|
||||
</header>
|
||||
@ -156,7 +163,7 @@
|
||||
<tr v-for="item in cart" :key="item.id">
|
||||
<td class="align-middle">
|
||||
<h6 class="fw-semibold mb-1">{{ item.title }}</h6>
|
||||
<button type="button" v-on:click="removeFromCart(item.id)" class="btn btn-sm btn-link p-0 text-danger fw-semibold">Remove</button>
|
||||
<button type="button" v-on:click="removeFromCart(item.id)" class="btn btn-sm btn-link p-0 text-danger fw-semibold" text-translate="true">Remove</button>
|
||||
</td>
|
||||
<td class="align-middle">
|
||||
<div class="d-flex align-items-center gap-2 justify-content-end quantity">
|
||||
@ -167,7 +174,7 @@
|
||||
<button type="button" v-on:click="updateQuantity(item.id, -1)" class="btn btn-minus">
|
||||
<span><vc:icon symbol="minus" /></span>
|
||||
</button>
|
||||
<input class="form-control hide-number-spin w-50px text-center" type="number" placeholder="Qty" min="1" step="1" :max="item.inventory" v-model.number="item.count">
|
||||
<input class="form-control hide-number-spin w-50px text-center" type="number" placeholder="@StringLocalizer["Qty"]" min="1" step="1" :max="item.inventory" v-model.number="item.count">
|
||||
<button type="button" v-on:click="updateQuantity(item.id, +1)" class="btn btn-plus">
|
||||
<span><vc:icon symbol="plus" /></span>
|
||||
</button>
|
||||
@ -182,7 +189,7 @@
|
||||
</table>
|
||||
<table class="table table-borderless my-4" v-if="showDiscount || enableTips">
|
||||
<tr v-if="showDiscount">
|
||||
<th class="align-middle">Discount</th>
|
||||
<th class="align-middle" text-translate="true">Discount</th>
|
||||
<th class="align-middle" colspan="3">
|
||||
<div class="input-group input-group-sm w-100px pull-right">
|
||||
<input class="form-control hide-number-spin" type="number" min="0" step="1" max="100" id="Discount" v-model.number="discountPercent">
|
||||
@ -191,7 +198,7 @@
|
||||
</th>
|
||||
</tr>
|
||||
<tr v-if="enableTips">
|
||||
<th class="align-middle">Tip</th>
|
||||
<th class="align-middle" text-translate="true">Tip</th>
|
||||
<th class="align-middle" colspan="3">
|
||||
<div class="btcpay-pills d-flex flex-wrap align-items-center justify-content-end gap-2" v-if="customTipPercentages">
|
||||
<div class="btcpay-pill d-flex align-items-center px-3" id="Tip-Custom" :class="{ active: !tipPercent && tip }" v-on:click.prevent="tipPercent = null">
|
||||
@ -219,25 +226,25 @@
|
||||
</table>
|
||||
<table class="table table-borderless mt-4 mb-0">
|
||||
<tr>
|
||||
<td class="align-middle">Subtotal</td>
|
||||
<td class="align-middle" text-translate="true">Subtotal</td>
|
||||
<td class="align-middle text-end" id="CartAmount">{{ formatCurrency(amountNumeric, true) }}</td>
|
||||
</tr>
|
||||
<tr v-if="discountNumeric">
|
||||
<td class="align-middle">Discount</td>
|
||||
<td class="align-middle" text-translate="true">Discount</td>
|
||||
<td class="align-middle text-end" id="CartDiscount">
|
||||
<span v-if="discountPercent">{{discountPercent}}% =</span>
|
||||
{{ formatCurrency(discountNumeric, true) }}
|
||||
</td>
|
||||
</tr>
|
||||
<tr v-if="tipNumeric">
|
||||
<td class="align-middle">Tip</td>
|
||||
<td class="align-middle" text-translate="true">Tip</td>
|
||||
<td class="align-middle text-end" id="CartTip">
|
||||
<span v-if="tipPercent">{{tipPercent}}% =</span>
|
||||
{{ formatCurrency(tipNumeric, true) }}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="align-middle h5 border-0">Total</td>
|
||||
<td class="align-middle h5 border-0" text-translate="true">Total</td>
|
||||
<td class="align-middle h5 border-0 text-end" id="CartTotal">{{ formatCurrency(totalNumeric, true) }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
@ -246,13 +253,13 @@
|
||||
<div v-if="payButtonLoading" class="spinner-border spinner-border-sm" id="pay-button-spinner" role="status">
|
||||
<span class="visually-hidden" text-translate="true">Loading...</span>
|
||||
</div>
|
||||
<template v-else>Pay</template>
|
||||
<template v-else text-translate="true">Pay</template>
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</form>
|
||||
<p id="CartItems" v-else class="text-muted text-center my-0">There are no items in your cart yet.</p>
|
||||
<p id="CartItems" v-else class="text-muted text-center my-0" text-translate="true">There are no items in your cart yet.</p>
|
||||
</div>
|
||||
</div>
|
||||
</aside>
|
||||
|
@ -3,7 +3,7 @@
|
||||
<form method="post" asp-action="ViewPointOfSale" asp-route-appId="@Model.AppId" asp-antiforgery="false">
|
||||
<div class="input-group">
|
||||
<span class="input-group-text">@Model.CurrencySymbol</span>
|
||||
<input class="form-control" type="number" step="@Model.Step" name="amount" placeholder="Amount">
|
||||
<input class="form-control" type="number" step="@Model.Step" name="amount" placeholder="@StringLocalizer["Amount"]">
|
||||
<button class="btn btn-primary" type="submit" text-translate="true">Pay</button>
|
||||
</div>
|
||||
</form>
|
||||
|
@ -101,7 +101,14 @@ else
|
||||
@if (item.Inventory.HasValue)
|
||||
{
|
||||
<span class="badge text-bg-light">
|
||||
@(item.Inventory > 0 ? $"{item.Inventory} left" : "Sold out")
|
||||
@if (item.Inventory > 0)
|
||||
{
|
||||
<span>@ViewLocalizer["{0} left", item.Inventory.ToString()]</span>
|
||||
}
|
||||
else
|
||||
{
|
||||
<span text-translate="true">Sold out</span>
|
||||
}
|
||||
</span>
|
||||
}
|
||||
</div>
|
||||
|
@ -10,7 +10,7 @@
|
||||
<vc:icon symbol="actions-refresh"/>
|
||||
<span v-if="recentTransactionsLoading" class="visually-hidden" text-translate="true">Loading...</span>
|
||||
</button>
|
||||
<button type="button" class="btn-close py-3" aria-label="Close" v-on:click="hideRecentTransactions">
|
||||
<button type="button" class="btn-close py-3" aria-label="@StringLocalizer["Close"]" v-on:click="hideRecentTransactions">
|
||||
<vc:icon symbol="close"/>
|
||||
</button>
|
||||
</div>
|
||||
|
@ -57,7 +57,7 @@
|
||||
<span class="badge text-bg-warning">
|
||||
@if (item.Inventory > 0)
|
||||
{
|
||||
<span text-translate="true">@ViewLocalizer["{0} left", item.Inventory.ToString()]</span>
|
||||
<span>@ViewLocalizer["{0} left", item.Inventory.ToString()]</span>
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -80,7 +80,7 @@
|
||||
{
|
||||
<div class="input-group mb-2">
|
||||
<span class="input-group-text">@Model.CurrencySymbol</span>
|
||||
<input class="form-control" type="number" min="@(item.Price ?? 0)" step="@Model.Step" name="amount" placeholder="Amount" value="@item.Price" required>
|
||||
<input class="form-control" type="number" min="@(item.Price ?? 0)" step="@Model.Step" name="amount" placeholder="@StringLocalizer["Amount"]" value="@item.Price" required>
|
||||
</div>
|
||||
}
|
||||
<button class="btn btn-primary w-100" type="submit">@Safe.Raw(buttonText)</button>
|
||||
@ -102,7 +102,7 @@
|
||||
<form method="post" asp-action="ViewPointOfSale" asp-route-appId="@Model.AppId" asp-antiforgery="false" autocomplete="off">
|
||||
<div class="input-group mb-2">
|
||||
<span class="input-group-text">@Model.CurrencySymbol</span>
|
||||
<input class="form-control" type="number" min="0" step="@Model.Step" name="amount" placeholder="Amount" required>
|
||||
<input class="form-control" type="number" min="0" step="@Model.Step" name="amount" placeholder="@StringLocalizer["Amount"]" required>
|
||||
</div>
|
||||
<button class="btn btn-primary w-100" type="submit">@Safe.Raw(Model.CustomButtonText ?? Model.ButtonText)</button>
|
||||
</form>
|
||||
|
@ -89,7 +89,7 @@
|
||||
@if (Model.ShowSearch)
|
||||
{
|
||||
<div class="w-100 mt-3">
|
||||
<input id="SearchTerm" class="form-control rounded-pill" placeholder="Search…" v-model="searchTerm" v-if="showSearch">
|
||||
<input id="SearchTerm" class="form-control rounded-pill" placeholder="@StringLocalizer["Search…"]" v-model="searchTerm" v-if="showSearch">
|
||||
</div>
|
||||
}
|
||||
@if (Model.ShowCategories)
|
||||
@ -135,7 +135,14 @@
|
||||
@if (item.Inventory.HasValue)
|
||||
{
|
||||
<span class="badge text-bg-warning inventory" v-text="inventoryText(@index)">
|
||||
@(item.Inventory > 0 ? $"{item.Inventory} left" : "Sold out")
|
||||
@if (item.Inventory > 0)
|
||||
{
|
||||
<span>@ViewLocalizer["{0} left", item.Inventory.ToString()]</span>
|
||||
}
|
||||
else
|
||||
{
|
||||
<span text-translate="true">Sold out</span>
|
||||
}
|
||||
</span>
|
||||
}
|
||||
</div>
|
||||
|
@ -9,7 +9,7 @@
|
||||
@inject BTCPayServer.Security.ContentSecurityPolicies Csp
|
||||
@model BTCPayServer.Plugins.PointOfSale.Models.UpdatePointOfSaleViewModel
|
||||
@{
|
||||
ViewData.SetActivePage(AppsNavPages.Update, "Update Point of Sale", Model.Id);
|
||||
ViewData.SetActivePage(AppsNavPages.Update, StringLocalizer["Update Point of Sale"], Model.Id);
|
||||
Csp.UnsafeEval();
|
||||
var checkoutFormOptions = await FormDataService.GetSelect(Model.StoreId, Model.FormId);
|
||||
var posPath = Url.Action("ViewPointOfSale", "UIPointOfSale", new { appId = Model.Id });
|
||||
@ -34,12 +34,12 @@
|
||||
<button id="page-primary" type="submit" class="btn btn-primary order-sm-1">Save</button>
|
||||
@if (Model.Archived)
|
||||
{
|
||||
<button type="submit" class="btn btn-outline-secondary" name="Archived" value="False">Unarchive</button>
|
||||
<button type="submit" class="btn btn-outline-secondary" name="Archived" value="False" text-translate="true">Unarchive</button>
|
||||
}
|
||||
else
|
||||
{
|
||||
<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>
|
||||
<a class="btn btn-secondary" asp-controller="UIPointOfSale" asp-action="ViewPointOfSale" asp-route-appId="@Model.Id" id="ViewApp" target="_blank" text-translate="true">View</a>
|
||||
<button type="button" class="btn btn-secondary px-3 d-inline-flex align-items-center" data-bs-toggle="modal" data-bs-target="#OpenPosModal">
|
||||
<vc:icon symbol="qr-code" />
|
||||
</button>
|
||||
@ -76,7 +76,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label asp-for="DefaultView" class="form-label" data-required>Choose Point of Sale Style</label>
|
||||
<label asp-for="DefaultView" class="form-label" data-required text-translate="true">Choose Point of Sale Style</label>
|
||||
<div class="btcpay-list-select">
|
||||
@foreach (var type in Enum.GetValues<PosViewType>())
|
||||
{
|
||||
@ -91,7 +91,7 @@
|
||||
<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>
|
||||
<div class="form-text">@StringLocalizer["Uses the store's default currency ({0}) if empty.", Model.StoreDefaultCurrency]</div>
|
||||
<span asp-validation-for="Currency" class="text-danger"></span>
|
||||
</div>
|
||||
</div>
|
||||
@ -112,7 +112,7 @@
|
||||
</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>
|
||||
<h3 class="mb-4" text-translate="true">Checkout</h3>
|
||||
<fieldset>
|
||||
<div class="form-group" id="button-price-text">
|
||||
<label asp-for="ButtonText" class="form-label" data-required></label>
|
||||
@ -126,7 +126,7 @@
|
||||
</div>
|
||||
</fieldset>
|
||||
<fieldset id="keypad-display" class="mt-2">
|
||||
<legend class="h5 mb-3 fw-semibold">Keypad</legend>
|
||||
<legend class="h5 mb-3 fw-semibold" text-translate="true">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>
|
||||
@ -147,7 +147,7 @@
|
||||
</div>
|
||||
</fieldset>
|
||||
<fieldset id="tips" class="mt-2">
|
||||
<legend class="h5 mb-3 fw-semibold">Tips</legend>
|
||||
<legend class="h5 mb-3 fw-semibold" text-translate="true">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-check-label"></label>
|
||||
@ -167,18 +167,18 @@
|
||||
</div>
|
||||
</fieldset>
|
||||
<fieldset id="discounts" class="mt-2">
|
||||
<legend class="h5 mb-3 fw-semibold">Discounts</legend>
|
||||
<legend class="h5 mb-3 fw-semibold" text-translate="true">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-check-label"></label>
|
||||
<div class="text-muted">Not recommended for customer self-checkout.</div>
|
||||
<div class="text-muted" text-translate="true">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>
|
||||
<legend class="h5 mb-3 fw-semibold" text-translate="true">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-check-label"></label>
|
||||
@ -202,21 +202,21 @@
|
||||
<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
|
||||
<span text-translate="true">Embed a payment button linking to POS item</span>
|
||||
<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>
|
||||
<p text-translate="true">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>
|
||||
<span text-translate="true">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>
|
||||
<span text-translate="true">For a specific item of your template</span>
|
||||
<pre class="p-3">@Model.Example2</pre>
|
||||
}
|
||||
</div>
|
||||
@ -225,13 +225,13 @@
|
||||
<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
|
||||
<span text-translate="true">Embed Point of Sale via iframe</span>
|
||||
<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.
|
||||
<span text-translate="true">You can embed this POS via an iframe.</span>
|
||||
@{
|
||||
var iframe = $"<iframe src='{Url.Action("ViewPointOfSale", "UIPointOfSale", new { appId = Model.Id }, Context.Request.Scheme)}' style='max-width: 100%; border: 0;'></iframe>";
|
||||
}
|
||||
@ -242,7 +242,7 @@
|
||||
<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
|
||||
<span text-translate="true">Redirects</span>
|
||||
<vc:icon symbol="caret-down" />
|
||||
</button>
|
||||
</h2>
|
||||
@ -264,7 +264,7 @@
|
||||
<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
|
||||
<span text-translate="true">Notification URL Callbacks</span>
|
||||
<vc:icon symbol="caret-down" />
|
||||
</button>
|
||||
</h2>
|
||||
@ -275,13 +275,13 @@
|
||||
<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>
|
||||
<p html-translate="true">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>
|
||||
<p html-translate="true"><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>
|
||||
<li html-translate="true">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 html-translate="true">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 text-translate="true">You can then ship your order</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
@ -293,30 +293,30 @@
|
||||
</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>
|
||||
<a class="btn btn-secondary" asp-action="ListInvoices" asp-controller="UIInvoice" asp-route-storeId="@Model.StoreId" asp-route-searchterm="@Model.SearchTerm" text-translate="true">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" permission="@Policies.CanModifyStoreSettings">
|
||||
@if (Model.Archived)
|
||||
{
|
||||
<span class="text-nowrap">Unarchive this app</span>
|
||||
<span class="text-nowrap" text-translate="true">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>
|
||||
<span class="text-nowrap" data-bs-toggle="tooltip" title="@StringLocalizer["Archive this app so that it does not appear in the apps list by default"]" text-translate="true">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" permission="@Policies.CanModifyStoreSettings">Delete this app</a>
|
||||
<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="@StringLocalizer["The app <strong>{0}</strong> and its settings will be permanently deleted.", Html.Encode(Model.AppName)]" data-confirm-input="@StringLocalizer["DELETE"]" permission="@Policies.CanModifyStoreSettings" text-translate="true">Delete this app</a>
|
||||
</div>
|
||||
|
||||
<partial name="_Confirm" model="@(new ConfirmModel("Delete app", "This app will be removed from this store.", "Delete"))" permission="@Policies.CanModifyStoreSettings" />
|
||||
<partial name="_Confirm" model="@(new ConfirmModel(StringLocalizer["Delete app"], StringLocalizer["This app will be removed from this store."], StringLocalizer["Delete"]))" permission="@Policies.CanModifyStoreSettings" />
|
||||
|
||||
<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">
|
||||
<h5 class="modal-title" text-translate="true">Scan the QR code to open the Point of Sale</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="@StringLocalizer["Close"]">
|
||||
<vc:icon symbol="close"/>
|
||||
</button>
|
||||
</div>
|
||||
|
@ -4,7 +4,7 @@
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">{{title}} <template v-if="fragments && fragments.length > 1">({{index+1}}/{{fragments.length}})</template></h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close">
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="@StringLocalizer["Close"]">
|
||||
<vc:icon symbol="close"/>
|
||||
</button>
|
||||
</div>
|
||||
|
@ -22,7 +22,7 @@
|
||||
<label for="EditorId" class="form-label" data-required>ID</label>
|
||||
<input id="EditorId" required class="form-control mb-2" v-model="editingItem && editingItem.id" v-on:change="onIdChange" />
|
||||
<div class="text-danger mb-3" v-if="errors.id">{{errors.id}}</div>
|
||||
<div class="form-text" v-else>Leave blank to generate ID from title.</div>
|
||||
<div class="form-text" v-else text-translate="true">Leave blank to generate ID from title.</div>
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
<div class="col-sm-6">
|
||||
@ -51,35 +51,35 @@
|
||||
<div class="text-danger" v-if="errors.price">{{errors.price}}</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="EditorImageUrl" class="form-label">Image Url</label>
|
||||
<label for="EditorImageUrl" class="form-label" text-translate="true">Image Url</label>
|
||||
<input id="EditorImageUrl" class="form-control mb-2" v-model="editingItem && editingItem.image" ref="txtImage" />
|
||||
<item-editor-upload upload-url=@Safe.Json(Url.Action("FileUpload", "UIApps", new { appId = Context.GetRouteValue("appId") })) v-on:uploaded="url => editingItem.image = url" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="EditorDescription" class="form-label">Description</label>
|
||||
<label for="EditorDescription" class="form-label" text-translate="true">Description</label>
|
||||
<textarea id="EditorDescription" rows="3" cols="40" class="form-control" v-model="editingItem && editingItem.description"></textarea>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="EditorCategories" class="form-label">Categories</label>
|
||||
<label for="EditorCategories" class="form-label" text-translate="true">Categories</label>
|
||||
<input id="EditorCategories" class="form-control mb-2" autocomplete="off" ref="editorCategories" />
|
||||
<div class="form-text">Easily filter the different items using categories, used only in the product list with cart.</div>
|
||||
<div class="form-text" text-translate="true">Easily filter the different items using categories, used only in the product list with cart.</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="EditorInventory" class="form-label">Inventory</label>
|
||||
<label for="EditorInventory" class="form-label" text-translate="true">Inventory</label>
|
||||
<input id="EditorInventory" type="number" inputmode="numeric" min="0" step="1" class="form-control mb-2" v-model="editingItem && editingItem.inventory" v-on:change="onInventoryChange" />
|
||||
<div class="form-text">Leave blank to not use this feature.</div>
|
||||
<div class="form-text" text-translate="true">Leave blank to not use this feature.</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="BuyButtonText" class="form-label">Buy Button Text</label>
|
||||
<label for="BuyButtonText" class="form-label" text-translate="true">Buy Button Text</label>
|
||||
<input id="BuyButtonText" type="text" class="form-control mb-2" v-model="editingItem && editingItem.buyButtonText" />
|
||||
</div>
|
||||
<div class="form-group d-flex align-items-center">
|
||||
<input type="checkbox" id="Disabled" class="btcpay-toggle me-3" :checked="editingItem && !editingItem.disabled" v-on:change="$event => editingItem.disabled = !$event.target.checked" />
|
||||
<label for="Disabled" class="form-check-label">Enable</label>
|
||||
<label for="Disabled" class="form-check-label" text-translate="true">Enable</label>
|
||||
</div>
|
||||
<vc:ui-extension-point location="app-template-editor-item-detail" model="Model"></vc:ui-extension-point>
|
||||
</div>
|
||||
<div v-if="!editingItem">Select an item to edit</div>
|
||||
<div v-if="!editingItem" text-translate="true">Select an item to edit</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@ -112,7 +112,7 @@
|
||||
</div>
|
||||
<button type="button" id="btAddItem" class="btn btn-link py-0 px-2 mt-2 mb-2 gap-1 add fw-semibold d-inline-flex align-items-center" v-on:click.stop="$emit('add-item', $event)">
|
||||
<vc:icon symbol="actions-add" />
|
||||
Add Item
|
||||
<span text-translate="true">Add Item</span>
|
||||
</button>
|
||||
</div>
|
||||
</template>
|
||||
@ -129,10 +129,10 @@
|
||||
<div class="d-flex flex-wrap align-items-end justify-content-between gap-3 mb-3">
|
||||
<ul class="nav nav-pills gap-4" role="tablist">
|
||||
<li class="nav-item" role="presentation">
|
||||
<button class="nav-link active" id="EditorTabButton" data-bs-toggle="pill" data-bs-target="#EditorTabPane" type="button" role="tab" aria-controls="EditorTabPane" aria-selected="true">Editor</button>
|
||||
<button class="nav-link active" id="EditorTabButton" data-bs-toggle="pill" data-bs-target="#EditorTabPane" type="button" role="tab" aria-controls="EditorTabPane" aria-selected="true" text-translate="true">Editor</button>
|
||||
</li>
|
||||
<li class="nav-item" role="presentation">
|
||||
<button class="nav-link" id="CodeTabButton" data-bs-toggle="pill" data-bs-target="#CodeTabPane" type="button" role="tab" aria-controls="CodeTabPane" aria-selected="false">Code</button>
|
||||
<button class="nav-link" id="CodeTabButton" data-bs-toggle="pill" data-bs-target="#CodeTabPane" type="button" role="tab" aria-controls="CodeTabPane" aria-selected="false" text-translate="true">Code</button>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
@ -151,7 +151,7 @@
|
||||
</div>
|
||||
<div class="col-xl-5 offcanvas-xl offcanvas-end" tabindex="-1" ref="editorOffcanvas">
|
||||
<div class="offcanvas-header justify-content-between p-3">
|
||||
<h5 class="offcanvas-title">Edit Item</h5>
|
||||
<h5 class="offcanvas-title" text-translate="true">Edit Item</h5>
|
||||
<button type="button" class="btn btn-sm rounded-pill" :class="{ 'btn-primary': itemChanged, 'btn-outline-secondary': !itemChanged }" v-on:click="hideOffcanvas" v-text="itemChanged ? 'Apply' : 'Close'"></button>
|
||||
</div>
|
||||
<div class="offcanvas-body p-3 p-xl-0">
|
||||
@ -161,7 +161,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="tab-pane fade" id="CodeTabPane" role="tabpanel" aria-labelledby="CodeTabButton" tabindex="0">
|
||||
<label for="TemplateConfig" class="form-label">Template JSON</label>
|
||||
<label for="TemplateConfig" class="form-label" text-translate="true">Template JSON</label>
|
||||
<textarea id="TemplateConfig" name="@Model.templateId" rows="21" cols="21" class="form-control font-monospace" style="font-size:.85rem" v-model="itemsJSON" v-on:change="updateFromJSON">@Model.template</textarea>
|
||||
<span asp-validation-for="@Model.templateId" class="text-danger"></span>
|
||||
</div>
|
||||
|
@ -48,19 +48,19 @@
|
||||
</div>
|
||||
<div id="passphrase-input" class="mt-4" style="display: none;">
|
||||
<div class="form-group">
|
||||
<label for="Password" class="form-label">Passphrase (Leave empty if there isn't any passphrase)</label>
|
||||
<label for="Password" class="form-label" text-translate="true">Passphrase (Leave empty if there isn't any passphrase)</label>
|
||||
<div class="input-group">
|
||||
<input id="Password" type="password" class="form-control">
|
||||
<button type="button" class="btn btn-secondary px-3 only-for-js" title="Toggle passphrase visibility" data-toggle-password="#Password">
|
||||
<button type="button" class="btn btn-secondary px-3 only-for-js" title="@StringLocalizer["Toggle passphrase visibility"]" data-toggle-password="#Password">
|
||||
<vc:icon symbol="actions-show" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="PasswordConfirmation" class="form-label">Passphrase confirmation</label>
|
||||
<label for="PasswordConfirmation" class="form-label" text-translate="true">Passphrase confirmation</label>
|
||||
<div class="input-group">
|
||||
<input id="PasswordConfirmation" type="password" class="form-control">
|
||||
<button type="button" class="btn btn-secondary px-3 only-for-js" title="Toggle passphrase visibility" data-toggle-password="#PasswordConfirmation">
|
||||
<button type="button" class="btn btn-secondary px-3 only-for-js" title="@StringLocalizer["Toggle passphrase visibility"]" data-toggle-password="#PasswordConfirmation">
|
||||
<vc:icon symbol="actions-show" />
|
||||
</button>
|
||||
</div>
|
||||
|
@ -1,4 +1,4 @@
|
||||
<h5 class="text-center fw-normal mb-4">
|
||||
<h5 class="text-center fw-normal mb-4" text-translate="true">
|
||||
BTCPay Server Supporters
|
||||
</h5>
|
||||
|
||||
@ -58,6 +58,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<p class="text-center">
|
||||
<a href="https://foundation.btcpayserver.org" target="_blank" rel="noreferrer noopener">View all supporters</a> or
|
||||
<a href="https://btcpayserver.org/donate/" target="_blank" rel="noreferrer noopener">Donate</a>
|
||||
<a href="https://foundation.btcpayserver.org" target="_blank" rel="noreferrer noopener" text-translate="true">View all supporters</a>
|
||||
<span text-translate="true">or</span>
|
||||
<a href="https://btcpayserver.org/donate/" target="_blank" rel="noreferrer noopener" text-translate="true">Donate</a>
|
||||
</p>
|
||||
|
@ -21,21 +21,21 @@
|
||||
</a>
|
||||
<a href="https://btcpayserver.org/donate/" target="_blank" rel="noreferrer noopener">
|
||||
<vc:icon symbol="donate"/>
|
||||
<span>Donate</span>
|
||||
<span text-translate="true">Donate</span>
|
||||
</a>
|
||||
<a asp-controller="UIHome" asp-action="SwaggerDocs" target="_blank">
|
||||
<vc:icon symbol="api"/>
|
||||
<span>API</span>
|
||||
<span text-translate="true">API</span>
|
||||
</a>
|
||||
<a href="https://docs.btcpayserver.org/" target="_blank" rel="noreferrer noopener">
|
||||
<vc:icon symbol="docs"/>
|
||||
<span>Docs</span>
|
||||
<span text-translate="true">Docs</span>
|
||||
</a>
|
||||
@if (!string.IsNullOrEmpty(_env.OnionUrl) && !Context.Request.IsOnion())
|
||||
{
|
||||
<button type="button" class="d-flex align-items-center btn btn-link" data-clipboard="@_env.OnionUrl" data-clipboard-hover>
|
||||
<vc:icon symbol="logo-tor"/>
|
||||
<span>Copy Tor URL</span>
|
||||
<span text-translate="true">Copy Tor URL</span>
|
||||
</button>
|
||||
}
|
||||
</div>
|
||||
@ -54,7 +54,7 @@
|
||||
<div class="toast-header">
|
||||
<span class="blazor-status__state btcpay-status"></span>
|
||||
<h6 class="blazor-status__title ms-2 mb-0 me-auto"></h6>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="toast" aria-label="Close">
|
||||
<button type="button" class="btn-close" data-bs-dismiss="toast" aria-label="@StringLocalizer["Close"]">
|
||||
<vc:icon symbol="close" />
|
||||
</button>
|
||||
</div>
|
||||
|
@ -34,27 +34,21 @@
|
||||
</header>
|
||||
<template id="badUrl">
|
||||
<div class="alert alert-danger alert-dismissible m-3" role="alert">
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close">
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="@StringLocalizer["Close"]">
|
||||
<vc:icon symbol="close"/>
|
||||
</button>
|
||||
<span>
|
||||
BTCPay is expecting you to access this website from <strong>@(expectedScheme)://@(expectedHost)/</strong>.
|
||||
If you use a reverse proxy, please set the <strong>X-Forwarded-Proto</strong> header to <strong id="browserScheme">@(expectedScheme)</strong>
|
||||
(<a href="https://docs.btcpayserver.org/FAQ/Deployment/#cause-3-btcpay-is-expecting-you-to-access-this-website-from" target="_blank" class="alert-link" rel="noreferrer noopener">More information</a>)
|
||||
</span>
|
||||
<span html-translate="true">BTCPay is expecting you to access this website from <strong>@(expectedScheme)://@(expectedHost)/</strong>. If you use a reverse proxy, please set the <strong>X-Forwarded-Proto</strong> header to <strong id="browserScheme">@(expectedScheme)</strong></span>
|
||||
(<a href="https://docs.btcpayserver.org/FAQ/Deployment/#cause-3-btcpay-is-expecting-you-to-access-this-website-from" target="_blank" class="alert-link" rel="noreferrer noopener" text-translate="true">More information</a>)
|
||||
</div>
|
||||
</template>
|
||||
<main id="mainContent">
|
||||
@if (!_env.IsSecure(_context.HttpContext))
|
||||
{
|
||||
<div id="insecureEnv" class="alert alert-danger alert-dismissible" style="position:absolute; top:75px;" role="alert">
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close">
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="@StringLocalizer["Close"]">
|
||||
<vc:icon symbol="close"/>
|
||||
</button>
|
||||
<span>
|
||||
Your access to BTCPay Server is over an unsecured network. If you are using the docker deployment method with NGINX and HTTPS is not available, you probably did not configure your DNS settings correctly. <br/>
|
||||
We disabled the register and login link so you don't leak your credentials.
|
||||
</span>
|
||||
<span text-translate="true">Your access to BTCPay Server is over an unsecured network. If you are using the docker deployment method with NGINX and HTTPS is not available, you probably did not configure your DNS settings correctly. We disabled the register and login link so you don't leak your credentials.</span>
|
||||
</div>
|
||||
}
|
||||
<section>
|
||||
|
@ -7,7 +7,7 @@
|
||||
<div class="alert alert-@parsedModel.SeverityCSS @(parsedModel.AllowDismiss? "alert-dismissible":"" ) @(ViewData["Margin"] ?? "mb-4") text-break" role="alert" v-pre>
|
||||
@if (parsedModel.AllowDismiss)
|
||||
{
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close">
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="@StringLocalizer["Close"]">
|
||||
<vc:icon symbol="close" />
|
||||
</button>
|
||||
}
|
||||
|
@ -11,10 +11,7 @@
|
||||
|
||||
@if (isEmailConfigured)
|
||||
{
|
||||
<p text-translate="true">
|
||||
We all forget passwords every now and then. Just provide email address tied to
|
||||
your account and we'll start the process of helping you recover your account.
|
||||
</p>
|
||||
<p text-translate="true">We all forget passwords sometimes. Just provide email address tied to your account, and we'll start the process of helping you recover your account.</p>
|
||||
|
||||
<form asp-action="ForgotPassword" method="post">
|
||||
@if (!ViewContext.ModelState.IsValid)
|
||||
|
@ -36,7 +36,7 @@
|
||||
<div class="form-group mt-4">
|
||||
<div class="btn-group w-100">
|
||||
<button type="submit" class="btn btn-primary btn-lg w-100" id="LoginButton"><span class="ps-3" text-translate="true" text-translate="true">Sign in</span></button>
|
||||
<button type="button" class="btn btn-outline-primary btn-lg w-auto only-for-js" data-bs-toggle="modal" data-bs-target="#scanModal" title="Scan Login code with camera">
|
||||
<button type="button" class="btn btn-outline-primary btn-lg w-auto only-for-js" data-bs-toggle="modal" data-bs-target="#scanModal" title="@StringLocalizer["Scan Login code with camera"]">
|
||||
<vc:icon symbol="scan-qr" />
|
||||
</button>
|
||||
</div>
|
||||
|
@ -4,10 +4,7 @@
|
||||
ViewData["Title"] = "Recovery code verification";
|
||||
}
|
||||
|
||||
<p text-translate="true">
|
||||
You have requested to login with a recovery code. This login will not be remembered until you provide
|
||||
an authenticator app code at login or disable 2FA and login again.
|
||||
</p>
|
||||
<p text-translate="true">You have requested to log in with a recovery code. This login will not be remembered until you provide an authenticator app code at login or disable 2FA and log in again.</p>
|
||||
<form method="post">
|
||||
<div class="form-group">
|
||||
<label asp-for="RecoveryCode" class="form-label"></label>
|
||||
|
@ -36,7 +36,7 @@
|
||||
<h2>
|
||||
@ViewData["Title"]
|
||||
<small>
|
||||
<a href="https://docs.btcpayserver.org/Apps/" target="_blank" rel="noreferrer noopener" title="More information...">
|
||||
<a href="https://docs.btcpayserver.org/Apps/" target="_blank" rel="noreferrer noopener" title="@StringLocalizer["More information..."]">
|
||||
<vc:icon symbol="info" />
|
||||
</a>
|
||||
</small>
|
||||
|
@ -1,6 +1,6 @@
|
||||
@model Fido2NetLib.CredentialCreateOptions
|
||||
@{
|
||||
ViewData.SetActivePage(ManageNavPages.TwoFactorAuthentication, "Register your security device");
|
||||
ViewData.SetActivePage(ManageNavPages.TwoFactorAuthentication, StringLocalizer["Register your security device"]);
|
||||
}
|
||||
|
||||
<div class="sticky-header">
|
||||
|
@ -3,18 +3,18 @@
|
||||
@using BTCPayServer.Client
|
||||
@model List<BTCPayServer.Data.FormData>
|
||||
@{
|
||||
ViewData.SetActivePage(StoreNavPages.Forms, "Forms");
|
||||
ViewData.SetActivePage(StoreNavPages.Forms, StringLocalizer["Forms"]);
|
||||
var storeId = Context.GetCurrentStoreId();
|
||||
}
|
||||
|
||||
<div class="sticky-header">
|
||||
<h2>
|
||||
<span text-translate="true">@ViewData["Title"]</span>
|
||||
<a href="https://docs.btcpayserver.org/Forms" target="_blank" rel="noreferrer noopener" title="More information...">
|
||||
<a href="https://docs.btcpayserver.org/Forms" target="_blank" rel="noreferrer noopener" title="@StringLocalizer["More information..."]">
|
||||
<vc:icon symbol="info" />
|
||||
</a>
|
||||
</h2>
|
||||
<a id="page-primary" asp-action="Create" asp-route-storeId="@storeId" class="btn btn-primary mt-3 mt-sm-0" role="button" permission="@Policies.CanModifyStoreSettings">
|
||||
<a id="page-primary" asp-action="Create" asp-route-storeId="@storeId" class="btn btn-primary mt-3 mt-sm-0" role="button" permission="@Policies.CanModifyStoreSettings" text-translate="true">
|
||||
Create Form
|
||||
</a>
|
||||
</div>
|
||||
|
@ -4,10 +4,10 @@
|
||||
@model BTCPayServer.Forms.ModifyForm
|
||||
@{
|
||||
Csp.UnsafeEval();
|
||||
var storeId = Context.GetCurrentStoreId();
|
||||
var formId = Context.GetRouteValue("id");
|
||||
var isNew = formId is null;
|
||||
ViewData.SetActivePage(StoreNavPages.Forms, $"{(isNew ? "Create" : "Edit")} Form", Model.Name);
|
||||
var storeId = Context.GetCurrentStoreId();
|
||||
ViewData.SetActivePage(StoreNavPages.Forms, isNew ? StringLocalizer["Create Form"] : StringLocalizer["Edit Form"], Model.Name);
|
||||
}
|
||||
|
||||
@section PageHeadContent {
|
||||
@ -30,17 +30,17 @@
|
||||
<template id="field-editor">
|
||||
<div class="field" v-if="field">
|
||||
<div class="form-group">
|
||||
<label for="field-editor-field-type" class="form-label" data-required>Type</label>
|
||||
<label for="field-editor-field-type" class="form-label" data-required text-translate="true">Type</label>
|
||||
<select id="field-editor-field-type" class="form-select" required v-model="field.type">
|
||||
<option v-for="option in fieldTypeOptions" :key="option" :value="option" v-text="option.charAt(0).toUpperCase() + option.slice(1)"></option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="field-editor-field-label" class="form-label" data-required>Label</label>
|
||||
<label for="field-editor-field-label" class="form-label" data-required text-translate="true">Label</label>
|
||||
<input id="field-editor-field-label" class="form-control" required v-model="field.label" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="field-editor-field-name" class="form-label" data-required>Name</label>
|
||||
<label for="field-editor-field-name" class="form-label" data-required text-translate="true">Name</label>
|
||||
<input id="field-editor-field-name" class="form-control" list="special-field-names" required v-model="field.name" />
|
||||
<div text-translate="true" class="form-text">The name of the field in the invoice's metadata.</div>
|
||||
<div text-translate="true" class="form-text text-info" v-if="field.name === 'invoice_currency'">The configured name means the value of this field will determine the invoice currency for public forms.</div>
|
||||
@ -56,11 +56,11 @@
|
||||
<vc:icon symbol="drag" />
|
||||
</button>
|
||||
<div class="field flex-grow-1">
|
||||
<label :for="`field-option-value-${index}`" class="form-label">Value</label>
|
||||
<label :for="`field-option-value-${index}`" class="form-label" text-translate="true">Value</label>
|
||||
<input :id="`field-option-value-${index}`" class="form-control" v-model.lazy="option.value" />
|
||||
</div>
|
||||
<div class="field flex-grow-1">
|
||||
<label :for="`field-option-text-${index}`" class="form-label">Text</label>
|
||||
<label :for="`field-option-text-${index}`" class="form-label" text-translate="true">Text</label>
|
||||
<input :id="`field-option-text-${index}`" class="form-control" v-model="option.text" />
|
||||
</div>
|
||||
<button type="button" class="btn b-0 control remove" v-on:click="removeOption($event, index)">
|
||||
@ -90,15 +90,15 @@
|
||||
<div class="options">
|
||||
<div v-if="field.valuemap" v-for="(v, k, index) in field.valuemap" :key="k" class="d-flex align-items-start gap-2 pt-3">
|
||||
<div class="field flex-grow-1">
|
||||
<label :for="`field-valuemap-value-${index}`" class="form-label">Original Value</label>
|
||||
<label :for="`field-valuemap-value-${index}`" class="form-label" text-translate="true">Original Value</label>
|
||||
<select v-if="mirroredField && mirroredField.type === 'select'" :id="`field-valuemap-value-${index}`" class="form-select" v-on:change="updateValueMap(k, $event.target.value, v)">
|
||||
<option v-for="option in mirroredField.options" v-if="option.text && option.value" :key="option.value" :value="option.value" :selected="k === option.value" v-text="`${option.value} (${option.text})`"></option>
|
||||
</select>
|
||||
<input v-else :id="`field-valuemap-value-${index}`" class="form-control" placeholder="Value to match" :value="k" v-on:change="updateValueMap(k, $event.target.value, v)" />
|
||||
<input v-else :id="`field-valuemap-value-${index}`" class="form-control" placeholder="@StringLocalizer["Value to match"]" :value="k" v-on:change="updateValueMap(k, $event.target.value, v)" />
|
||||
</div>
|
||||
<div class="field flex-grow-1">
|
||||
<label :for="`field-valuemap-mapped-${index}`" class="form-label">Mapped Value</label>
|
||||
<input :id="`field-valuemap-mapped-${index}`" class="form-control" placeholder="Value to set" :value="v" v-on:change="updateValueMap(k, k, $event.target.value)" />
|
||||
<label :for="`field-valuemap-mapped-${index}`" class="form-label" text-translate="true">Mapped Value</label>
|
||||
<input :id="`field-valuemap-mapped-${index}`" class="form-control" placeholder="@StringLocalizer["Value to set"]" :value="v" v-on:change="updateValueMap(k, k, $event.target.value)" />
|
||||
</div>
|
||||
<button type="button" class="btn b-0 control remove" v-on:click="removeValueMap($event, k)">
|
||||
<vc:icon symbol="remove" />
|
||||
@ -202,7 +202,7 @@
|
||||
</ol>
|
||||
<h2>
|
||||
@ViewData["Title"]
|
||||
<a href="https://docs.btcpayserver.org/Forms" target="_blank" rel="noreferrer noopener" title="More information...">
|
||||
<a href="https://docs.btcpayserver.org/Forms" target="_blank" rel="noreferrer noopener" title="@StringLocalizer["More information..."]">
|
||||
<vc:icon symbol="info" />
|
||||
</a>
|
||||
</h2>
|
||||
@ -230,10 +230,7 @@
|
||||
<input asp-for="Public" type="checkbox" class="btcpay-toggle" />
|
||||
<div>
|
||||
<label asp-for="Public"></label>
|
||||
<div class="form-text" text-translate="true">
|
||||
Standalone mode, which can be used to generate invoices
|
||||
independent of payment requests or apps.
|
||||
</div>
|
||||
<div class="form-text" text-translate="true">Standalone mode, which can be used to generate invoices independent of payment requests or apps.</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -272,7 +269,7 @@
|
||||
<div class="col-xl-5 offcanvas-xl offcanvas-end" tabindex="-1" ref="editorOffcanvas">
|
||||
<div class="offcanvas-header justify-content-between p-3">
|
||||
<h5 class="offcanvas-title" text-translate="true">Edit Field</h5>
|
||||
<button type="button" class="btn-close" aria-label="Close" v-on:click="hideOffcanvas">
|
||||
<button type="button" class="btn-close" aria-label="@StringLocalizer["Close"]" v-on:click="hideOffcanvas">
|
||||
<vc:icon symbol="close" />
|
||||
</button>
|
||||
</div>
|
||||
|
@ -36,11 +36,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="lead text-center">
|
||||
<p class="mb-0" text-translate="true">
|
||||
The combination of words below are called your recovery phrase.
|
||||
The recovery phrase allows you to access and restore your wallet.
|
||||
Write them down on a piece of paper in the exact order:
|
||||
</p>
|
||||
<p class="mb-0" text-translate="true">The combination of words below are called your recovery phrase. The recovery phrase allows you to access and restore your wallet. Write them down on a piece of paper in the exact order:</p>
|
||||
</div>
|
||||
<ol id="RecoveryPhrase" data-mnemonic="@Model.Mnemonic" class="d-inline-block my-5 mx-auto ps-4">
|
||||
@foreach (var word in Model.Words)
|
||||
|
@ -13,7 +13,7 @@
|
||||
<label for="test-payment-amount" class="control-label form-label">Fake a {{cryptoCode}} payment for testing</label>
|
||||
<div class="d-flex gap-2 mb-2">
|
||||
<div class="input-group">
|
||||
<input id="test-payment-amount" name="Amount" type="number" :step="isSats ? '1' : '0.00000001'" min="0" class="form-control" placeholder="Amount" v-model="amount" :readonly="paying || paymentMethodId === 'BTC-LN'" />
|
||||
<input id="test-payment-amount" name="Amount" type="number" :step="isSats ? '1' : '0.00000001'" min="0" class="form-control" placeholder="@StringLocalizer["Amount"]" v-model="amount" :readonly="paying || paymentMethodId === 'BTC-LN'" />
|
||||
<div id="test-payment-crypto-code" class="input-group-addon input-group-text" v-text="cryptoCode"></div>
|
||||
</div>
|
||||
<button class="btn btn-secondary flex-shrink-0 px-3 w-100px" type="submit" :disabled="paying" id="FakePayment">Pay</button>
|
||||
|
@ -9,7 +9,7 @@
|
||||
<div class="form-group mb-1">
|
||||
<label for="test-payment-amount" class="control-label">{{$t("Fake a @Model.PaymentMethodCurrency payment for testing")}}</label>
|
||||
<div class="input-group">
|
||||
<input id="test-payment-amount" name="Amount" type="number" step="0.00000001" min="0" class="form-control" placeholder="Amount" value="@Model.Due" />
|
||||
<input id="test-payment-amount" name="Amount" type="number" step="0.00000001" min="0" class="form-control" placeholder="@StringLocalizer["Amount"]" value="@Model.Due" />
|
||||
<div id="test-payment-crypto-code" class="input-group-addon">@Model.PaymentMethodCurrency</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -3,7 +3,7 @@
|
||||
@using Microsoft.AspNetCore.Mvc.TagHelpers
|
||||
@using BTCPayServer.Abstractions.TagHelpers
|
||||
@{
|
||||
ViewData.SetActivePage(InvoiceNavPages.Create, "Create Invoice");
|
||||
ViewData.SetActivePage(InvoiceNavPages.Create, StringLocalizer["Create Invoice"]);
|
||||
}
|
||||
|
||||
@section PageFootContent {
|
||||
|
@ -155,7 +155,7 @@
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h4 class="modal-title" id="RefundTitle">Issue Refund</h4>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close">
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="@StringLocalizer["Close"]">
|
||||
<vc:icon symbol="close" />
|
||||
</button>
|
||||
</div>
|
||||
@ -194,17 +194,17 @@
|
||||
}
|
||||
else
|
||||
{
|
||||
<button class="btn btn-secondary text-nowrap" data-bs-toggle="tooltip" title="You can only refund an invoice that has been settled. Please wait for the transaction to confirm on the blockchain before attempting to refund it." disabled>Issue refund</button>
|
||||
<button class="btn btn-secondary text-nowrap" data-bs-toggle="tooltip" title="@StringLocalizer["You can only refund an invoice that has been settled. Please wait for the transaction to confirm on the blockchain before attempting to refund it."]" disabled>Issue refund</button>
|
||||
}
|
||||
<form asp-action="ToggleArchive" asp-route-invoiceId="@Model.Id" method="post">
|
||||
<button type="submit" class="btn btn-secondary" id="btn-archive-toggle">
|
||||
@if (Model.Archived)
|
||||
{
|
||||
<span class="text-nowrap" data-bs-toggle="tooltip" title="Unarchive this invoice">Unarchive</span>
|
||||
<span class="text-nowrap" data-bs-toggle="tooltip" title="@StringLocalizer["Unarchive this invoice"]">Unarchive</span>
|
||||
}
|
||||
else
|
||||
{
|
||||
<span class="text-nowrap" data-bs-toggle="tooltip" title="Archive this invoice so that it does not appear in the invoice list by default">Archive</span>
|
||||
<span class="text-nowrap" data-bs-toggle="tooltip" title="@StringLocalizer["Archive this invoice so that it does not appear in the invoice list by default"]">Archive</span>
|
||||
}
|
||||
</button>
|
||||
</form>
|
||||
|
@ -1,47 +0,0 @@
|
||||
@inject UserManager<ApplicationUser> _userManager
|
||||
|
||||
@* This is a temporary infobox to inform users about the state changes in 1.4.0. It should be removed eventually. *@
|
||||
@if ((await _userManager.GetUserAsync(User)).GetBlob()?.ShowInvoiceStatusChangeHint is true)
|
||||
{
|
||||
<div class="alert alert-light alert-dismissible fade show mb-5" role="alert">
|
||||
<form method="post" asp-controller="UIManage" asp-action="DisableShowInvoiceStatusChangeHint" id="invoicestatuschangeform">
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close">
|
||||
<vc:icon symbol="close" />
|
||||
</button>
|
||||
<h5 class="alert-heading">Updated in v1.4.0</h5>
|
||||
<p class="mb-2" text-translate="true">Invoice states have been updated to match the Greenfield API:</p>
|
||||
<div class="row">
|
||||
<div class="col-12 col-md-6">
|
||||
<ul class="list-unstyled mb-md-0">
|
||||
<li>
|
||||
<span text-translate="true" class="badge badge-processing">Paid</span>
|
||||
<span text-translate="true" class="mx-1">is now shown as</span>
|
||||
<span text-translate="true" class="badge badge-processing">Processing</span>
|
||||
</li>
|
||||
<li class="mt-2">
|
||||
<span text-translate="true" class="badge badge-settled">Completed</span>
|
||||
<span text-translate="true" class="mx-1">is now shown as</span>
|
||||
<span text-translate="true" class="badge badge-settled">Settled</span>
|
||||
</li>
|
||||
<li class="mt-2">
|
||||
<span text-translate="true" class="badge badge-settled">Confirmed</span>
|
||||
<span text-translate="true" class="mx-1">is now shown as</span>
|
||||
<span text-translate="true" class="badge badge-settled">Settled</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="col-12 col-md-6 d-flex justify-content-md-end align-items-md-end">
|
||||
<button name="command" type="submit" value="save" class="btn btn-sm btn-outline-secondary" data-bs-dismiss="alert" text-translate="true">Don't Show Again</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<script>
|
||||
document.getElementById("invoicestatuschangeform").addEventListener("submit", event => {
|
||||
event.preventDefault();
|
||||
const xhttp = new XMLHttpRequest();
|
||||
xhttp.open('POST', event.target.getAttribute('action'), true);
|
||||
xhttp.send(new FormData(event.target));
|
||||
});
|
||||
</script>
|
||||
}
|
@ -5,7 +5,7 @@
|
||||
@inject DisplayFormatter DisplayFormatter
|
||||
@model InvoicesModel
|
||||
@{
|
||||
ViewData.SetActivePage(InvoiceNavPages.Index, "Invoices");
|
||||
ViewData.SetActivePage(InvoiceNavPages.Index, StringLocalizer["Invoices"]);
|
||||
var statusFilterCount = CountArrayFilter("status") + CountArrayFilter("exceptionstatus") + (HasBooleanFilter("includearchived") ? 1 : 0) + (HasBooleanFilter("unusual") ? 1 : 0);
|
||||
var hasDateFilter = HasArrayFilter("startdate") || HasArrayFilter("enddate");
|
||||
var appFilterCount = Model.Apps.Count(app => HasArrayFilter("appid", app.Id));
|
||||
@ -123,24 +123,20 @@
|
||||
<div class="flex-fill">
|
||||
<p text-translate="true" class="mb-2">Invoices are documents issued by the seller to a buyer to collect payment.</p>
|
||||
<p text-translate="true" class="mb-3">An invoice must be paid within a defined time interval at a fixed exchange rate to protect the issuer from price fluctuations.</p>
|
||||
<p class="mb-3">
|
||||
You can also apply filters to your search by searching for <code>filtername:value</code>.
|
||||
Be sure to split your search parameters with comma. Supported filters are:
|
||||
</p>
|
||||
<p class="mb-3" html-translate="true">You can also apply filters to your search by searching for <code>filtername:value</code>. Be sure to split your search parameters with comma. Supported filters are:</p>
|
||||
<ul>
|
||||
<li><code>orderid:id</code> for filtering a specific order</li>
|
||||
<li><code>itemcode:code</code> for filtering a specific type of item purchased through the pos or crowdfund apps</li>
|
||||
<li html-translate="true"><code>orderid:id</code> for filtering a specific order</li>
|
||||
<li html-translate="true"><code>itemcode:code</code> for filtering a specific type of item purchased through the pos or crowdfund apps</li>
|
||||
</ul>
|
||||
<a href="https://docs.btcpayserver.org/Invoices/" target="_blank" rel="noreferrer noopener" text-translate="true">Learn More</a>
|
||||
</div>
|
||||
<button type="button" class="btn-close ms-auto" data-bs-toggle="collapse" data-bs-target="#descriptor" aria-expanded="false" aria-label="Close">
|
||||
<button type="button" class="btn-close ms-auto" data-bs-toggle="collapse" data-bs-target="#descriptor" aria-expanded="false" aria-label="@StringLocalizer["Close"]">
|
||||
<vc:icon symbol="close" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<partial name="_StatusMessage" />
|
||||
<partial name="InvoiceStatusChangePartial" />
|
||||
|
||||
@* Custom Range Modal *@
|
||||
<div class="modal fade" id="customRangeModal" tabindex="-1" role="dialog" aria-labelledby="customRangeModalTitle" aria-hidden="true" data-bs-backdrop="static">
|
||||
@ -148,7 +144,7 @@
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="customRangeModalTitle" text-translate="true">Filter invoices by Custom Range</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close">
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="@StringLocalizer["Close"]">
|
||||
<vc:icon symbol="close" />
|
||||
</button>
|
||||
</div>
|
||||
@ -159,8 +155,8 @@
|
||||
<div class="input-group">
|
||||
<input id="dtpStartDate" class="form-control flatdtpicker" type="datetime-local"
|
||||
data-fdtp='{ "enableTime": true, "enableSeconds": true, "dateFormat": "Y-m-d H:i:S", "time_24hr": true, "defaultHour": 0 }'
|
||||
placeholder="Start Date" />
|
||||
<button type="button" class="btn btn-secondary input-group-clear" title="Clear">
|
||||
placeholder="@StringLocalizer["Start Date"]" />
|
||||
<button type="button" class="btn btn-secondary input-group-clear" title="@StringLocalizer["Clear"]">
|
||||
<vc:icon symbol="close" />
|
||||
</button>
|
||||
</div>
|
||||
@ -172,8 +168,8 @@
|
||||
<div class="input-group">
|
||||
<input id="dtpEndDate" class="form-control flatdtpicker" type="datetime-local"
|
||||
data-fdtp='{ "enableTime": true, "enableSeconds": true, "dateFormat": "Y-m-d H:i:S", "time_24hr": true, "defaultHour": 0 }'
|
||||
placeholder="End Date" />
|
||||
<button type="button" class="btn btn-secondary input-group-clear" title="Clear">
|
||||
placeholder="@StringLocalizer["End Date"]" />
|
||||
<button type="button" class="btn btn-secondary input-group-clear" title="@StringLocalizer["Clear"]">
|
||||
<vc:icon symbol="close" />
|
||||
</button>
|
||||
</div>
|
||||
@ -191,12 +187,12 @@
|
||||
<input asp-for="Count" type="hidden" />
|
||||
<input asp-for="TimezoneOffset" type="hidden" />
|
||||
<input asp-for="SearchTerm" type="hidden" value="@Model.Search.WithoutSearchText()"/>
|
||||
<input asp-for="SearchText" class="form-control" placeholder="Search…" />
|
||||
<input asp-for="SearchText" class="form-control" placeholder="@StringLocalizer["Search…"]" />
|
||||
<div class="dropdown">
|
||||
<button id="StatusOptionsToggle" class="btn btn-secondary dropdown-toggle dropdown-toggle-custom-caret" type="button" data-bs-toggle="dropdown" aria-expanded="false">
|
||||
@if (statusFilterCount > 0)
|
||||
{
|
||||
<span>@statusFilterCount Status</span>
|
||||
<span>@StringLocalizer["{0} Status", statusFilterCount]</span>
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -287,7 +283,7 @@
|
||||
<th class="date-col">
|
||||
<div class="d-flex align-items-center gap-1">
|
||||
<span text-translate="true">Date</span>
|
||||
<button type="button" class="btn btn-link p-0 switch-time-format only-for-js" title="Switch date format">
|
||||
<button type="button" class="btn btn-link p-0 switch-time-format only-for-js" title="@StringLocalizer["Switch date format"]">
|
||||
<vc:icon symbol="time" />
|
||||
</button>
|
||||
</div>
|
||||
|
@ -2,7 +2,7 @@
|
||||
@using BTCPayServer.Abstractions.Models
|
||||
@model UILNURLController.EditLightningAddressVM
|
||||
@{
|
||||
ViewData.SetActivePage("LightningAddress", nameof(StoreNavPages), "Lightning Address", Context.GetStoreData().Id);
|
||||
ViewData.SetActivePage("LightningAddress", nameof(StoreNavPages), StringLocalizer["Lightning Address"], Context.GetStoreData().Id);
|
||||
}
|
||||
|
||||
@section PageHeadContent {
|
||||
@ -65,21 +65,21 @@
|
||||
<div id="AdvancedSettings" class="collapse @(showAdvancedOptions ? "show" : "")">
|
||||
<div class="row">
|
||||
<div class="col-12 col-sm-auto">
|
||||
<div class="form-group" title="The currency to generate the invoice in when generated through this lightning address ">
|
||||
<div class="form-group" title="@StringLocalizer["The currency to generate the invoice in when generated through this lightning address"]">
|
||||
<label asp-for="Add.CurrencyCode" class="form-label"></label>
|
||||
<input asp-for="Add.CurrencyCode" class="form-control w-auto" currency-selection style="max-width:16ch;"/>
|
||||
<span asp-validation-for="Add.CurrencyCode" class="text-danger"></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12 col-sm-auto">
|
||||
<div class="form-group" title="Minimum amount of sats to allow to be sent to this ln address">
|
||||
<div class="form-group" title="@StringLocalizer["Minimum amount of sats to allow to be sent to this ln address"]">
|
||||
<label asp-for="Add.Min" class="form-label"></label>
|
||||
<input asp-for="Add.Min" class="form-control" type="number" inputmode="numeric" min="1" style="max-width:16ch;"/>
|
||||
<span asp-validation-for="Add.Min" class="text-danger"></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12 col-sm-auto">
|
||||
<div class="form-group" title="Maximum amount of sats to allow to be sent to this ln address">
|
||||
<div class="form-group" title="@StringLocalizer["Maximum amount of sats to allow to be sent to this ln address"]">
|
||||
<label asp-for="Add.Max" class="form-label"></label>
|
||||
<input asp-for="Add.Max" class="form-control" type="number" inputmode="numeric" min="1" max="@int.MaxValue" style="max-width:16ch;"/>
|
||||
<span asp-validation-for="Add.Max" class="text-danger"></span>
|
||||
@ -162,7 +162,7 @@
|
||||
}
|
||||
else
|
||||
{
|
||||
<p class="text-secondary">
|
||||
<p class="text-secondary" text-translate="true">
|
||||
There are no Lightning Addresses yet.
|
||||
</p>
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
@using LNURL
|
||||
@model Uri
|
||||
@{
|
||||
ViewData.SetActivePage(ManageNavPages.TwoFactorAuthentication, "Register your Lightning node for LNURL Auth");
|
||||
ViewData.SetActivePage(ManageNavPages.TwoFactorAuthentication, StringLocalizer["Register your Lightning node for LNURL Auth"]);
|
||||
var formats = new Dictionary<string, string>
|
||||
{
|
||||
{ "Bech32", LNURL.EncodeUri(Model, "login", true).ToString().ToUpperInvariant() },
|
||||
|
@ -1,9 +1,13 @@
|
||||
@namespace BTCPayServer.Client
|
||||
@using BTCPayServer.Abstractions.Models
|
||||
@inject BTCPayServer.Security.ContentSecurityPolicies Csp
|
||||
@using BTCPayServer.Abstractions.TagHelpers
|
||||
@using BTCPayServer.TagHelpers
|
||||
@using Microsoft.AspNetCore.Html
|
||||
@using Microsoft.AspNetCore.Mvc.TagHelpers
|
||||
@inject Security.ContentSecurityPolicies Csp
|
||||
@model BTCPayServer.Controllers.UIManageController.ApiKeysViewModel
|
||||
@{
|
||||
ViewData.SetActivePage(ManageNavPages.APIKeys, "API Keys");
|
||||
ViewData.SetActivePage(ManageNavPages.APIKeys, StringLocalizer["API Keys"]);
|
||||
Csp.UnsafeEval();
|
||||
}
|
||||
|
||||
@ -17,9 +21,10 @@
|
||||
<div class="row">
|
||||
<div class="col-xl-10 col-xxl-constrain">
|
||||
<p>
|
||||
The <a asp-controller="UIHome" asp-action="SwaggerDocs" target="_blank">BTCPay Server Greenfield API</a> offers programmatic access to your instance. You can manage your BTCPay
|
||||
Server (e.g. stores, invoices, users) as well as automate workflows and integrations (see <a href="https://docs.btcpayserver.org/Development/GreenFieldExample/" rel="noreferrer noopener">use case examples</a>).
|
||||
For that you need the API keys, which can be generated here. Find more information in the <a href="@Url.Action("SwaggerDocs", "UIHome")#section/Authentication" target="_blank" rel="noreferrer noopener">API authentication docs</a>.
|
||||
@ViewLocalizer["The {0} offers programmatic access to your instance. You can manage your BTCPay Server (e.g. stores, invoices, users) as well as automate workflows and integrations (see {1}). For that you need the API keys, which can be generated here. Find more information in the {2}.",
|
||||
Html.ActionLink(StringLocalizer["Greenfield API"], "SwaggerDocs", "UIHome", new { }, new { target = "_blank", rel = "noreferrer noopener" }),
|
||||
new HtmlString($"<a href=\"https://docs.btcpayserver.org/Development/GreenFieldExample/\" target=\"_blank\" rel=\"noreferrer noopener\">{StringLocalizer["use case examples"]}</a>"),
|
||||
Html.ActionLink(StringLocalizer["API authentication docs"], "SwaggerDocs", "UIHome", null, null, "section/Authentication", new { }, new { target = "_blank", rel = "noreferrer noopener" })]
|
||||
</p>
|
||||
|
||||
@if (Model.ApiKeyDatas.Any())
|
||||
|
@ -113,7 +113,7 @@
|
||||
<select asp-for="PermissionValues[i].SpecificStores[index]" class="form-select w-auto flex-grow-0" asp-items="@(new SelectList(new[] {store}, nameof(StoreData.Id), nameof(StoreData.StoreName), store.Id))"></select>
|
||||
}
|
||||
<span asp-validation-for="PermissionValues[i].SpecificStores[index]" class="text-danger"></span>
|
||||
<button type="submit" title="Remove Store Permission" name="command" value="@($"{Model.PermissionValues[i].Permission}:remove-store:{index}")" class="btn btn-danger">
|
||||
<button type="submit" title="@StringLocalizer["Remove Store Permission"]" name="command" value="@($"{Model.PermissionValues[i].Permission}:remove-store:{index}")" class="btn btn-danger">
|
||||
Remove
|
||||
</button>
|
||||
</div>
|
||||
|
@ -90,10 +90,7 @@
|
||||
<h2 class="h5 fw-semibold mt-4" text-translate="true">Permissions</h2>
|
||||
@if (!groupedPermissions.Any())
|
||||
{
|
||||
<p text-translate="true">
|
||||
There are no associated permissions to the API key being requested by the application.
|
||||
The application cannot do anything with your BTCPay Server account other than validating your account exists.
|
||||
</p>
|
||||
<p text-translate="true">There are no associated permissions to the API key being requested by the application. The application cannot do anything with your BTCPay Server account other than validating your account exists.</p>
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1,6 +1,6 @@
|
||||
@model ChangePasswordViewModel
|
||||
@{
|
||||
ViewData.SetActivePage(ManageNavPages.ChangePassword, "Change your password");
|
||||
ViewData.SetActivePage(ManageNavPages.ChangePassword, StringLocalizer["Change your password"]);
|
||||
}
|
||||
|
||||
<form method="post">
|
||||
|
@ -1,6 +1,11 @@
|
||||
@using BTCPayServer.Components.QRCode
|
||||
@using BTCPayServer.Migrations
|
||||
@using BTCPayServer.TagHelpers
|
||||
@using Microsoft.AspNetCore.Html
|
||||
@using Microsoft.AspNetCore.Mvc.TagHelpers
|
||||
@model EnableAuthenticatorViewModel
|
||||
@{
|
||||
ViewData.SetActivePage(ManageNavPages.TwoFactorAuthentication, "Enable Authenticator App");
|
||||
ViewData.SetActivePage(ManageNavPages.TwoFactorAuthentication, StringLocalizer["Enable Authenticator App"]);
|
||||
}
|
||||
<div class="sticky-header">
|
||||
<nav aria-label="breadcrumb">
|
||||
@ -21,19 +26,20 @@
|
||||
<div class="mb-2" text-translate="true">Download a two-factor authenticator app like …</div>
|
||||
<ul>
|
||||
<li>
|
||||
Authy for
|
||||
<a href="https://play.google.com/store/apps/details?id=com.authy.authy" rel="noreferrer noopener">Android</a> or
|
||||
<a href="https://apps.apple.com/us/app/authy/id494168017" rel="noreferrer noopener">iOS</a>
|
||||
@ViewLocalizer["{0} for {1} or {2}", "Authy",
|
||||
new HtmlString("<a href=\"https://play.google.com/store/apps/details?id=com.authy.authy\" target=\"_blank\" rel=\"noreferrer noopener\">Android</a>"),
|
||||
new HtmlString("<a href=\"https://apps.apple.com/us/app/authy/id494168017\" target=\"_blank\" rel=\"noreferrer noopener\">iOS</a>")]
|
||||
</li>
|
||||
<li>
|
||||
Microsoft Authenticator for
|
||||
<a href="https://play.google.com/store/apps/details?id=com.azure.authenticator" rel="noreferrer noopener">Android</a> or
|
||||
<a href="https://apps.apple.com/us/app/microsoft-authenticator/id983156458" rel="noreferrer noopener">iOS</a>
|
||||
@ViewLocalizer["{0} for {1} or {2}", "Microsoft Authenticator",
|
||||
new HtmlString("<a href=\"https://play.google.com/store/apps/details?id=com.azure.authenticator\" target=\"_blank\" rel=\"noreferrer noopener\">Android</a>"),
|
||||
new HtmlString("<a href=\"https://apps.apple.com/us/app/microsoft-authenticator/id983156458\" target=\"_blank\" rel=\"noreferrer noopener\">iOS</a>")]
|
||||
</li>
|
||||
<li>
|
||||
Google Authenticator for
|
||||
<a href="https://play.google.com/store/apps/details?id=com.google.android.apps.authenticator2&hl=en" rel="noreferrer noopener">Android</a> or
|
||||
<a href="https://apps.apple.com/us/app/google-authenticator/id388497605" rel="noreferrer noopener">iOS</a>
|
||||
|
||||
@ViewLocalizer["{0} for {1} or {2}", "Google Authenticator",
|
||||
new HtmlString("<a href=\"https://play.google.com/store/apps/details?id=com.google.android.apps.authenticator2&hl=en\" target=\"_blank\" rel=\"noreferrer noopener\">Android</a>"),
|
||||
new HtmlString("<a href=\"https://apps.apple.com/us/app/google-authenticator/id388497605\" target=\"_blank\" rel=\"noreferrer noopener\">iOS</a>")]
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
|
@ -1,6 +1,6 @@
|
||||
@model GenerateRecoveryCodesViewModel
|
||||
@{
|
||||
ViewData.SetActivePage(ManageNavPages.TwoFactorAuthentication, "Recovery codes");
|
||||
ViewData.SetActivePage(ManageNavPages.TwoFactorAuthentication, StringLocalizer["Recovery codes"]);
|
||||
}
|
||||
|
||||
<h2 class="mb-2 mb-lg-3" text-translate="true">@ViewData["Title"]</h2>
|
||||
|
@ -4,7 +4,7 @@
|
||||
@inject IFileService FileService
|
||||
@model IndexViewModel
|
||||
@{
|
||||
ViewData.SetActivePage(ManageNavPages.Index, "Update your account");
|
||||
ViewData.SetActivePage(ManageNavPages.Index, StringLocalizer["Update your account"]);
|
||||
var canUpload = await FileService.IsAvailable();
|
||||
}
|
||||
|
||||
@ -62,7 +62,7 @@
|
||||
<input asp-for="ImageFile" type="file" class="form-control flex-grow">
|
||||
@if (!string.IsNullOrEmpty(Model.ImageUrl))
|
||||
{
|
||||
<img src="@Model.ImageUrl" alt="Profile picture" class="profile-picture"/>
|
||||
<img src="@Model.ImageUrl" alt="@StringLocalizer["Profile Picture"]" class="profile-picture"/>
|
||||
}
|
||||
</div>
|
||||
<span asp-validation-for="ImageFile" class="text-danger"></span>
|
||||
@ -70,12 +70,12 @@
|
||||
}
|
||||
<h3 class="mt-5 mb-4" text-translate="true">Delete Account</h3>
|
||||
<div id="danger-zone">
|
||||
<a id="delete-user" class="btn btn-outline-danger mb-5" data-confirm-input="DELETE" data-bs-toggle="modal" data-bs-target="#ConfirmModal" asp-action="DeleteUserPost" data-description="This action will also delete all stores, invoices, apps and data associated with the user." text-translate="true">Delete Account</a>
|
||||
<a id="delete-user" class="btn btn-outline-danger mb-5" data-confirm-input="DELETE" data-bs-toggle="modal" data-bs-target="#ConfirmModal" asp-action="DeleteUserPost" data-description="@StringLocalizer["This action will also delete all stores, invoices, apps and data associated with the user."]" text-translate="true">Delete Account</a>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
<partial name="_Confirm"
|
||||
model="@(new ConfirmModel("Delete user", "The user will be permanently deleted. This action will also delete all stores, invoices, apps and data associated with your user.", "Delete", actionName: nameof(BTCPayServer.Controllers.UIManageController.DeleteUserPost)))"/>
|
||||
model="@(new ConfirmModel(StringLocalizer["Delete user"], StringLocalizer["The user will be permanently deleted. This action will also delete all stores, invoices, apps and data associated with your user."], StringLocalizer["Delete"], actionName: nameof(BTCPayServer.Controllers.UIManageController.DeleteUserPost)))"/>
|
||||
|
||||
@section PageFootContent {
|
||||
<partial name="_ValidationScriptsPartial"/>
|
||||
|
@ -1,6 +1,6 @@
|
||||
@inject UserManager<ApplicationUser> UserManager;
|
||||
@{
|
||||
ViewData.SetActivePage(ManageNavPages.LoginCodes, "Login Codes");
|
||||
ViewData.SetActivePage(ManageNavPages.LoginCodes, StringLocalizer["Login Codes"]);
|
||||
}
|
||||
|
||||
<div class="sticky-header">
|
||||
|
@ -1,6 +1,6 @@
|
||||
@model BTCPayServer.Controllers.UIManageController.NotificationSettingsViewModel
|
||||
@{
|
||||
ViewData.SetActivePage(ManageNavPages.Notifications, "Notification Settings");
|
||||
ViewData.SetActivePage(ManageNavPages.Notifications, StringLocalizer["Notification Settings"]);
|
||||
}
|
||||
|
||||
<form method="post" asp-action="NotificationSettings">
|
||||
@ -22,7 +22,7 @@
|
||||
@if (Model.All)
|
||||
{
|
||||
<p text-translate="true">All notifications are disabled.</p>
|
||||
<button type="submit" class="btn btn-primary" name="command" value="enable-all">Enable notifications</button>
|
||||
<button type="submit" class="btn btn-primary" name="command" value="enable-all" text-translate="true">Enable notifications</button>
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -33,9 +33,7 @@
|
||||
<div class="d-flex align-items-center my-3">
|
||||
<input type="hidden" asp-for="DisabledNotifications[index].Value" />
|
||||
<input type="checkbox" asp-for="DisabledNotifications[index].Selected" class="btcpay-toggle me-3" />
|
||||
<label class="form-check-label cursor-pointer" asp-for="DisabledNotifications[index].Selected">
|
||||
@item.Text
|
||||
</label>
|
||||
<label class="form-check-label cursor-pointer" asp-for="DisabledNotifications[index].Selected" text-translate="true">@item.Text</label>
|
||||
</div>
|
||||
}
|
||||
<div class="mt-4">
|
||||
|
@ -1,6 +1,6 @@
|
||||
@model BTCPayServer.Models.ManageViewModels.SetPasswordViewModel
|
||||
@{
|
||||
ViewData.SetActivePage(ManageNavPages.ChangePassword, "Set your password");
|
||||
ViewData.SetActivePage(ManageNavPages.ChangePassword, StringLocalizer["Set your password"]);
|
||||
}
|
||||
|
||||
<form method="post">
|
||||
@ -10,10 +10,7 @@
|
||||
</div>
|
||||
<partial name="_StatusMessage" />
|
||||
|
||||
<p class="text-info" text-translate="true">
|
||||
You do not have a local username/password for this site. Add a local
|
||||
account so you can log in without an external login.
|
||||
</p>
|
||||
<p class="text-info" text-translate="true">You do not have a local username/password for this site. Add a local account so you can log in without an external login.</p>
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
@if (!ViewContext.ModelState.IsValid)
|
||||
|
@ -1,7 +1,7 @@
|
||||
@using BTCPayServer.Abstractions.Models
|
||||
@model TwoFactorAuthenticationViewModel
|
||||
@{
|
||||
ViewData.SetActivePage(ManageNavPages.TwoFactorAuthentication, "Two-Factor Authentication");
|
||||
ViewData.SetActivePage(ManageNavPages.TwoFactorAuthentication, StringLocalizer["Two-Factor Authentication"]);
|
||||
}
|
||||
<div class="sticky-header">
|
||||
<h2 class="my-1" text-translate="true">@ViewData["Title"]</h2>
|
||||
@ -9,12 +9,7 @@
|
||||
<partial name="_StatusMessage" />
|
||||
<div class="row">
|
||||
<div class="col-xl-8 col-xxl-constrain">
|
||||
<p text-translate="true">
|
||||
Two-Factor Authentication (2FA) is an additional measure to protect your account.
|
||||
In addition to your password you will be asked for a second proof on login.
|
||||
This can be provided by an app (such as Google or Microsoft Authenticator)
|
||||
or a security device (like a Yubikey or your hardware wallet supporting FIDO2).
|
||||
</p>
|
||||
<p text-translate="true">Two-Factor Authentication (2FA) is an additional measure to protect your account. In addition to your password you will be asked for a second proof on login. This can be provided by an app (such as Google or Microsoft Authenticator) or a security device (like a Yubikey or your hardware wallet supporting FIDO2).</p>
|
||||
|
||||
<h4 class="mb-3" text-translate="true">App-based 2FA</h4>
|
||||
|
||||
@ -55,21 +50,21 @@
|
||||
<div class="list-group mb-3">
|
||||
@if (Model.Is2faEnabled)
|
||||
{
|
||||
<a asp-action="Disable2fa" class="list-group-item d-flex justify-content-between align-items-center list-group-item-action py-3" data-bs-toggle="modal" data-bs-target="#ConfirmModal" data-title="Disable two-factor authentication (2FA)" data-description="Disabling 2FA does not change the keys used in the authenticator apps. If you wish to change the key used in an authenticator app you should reset your authenticator keys." data-confirm="Disable" data-confirm-input="DISABLE">
|
||||
<a asp-action="Disable2fa" class="list-group-item d-flex justify-content-between align-items-center list-group-item-action py-3" data-bs-toggle="modal" data-bs-target="#ConfirmModal" data-title="@StringLocalizer["Disable two-factor authentication (2FA)"]" data-description="@StringLocalizer["Disabling 2FA does not change the keys used in the authenticator apps. If you wish to change the key used in an authenticator app you should reset your authenticator keys."]" data-confirm="@StringLocalizer["Disable"]" data-confirm-input="@StringLocalizer["DISABLE"]">
|
||||
<div>
|
||||
<h5 text-translate="true">Disable 2FA</h5>
|
||||
<p class="mb-0 me-3" text-translate="true">Re-enabling will not require you to reconfigure your app.</p>
|
||||
</div>
|
||||
<vc:icon symbol="caret-right"/>
|
||||
</a>
|
||||
<a asp-action="GenerateRecoveryCodes" class="list-group-item d-flex justify-content-between align-items-center list-group-item-action py-3" data-bs-toggle="modal" data-bs-target="#ConfirmModal" data-title="Reset recovery codes" data-description="Your existing recovery codes will no longer be valid!" data-confirm="Reset" data-confirm-input="RESET">
|
||||
<a asp-action="GenerateRecoveryCodes" class="list-group-item d-flex justify-content-between align-items-center list-group-item-action py-3" data-bs-toggle="modal" data-bs-target="#ConfirmModal" data-title="@StringLocalizer["Reset recovery codes"]" data-description="@StringLocalizer["Your existing recovery codes will no longer be valid!"]" data-confirm="@StringLocalizer["Reset"]" data-confirm-input="@StringLocalizer["RESET"]">
|
||||
<div>
|
||||
<h5 text-translate="true">Reset recovery codes</h5>
|
||||
<p class="mb-0 me-3" text-translate="true">Regenerate your 2FA recovery codes.</p>
|
||||
</div>
|
||||
<vc:icon symbol="caret-right"/>
|
||||
</a>
|
||||
<a asp-action="ResetAuthenticator" class="list-group-item d-flex justify-content-between align-items-center list-group-item-action py-3" data-bs-toggle="modal" data-bs-target="#ConfirmModal" data-title="Reset authenticator app" data-description="This process disables 2FA until you verify your authenticator app and will also reset your 2FA recovery codes. If you do not complete your authenticator app configuration you may lose access to your account." data-confirm="Reset" data-confirm-input="RESET">
|
||||
<a asp-action="ResetAuthenticator" class="list-group-item d-flex justify-content-between align-items-center list-group-item-action py-3" data-bs-toggle="modal" data-bs-target="#ConfirmModal" data-title="@StringLocalizer["Reset authenticator app"]" data-description="@StringLocalizer["This process disables 2FA until you verify your authenticator app and will also reset your 2FA recovery codes. If you do not complete your authenticator app configuration you may lose access to your account."]" data-confirm="@StringLocalizer["Reset"]" data-confirm-input="@StringLocalizer["RESET"]">
|
||||
<div>
|
||||
<h5 text-translate="true">Reset app</h5>
|
||||
<p class="mb-0 me-3" text-translate="true">Invalidates the current authenticator configuration. Useful if you believe your authenticator settings were compromised.</p>
|
||||
@ -120,11 +115,11 @@
|
||||
|
||||
@if (device.Type == Fido2Credential.CredentialType.FIDO2)
|
||||
{
|
||||
<a asp-controller="UIFido2" asp-action="Remove" asp-route-id="@device.Id" class="btn btn-outline-danger" data-bs-toggle="modal" data-bs-target="#ConfirmModal" data-title="Remove security device" data-description="Your account will no longer have the security device <strong>@Html.Encode(name)</strong> as an option for two-factor authentication." data-confirm="Remove" data-confirm-input="REMOVE" text-translate="true">Remove</a>
|
||||
<a asp-controller="UIFido2" asp-action="Remove" asp-route-id="@device.Id" class="btn btn-outline-danger" data-bs-toggle="modal" data-bs-target="#ConfirmModal" data-title="@StringLocalizer["Remove security device"]" data-description="@ViewLocalizer["Your account will no longer have the security device <strong>{0}</strong> as an option for two-factor authentication.", Html.Encode(name)]" data-confirm="@StringLocalizer["Remove"]" data-confirm-input="@StringLocalizer["REMOVE"]" text-translate="true">Remove</a>
|
||||
}
|
||||
else if (device.Type == Fido2Credential.CredentialType.LNURLAuth)
|
||||
{
|
||||
<a asp-controller="UILNURLAuth" asp-action="Remove" asp-route-id="@device.Id" class="btn btn-outline-danger" data-bs-toggle="modal" data-bs-target="#ConfirmModal" data-title="Remove Lightning security" data-description="Your account will no longer be linked to the lightning node <strong>@Html.Encode(name)</strong> as an option for two-factor authentication." data-confirm="Remove" data-confirm-input="REMOVE" text-translate="true">Remove</a>
|
||||
<a asp-controller="UILNURLAuth" asp-action="Remove" asp-route-id="@device.Id" class="btn btn-outline-danger" data-bs-toggle="modal" data-bs-target="#ConfirmModal" data-title="@StringLocalizer["Remove Lightning security"]" data-description="@ViewLocalizer["Your account will no longer be linked to the lightning node <strong>{0}</strong> as an option for two-factor authentication.", Html.Encode(name)]" data-confirm="@StringLocalizer["Remove"]" data-confirm-input="@StringLocalizer["REMOVE"]" text-translate="true">Remove</a>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
@ -133,7 +128,7 @@
|
||||
|
||||
<form asp-action="CreateCredential">
|
||||
<div class="input-group">
|
||||
<input type="text" class="form-control" name="Name" placeholder="Security device name"/>
|
||||
<input type="text" class="form-control" name="Name" placeholder="@StringLocalizer["Security device name"]"/>
|
||||
<select asp-items="@Html.GetEnumSelectList<Fido2Credential.CredentialType>()" class="form-select w-auto" name="type"></select>
|
||||
<button id="btn-add" type="submit" class="btn btn-primary" text-translate="true">
|
||||
Add
|
||||
@ -143,4 +138,4 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<partial name="_Confirm" model="@(new ConfirmModel("Two-Factor Authentication", "Placeholder", "Placeholder"))"/>
|
||||
<partial name="_Confirm" model="@(new ConfirmModel(StringLocalizer["Two-Factor Authentication"], StringLocalizer["Placeholder"], StringLocalizer["Placeholder"]))"/>
|
||||
|
@ -3,7 +3,7 @@
|
||||
@model MoneroLikePaymentMethodViewModel
|
||||
|
||||
@{
|
||||
ViewData.SetActivePage(Model.CryptoCode, $"{Model.CryptoCode} Settings", Model.CryptoCode);
|
||||
ViewData.SetActivePage(Model.CryptoCode, StringLocalizer["{0} Settings", Model.CryptoCode], Model.CryptoCode);
|
||||
}
|
||||
|
||||
<partial name="_StatusMessage" />
|
||||
@ -83,7 +83,7 @@
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="input-group my-3">
|
||||
<input type="text" class="form-control" placeholder="New account label" asp-for="NewAccountLabel">
|
||||
<input type="text" class="form-control" placeholder="@StringLocalizer["New account label"]" asp-for="NewAccountLabel">
|
||||
<button name="command" value="add-account" class="input-group-text btn btn-secondary" type="submit">Add account</button>
|
||||
</div>
|
||||
</div>
|
||||
@ -97,7 +97,7 @@
|
||||
|
||||
<div class="form-group">
|
||||
<label asp-for="SettlementConfirmationThresholdChoice" class="form-label"></label>
|
||||
<a href="https://docs.btcpayserver.org/FAQ/Stores/#consider-the-invoice-confirmed-when-the-payment-transaction" target="_blank" rel="noreferrer noopener" title="More information...">
|
||||
<a href="https://docs.btcpayserver.org/FAQ/Stores/#consider-the-invoice-confirmed-when-the-payment-transaction" target="_blank" rel="noreferrer noopener" title="@StringLocalizer["More information..."]">
|
||||
<vc:icon symbol="info" />
|
||||
</a>
|
||||
<select
|
||||
|
@ -1,7 +1,7 @@
|
||||
@model BTCPayServer.Services.Altcoins.Monero.UI.UIMoneroLikeStoreController.MoneroLikePaymentMethodListViewModel
|
||||
|
||||
@{
|
||||
ViewData.SetActivePage("Monero Settings", "Monero Settings", "Monero Settings");
|
||||
ViewData.SetActivePage("Monero Settings", StringLocalizer["{0} Settings", "Monero"], "Monero Settings");
|
||||
}
|
||||
|
||||
<div class="row">
|
||||
|
@ -44,7 +44,7 @@
|
||||
<input type="hidden" asp-for="Status" value="@Model.Status" />
|
||||
|
||||
<div class="col-12 col-md-6 col-lg-4 mb-3 mb-md-0">
|
||||
<input asp-for="SearchText" class="form-control" placeholder="Search…" />
|
||||
<input asp-for="SearchText" class="form-control" placeholder="@StringLocalizer["Search…"]" />
|
||||
</div>
|
||||
|
||||
<div class="btn-group col-12 col-md-auto mb-3 mb-md-0" role="group" aria-label="View Notification">
|
||||
@ -76,11 +76,11 @@
|
||||
}
|
||||
</button>
|
||||
<div class="dropdown-menu" aria-labelledby="StatusOptionsToggle">
|
||||
<a asp-action="Index" asp-route-count="@Model.Count" asp-route-status="@Model.Status" asp-route-searchTerm="@Model.Search.Toggle("type", "invoicestate")" class="dropdown-item @(HasArrayFilter("type", "invoicestate") ? "custom-active" : "")">Invoice</a>
|
||||
<a asp-action="Index" asp-route-count="@Model.Count" asp-route-status="@Model.Status" asp-route-searchTerm="@Model.Search.Toggle("type", "payout")" class="dropdown-item @(HasArrayFilter("type", "payout") ? "custom-active" : "")">Payouts</a>
|
||||
<a asp-action="Index" asp-route-count="@Model.Count" asp-route-status="@Model.Status" asp-route-searchTerm="@Model.Search.Toggle("type", "newversion")" class="dropdown-item @(HasArrayFilter("type", "newversion") ? "custom-active" : "")">New Version</a>
|
||||
<a asp-action="Index" asp-route-count="@Model.Count" asp-route-status="@Model.Status" asp-route-searchTerm="@Model.Search.Toggle("type", "pluginupdate")" class="dropdown-item @(HasArrayFilter("type", "pluginupdate") ? "custom-active" : "")">Plugin Updates</a>
|
||||
<a asp-action="Index" asp-route-count="@Model.Count" asp-route-status="@Model.Status" asp-route-searchTerm="@Model.Search.Toggle("type", "userupdate")" class="dropdown-item @(HasArrayFilter("type", "userupdate") ? "custom-active" : "")">User Updates</a>
|
||||
<a asp-action="Index" asp-route-count="@Model.Count" asp-route-status="@Model.Status" asp-route-searchTerm="@Model.Search.Toggle("type", "invoicestate")" class="dropdown-item @(HasArrayFilter("type", "invoicestate") ? "custom-active" : "")" text-translate="true">Invoice</a>
|
||||
<a asp-action="Index" asp-route-count="@Model.Count" asp-route-status="@Model.Status" asp-route-searchTerm="@Model.Search.Toggle("type", "payout")" class="dropdown-item @(HasArrayFilter("type", "payout") ? "custom-active" : "")" text-translate="true">Payouts</a>
|
||||
<a asp-action="Index" asp-route-count="@Model.Count" asp-route-status="@Model.Status" asp-route-searchTerm="@Model.Search.Toggle("type", "newversion")" class="dropdown-item @(HasArrayFilter("type", "newversion") ? "custom-active" : "")" text-translate="true">New Version</a>
|
||||
<a asp-action="Index" asp-route-count="@Model.Count" asp-route-status="@Model.Status" asp-route-searchTerm="@Model.Search.Toggle("type", "pluginupdate")" class="dropdown-item @(HasArrayFilter("type", "pluginupdate") ? "custom-active" : "")" text-translate="true">Plugin Updates</a>
|
||||
<a asp-action="Index" asp-route-count="@Model.Count" asp-route-status="@Model.Status" asp-route-searchTerm="@Model.Search.Toggle("type", "userupdate")" class="dropdown-item @(HasArrayFilter("type", "userupdate") ? "custom-active" : "")" text-translate="true">User Updates</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -88,7 +88,7 @@
|
||||
<button id="StoresOptionsToggle" class="btn btn-secondary dropdown-toggle dropdown-toggle-custom-caret w-100 w-md-auto" type="button" data-bs-toggle="dropdown" aria-expanded="false">
|
||||
@if (storesFilterCount > 0)
|
||||
{
|
||||
<span>@storesFilterCount Store@(storesFilterCount > 1 ? "s" : "")</span>
|
||||
<span>@(storesFilterCount == 1 ? StringLocalizer["{0} Store", storesFilterCount] : StringLocalizer["{0} Stores", storesFilterCount])</span>
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -110,8 +110,6 @@
|
||||
</div>
|
||||
</form>
|
||||
|
||||
|
||||
|
||||
@if (Model.Items.Count > 0)
|
||||
{
|
||||
<form method="post" asp-action="MassAction">
|
||||
@ -128,7 +126,7 @@
|
||||
<th class="date-col">
|
||||
<div class="d-flex align-items-center gap-1">
|
||||
<span text-translate="true">Date</span>
|
||||
<button type="button" class="btn btn-link p-0 switch-time-format only-for-js" title="Switch date format">
|
||||
<button type="button" class="btn btn-link p-0 switch-time-format only-for-js" title="@StringLocalizer["Switch date format"]">
|
||||
<vc:icon symbol="time" />
|
||||
</button>
|
||||
</div>
|
||||
@ -182,12 +180,12 @@
|
||||
<div class="d-inline-flex align-items-center gap-3">
|
||||
@if (!string.IsNullOrEmpty(item.ActionLink))
|
||||
{
|
||||
<a href="@item.ActionLink" class="btn btn-link p-0" rel="noreferrer noopener">Details</a>
|
||||
<a href="@item.ActionLink" class="btn btn-link p-0" rel="noreferrer noopener" text-translate="true">Details</a>
|
||||
}
|
||||
@if (!item.Seen)
|
||||
{
|
||||
<button class="btn btn-link p-0 btn-toggle-seen text-nowrap" type="submit" name="command" value="flip-individual:@(item.Id)">
|
||||
<span>Mark as seen</span>
|
||||
<span text-translate="true">Mark as seen</span>
|
||||
</button>
|
||||
}
|
||||
</div>
|
||||
@ -204,14 +202,11 @@
|
||||
}
|
||||
else
|
||||
{
|
||||
<p class="text-secondary mt-3">
|
||||
<p class="text-secondary mt-3" text-translate="true">
|
||||
There are no notifications.
|
||||
</p>
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
<style>
|
||||
.notification-row.loading {
|
||||
cursor: wait;
|
||||
|
@ -9,7 +9,7 @@
|
||||
@{
|
||||
var checkoutFormOptions = await FormDataService.GetSelect(Model.StoreId, Model.FormId);
|
||||
|
||||
ViewData.SetActivePage(PaymentRequestsNavPages.Create, $"{(string.IsNullOrEmpty(Model.Id) ? "Create" : "Edit")} Payment Request", Model.Id);
|
||||
ViewData.SetActivePage(PaymentRequestsNavPages.Create, string.IsNullOrEmpty(Model.Id) ? StringLocalizer["Create Payment Request"] : StringLocalizer["Edit Payment Request"], Model.Id);
|
||||
}
|
||||
|
||||
@section PageHeadContent {
|
||||
@ -87,8 +87,8 @@
|
||||
<div class="input-group ">
|
||||
<input asp-for="ExpiryDate"
|
||||
value="@(Model.ExpiryDate?.ToString("u", CultureInfo.InvariantCulture))"
|
||||
class="form-control flatdtpicker" min="today" placeholder="No expiry date has been set for this payment request" />
|
||||
<button id="ClearExpiryDate" class="btn btn-secondary input-group-clear" type="button" title="Clear">
|
||||
class="form-control flatdtpicker" min="today" placeholder="@StringLocalizer["No expiry date has been set for this payment request"]" />
|
||||
<button id="ClearExpiryDate" class="btn btn-secondary input-group-clear" type="button" title="@StringLocalizer["Clear"]">
|
||||
<vc:icon symbol="close" />
|
||||
</button>
|
||||
</div>
|
||||
@ -96,11 +96,10 @@
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label asp-for="Email" class="form-label"></label>
|
||||
<input type="email" asp-for="Email" placeholder="Firstname Lastname <email@example.com>" class="form-control" />
|
||||
<input type="email" asp-for="Email" placeholder="@StringLocalizer["Firstname Lastname <email@example.com>"]" class="form-control" />
|
||||
<span asp-validation-for="Email" class="text-danger"></span>
|
||||
<div id="PaymentRequestEmailHelpBlock" class="form-text">
|
||||
This will send notification mails to the recipient, as configured by the
|
||||
<a asp-action="StoreEmails" asp-controller="UIStores" asp-route-storeId="@Model.StoreId">email rules</a>.
|
||||
@ViewLocalizer["This will send notification mails to the recipient, as configured by the {0}.", Html.ActionLink(StringLocalizer["email rules"], "StoreEmails", "UIStores", new { storeId = Model.StoreId })]
|
||||
@if (Model.HasEmailRules is not true)
|
||||
{
|
||||
<div class="info-note mt-1 text-warning" role="alert">
|
||||
@ -148,11 +147,11 @@
|
||||
<a class="btn btn-secondary" asp-route-payReqId="@Model.Id" asp-action="ClonePaymentRequest" id="ClonePaymentRequest" permission="@Policies.CanModifyPaymentRequests" text-translate="true">Clone</a>
|
||||
@if (!Model.Archived)
|
||||
{
|
||||
<a class="btn btn-secondary" data-bs-toggle="tooltip" title="Archive this payment request so that it does not appear in the payment request list by default" asp-controller="UIPaymentRequest" asp-action="TogglePaymentRequestArchival" asp-route-payReqId="@Model.Id" id="ArchivePaymentRequest" permission="@Policies.CanModifyPaymentRequests" text-translate="true">Archive</a>
|
||||
<a class="btn btn-secondary" data-bs-toggle="tooltip" title="@StringLocalizer["Archive this payment request so that it does not appear in the payment request list by default"]" asp-controller="UIPaymentRequest" asp-action="TogglePaymentRequestArchival" asp-route-payReqId="@Model.Id" id="ArchivePaymentRequest" permission="@Policies.CanModifyPaymentRequests" text-translate="true">Archive</a>
|
||||
}
|
||||
else
|
||||
{
|
||||
<a class="btn btn-secondary" data-bs-toggle="tooltip" title="Unarchive this payment request" asp-controller="UIPaymentRequest" asp-action="TogglePaymentRequestArchival" asp-route-payReqId="@Model.Id" id="UnarchivePaymentRequest" permission="@Policies.CanModifyPaymentRequests" text-translate="true">Unarchive</a>
|
||||
<a class="btn btn-secondary" data-bs-toggle="tooltip" title="@StringLocalizer["Unarchive this payment request"]" asp-controller="UIPaymentRequest" asp-action="TogglePaymentRequestArchival" asp-route-payReqId="@Model.Id" id="UnarchivePaymentRequest" permission="@Policies.CanModifyPaymentRequests" text-translate="true">Unarchive</a>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
|
@ -42,7 +42,7 @@
|
||||
<p class="mb-3" text-translate="true">Requests may be paid in partial. They will remain valid until time expires or when paid what is due.</p>
|
||||
<a href="https://docs.btcpayserver.org/PaymentRequests/" target="_blank" rel="noreferrer noopener" text-translate="true">Learn More</a>
|
||||
</div>
|
||||
<button type="button" class="btn-close ms-auto" data-bs-toggle="collapse" data-bs-target="#descriptor" aria-expanded="false" aria-label="Close">
|
||||
<button type="button" class="btn-close ms-auto" data-bs-toggle="collapse" data-bs-target="#descriptor" aria-expanded="false" aria-label="@StringLocalizer["Close"]">
|
||||
<vc:icon symbol="close" />
|
||||
</button>
|
||||
</div>
|
||||
@ -54,7 +54,7 @@
|
||||
<input type="hidden" asp-for="Count" />
|
||||
<input type="hidden" asp-for="TimezoneOffset" />
|
||||
<input asp-for="SearchTerm" type="hidden" value="@Model.Search.WithoutSearchText()"/>
|
||||
<input asp-for="SearchText" class="form-control" placeholder="Search…" />
|
||||
<input asp-for="SearchText" class="form-control" placeholder="@StringLocalizer["Search…"]" />
|
||||
<div class="dropdown">
|
||||
<button id="StatusOptionsToggle" class="btn btn-secondary dropdown-toggle dropdown-toggle-custom-caret" type="button" data-bs-toggle="dropdown" aria-expanded="false">
|
||||
@if (statusFilterCount > 0)
|
||||
@ -86,7 +86,7 @@
|
||||
<th class="date-col">
|
||||
<div class="d-flex align-items-center gap-1">
|
||||
<span text-translate="true">Expiry</span>
|
||||
<button type="button" class="btn btn-link p-0 switch-time-format only-for-js" title="Switch date format">
|
||||
<button type="button" class="btn btn-link p-0 switch-time-format only-for-js" title="@StringLocalizer["Switch date format"]">
|
||||
<vc:icon symbol="time" />
|
||||
</button>
|
||||
</div>
|
||||
@ -138,7 +138,7 @@
|
||||
}
|
||||
else
|
||||
{
|
||||
<p class="text-secondary mt-3">
|
||||
<p class="text-secondary mt-3" text-translate="true">
|
||||
There are no payment requests matching your criteria.
|
||||
</p>
|
||||
}
|
||||
|
@ -145,7 +145,7 @@
|
||||
<template v-if="srvModel.allowCustomPaymentAmounts && !srvModel.anyPendingInvoice">
|
||||
<form v-on:submit="submitCustomAmountForm">
|
||||
<div class="input-group mb-3">
|
||||
<input type="number" class="form-control text-end hide-number-spin" v-model="customAmount" :readonly="!srvModel.allowCustomPaymentAmounts" :max="srvModel.amountDue" placeholder="Amount" step="any" required />
|
||||
<input type="number" class="form-control text-end hide-number-spin" v-model="customAmount" :readonly="!srvModel.allowCustomPaymentAmounts" :max="srvModel.amountDue" placeholder="@StringLocalizer["Amount"]" step="any" required />
|
||||
<span class="input-group-text">{{currency}}</span>
|
||||
</div>
|
||||
<button class="btn btn-primary btn-lg w-100 d-flex align-items-center justify-content-center text-nowrap" v-bind:class="{ 'btn-disabled': loading }" :disabled="loading" type="submit" id="PayInvoice">
|
||||
@ -189,7 +189,7 @@
|
||||
{
|
||||
<form method="get" asp-action="PayPaymentRequest" asp-route-payReqId="@Model.Id">
|
||||
<div class="input-group mb-3">
|
||||
<input type="number" class="form-control text-end hide-number-spin" name="amount" value="@Model.AmountDue" @if (!Model.AllowCustomPaymentAmounts) { @("readonly") } max="@Model.AmountDue" step="any" placeholder="Amount" required />
|
||||
<input type="number" class="form-control text-end hide-number-spin" name="amount" value="@Model.AmountDue" @if (!Model.AllowCustomPaymentAmounts) { @("readonly") } max="@Model.AmountDue" step="any" placeholder="@StringLocalizer["Amount"]" required />
|
||||
<span class="input-group-text">@Model.Currency.ToUpper()</span>
|
||||
</div>
|
||||
<button class="btn btn-primary btn-lg w-100 text-nowrap" type="submit" id="PayInvoice" text-translate="true">Pay Invoice</button>
|
||||
|
@ -5,7 +5,7 @@
|
||||
@model List<BTCPayServer.PayoutProcessors.UIPayoutProcessorsController.StorePayoutProcessorsView>
|
||||
@{
|
||||
var storeId = Context.GetStoreData().Id;
|
||||
ViewData.SetActivePage(StoreNavPages.PayoutProcessors, "Payout Processors", storeId);
|
||||
ViewData.SetActivePage(StoreNavPages.PayoutProcessors, StringLocalizer["Payout Processors"], storeId);
|
||||
}
|
||||
<div class="sticky-header">
|
||||
<h2 class="my-1" text-translate="true">@ViewData["Title"]</h2>
|
||||
@ -26,7 +26,7 @@
|
||||
<thead>
|
||||
<tr>
|
||||
<th text-translate="true">Payment Method</th>
|
||||
<th class="actions-col" permission="@Policies.CanModifyStoreSettings">Actions</th>
|
||||
<th class="actions-col" permission="@Policies.CanModifyStoreSettings"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
@ -2,7 +2,7 @@
|
||||
@model BTCPayServer.Controllers.ShowLightningNodeInfoViewModel
|
||||
@{
|
||||
Layout = null;
|
||||
ViewData["Title"] = $"{Model.StoreName} – {Model.CryptoCode} Lightning Node";
|
||||
ViewData["Title"] = $"{Model.StoreName} – {StringLocalizer["{0} Lightning Node", Model.CryptoCode]}";
|
||||
ViewData["StoreBranding"] = Model.StoreBranding;
|
||||
}
|
||||
<!DOCTYPE html>
|
||||
@ -19,12 +19,11 @@
|
||||
<partial name="_StoreHeader" model="(Model.StoreName, Model.StoreBranding)" />
|
||||
<section class="tile">
|
||||
<h2 class="h4 card-subtitle text-center text-secondary mt-1 mb-3" id="LightningNodeTitle">
|
||||
<span>@Model.CryptoCode</span>
|
||||
<span text-translate="true">Lightning Node</span>
|
||||
@StringLocalizer["{0} Lightning Node", Model.CryptoCode]
|
||||
</h2>
|
||||
<h4 class="d-flex align-items-center justify-content-center gap-2 my-4">
|
||||
<span class="btcpay-status btcpay-status--@(Model.Available ? "enabled" : "disabled")" style="margin-top:.1rem;"></span>
|
||||
<span id="LightningNodeStatus">@(Model.Available ? "Online" : "Unavailable")</span>
|
||||
<span id="LightningNodeStatus">@(Model.Available ? StringLocalizer["Online"] : StringLocalizer["Unavailable"])</span>
|
||||
</h4>
|
||||
@if (Model.Available)
|
||||
{
|
||||
|
@ -2,7 +2,7 @@
|
||||
@model BTCPayServer.Models.WalletViewModels.UpdatePullPaymentModel
|
||||
@{
|
||||
var storeId = Context.GetStoreData().Id;
|
||||
ViewData.SetActivePage(StoreNavPages.Create, "Edit Pull Payment", Model.Id);
|
||||
ViewData.SetActivePage(StoreNavPages.Create, StringLocalizer["Edit Pull Payment"], Model.Id);
|
||||
}
|
||||
|
||||
@section PageHeadContent {
|
||||
|
@ -43,11 +43,11 @@
|
||||
<div class="input-group">
|
||||
@if (Model.LnurlEndpoint is not null)
|
||||
{
|
||||
<button type="button" class="btn btn-secondary only-for-js" id="lnurlwithdraw-button" title="LNURL-Withdraw">
|
||||
<button type="button" class="btn btn-secondary only-for-js" id="lnurlwithdraw-button" title="@StringLocalizer["LNURL-Withdraw"]">
|
||||
<vc:icon symbol="qr-code" />
|
||||
</button>
|
||||
}
|
||||
<input class="form-control form-control-lg font-monospace" asp-for="Destination" placeholder="Enter destination to claim funds" required style="font-size:.9rem;height:42px;">
|
||||
<input class="form-control form-control-lg font-monospace" asp-for="Destination" placeholder="@StringLocalizer["Enter destination to claim funds"]" required style="font-size:.9rem;height:42px;">
|
||||
@if (Model.BitcoinOnly)
|
||||
{
|
||||
<span class="input-group-text">BTC</span>
|
||||
@ -61,14 +61,14 @@
|
||||
{
|
||||
<select class="form-select w-auto" asp-for="SelectedPayoutMethod" asp-items="Model.PayoutMethodIds.Select(id => new SelectListItem(id.ToString(), id.ToString()))"></select>
|
||||
}
|
||||
<button type="button" class="btn btn-secondary only-for-js" data-bs-toggle="modal" data-bs-target="#scanModal" title="Scan destination with camera" id="scandestination-button">
|
||||
<button type="button" class="btn btn-secondary only-for-js" data-bs-toggle="modal" data-bs-target="#scanModal" title="@StringLocalizer["Scan destination with camera"]" id="scandestination-button">
|
||||
<vc:icon symbol="scan-qr"/>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12 mb-3 col-sm-6 mb-sm-0 col-lg-3">
|
||||
<div class="input-group">
|
||||
<input type="number" inputmode="decimal" class="form-control form-control-lg text-end hide-number-spin" asp-for="ClaimedAmount" max="@Model.AmountDue" min="@Model.MinimumClaim" step="any" placeholder="Amount" required>
|
||||
<input type="number" inputmode="decimal" class="form-control form-control-lg text-end hide-number-spin" asp-for="ClaimedAmount" max="@Model.AmountDue" min="@Model.MinimumClaim" step="any" placeholder="@StringLocalizer["Amount"]" required>
|
||||
<span class="input-group-text px-3">@Model.Currency.ToUpper()</span>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -4,7 +4,7 @@
|
||||
@inject BTCPayServer.Security.ContentSecurityPolicies Csp
|
||||
@model StoreReportsViewModel
|
||||
@{
|
||||
ViewData.SetActivePage(StoreNavPages.Reporting, "Reporting");
|
||||
ViewData.SetActivePage(StoreNavPages.Reporting, StringLocalizer["Reporting"]);
|
||||
Csp.UnsafeEval();
|
||||
}
|
||||
@section PageHeadContent
|
||||
@ -22,7 +22,7 @@
|
||||
<div class="sticky-header">
|
||||
<h2>
|
||||
@ViewData["Title"]
|
||||
<a href="https://docs.btcpayserver.org/Accounting/" target="_blank" rel="noreferrer noopener" title="More information...">
|
||||
<a href="https://docs.btcpayserver.org/Accounting/" target="_blank" rel="noreferrer noopener" title="@StringLocalizer["More information..."]">
|
||||
<vc:icon symbol="info" />
|
||||
</a>
|
||||
</h2>
|
||||
@ -45,7 +45,7 @@
|
||||
<input id="fromDate" class="form-control flatdtpicker" type="datetime-local"
|
||||
data-fdtp='{ "enableTime": true, "enableSeconds": true, "dateFormat": "Y-m-d H:i:S", "time_24hr": true, "defaultHour": 0 }'
|
||||
placeholder="Start Date" />
|
||||
<button type="button" class="btn btn-primary input-group-clear" title="Clear">
|
||||
<button type="button" class="btn btn-primary input-group-clear" title="@StringLocalizer["Clear"]">
|
||||
<vc:icon symbol="close" />
|
||||
</button>
|
||||
</div>
|
||||
@ -53,7 +53,7 @@
|
||||
<input id="toDate" class="form-control flatdtpicker" type="datetime-local"
|
||||
data-fdtp='{ "enableTime": true, "enableSeconds": true, "dateFormat": "Y-m-d H:i:S", "time_24hr": true, "defaultHour": 0 }'
|
||||
placeholder="End Date" />
|
||||
<button type="button" class="btn btn-primary input-group-clear" title="Clear">
|
||||
<button type="button" class="btn btn-primary input-group-clear" title="@StringLocalizer["Clear"]">
|
||||
<vc:icon symbol="close" />
|
||||
</button>
|
||||
</div>
|
||||
|
@ -3,7 +3,7 @@
|
||||
@model BrandingViewModel;
|
||||
@inject IFileService FileService
|
||||
@{
|
||||
ViewData.SetActivePage(ServerNavPages.Branding, "Branding");
|
||||
ViewData.SetActivePage(ServerNavPages.Branding, StringLocalizer["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()));
|
||||
@ -31,10 +31,7 @@
|
||||
<div class="form-group">
|
||||
<label asp-for="ContactUrl" class="form-label"></label>
|
||||
<input asp-for="ContactUrl" class="form-control" />
|
||||
<div class="form-text" text-translate="true">
|
||||
Add an email address or an external URL where users can contact you for support requests
|
||||
through a "Contact Us" button, displayed at the bottom of the public facing pages.
|
||||
</div>
|
||||
<div class="form-text" text-translate="true">Add an email address or an external URL where users can contact you for support requests through a "Contact Us" button, displayed at the bottom of the public facing pages.</div>
|
||||
<span asp-validation-for="ContactUrl" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
@ -62,7 +59,7 @@
|
||||
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 class="form-text">@ViewLocalizer["In order to upload, a {0} must be configured.", Html.ActionLink(StringLocalizer["file storage"], "Files", "UIServer")]</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
@ -111,7 +108,7 @@
|
||||
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 class="form-text">@ViewLocalizer["In order to upload, a {0} must be configured.", Html.ActionLink(StringLocalizer["file storage"], "Files", "UIServer")]</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
|
@ -1,6 +1,6 @@
|
||||
@model LndServicesViewModel
|
||||
@{
|
||||
ViewData.SetActivePage(ServerNavPages.Services, $"C-Lightning {Model.ConnectionType}");
|
||||
ViewData.SetActivePage(ServerNavPages.Services, StringLocalizer["Core Lightning {0}", Model.ConnectionType]);
|
||||
}
|
||||
|
||||
<div class="sticky-header">
|
||||
|
@ -1,6 +1,6 @@
|
||||
@model LightningWalletServices
|
||||
@{
|
||||
ViewData.SetActivePage(ServerNavPages.Services, "BTCPay Server Configurator");
|
||||
ViewData.SetActivePage(ServerNavPages.Services, StringLocalizer["BTCPay Server Configurator"]);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
@using BTCPayServer.Controllers
|
||||
@model BTCPayServer.Controllers.UIServerController.CreateTemporaryFileUrlViewModel
|
||||
@{
|
||||
ViewData.SetActivePage(ServerNavPages.Services, $"Create temporary file link");
|
||||
ViewData.SetActivePage(ServerNavPages.Services, StringLocalizer["Create temporary file link"]);
|
||||
}
|
||||
|
||||
<form method="post">
|
||||
|
@ -2,7 +2,7 @@
|
||||
@using Microsoft.AspNetCore.Mvc.TagHelpers
|
||||
@model BTCPayServer.Controllers.RegisterFromAdminViewModel
|
||||
@{
|
||||
ViewData.SetActivePage(ServerNavPages.Users, "Create account");
|
||||
ViewData.SetActivePage(ServerNavPages.Users, StringLocalizer["Create account"]);
|
||||
var canSendEmail = ViewData["CanSendEmail"] is true;
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
@model BTCPayServer.Models.ServerViewModels.DynamicDnsViewModel
|
||||
@{
|
||||
ViewData.SetActivePage(ServerNavPages.Services, "Dynamic DNS Service");
|
||||
ViewData.SetActivePage(ServerNavPages.Services, StringLocalizer["Dynamic DNS Service"]);
|
||||
}
|
||||
|
||||
@section PageFootContent {
|
||||
@ -25,7 +25,7 @@
|
||||
<h2>
|
||||
<span>@ViewData["Title"]</span>
|
||||
<small>
|
||||
<a href="https://docs.btcpayserver.org/Apps/" target="_blank" rel="noreferrer noopener" title="More information...">
|
||||
<a href="https://docs.btcpayserver.org/Apps/" target="_blank" rel="noreferrer noopener" title="@StringLocalizer["More information..."]">
|
||||
<vc:icon symbol="info" />
|
||||
</a>
|
||||
</small>
|
||||
@ -45,7 +45,7 @@
|
||||
<input type="hidden" asp-for="Modify"/>
|
||||
<div class="form-group">
|
||||
<label asp-for="Settings.ServiceUrl" class="form-label"></label>
|
||||
<input id="ServiceUrl" asp-for="Settings.ServiceUrl" class="form-control" placeholder="Url"/>
|
||||
<input id="ServiceUrl" asp-for="Settings.ServiceUrl" class="form-control" placeholder="@StringLocalizer["Url"]"/>
|
||||
<div class="form-text">
|
||||
<span text-translate="true">Well-known Dynamic DNS providers are:</span>
|
||||
@for (var i = 0; i < Model.KnownServices.Length; i++)
|
||||
@ -59,7 +59,7 @@
|
||||
<label asp-for="Settings.Hostname" class="form-label"></label>
|
||||
@if (Model.Modify)
|
||||
{
|
||||
<input asp-for="Settings.Hostname" class="form-control" readonly placeholder="Hostname"/>
|
||||
<input asp-for="Settings.Hostname" class="form-control" readonly placeholder="@StringLocalizer["Hostname"]"/>
|
||||
<div class="form-text">
|
||||
<span text-translate="true">The DNS record has been refreshed:</span>
|
||||
@if (Model.LastUpdated != null)
|
||||
@ -70,17 +70,17 @@
|
||||
}
|
||||
else
|
||||
{
|
||||
<input asp-for="Settings.Hostname" class="form-control" placeholder="Hostname"/>
|
||||
<input asp-for="Settings.Hostname" class="form-control" placeholder="@StringLocalizer["Hostname"]"/>
|
||||
<span asp-validation-for="Settings.Hostname" class="text-danger"></span>
|
||||
}
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label asp-for="Settings.Login" class="form-label"></label>
|
||||
<input asp-for="Settings.Login" class="form-control" placeholder="Login"/>
|
||||
<input asp-for="Settings.Login" class="form-control" placeholder="@StringLocalizer["Login"]"/>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label asp-for="Settings.Password" class="form-label"></label>
|
||||
<input asp-for="Settings.Password" class="form-control" placeholder="Password"/>
|
||||
<input asp-for="Settings.Password" class="form-control" placeholder="@StringLocalizer["Password"]"/>
|
||||
</div>
|
||||
@if (Model.Modify)
|
||||
{
|
||||
|
@ -1,7 +1,7 @@
|
||||
@using BTCPayServer.Abstractions.Models
|
||||
@model BTCPayServer.Models.ServerViewModels.DynamicDnsViewModel[]
|
||||
@{
|
||||
ViewData.SetActivePage(ServerNavPages.Services, "Dynamic DNS Settings");
|
||||
ViewData.SetActivePage(ServerNavPages.Services, StringLocalizer["Dynamic DNS Settings"]);
|
||||
}
|
||||
<div class="sticky-header">
|
||||
<nav aria-label="breadcrumb">
|
||||
@ -14,7 +14,7 @@
|
||||
<h2>
|
||||
<span text-translate="true">@ViewData["Title"]</span>
|
||||
<small>
|
||||
<a href="https://docs.btcpayserver.org/Apps/" target="_blank" rel="noreferrer noopener" title="More information...">
|
||||
<a href="https://docs.btcpayserver.org/Apps/" target="_blank" rel="noreferrer noopener" title="@StringLocalizer["More information..."]">
|
||||
<vc:icon symbol="info" />
|
||||
</a>
|
||||
</small>
|
||||
@ -30,10 +30,7 @@
|
||||
<div class="row">
|
||||
<div class="col-md-8">
|
||||
<div class="form-group">
|
||||
<p text-translate="true">
|
||||
Dynamic DNS allows you to have a stable DNS name pointing to your server, even if your IP address changes regulary.
|
||||
This is recommended if you are hosting BTCPay Server at home and wish to have a clearnet domain to access your server.
|
||||
</p>
|
||||
<p text-translate="true">Dynamic DNS allows you to have a stable DNS name pointing to your server, even if your IP address changes regularly. This is recommended if you are hosting BTCPay Server at home and wish to have a clearnet domain to access your server.</p>
|
||||
<p>
|
||||
Note that you need to properly configure your NAT and BTCPay Server installation to get the HTTPS certificate.
|
||||
See the documentation for <a href="https://docs.btcpayserver.org/Deployment/DynamicDNS/" target="_blank" rel="noreferrer noopener">more information</a>.
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user