Bootstrap v5 migration (#2490)

* Swap bootstrap asset files

* Update themes and color definitions

* Move general bootstrap customizations

* Theme updates

Theme updates

* Remove BuildBundlerMinifier

This lead to an error, because BuildBundlerMinifier and BundlerMinifier.Core seem to conflict here. Details: https://stackoverflow.com/a/61119586

* Rewplace btn-block class with w-100

* Update badge classes

* Remove old font family head variable

* Update margin classes

* Cleanups

* Update float classes

* Update text classes

* Update padding classes

* Update border classes

* UPdate dropdown classes

* Update select classes

* Update neutral custom props

* Update bootstrap and customizations

* Update ChromeDriver; disable smooth scroll

https://github.com/SeleniumHQ/selenium/issues/8295

* Improve alert messages

* Improve bootstrap customizations

* Disable reduced motion

See also 7358282f

* Update Bootstrap data attributes

* Update file inputs

* Update input groups

* Replace deprecated jumbotron class

* Update variables; re-add negative margin util classes

* Update cards

* Update form labels

* Debug alerts

* Fix aria-labelledby associations

* Dropdown-related test fixes

* Fix CanUseWebhooks test

* Test fixes

* Nav updates

* Fix nav usage in wallet send and payouts

* Update alert and modal close buttons

* Re-add backdrop properties

* Upgrade Bootstrap to v5 final

* Update screen reader classes

* Update font-weight classes

* Update monospace font classes

* Update accordians

* Update close icon usage

* Cleanup

* Update scripts and style integrations

* Update input group texts

* Update LN node setup page

* Update more form control classes

* Update inline forms

* Add js specific test

* Upgrade Vue.js

* Remove unused JS

* Upgrade Bootstrap to v5.0.1

* Try container related test updates

* Separate jQuery bundle

* Remove jQuery from LND seed backup page

* Remove unused code

* Refactor email autofill js

* Refactor camera scanner JS

* Re-add tests

* Re-add BuildBundlerMinifier

* Do not minify bundles containing Bootstrap

Details https://github.com/madskristensen/BundlerMinifier/issues/558

* Update bundles

* Cleanup JS test

* Cleanup tests involving dropdowns

* Cleanup tests involving collapses

* Cleanup locale additions in ConfigureCore

* Cleanup bundles

* Remove duplicate status message

* Cleanup formatting

* Fix missing validation scripts

* Remove unused unminified Bootstrap js files

* Fix classic theme

* Fix Casa theme

* Fix PoS validation
This commit is contained in:
d11n 2021-05-19 04:39:27 +02:00 committed by GitHub
parent 0eace936b0
commit ed7031981b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
182 changed files with 21512 additions and 30000 deletions

View file

@ -23,7 +23,7 @@
<PackageReference Include="Newtonsoft.Json.Schema" Version="3.0.13" />
<PackageReference Include="Selenium.Support" Version="3.141.0" />
<PackageReference Include="Selenium.WebDriver" Version="3.141.0" />
<PackageReference Include="Selenium.WebDriver.ChromeDriver" Version="88.0.4324.9600" />
<PackageReference Include="Selenium.WebDriver.ChromeDriver" Version="90.0.4430.2400" />
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.2">
<PrivateAssets>all</PrivateAssets>
@ -53,8 +53,4 @@
<ProjectReference Include="..\BTCPayServer\BTCPayServer.csproj" />
</ItemGroup>
<ItemGroup>
<Folder Include="Pages" />
</ItemGroup>
</Project>

View file

@ -1,10 +1,13 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using BTCPayServer.Payments;
using BTCPayServer.Tests.Logging;
using BTCPayServer.Views.Stores;
using NBitcoin;
using OpenQA.Selenium;
using OpenQA.Selenium.Support.UI;
using Xunit;
using Xunit.Abstractions;

View file

@ -7,6 +7,7 @@ using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using OpenQA.Selenium;
using OpenQA.Selenium.Support.Extensions;
using OpenQA.Selenium.Support.UI;
using Xunit;
@ -27,46 +28,12 @@ namespace BTCPayServer.Tests
public static void AssertNoError(this IWebDriver driver)
{
try
{
Assert.NotEmpty(driver.FindElements(By.ClassName("navbar-brand")));
if (driver.PageSource.Contains("alert-danger"))
{
foreach (var dangerAlert in driver.FindElements(By.ClassName("alert-danger")))
Assert.False(dangerAlert.Displayed, "No alert should be displayed");
}
}
catch
{
StringBuilder builder = new StringBuilder();
builder.AppendLine();
foreach (var logKind in new[] { LogType.Browser, LogType.Client, LogType.Driver, LogType.Server })
{
try
{
var logs = driver.Manage().Logs.GetLog(logKind);
builder.AppendLine($"Selenium [{logKind}]:");
foreach (var entry in logs)
{
builder.AppendLine($"[{entry.Level}]: {entry.Message}");
}
}
catch
{
// ignored
}
builder.AppendLine("---------");
}
Logs.Tester.LogInformation(builder.ToString());
builder = new StringBuilder();
builder.AppendLine("Selenium [Sources]:");
builder.AppendLine(driver.PageSource);
builder.AppendLine("---------");
Logs.Tester.LogInformation(builder.ToString());
throw;
}
Assert.NotEmpty(driver.FindElements(By.ClassName("navbar-brand")));
if (!driver.PageSource.Contains("alert-danger")) return;
foreach (var dangerAlert in driver.FindElements(By.ClassName("alert-danger")))
Assert.False(dangerAlert.Displayed, $"No alert should be displayed, but found this on {driver.Url}: {dangerAlert.Text}");
}
public static T AssertViewModel<T>(this IActionResult result)
{
Assert.NotNull(result);
@ -112,6 +79,13 @@ namespace BTCPayServer.Tests
wait.Until(d=>((IJavaScriptExecutor)d).ExecuteScript("return document.readyState").Equals("complete"));
wait.Until(d=>((IJavaScriptExecutor)d).ExecuteScript("return typeof(jQuery) === 'undefined' || jQuery.active === 0").Equals(true));
}
// Open collapse via JS, because if we click the link it triggers the toggle animation.
// This leads to Selenium trying to click the button while it is moving resulting in an error.
public static void ToggleCollapse(this IWebDriver driver, string collapseId)
{
driver.ExecuteJavaScript($"document.getElementById('{collapseId}').classList.add('show')");
}
public static IWebElement WaitForElement(this IWebDriver driver, By selector)
{

View file

@ -271,10 +271,8 @@ namespace BTCPayServer.Tests
s.Driver.SwitchTo().Alert().Accept();
Assert.False(string.IsNullOrEmpty(s.Driver.FindElement(By.Id("PayJoinBIP21"))
.GetAttribute("value")));
s.Driver.FindElement(By.Id("SendMenu")).Click();
var nbxSeedButton = s.Driver.FindElement(By.CssSelector("button[value=nbx-seed]"));
new WebDriverWait(s.Driver, SeleniumTester.ImplicitWait).Until(d=> nbxSeedButton.Enabled);
nbxSeedButton.Click();
s.Driver.FindElement(By.Id("SendDropdownToggle")).Click();
s.Driver.FindElement(By.CssSelector("button[value=nbx-seed]")).Click();
await s.Server.WaitForEvent<NewOnChainTransactionEvent>(() =>
{
s.Driver.FindElement(By.CssSelector("button[value=payjoin]")).Click();
@ -309,7 +307,7 @@ namespace BTCPayServer.Tests
.GetAttribute("value")));
s.Driver.FindElement(By.Id("FeeSatoshiPerByte")).Clear();
s.Driver.FindElement(By.Id("FeeSatoshiPerByte")).SendKeys("2");
s.Driver.FindElement(By.Id("SendMenu")).Click();
s.Driver.FindElement(By.Id("SendDropdownToggle")).Click();
s.Driver.FindElement(By.CssSelector("button[value=nbx-seed]")).Click();
var txId = await s.Server.WaitForEvent<NewOnChainTransactionEvent>(() =>
{

View file

@ -63,21 +63,17 @@ namespace BTCPayServer.Tests
}
options.AddArguments($"window-size={windowSize.Width}x{windowSize.Height}");
options.AddArgument("shm-size=2g");
options.AddArgument("start-maximized");
var cds = ChromeDriverService.CreateDefaultService(chromeDriverPath);
cds.EnableVerboseLogging = true;
cds.Port = Utils.FreeTcpPort();
cds.HostName = "127.0.0.1";
cds.Start();
Driver = new ChromeDriver(cds, options,
// A bit less than test timeout
TimeSpan.FromSeconds(50));
if (runInBrowser)
{
// ensure maximized window size
// otherwise TESTS WILL FAIL because of different hierarchy in navigation menu
Driver.Manage().Window.Maximize();
}
Driver.Manage().Window.Maximize();
Logs.Tester.LogInformation($"Selenium: Using {Driver.GetType()}");
Logs.Tester.LogInformation($"Selenium: Browsing to {Server.PayTester.ServerUri}");
@ -159,11 +155,8 @@ namespace BTCPayServer.Tests
Driver.FindElement(By.Id("ScriptPubKeyType")).Click();
Driver.FindElement(By.CssSelector($"#ScriptPubKeyType option[value={format}]")).Click();
// Open advanced settings via JS, because if we click the link it triggers the toggle animation.
// This leads to Selenium trying to click the button while it is moving resulting in an error.
Driver.ExecuteJavaScript("document.getElementById('AdvancedSettings').classList.add('show')");
Driver.ToggleCollapse("AdvancedSettings");
Driver.SetCheckbox(By.Id("ImportKeysToRPC"), importkeys);
Driver.FindElement(By.Id("Continue")).Click();
@ -370,7 +363,7 @@ namespace BTCPayServer.Tests
Driver.FindElement(By.Id("bip21parse")).Click();
Driver.SwitchTo().Alert().SendKeys(bip21);
Driver.SwitchTo().Alert().Accept();
Driver.FindElement(By.Id("SendMenu")).Click();
Driver.FindElement(By.Id("SendDropdownToggle")).Click();
Driver.FindElement(By.CssSelector("button[value=nbx-seed]")).Click();
Driver.FindElement(By.CssSelector("button[value=broadcast]")).Click();
}

View file

@ -78,16 +78,16 @@ namespace BTCPayServer.Tests
Assert.Contains("server/services/lndseedbackup/BTC", s.Driver.PageSource);
s.Driver.Navigate().GoToUrl(s.Link("/server/services/lndseedbackup/BTC"));
s.Driver.FindElement(By.Id("details")).Click();
var seedEl = s.Driver.FindElement(By.Id("SeedTextArea"));
var seedEl = s.Driver.FindElement(By.Id("Seed"));
Assert.True(seedEl.Displayed);
Assert.Contains("about over million", seedEl.Text, StringComparison.OrdinalIgnoreCase);
var passEl = s.Driver.FindElement(By.Id("PasswordInput"));
var passEl = s.Driver.FindElement(By.Id("WalletPassword"));
Assert.True(passEl.Displayed);
Assert.Contains(passEl.Text, "hellorockstar", StringComparison.OrdinalIgnoreCase);
s.Driver.FindElement(By.Id("delete")).Click();
s.Driver.FindElement(By.Id("continue")).Click();
s.FindAlertMessage();
seedEl = s.Driver.FindElement(By.Id("SeedTextArea"));
seedEl = s.Driver.FindElement(By.Id("Seed"));
Assert.Contains("Seed removed", seedEl.Text, StringComparison.OrdinalIgnoreCase);
}
}
@ -574,7 +574,6 @@ namespace BTCPayServer.Tests
}
}
[Fact(Timeout = TestTimeout)]
public async Task CanUseCoinSelection()
{
@ -611,7 +610,7 @@ namespace BTCPayServer.Tests
});
await s.Server.ExplorerNode.GenerateAsync(1);
s.GoToWallet(walletId);
s.Driver.FindElement(By.Id("advancedSettings")).Click();
s.Driver.ToggleCollapse("AdvancedSettings");
s.Driver.WaitForAndClick(By.Id("toggleInputSelection"));
s.Driver.FindElement(By.Id(spentOutpoint.ToString()));
Assert.Equal("true", s.Driver.FindElement(By.Name("InputSelection")).GetAttribute("value").ToLowerInvariant());
@ -622,7 +621,7 @@ namespace BTCPayServer.Tests
var bob = new Key().PubKey.Hash.GetAddress(Network.RegTest);
SetTransactionOutput(s, 0, bob, 0.3m);
s.Driver.FindElement(By.Id("SendMenu")).Click();
s.Driver.FindElement(By.Id("SendDropdownToggle")).Click();
s.Driver.FindElement(By.Id("spendWithNBxplorer")).Click();
s.Driver.FindElement(By.CssSelector("button[value=broadcast]")).Click();
var happyElement = s.FindAlertMessage();
@ -643,15 +642,14 @@ namespace BTCPayServer.Tests
await s.StartAsync();
s.RegisterNewUser(true);
var (storeName, storeId) = s.CreateNewStore();
s.GoToStore(storeId, Views.Stores.StoreNavPages.Webhooks);
s.GoToStore(storeId, StoreNavPages.Webhooks);
Logs.Tester.LogInformation("Let's create two webhooks");
for (var i = 0; i < 2; i++)
{
s.Driver.FindElement(By.Id("CreateWebhook")).Click();
s.Driver.FindElement(By.Name("PayloadUrl")).SendKeys($"http://127.0.0.1/callback{i}");
new SelectElement(s.Driver.FindElement(By.Name("Everything")))
.SelectByValue("false");
new SelectElement(s.Driver.FindElement(By.Id("Everything"))).SelectByValue("false");
s.Driver.FindElement(By.Id("InvoiceCreated")).Click();
s.Driver.FindElement(By.Id("InvoiceProcessing")).Click();
s.Driver.FindElement(By.Name("add")).Click();
@ -745,9 +743,8 @@ namespace BTCPayServer.Tests
Logs.Tester.LogInformation("Let's see if we can delete store with some webhooks inside");
s.GoToStore(storeId);
// Open danger zone via JS, because if we click the link it triggers the toggle animation.
// This leads to Selenium trying to click the button while it is moving resulting in an error.
s.Driver.ExecuteJavaScript("document.getElementById('danger-zone').classList.add('show')");
s.Driver.ToggleCollapse("danger-zone");
s.Driver.FindElement(By.Id("delete-store")).Click();
s.Driver.FindElement(By.Id("continue")).Click();
s.FindAlertMessage();
@ -771,7 +768,7 @@ namespace BTCPayServer.Tests
s.Driver.FindElement(By.Id("Wallets")).Click();
s.Driver.FindElement(By.LinkText("Manage")).Click();
s.Driver.FindElement(By.Id("WalletSend")).Click();
s.Driver.FindElement(By.Id("SendMenu")).Click();
s.Driver.FindElement(By.Id("SendDropdownToggle")).Click();
//you cannot use the Sign with NBX option without saving private keys when generating the wallet.
Assert.DoesNotContain("nbx-seed", s.Driver.PageSource);
@ -858,7 +855,7 @@ namespace BTCPayServer.Tests
s.Driver.FindElement(By.Id("WalletSend")).Click();
var bob = new Key().PubKey.Hash.GetAddress(Network.RegTest);
SetTransactionOutput(s, 0, bob, 1);
s.Driver.FindElement(By.Id("SendMenu")).Click();
s.Driver.FindElement(By.Id("SendDropdownToggle")).Click();
s.Driver.FindElement(By.CssSelector("button[value=seed]")).Click();
// Input the seed
@ -879,15 +876,17 @@ namespace BTCPayServer.Tests
var jack = new Key().PubKey.Hash.GetAddress(Network.RegTest);
SetTransactionOutput(s, 0, jack, 0.01m);
s.Driver.FindElement(By.Id("SendMenu")).Click();
s.Driver.FindElement(By.Id("SendDropdownToggle")).Click();
s.Driver.FindElement(By.CssSelector("button[value=nbx-seed]")).Click();
Assert.Contains(jack.ToString(), s.Driver.PageSource);
Assert.Contains("0.01000000", s.Driver.PageSource);
s.Driver.FindElement(By.CssSelector("button[value=analyze-psbt]")).Click();
Assert.EndsWith("psbt", s.Driver.Url);
s.Driver.FindElement(By.CssSelector("#OtherActions")).Click();
s.Driver.FindElement(By.Id("OtherActionsDropdownToggle")).Click();
s.Driver.FindElement(By.CssSelector("button[value=broadcast]")).Click();
Assert.EndsWith("psbt/ready", s.Driver.Url);
s.Driver.FindElement(By.CssSelector("button[value=broadcast]")).Click();
Assert.Equal(walletTransactionLink, s.Driver.Url);
@ -903,13 +902,12 @@ namespace BTCPayServer.Tests
s.Driver.SwitchTo().Alert().SendKeys(bip21);
s.Driver.SwitchTo().Alert().Accept();
s.FindAlertMessage(StatusMessageModel.StatusSeverity.Info);
Assert.Equal(parsedBip21.Amount.ToString(false), s.Driver.FindElement(By.Id($"Outputs_0__Amount")).GetAttribute("value"));
Assert.Equal(parsedBip21.Address.ToString(), s.Driver.FindElement(By.Id($"Outputs_0__DestinationAddress")).GetAttribute("value"));
Assert.Equal(parsedBip21.Amount.ToString(false), s.Driver.FindElement(By.Id("Outputs_0__Amount")).GetAttribute("value"));
Assert.Equal(parsedBip21.Address.ToString(), s.Driver.FindElement(By.Id("Outputs_0__DestinationAddress")).GetAttribute("value"));
s.GoToWallet(new WalletId(storeId, "BTC"), WalletsNavPages.Settings);
var walletUrl = s.Driver.Url;
s.Driver.FindElement(By.Id("SettingsMenu")).Click();
s.Driver.FindElement(By.Id("OtherActionsDropdownToggle")).Click();
s.Driver.FindElement(By.CssSelector("button[value=view-seed]")).Click();
// Seed backup page
@ -989,14 +987,12 @@ namespace BTCPayServer.Tests
Assert.NotEmpty(s.Driver.FindElements(By.ClassName("payout")));
s.Driver.FindElement(By.Id($"{PayoutState.AwaitingApproval}-selectAllCheckbox")).Click();
s.Driver.FindElement(By.Id($"{PayoutState.AwaitingApproval}-actions")).Click();
s.Driver.FindElement(By.Id($"{PayoutState.AwaitingApproval}-approve-pay")).Click();
s.Driver.FindElement(By.Id("SendMenu")).Click();
s.Driver.FindElement(By.Id("SendDropdownToggle")).Click();
s.Driver.FindElement(By.CssSelector("button[value=nbx-seed]")).Click();
s.Driver.FindElement(By.CssSelector("button[value=broadcast]")).Click();
s.FindAlertMessage();
TestUtils.Eventually(() =>
@ -1053,8 +1049,9 @@ namespace BTCPayServer.Tests
private static void CanSetupEmailCore(SeleniumTester s)
{
s.Driver.FindElement(By.ClassName("dropdown-toggle")).Click();
s.Driver.FindElement(By.Id("QuickFillDropdownToggle")).Click();
s.Driver.FindElement(By.ClassName("dropdown-item")).Click();
s.Driver.FindElement(By.Id("Settings_Login")).SendKeys("test@gmail.com");
s.Driver.FindElement(By.CssSelector("button[value=\"Save\"]")).Submit();
s.FindAlertMessage();

View file

@ -47,7 +47,7 @@
<PackageReference Include="BIP78.Sender" Version="0.2.0" />
<PackageReference Include="BTCPayServer.Hwi" Version="1.1.3" />
<PackageReference Include="BTCPayServer.Lightning.All" Version="1.2.7" />
<PackageReference Include="BuildBundlerMinifier" Version="3.2.435" />
<PackageReference Include="BuildBundlerMinifier" Version="3.2.449" />
<PackageReference Include="BundlerMinifier.Core" Version="3.2.435" />
<PackageReference Include="BundlerMinifier.TagHelpers" Version="3.2.435" />
<PackageReference Include="CsvHelper" Version="15.0.5" />
@ -90,7 +90,6 @@
</ItemGroup>
<ItemGroup>
<None Include="wwwroot\main\bootstrap4-creativestart\creative.js" />
<None Include="wwwroot\vendor\font-awesome\fonts\fontawesome-webfont.svg" />
<None Include="wwwroot\vendor\font-awesome\fonts\fontawesome-webfont.woff2" />
<None Include="wwwroot\vendor\font-awesome\less\animated.less" />
@ -126,15 +125,10 @@
<None Include="wwwroot\vendor\jquery-easing\jquery.easing.min.js" />
<None Include="wwwroot\vendor\jquery\jquery.js" />
<None Include="wwwroot\vendor\jquery\jquery.min.js" />
<None Include="wwwroot\vendor\magnific-popup\jquery.magnific-popup.js" />
<None Include="wwwroot\vendor\magnific-popup\jquery.magnific-popup.min.js" />
<None Include="wwwroot\vendor\popper\popper.js" />
<None Include="wwwroot\vendor\popper\popper.min.js" />
<None Include="wwwroot\vendor\scrollreveal\scrollreveal.js" />
<None Include="wwwroot\vendor\scrollreveal\scrollreveal.min.js" />
</ItemGroup>
<ItemGroup>
<Folder Include="wwwroot\vendor\bootstrap" />
<Folder Include="wwwroot\vendor\clipboard.js\" />
<Folder Include="wwwroot\vendor\highlightjs\" />
<Folder Include="wwwroot\vendor\summernote" />

View file

@ -9,12 +9,12 @@
@if (Model.UnseenCount > 0)
{
<li class="nav-item dropdown" id="notifications-nav-item">
<a class="nav-link js-scroll-trigger @ViewData.IsActiveCategory(typeof(NotificationsNavPages))" href="#" id="navbarDropdown" role="button" data-toggle="dropdown">
<a class="nav-link js-scroll-trigger @ViewData.IsActiveCategory(typeof(NotificationsNavPages))" href="#" id="NotificationsDropdownToggle" role="button" data-bs-toggle="dropdown">
<span class="d-inline-block d-lg-none">Notifications</span>
<i class="fa fa-bell d-lg-inline-block d-none"></i>
<span class="notification-badge badge badge-pill badge-danger">@Model.UnseenCount</span>
<span class="notification-badge badge rounded-pill bg-danger">@Model.UnseenCount</span>
</a>
<div class="dropdown-menu dropdown-menu-right text-center notification-dropdown" aria-labelledby="navbarDropdown">
<div class="dropdown-menu dropdown-menu-end text-center notification-dropdown" aria-labelledby="NotificationsDropdownToggle">
<div class="d-flex align-items-center justify-content-between py-3 px-4 border-bottom border-light">
<h5 class="m-0">Notifications</h5>
<form asp-controller="Notifications" asp-action="MarkAllAsSeen" asp-route-returnUrl="@Context.Request.GetCurrentPathWithQueryString()" method="post">
@ -24,15 +24,15 @@
@foreach (var notif in Model.Last5)
{
<a asp-action="NotificationPassThrough" asp-controller="Notifications" asp-route-id="@notif.Id" class="notification d-flex align-items-center dropdown-item border-bottom border-light py-3 px-4">
<div class="mr-3">
<div class="me-3">
<vc:icon symbol="note" />
</div>
<div class="notification-item__content">
<div class="text-left text-wrap">
<div class="text-start text-wrap">
@notif.Body
</div>
<div class="text-left d-flex">
<div class="text-start d-flex">
<small class="text-muted" data-timeago-unixms="@notif.Created.ToUnixTimeMilliseconds()">@notif.Created.ToTimeAgo()</small>
</div>
</div>

View file

@ -9,7 +9,7 @@
<nav aria-label="..." class="w-100">
@if (Model.Total > Model.Count)
{
<ul class="pagination float-left">
<ul class="pagination float-start">
<li class="page-item @(Model.Skip == 0 ? "disabled" : null)">
<a class="page-link" tabindex="-1" href="@NavigatePages(-1, Model.Count)">&laquo;</a>
</li>
@ -35,7 +35,7 @@
@if (Model.Total >= pageSizeOptions.Min())
{
<ul class="pagination float-right">
<ul class="pagination float-end">
<li class="page-item disabled">
<span class="page-link">Page Size:</span>
</li>

View file

@ -431,9 +431,9 @@ namespace BTCPayServer.Controllers
? ""
: " or imported into an external wallet. If you no longer have access to your private key (recovery seed), immediately replace the wallet";
var description =
$"<p class=\"text-danger font-weight-bold\">Please note that this is a {walletType} wallet!</p>" +
$"<p class=\"text-danger font-weight-bold\">Do not replace the wallet if you have not backed it up{additionalText}.</p>" +
"<p class=\"text-left mb-0\">Replacing the wallet will erase the current wallet data from the server. " +
$"<p class=\"text-danger fw-bold\">Please note that this is a {walletType} wallet!</p>" +
$"<p class=\"text-danger fw-bold\">Do not replace the wallet if you have not backed it up{additionalText}.</p>" +
"<p class=\"text-start mb-0\">Replacing the wallet will erase the current wallet data from the server. " +
"The current wallet will be replaced once you finish the setup of the new wallet. If you cancel the setup, the current wallet will stay active .</p>";
return View("Confirm", new ConfirmModel
@ -479,9 +479,9 @@ namespace BTCPayServer.Controllers
? ""
: " or imported into an external wallet. If you no longer have access to your private key (recovery seed), immediately replace the wallet";
var description =
$"<p class=\"text-danger font-weight-bold\">Please note that this is a {walletType} wallet!</p>" +
$"<p class=\"text-danger font-weight-bold\">Do not remove the wallet if you have not backed it up{additionalText}.</p>" +
"<p class=\"text-left mb-0\">Removing the wallet will erase the wallet data from the server. " +
$"<p class=\"text-danger fw-bold\">Please note that this is a {walletType} wallet!</p>" +
$"<p class=\"text-danger fw-bold\">Do not remove the wallet if you have not backed it up{additionalText}.</p>" +
"<p class=\"text-start mb-0\">Removing the wallet will erase the wallet data from the server. " +
$"The store won't be able to receive {network.CryptoCode} onchain payments until a new wallet is set up.</p>";
return View("Confirm", new ConfirmModel

View file

@ -28,7 +28,7 @@ namespace BTCPayServer.HostedServices
_bootstrapUri = data.BootstrapCssUri;
if (String.IsNullOrWhiteSpace(data.CreativeStartCssUri))
_creativeStartUri = "/main/bootstrap4-creativestart/creative.css";
_creativeStartUri = "/main/bootstrap/creative.css";
else
_creativeStartUri = data.CreativeStartCssUri;

View file

@ -1,4 +1,5 @@
using System;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Net;
@ -29,10 +30,8 @@ using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Microsoft.Net.Http.Headers;
using NBitcoin;
using Microsoft.AspNetCore.Mvc;
using BTCPayServer.Controllers.GreenField;
using System.Globalization;
namespace BTCPayServer.Hosting
{

View file

@ -5,7 +5,6 @@ using System.Linq;
using System.Threading;
using System.Threading.Channels;
using System.Threading.Tasks;
using AngleSharp.Dom.Events;
using BTCPayServer.Client.Models;
using BTCPayServer.Configuration;
using BTCPayServer.Data;

View file

@ -34,6 +34,6 @@
</div>
</section>
@section Scripts {
@section PageFootContent {
<partial name="_ValidationScriptsPartial" />
}

View file

@ -6,7 +6,7 @@
Layout = "_LayoutSimple";
}
@section Scripts {
@section PageFootContent {
<partial name="_ValidationScriptsPartial" />
}
@ -33,20 +33,20 @@
<fieldset disabled="@(ViewData.ContainsKey("disabled") ? "disabled" : null)" >
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="Email"></label>
<label asp-for="Email" class="form-label"></label>
<input asp-for="Email" class="form-control" required tabindex="1" autofocus />
<span asp-validation-for="Email" class="text-danger"></span>
</div>
<div class="form-group">
<div class="d-flex justify-content-between">
<label asp-for="Password"></label>
<label asp-for="Password" class="form-label"></label>
<a asp-action="ForgotPassword" tabindex="5">Forgot password?</a>
</div>
<input asp-for="Password" class="form-control" required tabindex="2" />
<span asp-validation-for="Password" class="text-danger"></span>
</div>
<div class="form-group mt-4">
<button type="submit" class="btn btn-primary btn-block btn-lg" id="LoginButton" tabindex="3">Sign in</button>
<button type="submit" class="btn btn-primary btn-lg w-100" id="LoginButton" tabindex="3">Sign in</button>
</div>
</fieldset>
</form>

View file

@ -42,6 +42,3 @@
</div>
</section>
@section Scripts {
<partial name="_ValidationScriptsPartial" />
}

View file

@ -1,7 +1,6 @@
@model BTCPayServer.Fido2.Models.LoginWithFido2ViewModel
<form id="fidoForm" asp-action="LoginWithFido2" method="post" asp-route-returnUrl="@ViewData["ReturnUrl"]">
<input type="hidden" asp-for="Data"/>
<input type="hidden" asp-for="Response"/>
<input type="hidden" asp-for="UserId"/>
@ -15,7 +14,7 @@
<h2>FIDO2 Authentication</h2>
<hr class="primary">
<div>
<span id="spinner" class="fa fa-spinner fa-spin float-right ml-3 mr-5 mt-1 fido-running" style="font-size:2.5em"></span>
<span id="spinner" class="fa fa-spinner fa-spin float-end ms-3 me-5 mt-1 fido-running" style="font-size:2.5em"></span>
<p>Insert your security key into your computer's USB port. If it has a button, tap on it.</p>
</div>
<p id="error-message" class="d-none alert alert-danger"></p>

View file

@ -21,7 +21,7 @@
<form method="post" class="col-12">
<div asp-validation-summary="All" class="text-danger"></div>
<div class="form-group">
<label asp-for="RecoveryCode"></label>
<label asp-for="RecoveryCode" class="form-label"></label>
<input asp-for="RecoveryCode" class="form-control" autocomplete="off" />
<span asp-validation-for="RecoveryCode" class="text-danger"></span>
</div>
@ -31,7 +31,6 @@
</div>
</section>
@section Scripts {
@section PageFootContent {
<partial name="_ValidationScriptsPartial" />
}

View file

@ -5,7 +5,7 @@
Layout = "_LayoutSimple";
}
@section Scripts {
@section PageFootContent {
<partial name="_ValidationScriptsPartial" />
}
@ -60,7 +60,7 @@
</div>
}
<div class="form-group mt-4">
<button type="submit" class="btn btn-primary btn-block btn-lg" id="RegisterButton">Create account</button>
<button type="submit" class="btn btn-primary btn-lg w-100" id="RegisterButton">Create account</button>
</div>
</fieldset>
</form>

View file

@ -37,6 +37,6 @@
</div>
</section>
@section Scripts {
@section PageFootContent {
<partial name="_ValidationScriptsPartial" />
}

View file

@ -4,7 +4,7 @@
Layout = "_LayoutSimple";
}
@section Scripts {
@section PageFootContent {
<partial name="_ValidationScriptsPartial" />
}
@ -28,7 +28,6 @@
</div>
<div class="modal-body">
<form method="post" asp-action="SetPassword">
<div asp-validation-summary="All" class="text-danger"></div>
<input asp-for="Code" type="hidden"/>
@ -61,8 +60,7 @@
<input asp-for="ConfirmPassword" class="form-control"/>
<span asp-validation-for="ConfirmPassword" class="text-danger"></span>
</div>
<button type="submit" class="btn btn-primary btn-block btn-lg" id="SetPassword">Set password</button>
<button type="submit" class="btn btn-primary w-100 btn-lg" id="SetPassword">Set password</button>
</form>
</div>
</div>

View file

@ -2,6 +2,11 @@
@{
ViewData.SetActivePageAndTitle(AppsNavPages.Create, "Create a new app");
}
@section PageFootContent {
<partial name="_ValidationScriptsPartial" />
}
<section>
<div class="container">
<partial name="_StatusMessage" />
@ -13,21 +18,21 @@
<form asp-action="CreateApp">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="Name" class="control-label" data-required></label>
<label asp-for="Name" class="form-label" data-required></label>
<input asp-for="Name" class="form-control" required />
<span asp-validation-for="Name" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="SelectedAppType" class="control-label" data-required></label>
<select asp-for="SelectedAppType" asp-items="Model.AppTypes" class="form-control"></select>
<label asp-for="SelectedAppType" class="form-label" data-required></label>
<select asp-for="SelectedAppType" asp-items="Model.AppTypes" class="form-select"></select>
</div>
<div class="form-group">
<label asp-for="SelectedStore" class="control-label" data-required></label>
<select asp-for="SelectedStore" asp-items="Model.Stores" class="form-control"></select>
<label asp-for="SelectedStore" class="form-label" data-required></label>
<select asp-for="SelectedStore" asp-items="Model.Stores" class="form-select"></select>
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-primary" id="Create"/>
<a asp-action="ListApps" class="text-muted ml-3">Back to list</a>
<a asp-action="ListApps" class="text-muted ms-3">Back to list</a>
</div>
</form>
</div>

View file

@ -15,7 +15,7 @@
<div id="template-editor-app" v-cloak>
<div class="form-group">
<label class="control-label mb-3">@Model.title </label>
<label class="form-label mb-3">@Model.title </label>
@if (ViewContext.ViewData.ModelState.TryGetValue(Model.templateId, out var errors))
{
foreach (var error in errors.Errors)
@ -27,7 +27,7 @@
<div class="bg-light card">
<div class="card-body " v-bind:class="{ 'card-deck': items.length > 0}">
<div v-for="(item, index) of items" class="card my-2 card-wrapper template-item mr-0 ml-0" v-bind:key="item.id">
<div v-for="(item, index) of items" class="card my-2 card-wrapper template-item me-0 ms-0" v-bind:key="item.id">
<div v-if="anyImages" class="card-img-top border-bottom" v-bind:style="getImage(item)"></div>
<div class="card-body">
<h6 class="card-title" v-html="item.title"></h6>
@ -44,11 +44,11 @@
</button>
</div>
</div>
<div class="card-footer text-left">
<div class="card-footer text-start">
<button type="button" class="btn btn-secondary" v-on:click="editItem(-1)" id="btn-add">
<i class="fa fa-plus fa-fw"></i> Add
</button>
<button type="button" class="btn btn-secondary ml-2" v-on:click="toggleTemplateElement()" id="ToggleRawEditor">
<button type="button" class="btn btn-secondary ms-2" v-on:click="toggleTemplateElement()" id="ToggleRawEditor">
Toggle raw editor
</button>
</div>
@ -58,8 +58,8 @@
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" v-if="editingItem">{{editingItem.index>=0? "Edit" : "Create"}} item</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close" ref="close">
<span aria-hidden="true">&times;</span>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close" ref="close">
<vc:icon symbol="close" />
</button>
</div>
<div class="modal-body" v-if="editingItem">
@ -83,7 +83,7 @@
</div>
<div class="col-sm-3">
<label>Custom price</label>
<select class="form-control" v-model="editingItem.custom">
<select class="form-select" v-model="editingItem.custom">
<option v-for="option in customPriceOptions" :value="option.value">{{option.text}}</option>
</select>
</div>
@ -122,7 +122,7 @@
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal" v-on:click="clearEditingItem()">Close</button>
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal" v-on:click="clearEditingItem()">Close</button>
<button type="button" class="btn btn-primary" v-on:click="saveEditingItem()" id="SaveItemChanges">Save Changes</button>
</div>
</div>
@ -132,7 +132,7 @@
</div>
<script>
$(function() {
document.addEventListener("DOMContentLoaded", function () {
new Vue({
el: '#template-editor-app',
data: {

View file

@ -4,6 +4,17 @@
@{
ViewData.SetActivePageAndTitle(AppsNavPages.Update, "Update Crowdfund", Model.StoreName);
}
@section PageHeadContent {
<bundle name="wwwroot/bundles/crowdfund-admin-bundle.min.css" asp-append-version="true"></bundle>
}
@section PageFootContent {
<script src="~/vendor/moment/moment.js" asp-append-version="true"></script>
<partial name="_ValidationScriptsPartial" />
<bundle name="wwwroot/bundles/crowdfund-admin-bundle.min.js" asp-append-version="true"></bundle>
}
<section>
<div class="container">
<partial name="_StatusMessage" />
@ -16,49 +27,47 @@
<input type="hidden" asp-for="StoreId" />
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="Title" class="control-label" data-required></label>
<label asp-for="Title" class="form-label" data-required></label>
<input asp-for="Title" class="form-control" required />
<span asp-validation-for="Title" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Tagline" class="control-label"></label>
<label asp-for="Tagline" class="form-label"></label>
<input asp-for="Tagline" class="form-control" />
<span asp-validation-for="Tagline" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Description" class="control-label" data-required></label>
<label asp-for="Description" class="form-label" data-required></label>
<textarea asp-for="Description" rows="20" cols="40" class="form-control richtext"></textarea>
<span asp-validation-for="Description" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="TargetCurrency" class="control-label" data-required></label>
<label asp-for="TargetCurrency" class="form-label" data-required></label>
<input asp-for="TargetCurrency" class="form-control" required />
<span asp-validation-for="TargetCurrency" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="TargetAmount" class="control-label"></label>
<label asp-for="TargetAmount" class="form-label"></label>
<input asp-for="TargetAmount" class="form-control" />
<span asp-validation-for="TargetAmount" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="StartDate" class="control-label"></label>
<label asp-for="StartDate" class="form-label"></label>
<div class="input-group">
<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 for this crowdfund" />
<div class="input-group-append">
<button class="btn btn-secondary input-group-clear" type="button" title="Clear">
<span class=" fa fa-times"></span>
</button>
</div>
<button class="btn btn-secondary input-group-clear" type="button" title="Clear">
<span class="fa fa-times"></span>
</button>
</div>
<span asp-validation-for="StartDate" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="ResetEvery" class="control-label"></label>
<label asp-for="ResetEvery" class="form-label"></label>
<div class="input-group">
<input type="number" asp-for="ResetEveryAmount" placeholder="Amount" class="form-control">
<select class="custom-select" asp-for="ResetEvery">
<select class="form-select" asp-for="ResetEvery">
@foreach (var opt in Model.ResetEveryValues)
{
<option value="@opt">@opt</option>
@ -67,17 +76,15 @@
</div>
</div>
<div class="form-group">
<label asp-for="EndDate" class="control-label"></label>
<label asp-for="EndDate" class="form-label"></label>
<div class="input-group">
<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 for this crowdfund" />
<div class="input-group-append">
<button class="btn btn-secondary input-group-clear" type="button" title="Clear">
<span class=" fa fa-times"></span>
</button>
</div>
<button class="btn btn-secondary input-group-clear input-group-text" type="button" title="Clear">
<span class="fa fa-times"></span>
</button>
</div>
<span asp-validation-for="EndDate" class="text-danger"></span>
</div>
@ -85,12 +92,12 @@
<partial name="TemplateEditor" model="@(nameof(Model.PerksTemplate), "Perks")" />
<div class="form-group">
<label asp-for="PerksTemplate" class="control-label"></label>
<label asp-for="PerksTemplate" class="form-label"></label>
<textarea asp-for="PerksTemplate" rows="10" cols="40" class="js-product-template form-control"></textarea>
<span asp-validation-for="PerksTemplate" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="CustomCSSLink" class="control-label"></label>
<label asp-for="CustomCSSLink" class="form-label"></label>
<a href="https://docs.btcpayserver.org/Theme/#2-bootstrap-themes" target="_blank">
<span class="fa fa-question-circle-o text-secondary" title="More information..."></span>
</a>
@ -98,17 +105,17 @@
<span asp-validation-for="CustomCSSLink" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="MainImageUrl" class="control-label"></label>
<label asp-for="MainImageUrl" class="form-label"></label>
<input asp-for="MainImageUrl" class="form-control" />
<span asp-validation-for="MainImageUrl" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="EmbeddedCSS" class="control-label"></label>
<label asp-for="EmbeddedCSS" class="form-label"></label>
<textarea asp-for="EmbeddedCSS" rows="10" cols="40" class="form-control"></textarea>
<span asp-validation-for="EmbeddedCSS" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="NotificationUrl" class="control-label"></label>
<label asp-for="NotificationUrl" class="form-label"></label>
<input asp-for="NotificationUrl" class="form-control" />
<span asp-validation-for="NotificationUrl" class="text-danger"></span>
</div>
@ -169,7 +176,7 @@
</div>
</div>
<div class="form-group">
<label asp-for="DisqusShortname" class="control-label"></label>
<label asp-for="DisqusShortname" class="form-label"></label>
<input asp-for="DisqusShortname" class="form-control" />
<span asp-validation-for="DisqusShortname" class="text-danger"></span>
</div>
@ -198,8 +205,3 @@
</div>
</div>
</section>
@section Scripts {
<script src="~/vendor/moment/moment.js" asp-append-version="true"></script>
<bundle name="wwwroot/bundles/crowdfund-admin-bundle.min.js" asp-append-version="true"></bundle>
<bundle name="wwwroot/bundles/crowdfund-admin-bundle.min.css" asp-append-version="true"></bundle>
}

View file

@ -16,19 +16,19 @@
<input type="hidden" asp-for="StoreId" />
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="Title" class="control-label" data-required></label>
<label asp-for="Title" class="form-label" data-required></label>
<input asp-for="Title" class="form-control" required />
<span asp-validation-for="Title" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Currency" class="control-label" data-required></label>
<label asp-for="Currency" class="form-label" data-required></label>
<input asp-for="Currency" class="form-control" required />
<span asp-validation-for="Currency" class="text-danger"></span>
</div>
<div class="form-group">
<div class="form-group">
<label asp-for="DefaultView" class="control-label" data-required></label>
<select asp-for="DefaultView" asp-items="@Html.GetEnumSelectList<PosViewType>()" class="form-control" required></select>
<label asp-for="DefaultView" class="form-label" data-required></label>
<select asp-for="DefaultView" asp-items="@Html.GetEnumSelectList<PosViewType>()" class="form-select" required></select>
<span asp-validation-for="DefaultView" class="text-danger"></span>
</div>
<div class="form-check">
@ -48,27 +48,27 @@
</div>
</div>
<div class="form-group">
<label asp-for="ButtonText" class="control-label" data-required></label>
<label asp-for="ButtonText" class="form-label" data-required></label>
<input asp-for="ButtonText" class="form-control" required />
<span asp-validation-for="ButtonText" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="CustomButtonText" class="control-label" data-required></label>
<label asp-for="CustomButtonText" class="form-label" data-required></label>
<input asp-for="CustomButtonText" class="form-control" required />
<span asp-validation-for="CustomButtonText" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="CustomTipText" class="control-label" data-required></label>
<label asp-for="CustomTipText" class="form-label" data-required></label>
<input asp-for="CustomTipText" class="form-control" required />
<span asp-validation-for="CustomTipText" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="CustomTipPercentages" class="control-label"></label>
<label asp-for="CustomTipPercentages" class="form-label"></label>
<input asp-for="CustomTipPercentages" class="form-control" />
<span asp-validation-for="CustomTipPercentages" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="CustomCSSLink" class="control-label"></label>
<label asp-for="CustomCSSLink" class="form-label"></label>
<a href="https://docs.btcpayserver.org/Theme/#2-bootstrap-themes" target="_blank">
<span class="fa fa-question-circle-o text-secondary" title="More information..."></span>
</a>
@ -79,32 +79,32 @@
<partial name="TemplateEditor" model="@(nameof(Model.Template), "Products")" />
<div class="form-group">
<label asp-for="Template" class="control-label"></label>
<label asp-for="Template" class="form-label"></label>
<textarea asp-for="Template" rows="10" cols="40" class="js-product-template form-control"></textarea>
<span asp-validation-for="Template" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="NotificationUrl" class="control-label"></label>
<label asp-for="NotificationUrl" class="form-label"></label>
<input asp-for="NotificationUrl" class="form-control" />
<span asp-validation-for="NotificationUrl" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="RedirectUrl" class="control-label"></label>
<label asp-for="RedirectUrl" class="form-label"></label>
<input asp-for="RedirectUrl" class="form-control" />
<span asp-validation-for="RedirectUrl" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="RedirectAutomatically" class="control-label" data-required></label>
<select asp-for="RedirectAutomatically" asp-items="Model.RedirectAutomaticallySelectList" class="form-control" required></select>
<label asp-for="RedirectAutomatically" class="form-label"></label>
<select asp-for="RedirectAutomatically" asp-items="Model.RedirectAutomaticallySelectList" class="form-select"></select>
<span asp-validation-for="RedirectAutomatically" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Description" class="control-label"></label>
<label asp-for="Description" class="form-label"></label>
<textarea asp-for="Description" rows="10" cols="40" class="form-control richtext"></textarea>
<span asp-validation-for="Description" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="EmbeddedCSS" class="control-label"></label>
<label asp-for="EmbeddedCSS" class="form-label"></label>
<textarea asp-for="EmbeddedCSS" rows="10" cols="40" class="form-control"></textarea>
<span asp-validation-for="EmbeddedCSS" class="text-danger"></span>
</div>
@ -127,16 +127,14 @@
</div>
<div class="form-group">
<div class="accordion" id="accordian-dev-info">
<div class="card">
<div class="card-header" id="accordian-dev-info-embed-payment-button-header">
<h2 class="mb-0">
<button class="btn btn-link" type="button" data-toggle="collapse" data-target="#accordian-dev-info-embed-payment-button" aria-expanded="true" aria-controls="accordian-dev-info-embed-payment-button">
Embed Payment Button linking to POS item
</button>
</h2>
</div>
<div id="accordian-dev-info-embed-payment-button" class="collapse" aria-labelledby="accordian-dev-info-embed-payment-button-header" data-parent="#accordian-dev-info">
<div class="card-body">
<div class="accordion-item">
<h2 class="accordion-header" id="accordian-dev-info-embed-payment-button-header">
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#accordian-dev-info-embed-payment-button" aria-expanded="false" aria-controls="accordian-dev-info-embed-payment-button">
Embed Payment Button linking to POS item
</button>
</h2>
<div id="accordian-dev-info-embed-payment-button" class="accordion-collapse collapse" aria-labelledby="accordian-dev-info-embed-payment-button-header" data-bs-parent="#accordian-dev-info">
<div class="accordion-body">
<p>You can host point of sale buttons in an external website with the following code.</p>
@if (Model.Example1 != null)
{
@ -151,17 +149,14 @@
</div>
</div>
</div>
<div class="card">
<div class="card-header" id="accordian-dev-info-embed-pos-iframe-header">
<h2 class="mb-0">
<button class="btn btn-link collapsed" type="button" data-toggle="collapse" data-target="#accordian-dev-info-embed-pos-iframe" aria-expanded="false" aria-controls="accordian-dev-info-embed-pos-iframe">
Embed POS with Iframe
</button>
</h2>
</div>
<div id="accordian-dev-info-embed-pos-iframe" class="collapse" aria-labelledby="accordian-dev-info-embed-pos-iframe-header" data-parent="#accordian-dev-info">
<div class="card-body">
<div class="accordion-item">
<h2 class="accordion-header" id="accordian-dev-info-embed-pos-iframe-header">
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#accordian-dev-info-embed-pos-iframe" aria-expanded="false" aria-controls="accordian-dev-info-embed-pos-iframe">
Embed POS with Iframe
</button>
</h2>
<div id="accordian-dev-info-embed-pos-iframe" class="accordion-collapse collapse" aria-labelledby="accordian-dev-info-embed-pos-iframe-header" data-bs-parent="#accordian-dev-info">
<div class="accordion-body">
You can embed the POS using an iframe
@{
var iframe = $"<iframe src='{(Url.Action("ViewPointOfSale", "AppsPublic", new { appId = Model.Id }, Context.Request.Scheme))}' style='max-width: 100%; border: 0;'></iframe>";
@ -170,16 +165,14 @@
</div>
</div>
</div>
<div class="card">
<div class="card-header" id="accordian-dev-info-notification-header">
<h2 class="mb-0">
<button class="btn btn-link collapsed" type="button" data-toggle="collapse" data-target="#accordian-dev-info-notification" aria-expanded="false" aria-controls="accordian-dev-info-notification">
Notification Url Callbacks
</button>
</h2>
</div>
<div id="accordian-dev-info-notification" class="collapse" aria-labelledby="accordian-dev-info-notification-header" data-parent="#accordian-dev-info">
<div class="card-body">
<div class="accordion-item">
<h2 class="accordion-header" id="accordian-dev-info-notification-header">
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#accordian-dev-info-notification" aria-expanded="false" aria-controls="accordian-dev-info-notification">
Notification Url Callbacks
</button>
</h2>
<div id="accordian-dev-info-notification" class="accordion-collapse collapse" aria-labelledby="accordian-dev-info-notification-header" data-bs-parent="#accordian-dev-info">
<div class="accordion-body">
<p>A <code>POST</code> callback will be sent to notification with the following form will be sent to <code>notificationUrl</code> once the enough is paid and once again once there is enough confirmations to the payment:</p>
<pre><code class="json">@Model.ExampleCallback</code></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>
@ -196,13 +189,18 @@
</div>
</div>
</form>
</div>
</div>
</div>
</section>
@section Scripts {
@section PageHeadContent {
<link rel="stylesheet" href="~/vendor/highlightjs/default.min.css" asp-append-version="true">
<bundle name="wwwroot/bundles/pos-admin-bundle.min.css" asp-append-version="true"></bundle>
}
@section PageFootContent {
<partial name="_ValidationScriptsPartial" />
<script src="~/vendor/highlightjs/highlight.min.js" asp-append-version="true"></script>
<script>hljs.initHighlightingOnLoad();</script>
<script id="template-product-item" type="text/template">
@ -211,7 +209,7 @@
{image}
<div class="card-body">
<h6 class="card-title">{title}</h6>
<a href="#" class="js-product-edit btn btn-primary" data-toggle="modal" data-target="#product-modal">Edit</a>
<a href="#" class="js-product-edit btn btn-primary" data-bs-toggle="modal" data-bs-target="#product-modal">Edit</a>
<a href="#" class="js-product-remove btn btn-danger"><i class="fa fa-trash"></i></a>
</div>
</div>
@ -237,7 +235,7 @@
</div>
<div class="col-sm-3">
<label>Custom price</label>
<select class="js-product-custom form-control">
<select class="js-product-custom form-select">
{custom}
</select>
</div>
@ -264,5 +262,4 @@
</script>
<bundle name="wwwroot/bundles/pos-admin-bundle.min.js" asp-append-version="true"></bundle>
<bundle name="wwwroot/bundles/pos-admin-bundle.min.css" asp-append-version="true"></bundle>
}

View file

@ -71,25 +71,20 @@
}
@if (Model.ViewCrowdfundViewModel.Started && !Model.ViewCrowdfundViewModel.Ended)
{
<div class="form-group">
<label asp-for="Email"></label>
<input asp-for="Email" type="email" class="form-control"/>
<span asp-validation-for="Email" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Amount"></label>
<div class="input-group mb-3">
<input asp-for="Amount" type="number" step="any" class="form-control"/>
<div class="input-group-append">
<div class="form-group">
<label asp-for="Email"></label>
<input asp-for="Email" type="email" class="form-control"/>
<span asp-validation-for="Email" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Amount"></label>
<div class="input-group mb-3">
<input asp-for="Amount" type="number" step="any" class="form-control"/>
<span class="input-group-text">@Model.ViewCrowdfundViewModel.TargetCurrency.ToUpperInvariant()</span>
</div>
</div>
<span asp-validation-for="Amount" class="text-danger"></span>
</div>
<input type="hidden" asp-for="RedirectToCheckout"/>
<button type="submit" class="btn btn-primary" >Contribute</button>
<span asp-validation-for="Amount" class="text-danger"></span>
</div>
<input type="hidden" asp-for="RedirectToCheckout"/>
<button type="submit" class="btn btn-primary">Contribute</button>
}
</form>

View file

@ -77,11 +77,11 @@
<h5>@(Model.Info.CurrentAmount + Model.Info.CurrentPendingAmount) @Model.TargetCurrency </h5>
<h5 class="text-muted">Raised</h5>
</div>
<div class="col-sm border-right">
<div class="col-sm border-right">
<h5>@(Model.Info.PendingProgressPercentage.GetValueOrDefault(0) + Model.Info.ProgressPercentage.GetValueOrDefault(0))%</h5>
<h5 class="text-muted">Of Goal</h5>
</div>
<div class="col-sm text-right">
<div class="col-sm text-end">
<h5>
@Model.Info.TotalContributors
</h5>
@ -136,18 +136,12 @@
<div class="col-md-4 col-sm-12">
<partial
name="/Views/AppsPublic/Crowdfund/ContributeForm.cshtml"
model="@(new ContributeToCrowdfund()
{
ViewCrowdfundViewModel = Model,
RedirectToCheckout = true,
})"></partial>
model="@(new ContributeToCrowdfund { ViewCrowdfundViewModel = Model, RedirectToCheckout = true })"></partial>
</div>
</div>
</div>
<div class="card-footer text-muted d-flex" >
<div class="align-self-end pr-4">Updated @Model.Info.LastUpdated</div>
<div class="card-footer text-muted d-flex">
<div class="align-self-end pe-4">Updated @Model.Info.LastUpdated</div>
</div>
</div>
</div>

View file

@ -144,7 +144,7 @@
<h2 class="text-muted" v-if="srvModel.tagline" id="crowdfund-body-header-tagline">{{srvModel.tagline}}</h2>
</div>
<div class="col-sm-12 col-md-4 col-lg-3" id="crowdfund-body-header-cta-container">
<button v-if="active" id="crowdfund-body-header-cta" class="btn btn-lg btn-primary w-100 font-weight-bold" v-on:click="contributeModalOpen = true">Contribute</button>
<button v-if="active" id="crowdfund-body-header-cta" class="btn btn-lg btn-primary w-100 fw-bold" v-on:click="contributeModalOpen = true">Contribute</button>
</div>
</div>
</div>
@ -194,7 +194,7 @@
</div>
<div class="card-footer text-muted d-flex" v-if="srvModel.animationsEnabled || srvModel.soundsEnabled">
<div class="align-self-end pr-4">Updated {{lastUpdated}}</div>
<div class="align-self-end pe-4">Updated {{lastUpdated}}</div>
<div class="form-check mx-1" v-if="srvModel.animationsEnabled || animation">
<input class="form-check-input" type="checkbox" id="cbAnime" v-model="animation">
<label class="form-check-label" for="cbAnime">
@ -251,7 +251,7 @@
<div class="perk-zoom " v-if="canExpand">
<div class="perk-zoom-bg bg-primary"> </div>
<div class="perk-zoom-text w-100 text-center text-white font-weight-bold">
<div class="perk-zoom-text w-100 text-center text-white fw-bold">
Select this contribution perk
</div>
</div>
@ -284,20 +284,18 @@
:min="perk.price.value"
step="any"
placeholder="Contribution Amount"
required >
<div class="input-group-append">
<span class='input-group-text'>{{targetCurrency}}</span>
<button
class="btn btn-primary"
v-bind:class="{ 'btn-disabled': loading}"
:disabled="!active || loading"
type="submit">
<div v-if="loading" class="spinner-grow spinner-grow-sm" role="status">
<span class="sr-only">Loading...</span>
</div>
{{perk.buyButtonText || 'Continue'}}
</button>
</div>
required>
<span class='input-group-text'>{{targetCurrency}}</span>
<button
class="btn btn-primary"
v-bind:class="{ 'btn-disabled': loading}"
:disabled="!active || loading"
type="submit">
<div v-if="loading" class="spinner-grow spinner-grow-sm" role="status">
<span class="visually-hidden">Loading...</span>
</div>
{{perk.buyButtonText || 'Continue'}}
</button>
</div>
</div>
<div class="card-footer d-flex justify-content-between" v-if="perk.sold || perk.inventory != null">

View file

@ -8,40 +8,34 @@
<script id="template-cart-item" type="text/template">
<tr data-id="{id}">
{image}
<td class="align-middle pr-0 pl-2"><b>{title}</b></td>
<td class="align-middle pe-0 ps-2"><b>{title}</b></td>
<td class="align-middle px-0">
<a class="js-cart-item-remove btn btn-link" href="#"><i class="fa fa-trash text-muted"></i></a>
</td>
<td class="align-middle px-0">
<div class="input-group align-items-center">
<div class="input-group-prepend">
<a class="js-cart-item-minus btn btn-link px-2" href="#"><i class="fa fa-minus-circle fa-fw text-danger"></i></a>
</div>
<a class="js-cart-item-minus btn btn-link px-2" href="#"><i class="fa fa-minus-circle fa-fw text-danger"></i></a>
<input class="js-cart-item-count form-control form-control-sm pull-left" type="number" step="1" name="count" placeholder="Qty" max="{inventory}" value="{count}" data-prev="{count}">
<div class="input-group-append">
<a class="js-cart-item-plus btn btn-link px-2" href="#">
<i class="fa fa-plus-circle fa-fw text-success"></i>
</a>
</div>
<a class="input-group-text js-cart-item-plus btn btn-link px-2" href="#">
<i class="fa fa-plus-circle fa-fw text-success"></i>
</a>
</div>
</td>
<td class="align-middle text-right">{price}</td>
<td class="align-middle text-end">{price}</td>
</tr>
</script>
<script id="template-cart-item-image" type="text/template">
<td class="align-middle pr-0" width="1%"><img src="{image}" width="50" alt=""></td>
<td class="align-middle pe-0" width="1%"><img src="{image}" width="50" alt=""></td>
</script>
<script id="template-cart-custom-amount" type="text/template">
<tr>
<td colspan="5">
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-shopping-cart fa-fw"></i></span>
</div>
<span class="input-group-text"><i class="fa fa-shopping-cart fa-fw"></i></span>
<input class="js-cart-custom-amount form-control" type="number" min="0" step="@Model.Step" name="amount" placeholder="Pay what you want">
<div class="input-group-append">
<div class="input-group-text">
<a class="js-cart-custom-amount-remove btn btn-danger" href="#"><i class="fa fa-times"></i></a>
</div>
</div>
@ -54,13 +48,9 @@
<tr>
<th colspan="5" class="border-0 pb-0">
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-shopping-cart fa-fw"></i></span>
</div>
<span class="input-group-text"><i class="fa fa-shopping-cart fa-fw"></i></span>
<input class="js-cart-custom-amount form-control" type="number" min="0" step="@Model.Step" name="amount" value="{customAmount}" placeholder="Pay what you want">
<div class="input-group-append">
<a class="js-cart-custom-amount-remove btn btn-danger" href="#"><i class="fa fa-times"></i></a>
</div>
<a class="js-cart-custom-amount-remove btn btn-danger" href="#"><i class="fa fa-times"></i></a>
</div>
</th>
</tr>
@ -70,13 +60,9 @@
<tr>
<th colspan="5" class="border-top-0">
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-percent fa-fw"></i></span>
</div>
<span class="input-group-text"><i class="fa fa-percent fa-fw"></i></span>
<input class="js-cart-discount form-control" type="number" min="0" step="@Model.Step" value="{discount}" name="discount" placeholder="Discount in %">
<div class="input-group-append">
<a class="js-cart-discount-remove btn btn-danger" href="#"><i class="fa fa-times"></i></a>
</div>
<a class="js-cart-discount-remove btn btn-danger" href="#"><i class="fa fa-times"></i></a>
</div>
</th>
</tr>
@ -92,13 +78,9 @@
<tr>
<th colspan="5" class="border-0">
<div class="input-group mb-2">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-money fa-fw"></i></span>
</div>
<span class="input-group-text"><i class="fa fa-money fa-fw"></i></span>
<input class="js-cart-tip form-control form-control-lg" type="number" min="0" step="@Model.Step" value="{tip}" name="tip" placeholder="Tip in @(Model.CurrencyInfo.CurrencySymbol != null ? Model.CurrencyInfo.CurrencySymbol : Model.CurrencyCode)">
<div class="input-group-append">
<a class="js-cart-tip-remove btn btn-lg btn-danger" href="#"><i class="fa fa-times"></i></a>
</div>
<a class="js-cart-tip-remove btn btn-lg btn-danger" href="#"><i class="fa fa-times"></i></a>
</div>
<div class="row mb-1">
@if (customTipPercentages != null && customTipPercentages.Length > 0)
@ -107,7 +89,7 @@
{
var percentage = customTipPercentages[i];
<div class="col">
<a class="js-cart-tip-btn btn btn-lg btn-light btn-block border mb-2" href="#" data-tip="@percentage">@percentage%</a>
<a class="js-cart-tip-btn btn btn-lg btn-light w-100 border mb-2" href="#" data-tip="@percentage">@percentage%</a>
</div>
}
}
@ -120,7 +102,7 @@
<script id="template-cart-total" type="text/template">
<tr>
<th colspan="1" class="pb-4 h4">Total</th>
<th colspan="4" class="pb-4 h4 text-right">
<th colspan="4" class="pb-4 h4 text-end">
<span class="js-cart-total">{total}</span>
</th>
</tr>
@ -131,7 +113,7 @@
<div class="modal-content">
<div class="modal-header bg-primary text-white border-0">
<h5 class="modal-title">Confirmation</h5>
<button type="button" class="close text-white" data-dismiss="modal" aria-label="Close">
<button type="button" class="close text-white" data-bs-dismiss="modal" aria-label="Close">
<span aria-hidden="true">
<i class="fa fa-times fa-fw"></i>
</span>
@ -169,7 +151,7 @@
}
<tr>
<td class="h3 table-light">Total</td>
<td class="h3 table-light text-right">
<td class="h3 table-light text-end">
<span class="js-cart-summary-total text-nowrap"></span>
</td>
</tr>
@ -204,10 +186,10 @@
<div class="row">
<partial name="_StatusMessage" />
<div class="col-sm-4 col-lg-2 order-sm-last text-right mb-2">
<div class="col-sm-4 col-lg-2 order-sm-last text-end mb-2">
<a class="js-cart btn btn-lg btn-outline-primary" href="#">
<i class="fa fa-shopping-basket"></i>&nbsp;
<span class="badge badge-light badge-pill">
<span class="badge bg-light rounded-pill">
<span id="js-cart-items">0</span>
</span>
</a>
@ -230,14 +212,13 @@
</div>
<div id="js-pos-list" class="text-center mx-auto px-4">
<div class="row card-deck my-3">
@for (var index = 0; index < Model.Items.Length; index++)
{
var item = Model.Items[index];
var image = item.Image;
var description = item.Description;
<div class="js-add-cart card my-2 card-wrapper" data-index="@index">
<div class="js-add-cart card px-0 m-2 card-wrapper" data-index="@index">
@if (!String.IsNullOrWhiteSpace(image))
{
@:<img class="card-img-top" src="@image" alt="Card image cap" asp-append-version="true">
@ -280,7 +261,7 @@
<nav id="sidebar" class="bg-dark text-white">
<div class="bg-primary p-3 clearfix">
<h3 class="text-white m-0 pull-left">Cart</h3>
<a class="js-cart btn btn-sm bg-white text-black pull-right ml-5" href="#">
<a class="js-cart btn btn-sm bg-white text-black pull-right ms-5" href="#">
<i class="fa fa-times fa-lg"></i>
</a>
<a class="js-cart-destroy btn btn-danger pull-right" href="#" style="display: none;">Empty cart <i class="fa fa-trash fa-fw fa-lg"></i></a>
@ -293,7 +274,7 @@
<th class="text-center" width="20%">
<div style="width: 84px">Quantity</div>
</th>
<th class="text-right" width="25%">
<th class="text-end" width="25%">
<div style="min-width: 50px">Price</div>
</th>
</tr>
@ -305,7 +286,7 @@
<thead></thead>
</table>
<button id="js-cart-confirm" data-toggle="modal" data-target="#cartModal" class="btn btn-primary btn-lg btn-block mb-3 p-3" disabled="disabled" type="submit">
<button id="js-cart-confirm" data-bs-toggle="modal" data-bs-target="#cartModal" class="btn btn-primary btn-lg w-100 mb-3 p-3" disabled="disabled" type="submit">
<b>Confirm</b>
</button>

View file

@ -9,13 +9,9 @@
<div class="py-5 px-3">
<form method="post" asp-controller="AppsPublic" asp-action="ViewPointOfSale" asp-route-appId="@Model.AppId" asp-antiforgery="false" data-buy>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text">@Model.CurrencySymbol</span>
</div>
<span class="input-group-text">@Model.CurrencySymbol</span>
<input class="form-control" type="number" step="@Model.Step" name="amount" placeholder="Amount">
<div class="input-group-append">
<button class="btn btn-primary" type="submit">Pay</button>
</div>
<button class="btn btn-primary" type="submit">Pay</button>
</div>
</form>

View file

@ -15,7 +15,7 @@
<div class="overflow-hidden col-12">@Safe.Raw(Model.Description)</div>
</div>
}
<div class="row card-deck my-3 mx-auto">
<div class="row card-deck my-3 mx-auto">
@for (int x = 0; x < Model.Items.Length; x++)
{
var item = Model.Items[x];
@ -26,7 +26,7 @@
: item.BuyButtonText)
.Replace("{0}",item.Price.Formatted)
.Replace("{Price}",item.Price.Formatted);
<div class="card my-2" data-id="@x">
<div class="card px-0 m-2" data-id="@x">
@if (!String.IsNullOrWhiteSpace(item.Image))
{
<img class="card-img-top" src="@item.Image" alt="Card image cap" asp-append-version="true">
@ -74,7 +74,7 @@
}
@if (Model.ShowCustomAmount)
{
<div class="card my-2">
<div class="card px-0 m-2">
@{CardBody("Custom Amount", "Create invoice to pay custom amount");}
<div class="card-footer bg-transparent border-0">
<form method="post" asp-controller="AppsPublic" asp-action="ViewPointOfSale" asp-route-appId="@Model.AppId" asp-antiforgery="false" data-buy>
@ -95,15 +95,9 @@
private void PayFormInputContent(string buttonText, decimal? minPriceValue = null, decimal? priceValue = null)
{
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text">@Model.CurrencySymbol</span>
</div>
<span class="input-group-text">@Model.CurrencySymbol</span>
<input class="form-control" type="number" min="@(minPriceValue ?? 0)" step="@Model.Step" name="amount" placeholder="Amount" value="@priceValue">
<div class="input-group-append">
<button class="btn btn-primary text-nowrap" type="submit">
@buttonText
</button>
</div>
<button class="btn btn-primary text-nowrap" type="submit">@buttonText</button>
</div>
}

View file

@ -21,7 +21,7 @@
}
@if (!Context.Request.Query.ContainsKey("simple"))
{
<script type="text/javascript">
<script>
var srvModel = @Safe.Json(Model);
</script>
<bundle name="wwwroot/bundles/crowdfund-bundle-1.min.js" asp-append-version="true"></bundle>

View file

@ -28,8 +28,7 @@
</div>
<div class="form-group">
<label asp-for="Mode"></label>
<select asp-for="Mode" asp-items="Model.Modes" class="form-control">
</select>
<select asp-for="Mode" asp-items="Model.Modes" class="form-select"></select>
</div>
<div class="form-group">
<label asp-for="AmountMarkupPercentage"></label>
@ -45,6 +44,6 @@
</div>
</div>
@section Scripts {
@section PageFootContent {
<partial name="_ValidationScriptsPartial" />
}

View file

@ -8,7 +8,7 @@
<img src="~/img/btcpay-logo.svg" alt="BTCPay Server" class="head-logo" height="70" asp-append-version="true" />
</a>
<h1 class="text-uppercase mt-3 ml-4">@ViewData["Title"]</h1>
<h1 class="text-uppercase mt-3 ms-4">@ViewData["Title"]</h1>
</div>
</div>

View file

@ -86,6 +86,6 @@
</div>
</div>
@section Scripts {
@section PageFootContent {
@await Html.PartialAsync("_ValidationScriptsPartial")
}

View file

@ -60,6 +60,6 @@
<a asp-action="UpdateChainConfig" asp-controller="EthereumConfig" asp-route-chainId="@chain">Configure Web3 for chain @chain</a>
}
}
@section Scripts {
@section PageFootContent {
@await Html.PartialAsync("_ValidationScriptsPartial")
}

View file

@ -9,7 +9,7 @@
<div class="row">
<div class="col-lg-12 section-heading">
<div>
<span id="spinner" class="fa fa-spinner fa-spin float-right ml-3 mr-5 mt-1 fido-running" style="font-size:2.5em"></span>
<span id="spinner" class="fa fa-spinner fa-spin float-end ms-3 me-5 mt-1 fido-running" style="font-size:2.5em"></span>
<p>Insert your security key into your computer's USB port. If it has a button, tap on it.</p>
</div>
<p id="error-message" class="d-none alert alert-danger"></p>

View file

@ -7,7 +7,7 @@
<thead>
<tr>
<th>Name</th>
<th class="text-right">Actions</th>
<th class="text-end">Actions</th>
</tr>
</thead>
<tbody>
@ -15,7 +15,7 @@
{
<tr>
<td>@(string.IsNullOrEmpty(device.Name)? "Unnamed FIDO2 credential": device.Name)</td>
<td class="text-right">
<td class="text-end">
<a asp-action="Remove" asp-route-id="@device.Id">Remove</a>
</td>
</tr>
@ -30,13 +30,17 @@
}
</tbody>
</table>
<form asp-action="Create" method="get" class="form-inline">
<div class="form-group">
<input type="text" class="form-control" name="Name" placeholder="New Credential Name"/>
<button type="submit" class="btn btn-primary ml-2">
<span class="fa fa-plus"></span>
Add New Credential
</button>
<form asp-action="Create" method="get">
<div class="row g-1">
<div class="col">
<input type="text" class="form-control" name="Name" placeholder="New Credential Name"/>
</div>
<div class="col">
<button type="submit" class="btn btn-primary ms-2">
<span class="fa fa-plus"></span>
Add New Credential
</button>
</div>
</div>
</form>

View file

@ -116,25 +116,25 @@
</div>
<div class="row social-row">
<div class="col-6 col-md-3 ml-auto text-center">
<div class="col-6 col-md-3 ms-auto text-center">
<a href="https://chat.btcpayserver.org/" target="_blank">
<img src="~/img/mattermost.svg" alt="Mattermost" class="social-logo" asp-append-version="true" />
<span>On Mattermost</span>
</a>
</div>
<div class="col-6 col-md-3 ml-auto text-center">
<div class="col-6 col-md-3 ms-auto text-center">
<a href="https://slack.btcpayserver.org/" target="_blank">
<img src="~/img/slack.svg" alt="Slack" class="social-logo" asp-append-version="true" />
<span>On Slack</span>
</a>
</div>
<div class="col-6 col-md-3 mr-auto text-center">
<div class="col-6 col-md-3 me-auto text-center">
<a href="https://twitter.com/BtcpayServer" target="_blank">
<img src="~/img/twitter.svg" alt="Twitter" class="social-logo" asp-append-version="true" />
<span>On Twitter</span>
</a>
</div>
<div class="col-6 col-md-3 mr-auto text-center">
<div class="col-6 col-md-3 me-auto text-center">
<a href="https://github.com/btcpayserver/btcpayserver" target="_blank">
<img src="~/img/github.svg" alt="Github" class="social-logo" asp-append-version="true" />
<span>On Github</span>

View file

@ -4,19 +4,21 @@
ViewData["Title"] = "Your recovery phrase";
}
@section Scripts {
<partial name="_ValidationScriptsPartial" />
@section PageHeadContent {
<style>
@@media (min-width: 476px) { ol#RecoveryPhrase {max-height:16em;} }
@@media (min-width: 768px) { ol#RecoveryPhrase {max-height:12em;} }
@@media (min-width: 1200px) { ol#RecoveryPhrase {max-height:8em;} }
form#RecoveryConfirmation button { position: absolute; bottom:0; left:50%; width:200px; margin-left:-100px; }
form#RecoveryConfirmation button:not([disabled]) { display: none; }
form#RecoveryConfirmation input:checked ~ button[disabled] { display: none; }
form#RecoveryConfirmation input:checked + button:not([disabled]) { display: inline-block; }
</style>
}
<style>
@@media (min-width: 476px) { ol#RecoveryPhrase {max-height:16em;} }
@@media (min-width: 768px) { ol#RecoveryPhrase {max-height:12em;} }
@@media (min-width: 1200px) { ol#RecoveryPhrase {max-height:8em;} }
form#RecoveryConfirmation button { position: absolute; bottom:0; left:50%; width:200px; margin-left:-100px; }
form#RecoveryConfirmation button:not([disabled]) { display: none; }
form#RecoveryConfirmation input:checked ~ button[disabled] { display: none; }
form#RecoveryConfirmation input:checked + button:not([disabled]) { display: inline-block; }
</style>
@section PageFootContent {
<partial name="_ValidationScriptsPartial" />
}
<div class="row justify-content-md-center">
<div class="col-lg-10 text-center">
@ -33,10 +35,10 @@
<span class="d-sm-block"><strong>Write them down on a piece of paper in the exact order.</strong></span>
</p>
</div>
<ol id="RecoveryPhrase" data-mnemonic="@Model.Mnemonic" class="my-5 d-flex flex-column flex-wrap justify-content-center align-items-center text-left p-0">
<ol id="RecoveryPhrase" data-mnemonic="@Model.Mnemonic" class="my-5 d-flex flex-column flex-wrap justify-content-center align-items-center text-start p-0">
@foreach (var word in Model.Words)
{
<li class="ml-4 px-3 py-2 text-secondary" style="flex: 0 1;min-width:10em;">
<li class="ms-4 px-3 py-2 text-secondary" style="flex: 0 1;min-width:10em;">
<span class="text-dark h5">@word</span>
</li>
}
@ -73,7 +75,7 @@
{
<form id="RecoveryConfirmation" action="@Model.ReturnUrl" class="d-flex align-items-start justify-content-center" style="margin-top:4rem;padding-bottom: 80px">
<label class="form-check-label lead order-2" for="confirm">I have written down my recovery phrase and stored it in a secure location</label>
<input type="checkbox" class="mt-2 mr-3 order-1" id="confirm">
<input type="checkbox" class="mt-2 me-3 order-1" id="confirm">
<button type="submit" class="btn btn-primary btn-lg px-5 order-3" id="submit">Done</button>
<button type="submit" class="btn btn-primary btn-lg px-5 order-3" disabled>Done</button>
</form>

View file

@ -168,7 +168,7 @@
<span class="submission-error-label" v-show="emailAddressInputInvalid">{{$t("Please enter a valid email address")}}</span>
</div>
<div class="input-wrapper">
<input class="bp-input email-input "
<input class="bp-input email-input"
v-bind:class="{ 'ng-pristine ng-submitted ng-touched': !emailAddressInputDirty, 'ng-invalid form-input-invalid': emailAddressInputInvalid }" id="emailAddressFormInput"
v-bind:placeholder="$t('Your email')" type="email" v-model="emailAddressInput"
v-on:change="onEmailChange">

View file

@ -17,10 +17,11 @@
<bundle name="wwwroot/bundles/checkout-bundle.min.css" asp-append-version="true" />
<script type="text/javascript">
<script>
var initialSrvModel = @Safe.Json(Model);
</script>
<bundle name="wwwroot/bundles/bootstrap-bundle.min.js" asp-append-version="true" />
<bundle name="wwwroot/bundles/checkout-bundle.min.js" asp-append-version="true" />
<script>vex.defaultOptions.className = 'vex-theme-btcpay'</script>
@ -112,7 +113,7 @@
</div>
</div>
</invoice>
<script type="text/javascript">
<script>
var availableLanguages = @Safe.Json(langService.GetLanguages().Select((language) => language.Code));;
var storeDefaultLang = @Safe.Json(langService.FindBestMatch(Model.DefaultLang)?.Code ?? Model.DefaultLang);
var fallbackLanguage = "en";

View file

@ -2,14 +2,19 @@
@{
ViewData.SetActivePageAndTitle(InvoiceNavPages.Create, "Create an invoice");
}
<script>
$(function() {
$("#create-invoice-form").on("submit",
function() {
$(this).find("input[type='submit']").prop('disabled', true);
});
})
</script>
@section PageFootContent {
<partial name="_ValidationScriptsPartial" />
<script>
document.addEventListener("DOMContentLoaded", function () {
$("#create-invoice-form").on("submit",
function() {
$(this).find("input[type='submit']").prop('disabled', true);
});
})
</script>
}
<section>
<div class="container">
<partial name="_StatusMessage" />
@ -21,53 +26,53 @@
<form asp-action="CreateInvoice" method="post" id="create-invoice-form">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="Amount" class="control-label" data-required></label>
<label asp-for="Amount" class="form-label" data-required></label>
<input asp-for="Amount" class="form-control" required />
<span asp-validation-for="Amount" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Currency" class="control-label" data-required></label>
<label asp-for="Currency" class="form-label" data-required></label>
<input asp-for="Currency" class="form-control" required />
<span asp-validation-for="Currency" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="OrderId" class="control-label"></label>
<label asp-for="OrderId" class="form-label"></label>
<input asp-for="OrderId" class="form-control" />
<span asp-validation-for="OrderId" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="ItemDesc" class="control-label"></label>
<label asp-for="ItemDesc" class="form-label"></label>
<input asp-for="ItemDesc" class="form-control" />
<span asp-validation-for="ItemDesc" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="PosData" class="control-label"></label>
<label asp-for="PosData" class="form-label"></label>
<input asp-for="PosData" class="form-control" />
<span asp-validation-for="PosData" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="BuyerEmail" class="control-label"></label>
<label asp-for="BuyerEmail" class="form-label"></label>
<input asp-for="BuyerEmail" class="form-control" />
<span asp-validation-for="BuyerEmail" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="NotificationUrl" class="control-label"></label>
<label asp-for="NotificationUrl" class="form-label"></label>
<input asp-for="NotificationUrl" class="form-control" />
<span asp-validation-for="NotificationUrl" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="StoreId" class="control-label"></label>
<select asp-for="StoreId" asp-items="Model.Stores" class="form-control"></select>
<label asp-for="StoreId" class="form-label"></label>
<select asp-for="StoreId" asp-items="Model.Stores" class="form-select"></select>
<span asp-validation-for="StoreId" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="SupportedTransactionCurrencies" class="control-label"></label>
<select asp-for="SupportedTransactionCurrencies" asp-items="Model.AvailablePaymentMethods" class="form-control" multiple="multiple"></select>
<label asp-for="SupportedTransactionCurrencies" class="form-label"></label>
<select asp-for="SupportedTransactionCurrencies" asp-items="Model.AvailablePaymentMethods" class="form-select" multiple="multiple"></select>
<span asp-validation-for="SupportedTransactionCurrencies" class="text-danger"></span>
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-primary" id="Create" />
<a asp-action="ListInvoices" class="text-muted ml-3">Back to list</a>
<a asp-action="ListInvoices" class="text-muted ms-3">Back to list</a>
</div>
</form>
</div>

View file

@ -3,7 +3,7 @@
ViewData["Title"] = $"Invoice {Model.Id}";
}
@section HeaderContent{
@section PageHeadContent {
<meta name="robots" content="noindex,nofollow">
<style>
#posData td > table:last-child { margin-bottom: 0 !important; }
@ -17,7 +17,7 @@
<div class="row mb-4">
<h2 class="col-xs-12 col-lg-9 mb-4 mb-lg-0">@ViewData["Title"]</h2>
<div class="col-xs-12 col-lg-3 mb-2 mb-lg-0 text-lg-right">
<div class="col-xs-12 col-lg-3 mb-2 mb-lg-0 text-lg-end">
<div class="d-inline-flex">
@if (Model.CanRefund)
{
@ -25,17 +25,17 @@
}
else
{
<button href="#" class="btn btn-secondary text-nowrap" data-toggle="tooltip" title="You can only issue refunds on invoices with confirmed payments" disabled>Issue refund <span class="fa fa-undo"></span></button>
<button href="#" class="btn btn-secondary text-nowrap" data-bs-toggle="tooltip" title="You can only issue refunds on invoices with confirmed payments" disabled>Issue refund <span class="fa fa-undo"></span></button>
}
<form class="p-0 ml-2" asp-action="ToggleArchive" asp-route-invoiceId="@Model.Id" method="post">
<form class="p-0 ms-2" asp-action="ToggleArchive" asp-route-invoiceId="@Model.Id" method="post">
<button type="submit" class="btn @(Model.Archived ? "btn-warning" : "btn btn-danger")" id="btn-archive-toggle">
@if (Model.Archived)
{
<span class="text-nowrap" data-toggle="tooltip" title="Unarchive this invoice">Archived <i class=" ml-1 fa fa-close"></i></span>
<span class="text-nowrap" data-bs-toggle="tooltip" title="Unarchive this invoice">Archived <i class="ms-1 fa fa-close"></i></span>
}
else
{
<span class="text-nowrap" data-toggle="tooltip" title="Archive this invoice so that it does not appear in the invoice list by default">Archive <i class=" ml-1 fa fa-archive"></i></span>
<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 <i class="ms-1 fa fa-archive"></i></span>
}
</button>
</form>
@ -231,7 +231,7 @@
asp-route-deliveryId="@delivery.Id"
method="post">
<div class="d-flex align-items-center">
<span class="d-flex align-items-center flex-fill mr-3">
<span class="d-flex align-items-center flex-fill me-3">
@if (delivery.Success)
{
<span class="d-flex align-items-center fa fa-check text-success" title="Success"></span>
@ -240,7 +240,7 @@
{
<span class="d-flex align-items-center fa fa-times text-danger" title="@delivery.ErrorMessage"></span>
}
<span class="ml-3">
<span class="ms-3">
<a
asp-action="WebhookDelivery"
asp-route-invoiceId="@Model.Id"
@ -259,7 +259,7 @@
<button id="#redeliver-@delivery.Id"
type="submit"
class="btn btn-info py-1 ml-3 redeliver">
class="btn btn-info py-1 ms-3 redeliver">
Redeliver
</button>
</span>

View file

@ -3,20 +3,183 @@
ViewData.SetActivePageAndTitle(InvoiceNavPages.Index, "Invoices");
var storeIds = string.Join("", Model.StoreIds.Select(storeId => $",storeid:{storeId}"));
}
@section HeadScripts {
@section PageHeadContent {
<style type="text/css">
.invoice-payments {
padding-left: 2rem;
}
.invoice-payments h3 {
font-size: 15px;
font-weight: bold;
}
.wraptext200 {
max-width: 200px;
text-overflow: ellipsis;
overflow: hidden;
display: block;
white-space: nowrap;
}
.pavpill {
display: inline-block;
padding: 0.3em 0.5em;
font-size: 85%;
font-weight: 500;
line-height: 1;
text-align: center;
white-space: nowrap;
vertical-align: baseline;
border-radius: 0.25rem;
}
.badge .dropdown-toggle {
cursor: pointer;
padding: 0;
}
.dropdown-item {
cursor: pointer;
}
.badge-new {
background: #d4edda;
color: #000;
}
.badge-expired {
background: #eee;
color: #000;
}
.badge-invalid {
background: #c94a47;
color: #fff;
}
.badge-confirmed,
.badge-paid {
background: #f1c332;
color: #000;
}
.badge-complete {
background: #329f80;
color: #fff;
}
</style>
}
@section PageFootContent {
@*Without async, somehow selenium do not manage to click on links in this page*@
<script src="~/modal/btcpay.js" asp-append-version="true" async></script>
@* Custom Range Modal *@
<script>
$('#btnCustomRangeDate').on('click', function (sender) {
var filterString = "";
var dtpStartDate = $("#dtpStartDate").val();
if (dtpStartDate !== null && dtpStartDate !== "") {
filterString = "startDate%3A" + dtpStartDate;
}
var dtpEndDate = $("#dtpEndDate").val();
if (dtpEndDate !== null && dtpEndDate !== "") {
if (filterString !== "") {
filterString += ",";
}
filterString += "endDate%3A" + dtpEndDate;
}
if (filterString !== "") {
var redirectUri = "/invoices?Count=" + $("#Count").val() +
"&timezoneoffset=" + $("#TimezoneOffset").val() +
"&SearchTerm=" + filterString;
window.location.href = redirectUri;
} else {
$("#dtpStartDate").next().trigger("focus");
}
})
function selectAll(e)
{
var items = document.getElementsByClassName("selector");
for (var i = 0; i < items.length; i++) {
items[i].checked = e.checked;
}
}
function getDateStringWithOffset(hoursDiff) {
var datenow = new Date();
var newDate = new Date(datenow.getTime() - (hoursDiff * 60 * 60 * 1000));
var str = newDate.toLocaleDateString() + " " + newDate.toLocaleTimeString();
return str;
}
function changeInvoiceState(sender, invoiceId, newState) {
var pavpill = $("#pavpill_" + invoiceId);
var originalHtml = pavpill.html();
pavpill.html("<span class='fa fa-bitcoin fa-spin' style='margin-left:16px;'></span>");
$.post("invoices/" + invoiceId + "/changestate/" + newState)
.done(function (data) {
var statusHtml = "<span class='badge badge-" + newState + "'>" + data.statusString + " <span class='fa fa-check'></span></span>";
pavpill.replaceWith(statusHtml);
})
.fail(function (data) {
pavpill.html(originalHtml.replace("dropdown-menu pull-right show", "dropdown-menu pull-right"));
alert("Invoice state update failed");
});
}
document.addEventListener("DOMContentLoaded", function () {
var timezoneOffset = new Date().getTimezoneOffset();
$(".export-link, a.dropdown-item").each(function () {
this.href = this.href.replace("timezoneoffset=0", "timezoneoffset=" + timezoneOffset);
});
$("#invoices")
.on("click", ".invoice-row .invoice-details-toggle", function(e) {
e.preventDefault();
e.stopPropagation(true);
const $btnToggle = $(e.currentTarget);
const $invoiceRow = $btnToggle.parents(".invoice-row");
const $detailsRow = $invoiceRow.next(".invoice-details-row");
$detailsRow.toggle(0, function () {
const $icon = $btnToggle.children().first();
if ($(this).is(':visible')) {
$icon.removeClass('fa-angle-double-down').addClass('fa-angle-double-up');
} else {
$icon.removeClass('fa-angle-double-up').addClass('fa-angle-double-down');
}
});
})
.on("click", ".invoice-row", function(e) {
const $invoiceRow = $(e.currentTarget);
if (!$(e.target).is("a,.badge,.selector")) {
$invoiceRow.find(".selector").trigger("click");
}
});
});
</script>
}
@Html.HiddenFor(a => a.Count)
<section>
<div class="container">
<partial name="_StatusMessage" />
<partial name="_StatusMessage" />
<div class="d-sm-flex align-items-center justify-content-between mb-4">
<h2 class="mb-0">
@ViewData["Title"]
<small>
<a href="https://docs.btcpayserver.org/PaymentRequests/" class="ml-1" target="_blank">
<a href="https://docs.btcpayserver.org/PaymentRequests/" class="ms-1" target="_blank">
<span class="fa fa-question-circle-o text-secondary" title="More information..."></span>
</a>
</small>
@ -28,55 +191,50 @@
</div>
<div class="row">
<div class="col-12 col-lg-6 mb-5 mb-lg-2 ml-auto">
<div class="col-12 col-lg-6 mb-5 mb-lg-2 ms-auto">
<form asp-action="ListInvoices" method="get">
<input type="hidden" asp-for="Count"/>
<input asp-for="TimezoneOffset" type="hidden"/>
<div class="input-group">
<div class="input-group-prepend">
<a href="#help" class="input-group-text text-secondary text-decoration-none" data-toggle="collapse">
<span class="fa fa-filter"></span>
</a>
</div>
<a href="#help" class="input-group-text text-secondary text-decoration-none" data-bs-toggle="collapse">
<span class="fa fa-filter"></span>
</a>
<input asp-for="SearchTerm" class="form-control"/>
<div class="input-group-append">
<button type="submit" class="btn btn-secondary" title="Search invoice">
<span class="fa fa-search"></span> Search
</button>
<button type="button" class="btn btn-secondary dropdown-toggle dropdown-toggle-split" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<span class="sr-only">Toggle Dropdown</span>
</button>
<button type="submit" class="btn btn-secondary" title="Search invoice">
<span class="fa fa-search"></span> Search
</button>
<button type="button" id="SearchOptionsToggle" class="btn btn-secondary dropdown-toggle dropdown-toggle-split" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<span class="visually-hidden">Toggle Dropdown</span>
</button>
<div class="dropdown-menu dropdown-menu-right">
<a class="dropdown-item" asp-action="ListInvoices" asp-route-count="@Model.Count" asp-route-searchTerm="status:invalid@{@storeIds}">Invalid Invoices</a>
<a class="dropdown-item" asp-action="ListInvoices" asp-route-count="@Model.Count" asp-route-searchTerm="status:paid,status:confirmed,status:complete@{@storeIds}">Paid Invoices</a>
<a class="dropdown-item" asp-action="ListInvoices" asp-route-count="@Model.Count" asp-route-searchTerm="exceptionstatus:paidLate@{@storeIds}">Paid Late Invoices</a>
<a class="dropdown-item" asp-action="ListInvoices" asp-route-count="@Model.Count" asp-route-searchTerm="exceptionstatus:paidPartial@{@storeIds}">Paid Partial Invoices</a>
<a class="dropdown-item" asp-action="ListInvoices" asp-route-count="@Model.Count" asp-route-searchTerm="exceptionstatus:paidOver@{@storeIds}">Paid Over Invoices</a>
<a class="dropdown-item" asp-action="ListInvoices" asp-route-count="@Model.Count" asp-route-searchTerm="unusual:true@{@storeIds}">Unusual Invoices</a>
<a class="dropdown-item" asp-action="ListInvoices" asp-route-count="@Model.Count" asp-route-searchTerm="includearchived:true@{@storeIds}">Archived Invoices</a>
<div role="separator" class="dropdown-divider"></div>
<a class="dropdown-item" asp-action="ListInvoices" asp-route-count="@Model.Count" asp-route-timezoneoffset="0" asp-route-searchTerm="startDate:-24h@{@storeIds}">Last 24 hours</a>
<a class="dropdown-item" asp-action="ListInvoices" asp-route-count="@Model.Count" asp-route-timezoneoffset="0" asp-route-searchTerm="startDate:-3d@{@storeIds}">Last 3 days</a>
<a class="dropdown-item" asp-action="ListInvoices" asp-route-count="@Model.Count" asp-route-timezoneoffset="0" asp-route-searchTerm="startDate:-7d@{@storeIds}">Last 7 days</a>
<button type="button" class="dropdown-item" data-toggle="modal" data-target="#customRangeModal" data-backdrop="static">Custom Range</button>
<div role="separator" class="dropdown-divider"></div>
<a class="dropdown-item" href="?searchTerm=">Unfiltered</a>
</div>
<div class="dropdown-menu dropdown-menu-end" aria-labelledby="SearchOptionsToggle">
<a class="dropdown-item" asp-action="ListInvoices" asp-route-count="@Model.Count" asp-route-searchTerm="status:invalid@{@storeIds}">Invalid Invoices</a>
<a class="dropdown-item" asp-action="ListInvoices" asp-route-count="@Model.Count" asp-route-searchTerm="status:paid,status:confirmed,status:complete@{@storeIds}">Paid Invoices</a>
<a class="dropdown-item" asp-action="ListInvoices" asp-route-count="@Model.Count" asp-route-searchTerm="exceptionstatus:paidLate@{@storeIds}">Paid Late Invoices</a>
<a class="dropdown-item" asp-action="ListInvoices" asp-route-count="@Model.Count" asp-route-searchTerm="exceptionstatus:paidPartial@{@storeIds}">Paid Partial Invoices</a>
<a class="dropdown-item" asp-action="ListInvoices" asp-route-count="@Model.Count" asp-route-searchTerm="exceptionstatus:paidOver@{@storeIds}">Paid Over Invoices</a>
<a class="dropdown-item" asp-action="ListInvoices" asp-route-count="@Model.Count" asp-route-searchTerm="unusual:true@{@storeIds}">Unusual Invoices</a>
<a class="dropdown-item" asp-action="ListInvoices" asp-route-count="@Model.Count" asp-route-searchTerm="includearchived:true@{@storeIds}">Archived Invoices</a>
<div role="separator" class="dropdown-divider"></div>
<a class="dropdown-item" asp-action="ListInvoices" asp-route-count="@Model.Count" asp-route-timezoneoffset="0" asp-route-searchTerm="startDate:-24h@{@storeIds}">Last 24 hours</a>
<a class="dropdown-item" asp-action="ListInvoices" asp-route-count="@Model.Count" asp-route-timezoneoffset="0" asp-route-searchTerm="startDate:-3d@{@storeIds}">Last 3 days</a>
<a class="dropdown-item" asp-action="ListInvoices" asp-route-count="@Model.Count" asp-route-timezoneoffset="0" asp-route-searchTerm="startDate:-7d@{@storeIds}">Last 7 days</a>
<button type="button" class="dropdown-item" data-bs-toggle="modal" data-bs-target="#customRangeModal">Custom Range</button>
<div role="separator" class="dropdown-divider"></div>
<a class="dropdown-item" href="?searchTerm=">Unfiltered</a>
</div>
</div>
<span asp-validation-for="SearchTerm" class="text-danger"></span>
</form>
@* Custom Range Modal *@
<div class="modal fade" id="customRangeModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalCenterTitle" aria-hidden="true">
<div class="modal fade" id="customRangeModal" tabindex="-1" role="dialog" aria-labelledby="customRangeModalTitle" aria-hidden="true" data-bs-backdrop="static">
<div class="modal-dialog modal-dialog-centered" role="document" style="max-width: 550px;">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLongTitle">Filter invoices by Custom Range</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
<h5 class="modal-title" id="customRangeModalTitle">Filter invoices by Custom Range</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close">
<vc:icon symbol="close" />
</button>
</div>
<div class="modal-body">
@ -87,11 +245,9 @@
<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" />
<div class="input-group-append">
<button type="button" class="btn btn-primary input-group-clear" title="Clear">
<span class=" fa fa-times"></span>
</button>
</div>
<button type="button" class="btn btn-primary input-group-clear" title="Clear">
<span class="fa fa-times"></span>
</button>
</div>
</div>
</div>
@ -102,11 +258,9 @@
<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" />
<div class="input-group-append">
<button type="button" class="btn btn-primary input-group-clear" title="Clear">
<span class="fa fa-times"></span>
</button>
</div>
<button type="button" class="btn btn-primary input-group-clear" title="Clear">
<span class="fa fa-times"></span>
</button>
</div>
</div>
</div>
@ -117,35 +271,6 @@
</div>
</div>
</div>
<script type="text/javascript">
$('#btnCustomRangeDate').on('click', function (sender) {
var filterString = "";
var dtpStartDate = $("#dtpStartDate").val();
if (dtpStartDate !== null && dtpStartDate !== "") {
filterString = "startDate%3A" + dtpStartDate;
}
var dtpEndDate = $("#dtpEndDate").val();
if (dtpEndDate !== null && dtpEndDate !== "") {
if (filterString !== "") {
filterString += ",";
}
filterString += "endDate%3A" + dtpEndDate;
}
if (filterString !== "") {
var redirectUri = "/invoices?Count=" + $("#Count").val() +
"&timezoneoffset=" + $("#TimezoneOffset").val() +
"&SearchTerm=" + filterString;
window.location.href = redirectUri;
} else {
$("#dtpStartDate").next().trigger("focus");
}
})
</script>
@* Custom Range Modal *@
</div>
</div>
@ -178,38 +303,28 @@
@if (Model.Total > 0)
{
<form method="post" id="MassAction" asp-action="MassAction" class="mt-lg-n5">
<span class="mr-2">
<button class="btn btn-secondary dropdown-toggle mb-1" type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<span class="me-2">
<button class="btn btn-secondary dropdown-toggle mb-1" type="button" id="ActionsDropdownToggle" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
Actions
</button>
<div class="dropdown-menu">
<div class="dropdown-menu" aria-labelledby="ActionsDropdownToggle">
<button type="submit" asp-action="MassAction" class="dropdown-item" name="command" value="archive"><i class="fa fa-archive"></i> Archive</button>
</div>
</span>
<span>
<a class="btn btn-secondary dropdown-toggle mb-1" href="#" role="button" id="dropdownMenuLink" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<a class="btn btn-secondary dropdown-toggle mb-1" href="#" role="button" id="ExportDropdownToggle" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
Export
</a>
<div class="dropdown-menu" aria-labelledby="dropdownMenuLink">
<div class="dropdown-menu" aria-labelledby="ExportDropdownToggle">
<a asp-action="Export" asp-route-timezoneoffset="0" asp-route-format="csv" asp-route-searchTerm="@Model.SearchTerm" class="dropdown-item export-link" target="_blank">CSV</a>
<a asp-action="Export" asp-route-timezoneoffset="0" asp-route-format="json" asp-route-searchTerm="@Model.SearchTerm" class="dropdown-item export-link" target="_blank">JSON</a>
</div>
</span>
<a href="https://docs.btcpayserver.org/Accounting/" class="ml-1" target="_blank">
<a href="https://docs.btcpayserver.org/Accounting/" class="ms-1" target="_blank">
<span class="fa fa-question-circle-o text-secondary" title="More information..."></span>
</a>
<script type="text/javascript">
function selectAll(e)
{
var items = document.getElementsByClassName("selector");
for (var i = 0; i < items.length; i++) {
items[i].checked = e.checked;
}
}
</script>
<table id="invoices" class="table table-sm table-responsive-md">
<thead>
<tr>
@ -255,12 +370,12 @@
<td>
@if (invoice.Details.Archived)
{
<span class="badge badge-warning">archived</span>
<span class="badge bg-warning">archived</span>
}
@if (invoice.CanMarkStatus)
{
<div id="pavpill_@invoice.InvoiceId" class="badge badge-@invoice.Status.ToString().ToLower()">
<span class="dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<span class="dropdown-toggle" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
@invoice.Status.ToString()
</span>
<div class="dropdown-menu pull-right">
@ -332,125 +447,4 @@
</p>
}
</div>
<script type="text/javascript">
function getDateStringWithOffset(hoursDiff) {
var datenow = new Date();
var newDate = new Date(datenow.getTime() - (hoursDiff * 60 * 60 * 1000));
var str = newDate.toLocaleDateString() + " " + newDate.toLocaleTimeString();
return str;
}
function changeInvoiceState(sender, invoiceId, newState) {
var pavpill = $("#pavpill_" + invoiceId);
var originalHtml = pavpill.html();
pavpill.html("<span class='fa fa-bitcoin fa-spin' style='margin-left:16px;'></span>");
$.post("invoices/" + invoiceId + "/changestate/" + newState)
.done(function (data) {
var statusHtml = "<span class='badge badge-" + newState + "'>" + data.statusString + " <span class='fa fa-check'></span></span>";
pavpill.replaceWith(statusHtml);
})
.fail(function (data) {
pavpill.html(originalHtml.replace("dropdown-menu pull-right show", "dropdown-menu pull-right"));
alert("Invoice state update failed");
});
}
$(function () {
var timezoneOffset = new Date().getTimezoneOffset();
$(".export-link, a.dropdown-item").each(function () {
this.href = this.href.replace("timezoneoffset=0", "timezoneoffset=" + timezoneOffset);
});
$("#invoices")
.on("click", ".invoice-row .invoice-details-toggle", function(e) {
e.preventDefault();
e.stopPropagation(true);
const $btnToggle = $(e.currentTarget);
const $invoiceRow = $btnToggle.parents(".invoice-row");
const $detailsRow = $invoiceRow.next(".invoice-details-row");
$detailsRow.toggle(0, function () {
const $icon = $btnToggle.children().first();
if ($(this).is(':visible')) {
$icon.removeClass('fa-angle-double-down').addClass('fa-angle-double-up');
} else {
$icon.removeClass('fa-angle-double-up').addClass('fa-angle-double-down');
}
});
})
.on("click", ".invoice-row", function(e) {
const $invoiceRow = $(e.currentTarget);
if (!$(e.target).is("a,.badge,.selector")) {
$invoiceRow.find(".selector").trigger("click");
}
});
});
</script>
<style type="text/css">
.invoice-payments {
padding-left: 2rem;
}
.invoice-payments h3 {
font-size: 15px;
font-weight: bold;
}
.wraptext200 {
max-width: 200px;
text-overflow: ellipsis;
overflow: hidden;
display: block;
white-space: nowrap;
}
.pavpill {
display: inline-block;
padding: 0.3em 0.5em;
font-size: 85%;
font-weight: 500;
line-height: 1;
text-align: center;
white-space: nowrap;
vertical-align: baseline;
border-radius: 0.25rem;
}
.badge .dropdown-toggle {
cursor: pointer;
padding: 0;
}
.dropdown-item {
cursor: pointer;
}
.badge-new {
background: #d4edda;
color: #000;
}
.badge-expired {
background: #eee;
color: #000;
}
.badge-invalid {
background: #c94a47;
color: #fff;
}
.badge-confirmed,
.badge-paid {
background: #f1c332;
color: #000;
}
.badge-complete {
background: #329f80;
color: #fff;
}
</style>
</section>

View file

@ -14,12 +14,12 @@
{
<th>Address</th>
}
<th class="text-right">Rate</th>
<th class="text-right">Paid</th>
<th class="text-right">Due</th>
<th class="text-end">Rate</th>
<th class="text-end">Paid</th>
<th class="text-end">Due</th>
@if (invoice.StatusException == InvoiceExceptionStatus.PaidOver)
{
<th class="text-right">Overpaid</th>
<th class="text-end">Overpaid</th>
}
</tr>
</thead>
@ -34,12 +34,12 @@
<span class="text-truncate d-block" style="max-width: 400px">@payment.Address</span>
</td>
}
<td class="text-right">@payment.Rate</td>
<td class="text-right">@payment.Paid</td>
<td class="text-right">@payment.Due</td>
<td class="text-end">@payment.Rate</td>
<td class="text-end">@payment.Paid</td>
<td class="text-end">@payment.Due</td>
@if (invoice.StatusException == InvoiceExceptionStatus.PaidOver)
{
<td class="text-right">@payment.Overpaid</td>
<td class="text-end">@payment.Overpaid</td>
}
</tr>
}

View file

@ -18,12 +18,12 @@
{
case RefundSteps.SelectPaymentMethod:
<div class="form-group">
<label asp-for="SelectedPaymentMethod"></label>
<select asp-items="Model.AvailablePaymentMethods" asp-for="SelectedPaymentMethod" class="form-control"></select>
<label asp-for="SelectedPaymentMethod" class="form-label"></label>
<select asp-items="Model.AvailablePaymentMethods" asp-for="SelectedPaymentMethod" class="form-select"></select>
<span asp-validation-for="SelectedPaymentMethod" class="text-danger"></span>
</div>
<div class="form-group">
<button id="ok" type="submit" class="btn btn-primary btn-block btn-lg">Next</button>
<button id="ok" type="submit" class="btn btn-primary btn-lg w-100">Next</button>
</div>
break;
case RefundSteps.SelectRate:
@ -61,7 +61,7 @@
<small class="form-text text-muted">The specified amount with the specified currency, at the rate when the refund will be sent. </small>
</div>
<div class="form-group">
<button id="ok" type="submit" class="btn btn-primary btn-block btn-lg">Create refund</button>
<button id="ok" type="submit" class="btn btn-primary btn-lg w-100">Create refund</button>
</div>
break;
case RefundSteps.SelectCustomAmount:
@ -73,18 +73,16 @@
<input type="hidden" asp-for="SelectedRefundOption"/>
<div class="form-group">
<label asp-for="CustomAmount"></label>
<label asp-for="CustomAmount" class="form-label"></label>
<div class="input-group">
<input asp-for="CustomAmount" type="number" step="any" asp-format="{0}" class="form-control"/>
<div class="input-group-append">
<input asp-for="CustomCurrency" type="text"class="form-control"/>
</div>
<input asp-for="CustomCurrency" type="text" class="form-control"/>
</div>
<span asp-validation-for="CustomAmount" class="text-danger w-100"></span>
<span asp-validation-for="CustomCurrency" class="text-danger w-100"></span>
</div>
<div class="form-group">
<button id="ok" type="submit" class="btn btn-primary btn-block btn-lg">Next</button>
<button id="ok" type="submit" class="btn btn-primary btn-lg w-100">Next</button>
</div>
break;
}

View file

@ -15,7 +15,7 @@
<th>Label</th>
<th class="w-125px">Key</th>
<th>Permissions</th>
<th class="text-right">Actions</th>
<th class="text-end">Actions</th>
</tr>
</thead>
<tbody>
@ -56,7 +56,7 @@
</ul>
}
</td>
<td class="text-right">
<td class="text-end">
<a asp-action="RemoveAPIKey" asp-route-id="@keyData.Id" asp-controller="Manage">Remove</a>
<span>-</span>
<button type="button" class="btn btn-link only-for-js" data-qr="@index">Show QR</button>
@ -79,16 +79,18 @@
Generate new key
</a>
@section PageHeadContent {
<link href="~/vendor/vue-qrcode-reader/vue-qrcode-reader.css" rel="stylesheet" asp-append-version="true"/>
}
@section PageFootContent {
<script src="~/vendor/vuejs/vue.min.js" asp-append-version="true"></script>
<script src="~/vendor/vue-qrcode/vue-qrcode.min.js" asp-append-version="true"></script>
<script src="~/vendor/bc-ur/web-bundle.js" asp-append-version="true"></script>
<script src="~/vendor/vue-qrcode-reader/vue-qrcode-reader.browser.js" asp-append-version="true"></script>
<script src="~/js/copy-to-clipboard.js" asp-append-version="true"></script>
<link href="~/vendor/vue-qrcode-reader/vue-qrcode-reader.css" rel="stylesheet" asp-append-version="true"/>
<partial name="ShowQR"/>
<script>
$(document).ready(function(){
document.addEventListener("DOMContentLoaded", function () {
$("[data-reveal-btn]").on("click", function (){
var $revealButton = $(this);
$revealButton.attr("hidden", "true");
@ -118,3 +120,7 @@
});
});
</script>
}
<partial name="ShowQR"/>

View file

@ -7,6 +7,17 @@
ViewData.SetActivePageAndTitle(ManageNavPages.APIKeys, "Add API Key");
}
@section PageHeadContent {
<style>
.remove-btn { font-size: 1.5rem; border-radius: 0; }
.remove-btn:hover { background-color: #CCCCCC; }
</style>
}
@section PageFootContent {
<partial name="_ValidationScriptsPartial"/>
}
<h2 class="mb-4">@ViewData["PageTitle"]</h2>
<p>Generate a new api key to use BTCPay through its API.</p>
@ -38,8 +49,8 @@
{
<div class="list-group-item form-group py-3">
<div class="form-check">
<input id="@Model.PermissionValues[i].Permission" type="checkbox" asp-for="PermissionValues[i].Value" class="form-check-input ml-n4" />
<label for="@Model.PermissionValues[i].Permission" class="h5 form-check-label mr-2 mb-1">@Model.PermissionValues[i].Title</label>
<input id="@Model.PermissionValues[i].Permission" type="checkbox" asp-for="PermissionValues[i].Value" class="form-check-input ms-n4" />
<label for="@Model.PermissionValues[i].Permission" class="h5 form-check-label me-2 mb-1">@Model.PermissionValues[i].Title</label>
<button type="submit" class="btn btn-link p-0 mb-1" name="command" value="@($"{Model.PermissionValues[i].Permission}:change-store-mode")">Select specific stores</button>
<span asp-validation-for="PermissionValues[i].Value" class="text-danger"></span>
<span class="form-text text-muted">@Model.PermissionValues[i].Description</span>
@ -64,19 +75,17 @@
<div class="input-group my-3">
@if (Model.PermissionValues[i].SpecificStores[index] == null)
{
<select asp-for="PermissionValues[i].SpecificStores[index]" class="form-control" asp-items="@(new SelectList(Model.Stores.Where(data => !Model.PermissionValues[i].SpecificStores.Contains(data.Id)), nameof(StoreData.Id), nameof(StoreData.StoreName)))"></select>
<select asp-for="PermissionValues[i].SpecificStores[index]" class="form-select" asp-items="@(new SelectList(Model.Stores.Where(data => !Model.PermissionValues[i].SpecificStores.Contains(data.Id)), nameof(StoreData.Id), nameof(StoreData.StoreName)))"></select>
}
else
{
var store = Model.Stores.SingleOrDefault(data => data.Id == Model.PermissionValues[i].SpecificStores[index]);
<select asp-for="PermissionValues[i].SpecificStores[index]" class="form-control" asp-items="@(new SelectList(new[] {store}, nameof(StoreData.Id), nameof(StoreData.StoreName), store.Id))"></select>
<select asp-for="PermissionValues[i].SpecificStores[index]" class="form-select" 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>
<div class="input-group-append">
<button type="submit" title="Remove Store Permission" name="command" value="@($"{Model.PermissionValues[i].Permission}:remove-store:{index}")" class="btn btn-danger">
Remove
</button>
</div>
<button type="submit" title="Remove Store Permission" name="command" value="@($"{Model.PermissionValues[i].Permission}:remove-store:{index}")" class="btn btn-danger">
Remove
</button>
</div>
}
@if (Model.PermissionValues[i].SpecificStores.Count < Model.Stores.Length)
@ -92,8 +101,8 @@
{
<div class="list-group-item form-group py-3">
<div class="form-check">
<input id="@Model.PermissionValues[i].Permission" type="checkbox" asp-for="PermissionValues[i].Value" class="form-check-input ml-n4" />
<label for="@Model.PermissionValues[i].Permission" class="h5 form-check-label mr-2 mb-1">@Model.PermissionValues[i].Title</label>
<input id="@Model.PermissionValues[i].Permission" type="checkbox" asp-for="PermissionValues[i].Value" class="form-check-input ms-n4" />
<label for="@Model.PermissionValues[i].Permission" class="h5 form-check-label me-2 mb-1">@Model.PermissionValues[i].Title</label>
<span asp-validation-for="PermissionValues[i].Value" class="text-danger"></span>
<span class="form-text text-muted">@Model.PermissionValues[i].Description</span>
</div>
@ -105,18 +114,3 @@
<button type="submit" class="btn btn-primary" id="Generate">Generate API Key</button>
</form>
@section Scripts {
<partial name="_ValidationScriptsPartial" />
<style>
.remove-btn {
font-size: 1.5rem;
border-radius: 0;
}
.remove-btn:hover {
background-color: #CCCCCC;
}
</style>
}

View file

@ -37,7 +37,7 @@
<div asp-validation-summary="All" class="text-danger"></div>
<div class="list-group-item ">
<div class="form-group">
<label asp-for="Label"></label>
<label asp-for="Label" class="form-label"></label>
<input asp-for="Label" class="form-control"/>
<span asp-validation-for="Label" class="text-danger"></span>
</div>
@ -108,18 +108,18 @@
}
@for (var index = 0; index < Model.PermissionValues[i].SpecificStores.Count; index++)
{
<div class="list-group-item transaction-output-form p-0 pl-lg-2">
<div class="list-group-item transaction-output-form p-0 ps-lg-2">
<div class="row">
<div class="col-sm-12 col-md-12 col-lg-10 py-2 ">
<div class="col-sm-12 col-md-12 col-lg-10 py-2">
<div class="form-group my-0">
@if (Model.PermissionValues[i].SpecificStores[index] == null)
{
<select asp-for="PermissionValues[i].SpecificStores[index]" class="form-control" asp-items="@(new SelectList(Model.Stores.Where(data => !Model.PermissionValues[i].SpecificStores.Contains(data.Id)), nameof(StoreData.Id), nameof(StoreData.StoreName)))"></select>
<select asp-for="PermissionValues[i].SpecificStores[index]" class="form-select" asp-items="@(new SelectList(Model.Stores.Where(data => !Model.PermissionValues[i].SpecificStores.Contains(data.Id)), nameof(StoreData.Id), nameof(StoreData.StoreName)))"></select>
}
else
{
var store = Model.Stores.SingleOrDefault(data => data.Id == Model.PermissionValues[i].SpecificStores[index]);
<select asp-for="PermissionValues[i].SpecificStores[index]" class="form-control" asp-items="@(new SelectList(new[] {store}, nameof(StoreData.Id), nameof(StoreData.StoreName), store.Id))"></select>
<select asp-for="PermissionValues[i].SpecificStores[index]" class="form-select" 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>
@ -127,7 +127,7 @@
</div>
<div class="col-sm-12 col-md-12 col-lg-2 pull-right">
<button type="submit" title="Remove Store Permission" name="command" value="@($"{Model.PermissionValues[i].Permission}:remove-store:{index}")"
class="d-block d-lg-none d-xl-none btn btn-danger mb-2 ml-2">
class="d-block d-lg-none d-xl-none btn btn-danger mb-2 ms-2">
Remove
</button>
<button type="submit" title="Remove Store Permission" name="command" value="@($"{Model.PermissionValues[i].Permission}:remove-store:{index}")"
@ -140,7 +140,7 @@
@if (Model.PermissionValues[i].SpecificStores.Count < Model.Stores.Length)
{
<div class="list-group-item">
<button type="submit" name="command" value="@($"{Model.PermissionValues[i].Permission}:add-store")" class="ml-1 btn btn-secondary">Add another store </button>
<button type="submit" name="command" value="@($"{Model.PermissionValues[i].Permission}:add-store")" class="ms-1 btn btn-secondary">Add another store </button>
</div>
}
}

View file

@ -30,6 +30,6 @@
</div>
</div>
@section Scripts {
@section PageFootContent {
<partial name="_ValidationScriptsPartial" />
}

View file

@ -9,7 +9,7 @@
<!DOCTYPE html>
<html lang="en">
<head>
<partial name="Header" />
<partial name="LayoutHead" />
</head>
<body class="bg-light">
<div class="modal-dialog modal-dialog-centered min-vh-100">
@ -37,5 +37,6 @@
</form>
</div>
</div>
<partial name="LayoutFoot" />
</body>
</html>

View file

@ -24,7 +24,7 @@
<li class="mb-5">
<p class="mb-2">Scan the QR Code or enter the following key into your two factor authenticator app:</p>
<p class="mb-4">
<code class="mr-3">@Model.SharedKey</code>
<code class="me-3">@Model.SharedKey</code>
<span class="text-secondary">(spaces and casing do not matter)</span>
</p>
<div id="qrCode"></div>
@ -42,7 +42,7 @@
<input asp-for="AuthenticatorUri" type="hidden" />
<input asp-for="SharedKey" type="hidden" />
<div class="form-group">
<label asp-for="Code" class="control-label">Verification Code</label>
<label asp-for="Code" class="form-label">Verification Code</label>
<input asp-for="Code" class="form-control" autocomplete="off" />
<span asp-validation-for="Code" class="text-danger"></span>
</div>
@ -55,18 +55,17 @@
</ol>
</div>
@section Scripts {
@section PageFootContent {
<partial name="_ValidationScriptsPartial" />
<script type="text/javascript" src="~/js/qrcode.js" asp-append-version="true"></script>
<script type="text/javascript">
new QRCode(document.getElementById("qrCode"),
{
text: @Safe.Json(Model.AuthenticatorUri),
width: 200,
height: 200,
useSVG: true,
correctLevel : QRCode.CorrectLevel.M
});
<script src="~/js/qrcode.js" asp-append-version="true"></script>
<script>
new QRCode(document.getElementById("qrCode"), {
text: @Safe.Json(Model.AuthenticatorUri),
width: 200,
height: 200,
useSVG: true,
correctLevel : QRCode.CorrectLevel.M
});
$("#qrCode > img").css({ "margin": "auto" });
</script>
}

View file

@ -24,7 +24,7 @@
<div class="col-md-6 mb-3 d-flex align-items-end">
@if (Model.IsEmailConfirmed)
{
<span class="badge badge-success p-2 my-1">
<span class="badge bg-success p-2 my-1">
<span class="fa fa-check"></span>
confirmed
</span>
@ -38,6 +38,6 @@
<button type="submit" id="save" class="btn btn-primary">Save</button>
</form>
@section Scripts {
@section PageFootContent {
<partial name="_ValidationScriptsPartial" />
}

View file

@ -14,12 +14,12 @@
<form method="post">
<div asp-validation-summary="All" class="text-danger"></div>
<div class="form-group">
<label asp-for="NewPassword"></label>
<label asp-for="NewPassword" class="form-label"></label>
<input asp-for="NewPassword" class="form-control" />
<span asp-validation-for="NewPassword" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="ConfirmPassword"></label>
<label asp-for="ConfirmPassword" class="form-label"></label>
<input asp-for="ConfirmPassword" class="form-control" />
<span asp-validation-for="ConfirmPassword" class="text-danger"></span>
</div>
@ -28,6 +28,6 @@
</div>
</div>
@section Scripts {
@section PageFootContent {
<partial name="_ValidationScriptsPartial" />
}

View file

@ -43,14 +43,14 @@
<a asp-action="Disable2faWarning" class="list-group-item d-flex justify-content-between align-items-center list-group-item-action py-3">
<div>
<h5 >Disable 2FA</h5>
<p class="mb-0 mr-3">Disable two-factor authentication. Re-enabling will not require you to reconfigure your Authenticator app. </p>
<p class="mb-0 me-3">Disable two-factor authentication. Re-enabling will not require you to reconfigure your Authenticator app. </p>
</div>
<i class="fa fa-chevron-right"></i>
</a>
<a asp-action="GenerateRecoveryCodes" class="list-group-item d-flex justify-content-between align-items-center list-group-item-action py-3">
<div>
<h5 >Reset recovery codes</h5>
<p class="mb-0 mr-3">Regenerate your two-factor recovery codes.</p>
<p class="mb-0 me-3">Regenerate your two-factor recovery codes.</p>
</div>
<i class="fa fa-chevron-right"></i>
</a>
@ -58,14 +58,14 @@
<a asp-action="EnableAuthenticator" class="list-group-item d-flex justify-content-between align-items-center list-group-item-action py-3">
<div>
<h5 >Configure Authenticator app</h5>
<p class="mb-0 mr-3">Display the key or QR code to configure an authenticator app with your current setup.</p>
<p class="mb-0 me-3">Display the key or QR code to configure an authenticator app with your current setup.</p>
</div>
<i class="fa fa-chevron-right"></i>
</a>
<a asp-action="ResetAuthenticatorWarning" class="list-group-item d-flex justify-content-between align-items-center list-group-item-action py-3">
<div>
<h5 >Reset Authenticator app</h5>
<p class="mb-0 mr-3">Invalidates the current authenticator configuration. Useful if you believe your authenticator settings were compromised.</p>
<p class="mb-0 me-3">Invalidates the current authenticator configuration. Useful if you believe your authenticator settings were compromised.</p>
</div>
<i class="fa fa-chevron-right"></i>
</a>
@ -75,13 +75,13 @@
<a asp-action="EnableAuthenticator" class="list-group-item d-flex justify-content-between align-items-center list-group-item-action py-3">
<div>
<h5 >Enable 2FA</h5>
<p class="mb-0 mr-3">Enable two-factor authentication using TOTP with apps such as Google Authenticator.</p>
<p class="mb-0 me-3">Enable two-factor authentication using TOTP with apps such as Google Authenticator.</p>
</div>
<i class="fa fa-chevron-right"></i>
</a>
}
</div>
@section Scripts {
@section PageFootContent {
<partial name="_ValidationScriptsPartial" />
}

View file

@ -1,5 +1,5 @@
@inject SignInManager<ApplicationUser> SignInManager
<div class="nav flex-column mb-4">
<nav id="sideNav" class="nav flex-column mb-4">
<a id="@ManageNavPages.Index.ToString()" class="nav-link @ViewData.IsActivePage(ManageNavPages.Index)" asp-controller="Manage" asp-action="Index">Profile</a>
<a id="@ManageNavPages.ChangePassword.ToString()" class="nav-link @ViewData.IsActivePage(ManageNavPages.ChangePassword)" asp-controller="Manage" asp-action="ChangePassword">Password</a>
<a id="@ManageNavPages.TwoFactorAuthentication.ToString()" class="nav-link @ViewData.IsActivePage(ManageNavPages.TwoFactorAuthentication)" asp-controller="Manage" asp-action="TwoFactorAuthentication">Two-factor authentication</a>
@ -7,4 +7,4 @@
<a id="@ManageNavPages.APIKeys.ToString()" class="nav-link @ViewData.IsActivePage(ManageNavPages.APIKeys)" asp-controller="Manage" asp-action="APIKeys">API Keys</a>
<a id="@ManageNavPages.Notifications.ToString()" class="nav-link @ViewData.IsActivePage(ManageNavPages.Notifications)" asp-controller="Manage" asp-action="NotificationSettings">Notifications</a>
<vc:ui-extension-point location="user-nav"/>
</div>
</nav>

View file

@ -34,12 +34,12 @@
<h3 class="card-title p-2">Upload Wallet</h3>
<div class="form-group p-2">
<label asp-for="WalletFile"></label>
<input class="form-control-file" asp-for="WalletFile" required>
<input class="form-control" asp-for="WalletFile" required>
<span asp-validation-for="WalletFile" class="text-danger"></span>
</div>
<div class="form-group p-2">
<label asp-for="WalletKeysFile"></label>
<input class="form-control-file" asp-for="WalletKeysFile" required>
<input class="form-control" asp-for="WalletKeysFile" required>
<span asp-validation-for="WalletKeysFile" class="text-danger"></span>
</div>
<div class="form-group p-2">
@ -81,11 +81,8 @@
<div class="form-group">
<div class="input-group my-3">
<input type="text" class="form-control" placeholder="New account label" asp-for="NewAccountLabel">
<div class="input-group-append">
<button name="command" value="add-account" class="btn btn-secondary" type="submit">Add account</button>
</div>
<button name="command" value="add-account" class="input-group-text btn btn-secondary" type="submit">Add account</button>
</div>
</div>
}
@ -109,6 +106,6 @@
</div>
</div>
@section Scripts {
@section PageFootContent {
@await Html.PartialAsync("_ValidationScriptsPartial")
}

View file

@ -51,6 +51,6 @@
</div>
</div>
@section Scripts {
@section PageFootContent {
@await Html.PartialAsync("_ValidationScriptsPartial")
}

View file

@ -18,7 +18,7 @@
<div class="row button-row">
<div class="col-lg-6">
<span class="dropdown" style="display:none;" id="MassAction">
<button class="btn btn-primary dropdown-toggle" type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<button class="btn btn-primary dropdown-toggle" type="button" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
Actions
</button>
<div class="dropdown-menu">
@ -47,7 +47,7 @@
</a>
</th>
<th>Message</th>
<th class="text-right">Actions</th>
<th class="text-end">Actions</th>
</tr>
</thead>
<tbody>
@ -65,7 +65,7 @@
<td onclick="toggleRowCheckbox(this)">
@item.Body
</td>
<td class="text-right font-weight-normal">
<td class="text-end fw-normal">
@if (!String.IsNullOrEmpty(item.ActionLink))
{
<a href="@item.ActionLink" class="btn btn-link p-0">Details</a>
@ -132,7 +132,7 @@ tr.seen td {
updateSelectors();
}
$(function () {
document.addEventListener("DOMContentLoaded", function () {
$(".selector").change(updateSelectors);
updateSelectors();
});

View file

@ -5,6 +5,16 @@
@{
ViewData.SetActivePageAndTitle(PaymentRequestsNavPages.Create, (string.IsNullOrEmpty(Model.Id) ? "Create" : "Edit") + " Payment Request");
}
@section PageHeadContent {
<bundle name="wwwroot/bundles/payment-request-admin-bundle.min.css" asp-append-version="true"></bundle>
}
@section PageFootContent {
<script src="~/vendor/moment/moment.js" asp-append-version="true"></script>
<partial name="_ValidationScriptsPartial" />
<bundle name="wwwroot/bundles/payment-request-admin-bundle.min.js" asp-append-version="true"></bundle>
}
<section>
<div class="container">
<partial name="_StatusMessage" />
@ -17,17 +27,17 @@
<input type="hidden" name="Id" value="@Model.Id" />
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="Title" class="control-label" data-required></label>
<label asp-for="Title" class="form-label" data-required></label>
<input asp-for="Title" class="form-control" required />
<span asp-validation-for="Title" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Amount" class="control-label" data-required></label>
<label asp-for="Amount" class="form-label" data-required></label>
<input type="number" step="any" asp-for="Amount" class="form-control" required />
<span asp-validation-for="Amount" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Currency" class="control-label" data-required></label>
<label asp-for="Currency" class="form-label" data-required></label>
<input asp-for="Currency" class="form-control" required />
<span asp-validation-for="Currency" class="text-danger"></span>
</div>
@ -37,10 +47,10 @@
<span asp-validation-for="AllowCustomPaymentAmounts" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="StoreId" class="control-label"></label>
<label asp-for="StoreId" class="form-label"></label>
@if (string.IsNullOrEmpty(Model.Id))
{
<select asp-for="StoreId" asp-items="Model.Stores" class="form-control"></select>
<select asp-for="StoreId" asp-items="Model.Stores" class="form-select"></select>
}
else
{
@ -50,31 +60,29 @@
<span asp-validation-for="StoreId" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Email" class="control-label"></label>
<label asp-for="Email" class="form-label"></label>
<input type="email" asp-for="Email" class="form-control" />
<span asp-validation-for="Email" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="ExpiryDate" class="control-label"></label>
<label asp-for="ExpiryDate" class="form-label"></label>
<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" />
<div class="input-group-append">
<button class="btn btn-secondary input-group-clear" type="button" title="Clear">
<span class=" fa fa-times"></span>
</button>
</div>
class="form-control flatdtpicker" min="today" placeholder="No expiry date has been set for this payment request" />x
<button class="btn btn-secondary input-group-clear" type="button" title="Clear">
<span class="fa fa-times"></span>
</button>
</div>
<span asp-validation-for="ExpiryDate" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Description" class="control-label"></label>
<label asp-for="Description" class="form-label"></label>
<textarea asp-for="Description" class="form-control richtext"></textarea>
<span asp-validation-for="Description" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="CustomCSSLink" class="control-label"></label>
<label asp-for="CustomCSSLink" class="form-label"></label>
<a href="https://docs.btcpayserver.org/Theme/#2-bootstrap-themes" target="_blank">
<span class="fa fa-question-circle-o text-secondary" title="More information..."></span>
</a>
@ -82,7 +90,7 @@
<span asp-validation-for="CustomCSSLink" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="EmbeddedCSS" class="control-label"></label>
<label asp-for="EmbeddedCSS" class="form-label"></label>
<textarea asp-for="EmbeddedCSS" rows="10" cols="40" class="form-control"></textarea>
<span asp-validation-for="EmbeddedCSS" class="text-danger"></span>
</div>
@ -99,22 +107,17 @@
<a class="btn btn-secondary" asp-route-id="@Context.GetRouteValue("id")" asp-action="ClonePaymentRequest" id="@Model.Id">Clone</a>
@if (!Model.Archived)
{
<a class="btn btn-secondary" data-toggle="tooltip" title="Archive this payment request so that it does not appear in the payment request list by default" asp-route-id="@Context.GetRouteValue("id")" asp-controller="PaymentRequest" asp-action="TogglePaymentRequestArchival">Archive</a>
<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-route-id="@Context.GetRouteValue("id")" asp-controller="PaymentRequest" asp-action="TogglePaymentRequestArchival">Archive</a>
}
else
{
<a class="btn btn-secondary" data-toggle="tooltip" title="Unarchive this payment request" asp-route-id="@Context.GetRouteValue("id")" asp-controller="PaymentRequest" asp-action="TogglePaymentRequestArchival">Unarchive</a>
<a class="btn btn-secondary" data-bs-toggle="tooltip" title="Unarchive this payment request" asp-route-id="@Context.GetRouteValue("id")" asp-controller="PaymentRequest" asp-action="TogglePaymentRequestArchival">Unarchive</a>
}
}
<a asp-action="GetPaymentRequests" class="text-muted ml-3">Back to list</a>
<a asp-action="GetPaymentRequests" class="text-muted ms-3">Back to list</a>
</div>
</form>
</div>
</div>
</div>
</section>
@section Scripts {
<script src="~/vendor/moment/moment.js" asp-append-version="true"></script>
<bundle name="wwwroot/bundles/payment-request-admin-bundle.min.js" asp-append-version="true"></bundle>
<bundle name="wwwroot/bundles/payment-request-admin-bundle.min.css" asp-append-version="true"></bundle>
}

View file

@ -12,7 +12,7 @@
<h2 class="mb-0">
@ViewData["Title"]
<small>
<a href="https://docs.btcpayserver.org/PaymentRequests/" class="ml-1" target="_blank">
<a href="https://docs.btcpayserver.org/PaymentRequests/" class="ms-1" target="_blank">
<span class="fa fa-question-circle-o text-secondary" title="More information..."></span>
</a>
</small>
@ -24,25 +24,22 @@
</div>
<div class="row">
<div class="col-12 col-lg-6 mb-3 ml-auto">
<div class="col-12 col-lg-6 mb-3 ms-auto">
<form asp-action="GetPaymentRequests" method="get">
<input type="hidden" asp-for="Count"/>
<input type="hidden" asp-for="TimezoneOffset" />
<div class="input-group">
<input asp-for="SearchTerm" class="form-control" style="width:300px;"/>
<div class="input-group-append">
<button type="submit" class="btn btn-secondary" title="Search invoice">
<span class="fa fa-search"></span> Search
</button>
<button type="button" class="btn btn-secondary dropdown-toggle dropdown-toggle-split" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<span class="sr-only">Toggle Dropdown</span>
</button>
<div class="dropdown-menu dropdown-menu-right">
<a class="dropdown-item" asp-action="GetPaymentRequests" asp-route-count="@Model.Count" asp-route-searchTerm="includearchived:true">Include Archived Payment Reqs</a>
<div role="separator" class="dropdown-divider"></div>
<a class="dropdown-item" href="?searchTerm=">Unfiltered</a>
</div>
<button type="submit" class="btn btn-secondary" title="Search invoice">
<span class="fa fa-search"></span> Search
</button>
<button type="button" class="btn btn-secondary dropdown-toggle dropdown-toggle-split" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<span class="visually-hidden">Toggle Dropdown</span>
</button>
<div class="dropdown-menu dropdown-menu-end">
<a class="dropdown-item" asp-action="GetPaymentRequests" asp-route-count="@Model.Count" asp-route-searchTerm="includearchived:true">Include Archived Payment Reqs</a>
<div role="separator" class="dropdown-divider"></div>
<a class="dropdown-item" href="?searchTerm=">Unfiltered</a>
</div>
</div>
<span asp-validation-for="SearchTerm" class="text-danger"></span>
@ -59,9 +56,9 @@
<tr>
<th>Title</th>
<th>Expiry</th>
<th class="text-right">Price</th>
<th class="text-right">Status</th>
<th class="text-right">Actions</th>
<th class="text-end">Price</th>
<th class="text-end">Status</th>
<th class="text-end">Actions</th>
</tr>
</thead>
<tbody>
@ -70,9 +67,9 @@
<tr>
<td>@item.Title</td>
<td>@(item.ExpiryDate?.ToString("g") ?? "No Expiry")</td>
<td class="text-right">@item.Amount @item.Currency</td>
<td class="text-right">@item.Status</td>
<td class="text-right">
<td class="text-end">@item.Amount @item.Currency</td>
<td class="text-end">@item.Status</td>
<td class="text-end">
<a asp-action="EditPaymentRequest" asp-route-id="@item.Id">Edit</a>
<span> - </span>
<a asp-action="ViewPaymentRequest" asp-route-id="@item.Id">View</a>

View file

@ -77,14 +77,14 @@
&nbsp;
<span class="text-nowrap d-print-none" v-text="lastUpdated" v-cloak>@Model.LastUpdated.ToString("g")</span>
<span class="text-nowrap d-none d-print-block" v-text="lastUpdatedDate">@Model.LastUpdated.ToString("g")</span>
<button type="button" class="btn btn-link d-none d-lg-inline-block d-print-none border-0 p-0 ml-4 only-for-js" v-on:click="window.print" v-cloak>
<button type="button" class="btn btn-link d-none d-lg-inline-block d-print-none border-0 p-0 ms-4 only-for-js" v-on:click="window.print" v-cloak>
Print
</button>
<button type="button" class="btn btn-link d-none d-lg-inline-block d-print-none border-0 p-0 ml-4 only-for-js" v-on:click="window.copyUrlToClipboard" v-cloak>
<button type="button" class="btn btn-link d-none d-lg-inline-block d-print-none border-0 p-0 ms-4 only-for-js" v-on:click="window.copyUrlToClipboard" v-cloak>
Copy Link
</button>
</div>
<div class="col col-12 col-sm-6 text-sm-right col-lg-4 mt-lg-n4 pt-lg-1 d-print-none">
<div class="col col-12 col-sm-6 text-sm-end col-lg-4 mt-lg-n4 pt-lg-1 d-print-none">
@if (Model.IsPending && !Model.Archived && Model.ExpiryDate.HasValue)
{
<noscript>@Model.Status</noscript>
@ -105,10 +105,8 @@
<div class="row">
<div class="col col-12 col-sm-6 col-md-12">
<div class="input-group">
<input type="number" class="form-control text-right hide-number-spin" name="amount" value="@Model.AmountDue" @if (!Model.AllowCustomPaymentAmounts) { @("readonly") } max="@Model.AmountDue" step="any" placeholder="Amount" required />
<div class="input-group-append">
<span class="input-group-text">@Model.Currency.ToUpper()</span>
</div>
<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 />
<span class="input-group-text">@Model.Currency.ToUpper()</span>
</div>
</div>
<div class="col mt-2 col-12 col-sm-6 mt-sm-0 col-md-12 mt-md-2">
@ -132,8 +130,8 @@
}
else
{
<div class="h2 text-md-right">
<span class="badge @if (Model.Status == "Settled") { @("badge-primary") } else if (Model.Status == "Expired") { @("badge-danger") } else { @("badge-info") }">
<div class="h2 text-md-end">
<span class="badge @if (Model.Status == "Settled") { @("bg-primary") } else if (Model.Status == "Expired") { @("bg-danger") } else { @("bg-info") }">
@Model.Status
@if (Model.Archived)
{
@ -149,16 +147,14 @@
<div class="row">
<div class="col col-12 col-sm-6 col-md-12">
<div class="input-group">
<input type="number" class="form-control text-right hide-number-spin" v-model="customAmount" :readonly="!srvModel.allowCustomPaymentAmounts" :max="srvModel.amountDue" placeholder="Amount" step="any" required />
<div class="input-group-append">
<span class="input-group-text">{{currency}}</span>
</div>
<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 />
<span class="input-group-text">{{currency}}</span>
</div>
</div>
<div class="col mt-2 col-12 col-sm-6 mt-sm-0 col-md-12 mt-md-2">
<button class="btn btn-primary w-100 d-flex d-print-none align-items-center justify-content-center text-nowrap" v-bind:class="{ 'btn-disabled': loading}" :disabled="loading" type="submit">
<div v-if="loading" class="spinner-grow spinner-grow-sm mr-2" role="status">
<span class="sr-only">Loading...</span>
<div v-if="loading" class="spinner-grow spinner-grow-sm me-2" role="status">
<span class="visually-hidden">Loading...</span>
</div>
Pay Invoice
</button>
@ -168,22 +164,22 @@
</template>
<template v-else>
<button class="btn btn-primary w-100 d-flex d-print-none align-items-center justify-content-center text-nowrap" :class="{ 'btn-lg': !(srvModel.anyPendingInvoice && !srvModel.pendingInvoiceHasPayments)}" v-on:click="pay(null)" :disabled="loading">
<div v-if="loading" class="spinner-grow spinner-grow-sm mr-2" role="status">
<span class="sr-only">Loading...</span>
<div v-if="loading" class="spinner-grow spinner-grow-sm me-2" role="status">
<span class="visually-hidden">Loading...</span>
</div>
<span>Pay Invoice</span>
</button>
<button class="btn btn-outline-secondary mt-2 w-100 d-flex d-print-none align-items-center justify-content-center text-nowrap" v-if="srvModel.anyPendingInvoice && !srvModel.pendingInvoiceHasPayments" v-on:click="cancelPayment()" :disabled="loading">
<span v-if="loading" class="spinner-grow spinner-grow-sm mr-2" role="status">
<span class="sr-only">Loading...</span>
<span v-if="loading" class="spinner-grow spinner-grow-sm me-2" role="status">
<span class="visually-hidden">Loading...</span>
</span>
<span>Cancel Invoice</span>
</button>
</template>
</template>
<template v-else>
<div class="h2 text-md-right">
<span class="badge" :class="{ 'badge-primary': srvModel.status === 'Settled', 'badge-danger': srvModel.status === 'Expired', 'badge-info': (srvModel.status !== 'Settled' && srvModel.status !== 'Expired') }">
<div class="h2 text-md-end">
<span class="badge" :class="{ 'bg-primary': srvModel.status === 'Settled', 'bg-danger': srvModel.status === 'Expired', 'bg-info': (srvModel.status !== 'Settled' && srvModel.status !== 'Expired') }">
{{srvModel.status}}
<span v-if="srvModel.archived">(archived)</span>
</span>
@ -199,7 +195,7 @@
<partial name="_StatusMessage" model="@(new ViewDataDictionary(ViewData){ { "Margin", "mb-4" } })" />
<div class="row">
<div class="col col-12 col-lg-6 mb-4">
<div class="jumbotron h-100 m-0 p-sm-5">
<div class="bg-tile h-100 m-0 p-3 p-sm-5">
<h2 class="h4 mb-3">Invoice Summary</h2>
<div v-html="srvModel.description">
@if (!string.IsNullOrEmpty(Model.Description) && Model.Description != "<br>")
@ -210,23 +206,23 @@
</div>
</div>
<div class="col col-12 col-lg-6 mb-4">
<div class="jumbotron h-100 m-0 p-sm-5">
<div class="bg-tile h-100 m-0 p-3 p-sm-5">
<h2 class="h4 mb-3">Payment Details</h2>
<dl class="mb-0 mt-md-4">
<div class="d-flex d-print-inline-block flex-column mb-4 mr-5">
<dt class="h4 font-weight-normal text-nowrap text-primary text-print-default order-2 order-sm-1 mb-0" v-text="srvModel.amountDueFormatted">@Model.AmountDueFormatted</dt>
<div class="d-flex d-print-inline-block flex-column mb-4 me-5">
<dt class="h4 fw-normal text-nowrap text-primary text-print-default order-2 order-sm-1 mb-0" v-text="srvModel.amountDueFormatted">@Model.AmountDueFormatted</dt>
<dd class="text-muted order-1 order-sm-2 mb-1" data-test="amount-due-title">Amount due</dd>
</div>
<div class="progress bg-light d-none d-sm-flex mb-sm-4 d-print-none" style="height:5px">
<div class="progress-bar bg-primary" role="progressbar" style="width:@((Model.AmountCollected/Model.Amount)*100)%" v-bind:style="{ width: (srvModel.amountCollected/srvModel.amount*100) + '%' }"></div>
</div>
<div class="d-flex d-print-inline-block flex-column mb-4 mr-5 d-sm-inline-flex mb-sm-0">
<dt class="h4 font-weight-normal text-nowrap order-2 order-sm-1 mb-0" v-text="srvModel.amountCollectedFormatted">@Model.AmountCollectedFormatted</dt>
<div class="d-flex d-print-inline-block flex-column mb-4 me-5 d-sm-inline-flex mb-sm-0">
<dt class="h4 fw-normal text-nowrap order-2 order-sm-1 mb-0" v-text="srvModel.amountCollectedFormatted">@Model.AmountCollectedFormatted</dt>
<dd class="text-muted order-1 order-sm-2 mb-1">Amount paid</dd>
</div>
<div class="d-flex d-print-inline-block flex-column mb-0 d-sm-inline-flex float-sm-right">
<dt class="h4 text-sm-right font-weight-normal text-nowrap order-2 order-sm-1 mb-0" v-text="srvModel.amountFormatted">@Model.AmountFormatted</dt>
<dd class="text-muted text-sm-right order-1 order-sm-2 mb-1">Total requested</dd>
<div class="d-flex d-print-inline-block flex-column mb-0 d-sm-inline-flex float-sm-end">
<dt class="h4 text-sm-end fw-normal text-nowrap order-2 order-sm-1 mb-0" v-text="srvModel.amountFormatted">@Model.AmountFormatted</dt>
<dd class="text-muted text-sm-end order-1 order-sm-2 mb-1">Total requested</dd>
</div>
</dl>
</div>
@ -234,7 +230,7 @@
</div>
<div class="row">
<div class="col">
<div class="jumbotron h-100 m-0 p-sm-5">
<div class="bg-tile h-100 m-0 p-3 p-sm-5">
<h2 class="h4 mb-3">Payment History</h2>
<div class="table-responsive">
<noscript>
@ -247,11 +243,11 @@
<table class="table my-0">
<thead>
<tr class="table-borderless">
<th class="font-weight-normal text-secondary" scope="col">Invoice Id</th>
<th class="font-weight-normal text-secondary w-175px">Expiry</th>
<th class="font-weight-normal text-secondary text-right w-125px">Amount</th>
<th class="font-weight-normal text-secondary text-right w-125px"></th>
<th class="font-weight-normal text-secondary text-right">Status</th>
<th class="fw-normal text-secondary" scope="col">Invoice Id</th>
<th class="fw-normal text-secondary w-175px">Expiry</th>
<th class="fw-normal text-secondary text-end w-125px">Amount</th>
<th class="fw-normal text-secondary text-end w-125px"></th>
<th class="fw-normal text-secondary text-end">Status</th>
</tr>
</thead>
<tbody>
@ -260,23 +256,23 @@
<tr>
<td>@invoice.Id</td>
<td>@invoice.ExpiryDate.ToString("g")</td>
<td class="text-right">@invoice.AmountFormatted</td>
<td class="text-right"></td>
<td class="text-right text-print-default @StatusTextClass(invoice.State)">@invoice.StateFormatted</td>
<td class="text-end">@invoice.AmountFormatted</td>
<td class="text-end"></td>
<td class="text-end text-print-default @StatusTextClass(invoice.State)">@invoice.StateFormatted</td>
</tr>
if (invoice.Payments != null && invoice.Payments.Any())
{
<tr class="table-borderless table-light">
<th class="pl-3 font-weight-normal text-secondary">Transaction Id</th>
<th class="font-weight-normal text-secondary">Received</th>
<th class="font-weight-normal text-secondary text-right">Paid</th>
<th class="font-weight-normal text-secondary text-right">Rate</th>
<th class="font-weight-normal text-secondary text-right">Payment</th>
<th class="fw-normal text-secondary ps-3">Transaction Id</th>
<th class="fw-normal text-secondary">Received</th>
<th class="fw-normal text-secondary text-end">Paid</th>
<th class="fw-normal text-secondary text-end">Rate</th>
<th class="fw-normal text-secondary text-end">Payment</th>
</tr>
@foreach (var payment in invoice.Payments)
{
<tr class="table-borderless table-light">
<td class="pl-3 text-break">
<td class="ps-3 text-break">
@if (!string.IsNullOrEmpty(payment.Link))
{
<a href="@payment.Link" class="text-print-default" target="_blank">@payment.Id</a>
@ -287,9 +283,9 @@
}
</td>
<td>@payment.ReceivedDate.ToString("g")</td>
<td class="text-right">@payment.PaidFormatted</td>
<td class="text-right">@payment.RateFormatted</td>
<td class="text-right text-nowrap">@payment.Amount @payment.PaymentMethod</td>
<td class="text-end">@payment.PaidFormatted</td>
<td class="text-end">@payment.RateFormatted</td>
<td class="text-end text-nowrap">@payment.Amount @payment.PaymentMethod</td>
</tr>
}
}
@ -306,11 +302,11 @@
<table class="table my-0">
<thead>
<tr class="table-borderless">
<th class="font-weight-normal text-secondary" scope="col">Invoice Id</th>
<th class="font-weight-normal text-secondary w-175px">Expiry</th>
<th class="font-weight-normal text-secondary text-right w-125px">Amount</th>
<th class="font-weight-normal text-secondary text-right w-125px"></th>
<th class="font-weight-normal text-secondary text-right">Status</th>
<th class="fw-normal text-secondary" scope="col">Invoice Id</th>
<th class="fw-normal text-secondary w-175px">Expiry</th>
<th class="fw-normal text-secondary text-end w-125px">Amount</th>
<th class="fw-normal text-secondary text-end w-125px"></th>
<th class="fw-normal text-secondary text-end">Status</th>
</tr>
</thead>
<tbody>
@ -318,27 +314,27 @@
<tr>
<td>{{invoice.id}}</td>
<td v-text="formatDate(invoice.expiryDate)"></td>
<td class="text-right">{{invoice.amountFormatted}}</td>
<td class="text-right"></td>
<td class="text-right text-print-default" :class="statusTextClass(invoice.stateFormatted)">{{invoice.stateFormatted}}</td>
<td class="text-end">{{invoice.amountFormatted}}</td>
<td class="text-end"></td>
<td class="text-end text-print-default" :class="statusTextClass(invoice.stateFormatted)">{{invoice.stateFormatted}}</td>
</tr>
<template v-if="invoice.payments && invoice.payments.length > 0">
<tr class="table-borderless table-light">
<th class="pl-3 font-weight-normal text-secondary">Transaction Id</th>
<th class="font-weight-normal text-secondary">Received</th>
<th class="font-weight-normal text-secondary text-right">Paid</th>
<th class="font-weight-normal text-secondary text-right">Rate</th>
<th class="font-weight-normal text-secondary text-right">Payment</th>
<th class="fw-normal text-secondary ps-3">Transaction Id</th>
<th class="fw-normal text-secondary">Received</th>
<th class="fw-normal text-secondary text-end">Paid</th>
<th class="fw-normal text-secondary text-end">Rate</th>
<th class="fw-normal text-secondary text-end">Payment</th>
</tr>
<tr v-for="payment of invoice.payments" class="table-borderless table-light">
<td class="pl-3 text-break">
<td class="ps-3 text-break">
<a v-if="payment.link" :href="payment.link" class="text-print-default" target="_blank">{{payment.id}}</a>
<span v-else>{{payment.id}}</span>
</td>
<td v-text="formatDate(payment.receivedDate)"></td>
<td class="text-right">{{payment.paidFormatted}}</td>
<td class="text-right">{{payment.rateFormatted}}</td>
<td class="text-right text-nowrap">{{payment.amount.noExponents()}} {{payment.paymentMethod}}</td>
<td class="text-end">{{payment.paidFormatted}}</td>
<td class="text-end">{{payment.rateFormatted}}</td>
<td class="text-end text-nowrap">{{payment.amount.noExponents()}} {{payment.paymentMethod}}</td>
</tr>
</template>
</template>

View file

@ -53,9 +53,7 @@
</div>
<div class="input-group d-flex" data-clipboard="@Model.NodeInfo">
<input type="text" class="form-control" style="cursor: copy" readonly="readonly" value="@Model.NodeInfo" id="peer-info"/>
<div class="input-group-append">
<button type="button" class="btn btn-outline-secondary" data-clipboard-confirm>Copy node info</button>
</div>
<button type="button" class="btn btn-outline-secondary" data-clipboard-confirm>Copy node info</button>
</div>
}
</div>

View file

@ -55,14 +55,12 @@
<form asp-action="ClaimPullPayment" asp-route-pullPaymentId="@Model.Id" class="w-100">
<div class="row align-items-center" style="width:calc(100% + 30px)">
<div class="col-12 mb-3 col-lg-6 mb-lg-0">
<input class="form-control form-control-lg text-monospace w-100" asp-for="Destination" placeholder="Enter destination address to claim funds …" required style="font-size:.9rem;height:42px;">
<input class="form-control form-control-lg font-monospace w-100" asp-for="Destination" placeholder="Enter destination address to claim funds …" required style="font-size:.9rem;height:42px;">
</div>
<div class="col-12 mb-3 col-sm-6 mb-sm-0 col-lg-3">
<div class="input-group">
<input type="number" class="form-control form-control-lg text-right hide-number-spin" asp-for="ClaimedAmount" max="@Model.AmountDue" min="@Model.MinimumClaim" step="any" placeholder="Amount" required>
<div class="input-group-append">
<span class="input-group-text px-3">@Model.Currency.ToUpper()</span>
</div>
<input type="number" 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>
<span class="input-group-text px-3">@Model.Currency.ToUpper()</span>
</div>
</div>
<div class="col-12 col-sm-6 col-lg-3">
@ -83,7 +81,7 @@
}
<div class="row">
<div class="col col-12 col-lg-6 mb-4">
<div class="jumbotron h-100 m-0 p-sm-5">
<div class="bg-tile h-100 m-0 p-3 p-sm-5">
@if (!Model.Title.IsNullOrWhiteSpace())
{
<h2 class="h4 mb-3">@Model.Title</h2>
@ -97,7 +95,7 @@
<span class="text-muted text-nowrap">Last Updated</span>
&nbsp;
<span class="text-nowrap">@Model.LastRefreshed.ToString("g")</span>
<button type="button" class="btn btn-link d-none d-lg-inline-block d-print-none border-0 p-0 ml-4 only-for-js" id="copyLink">
<button type="button" class="btn btn-link d-none d-lg-inline-block d-print-none border-0 p-0 ms-4 only-for-js" id="copyLink">
Copy Link
</button>
</div>
@ -116,23 +114,23 @@
</div>
</div>
<div class="col col-12 col-lg-6 mb-4">
<div class="jumbotron h-100 m-0 p-sm-5">
<div class="bg-tile h-100 m-0 p-3 p-sm-5">
<h2 class="h4 mb-3">Payment Details</h2>
<dl class="mb-0 mt-md-4">
<div class="d-flex d-print-inline-block flex-column mb-4 mr-5">
<dt class="h4 font-weight-normal text-nowrap text-primary text-print-default order-2 order-sm-1 mb-0">@Model.AmountDueFormatted</dt>
<div class="d-flex d-print-inline-block flex-column mb-4 me-5">
<dt class="h4 fw-normal text-nowrap text-primary text-print-default order-2 order-sm-1 mb-0">@Model.AmountDueFormatted</dt>
<dd class="text-muted order-1 order-sm-2 mb-1">Available claim</dd>
</div>
<div class="progress bg-light d-none d-sm-flex mb-sm-4 d-print-none" style="height:5px">
<div class="progress-bar bg-primary" role="progressbar" style="width:@((Model.AmountCollected / Model.Amount) * 100)%"></div>
</div>
<div class="d-flex d-print-inline-block flex-column mb-4 mr-5 d-sm-inline-flex mb-sm-0">
<dt class="h4 font-weight-normal text-nowrap order-2 order-sm-1 mb-0">@Model.AmountCollectedFormatted</dt>
<div class="d-flex d-print-inline-block flex-column mb-4 me-5 d-sm-inline-flex mb-sm-0">
<dt class="h4 fw-normal text-nowrap order-2 order-sm-1 mb-0">@Model.AmountCollectedFormatted</dt>
<dd class="text-muted order-1 order-sm-2 mb-1">Already claimed</dd>
</div>
<div class="d-flex d-print-inline-block flex-column mb-0 d-sm-inline-flex float-sm-right">
<dt class="h4 text-sm-right font-weight-normal text-nowrap order-2 order-sm-1 mb-0">@Model.AmountFormatted</dt>
<dd class="text-muted text-sm-right order-1 order-sm-2 mb-1">Claim limit</dd>
<div class="d-flex d-print-inline-block flex-column mb-0 d-sm-inline-flex float-sm-end">
<dt class="h4 text-sm-end fw-normal text-nowrap order-2 order-sm-1 mb-0">@Model.AmountFormatted</dt>
<dd class="text-muted text-sm-end order-1 order-sm-2 mb-1">Claim limit</dd>
</div>
</dl>
</div>
@ -140,7 +138,7 @@
</div>
<div class="row">
<div class="col">
<div class="jumbotron h-100 m-0 p-sm-5">
<div class="bg-tile h-100 m-0 p-3 p-sm-5">
<h2 class="h4 mb-3">Awaiting Claims</h2>
<div class="table-responsive">
@if (Model.Payouts.Any())
@ -148,9 +146,9 @@
<table class="table my-0">
<thead>
<tr class="table-borderless">
<th class="font-weight-normal text-secondary" scope="col">Destination</th>
<th class="font-weight-normal text-secondary text-right text-nowrap">Amount requested</th>
<th class="font-weight-normal text-secondary text-right">Status</th>
<th class="fw-normal text-secondary" scope="col">Destination</th>
<th class="fw-normal text-secondary text-end text-nowrap">Amount requested</th>
<th class="fw-normal text-secondary text-end">Status</th>
</tr>
</thead>
<tbody>
@ -160,8 +158,8 @@
<td class="text-break">
@invoice.Destination
</td>
<td class="text-right">@invoice.AmountFormatted</td>
<td class="text-right text-nowrap">
<td class="text-end">@invoice.AmountFormatted</td>
<td class="text-end text-nowrap">
@if (!string.IsNullOrEmpty(invoice.Link))
{
<a class="transaction-link text-print-default @StatusTextClass(invoice.Status.ToString())" href="@invoice.Link">@invoice.Status.GetStateString()</a>

View file

@ -20,7 +20,7 @@
<h5>Compatible wallets</h5>
<div>
<a href="https://github.com/ZeusLN/zeus" target="_blank" class="d-inline-block mr-3 mb-3 text-center">
<a href="https://github.com/ZeusLN/zeus" target="_blank" class="d-inline-block me-3 mb-3 text-center">
<img src="~/img/zeus.jpg" width="100" height="100" asp-append-version="true" alt="Zeus" />
<div class="mt-2">Zeus</div>
</a>
@ -48,7 +48,7 @@
<div id="qrCode"></div>
<div id="qrCodeData" data-url="@Model.QRCode"></div>
</div>
<p>See QR Code information by clicking <a href="#detailsQR" data-toggle="collapse">here</a></p>
<p>See QR Code information by clicking <a href="#detailsQR" data-bs-toggle="collapse">here</a></p>
<div id="detailsQR" class="collapse">
<div class="form-group">
<label>QR Code data</label>
@ -62,7 +62,7 @@
<div class="form-group">
<h5>More details...</h5>
<p>Alternatively, you can see the settings by clicking <a href="#details" data-toggle="collapse">here</a></p>
<p>Alternatively, you can see the settings by clicking <a href="#details" data-bs-toggle="collapse">here</a></p>
</div>
<div id="details" class="collapse">
@if (Model.Uri == null)
@ -130,15 +130,14 @@
</div>
</div>
@section Scripts {
@section PageFootContent {
<partial name="_ValidationScriptsPartial" />
@if (Model.QRCode != null)
{
<script type="text/javascript" src="~/js/qrcode.js" asp-append-version="true"></script>
<script type="text/javascript">
new QRCode(document.getElementById("qrCode"),
{
<script src="~/js/qrcode.js" asp-append-version="true"></script>
<script>
new QRCode(document.getElementById("qrCode"), {
text: @Safe.Json(Model.QRCode),
width: 200,
height: 200,

View file

@ -26,6 +26,6 @@
</div>
</div>
@section Scripts {
@section PageFootContent {
<partial name="_ValidationScriptsPartial" />
}

View file

@ -19,13 +19,10 @@
<span asp-validation-for="IsDownload" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="TimeAmount" class="control-label"></label>
<label asp-for="TimeAmount" class="form-label"></label>
<div class="input-group">
<input type="number" asp-for="TimeAmount" class="form-control">
<div class="input-group-append">
<select asp-for="TimeType" asp-items="@Html.GetEnumSelectList<ServerController.CreateTemporaryFileUrlViewModel.TmpFileTimeType>()" class="custom-select"></select>
</div>
<select asp-for="TimeType" asp-items="@Html.GetEnumSelectList<ServerController.CreateTemporaryFileUrlViewModel.TmpFileTimeType>()" class="form-select"></select>
</div>
<span asp-validation-for="TimeAmount" class="text-danger"></span>
@ -36,6 +33,6 @@
</div>
</div>
@section Scripts {
@section PageFootContent {
<partial name="_ValidationScriptsPartial" />
}

View file

@ -50,6 +50,6 @@
</div>
</div>
@section Scripts {
@section PageFootContent {
<partial name="_ValidationScriptsPartial" />
}

View file

@ -25,6 +25,6 @@
</div>
</div>
@section Scripts {
@section PageFootContent {
<partial name="_ValidationScriptsPartial" />
}

View file

@ -12,6 +12,6 @@
</div>
</div>
@section Scripts {
@section PageFootContent {
<partial name="_ValidationScriptsPartial" />
}

View file

@ -35,6 +35,6 @@
</div>
</div>
@section Scripts {
@section PageFootContent {
<partial name="_ValidationScriptsPartial" />
}

View file

@ -5,7 +5,6 @@
<partial name="EmailsBody" model="Model" />
@section Scripts {
@section PageFootContent {
<partial name="_ValidationScriptsPartial" />
}

View file

@ -76,7 +76,7 @@ else
<li class="list-group-item">
<div class="row px-0 mx-0">
<span class="col-sm-12 col-md-2">Url: </span>
<a class="col-sm-12 col-md-10 text-right" asp-action="GetFile" asp-controller="Storage" asp-route-fileId="@Model.SelectedFileId" target="_blank">
<a class="col-sm-12 col-md-10 text-end" asp-action="GetFile" asp-controller="Storage" asp-route-fileId="@Model.SelectedFileId" target="_blank">
@Url.Action("GetFile", "Storage", new
{
fileId = Model.SelectedFileId
@ -87,7 +87,7 @@ else
<li class="list-group-item ">
<div class="row px-0 mx-0">
<span class="col-sm-12 col-md-2">Direct Url: </span>
<a class="col-sm-12 col-md-10 text-right" href="@Model.DirectFileUrl" target="_blank">@Model.DirectFileUrl</a>
<a class="col-sm-12 col-md-10 text-end" href="@Model.DirectFileUrl" target="_blank">@Model.DirectFileUrl</a>
</div>
</li>
</ul>
@ -99,30 +99,7 @@ else
{
<form asp-action="CreateFile" method="post" enctype="multipart/form-data">
<h4 class="mt-5 mb-3">Upload File</h4>
<div class="custom-file mb-3">
<input type="file" class="custom-file-input" name="file" id="file" required>
<label class="custom-file-label" for="customFile">Choose file</label>
</div>
<input type="file" class="form-control mb-3" name="file" id="file" required>
<button class="btn btn-primary" role="button"><span class="fa fa-plus"></span> Upload file</button>
</form>
@section Scripts {
<script>
$(document).ready(function () {
$('.custom-file-input').on('change',
function () {
var label = $(this).next('label');
if (document.getElementById("file").files.length > 0) {
var fileName = document.getElementById("file").files[0].name;
label.addClass("selected").html(fileName);
} else {
label.removeClass("selected").html("Choose file");
}
});
});
</script>
}
}

View file

@ -8,7 +8,9 @@
@if (Model.ShowQR)
{
<div class="alert alert-warning alert-dismissible" role="alert">
<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close">
<vc:icon symbol="close" />
</button>
<div>
<span><b>CONFIDENTIAL:</b> This QR Code is confidential, close this window as soon as you don't need it anymore.<br /></span>
<span>A malicious actor with access to this QR Code could steal the funds on your lightning wallet.</span>
@ -56,15 +58,14 @@
</div>
</div>
@section Scripts {
@section PageFootContent {
<partial name="_ValidationScriptsPartial" />
@if (Model.ShowQR)
{
<script type="text/javascript" src="~/js/qrcode.js" asp-append-version="true"></script>
<script type="text/javascript">
new QRCode(document.getElementById("qrCode"),
{
<script src="~/js/qrcode.js" asp-append-version="true"></script>
<script>
new QRCode(document.getElementById("qrCode"), {
text: @Safe.Json(Model.ServiceLink),
width: 200,
height: 200,

View file

@ -96,9 +96,7 @@
{
<div class="alert alert-danger mb-5">
Some plugins were disabled due to fatal errors. They may be incompatible with this version of BTCPay Server.
<button class="btn btn-danger" data-toggle="collapse" data-target="#disabled-plugins">
View disabled plugins
</button>
<button class="btn btn-danger" data-bs-toggle="collapse" data-bs-target="#disabled-plugins">View disabled plugins</button>
</div>
}
@if (Model.Commands.Any())
@ -126,17 +124,17 @@
<div class="col col-12 col-lg-6 mb-4">
<div class="card h-100">
<div class="card-body">
<h4 class="card-title d-inline-block" title="@plugin.Identifier" data-toggle="tooltip">@plugin.Name</h4>
<h4 class="card-title d-inline-block" title="@plugin.Identifier" data-bs-toggle="tooltip">@plugin.Name</h4>
<div class="d-flex flex-wrap align-items-center mb-3">
<h5 class="card-subtitle text-muted d-flex align-items-center mr-3">
<h5 class="card-subtitle text-muted d-flex align-items-center me-3">
@plugin.Version
@if (plugin.SystemPlugin)
{
<div class="badge badge-secondary ml-2">System plugin</div>
<div class="badge bg-secondary ms-2">System plugin</div>
}
else if (updateAvailable)
{
<div class="badge badge-info ml-2">
<div class="badge bg-info ms-2">
@matchedAvailable.Version available
</div>
}
@ -144,8 +142,8 @@
@if (updateAvailable)
{
<span class="nav version-switch mt-n1" role="tablist">
<a data-toggle="tab" href="#@tabId-current" class="nav-link px-0 small text-info show active">Show current version</a>
<a data-toggle="tab" href="#@tabId-update" class="nav-link px-0 small text-info">Show update information</a>
<a data-bs-toggle="tab" href="#@tabId-current" class="nav-link px-0 small text-info show active">Show current version</a>
<a data-bs-toggle="tab" href="#@tabId-update" class="nav-link px-0 small text-info">Show update information</a>
</span>
}
</div>
@ -163,7 +161,7 @@
@dependency
@if (!DependencyMet(dependency))
{
<span title="Dependency not met." data-toggle="tooltip" class="fa fa-warning text-danger"></span>
<span title="Dependency not met." data-bs-toggle="tooltip" class="fa fa-warning text-danger"></span>
}
</li>
}
@ -185,7 +183,7 @@
@dependency
@if (!DependencyMet(dependency))
{
<span title="Dependency not met." data-toggle="tooltip" class="fa fa-warning text-danger"></span>
<span title="Dependency not met." data-bs-toggle="tooltip" class="fa fa-warning text-danger"></span>
}
</li>
}
@ -211,13 +209,13 @@
{
@if (updateAvailable && DependenciesMet(matchedAvailable.Dependencies))
{
<form asp-action="InstallPlugin" asp-route-plugin="@plugin.Identifier" asp-route-update="true" class="mr-3">
<form asp-action="InstallPlugin" asp-route-plugin="@plugin.Identifier" asp-route-update="true" class="me-3">
<button type="submit" class="btn btn-secondary">Update</button>
</form>
}
@if (DependentOn(plugin.Identifier))
{
<button type="button" class="btn btn-outline-danger" data-toggle="tooltip" title="This plugin cannot be uninstalled as it is depended on by other plugins.">Uninstall <span class="fa fa-exclamation"></span></button>
<button type="button" class="btn btn-outline-danger" data-bs-toggle="tooltip" title="This plugin cannot be uninstalled as it is depended on by other plugins.">Uninstall <span class="fa fa-exclamation"></span></button>
}
else
{
@ -244,12 +242,12 @@
<div class="col col-12 col-lg-6 mb-4">
<div class="card h-100">
<div class="card-body">
<h4 class="card-title d-inline-block" data-toggle="tooltip" title="@plugin.Identifier">@plugin.Name</h4>
<h4 class="card-title d-inline-block" data-bs-toggle="tooltip" title="@plugin.Identifier">@plugin.Name</h4>
<h5 class="card-subtitle mb-3 text-muted d-flex align-items-center">
@plugin.Version
@if (pluginT.Item2)
{
<div class="badge badge-light ml-2" data-toggle="tooltip" title="This plugin has been recommended to be installed by your deployment method." class="text-nowrap">Recommended <span class="fa fa-question-circle-o text-secondary"></span></div>
<div class="badge bg-light ms-2 text-nowrap" data-bs-toggle="tooltip" title="This plugin has been recommended to be installed by your deployment method.">Recommended <span class="fa fa-question-circle-o text-secondary"></span></div>
}
</h5>
<p class="card-text">@plugin.Description</p>
@ -263,7 +261,7 @@
@dependency
@if (!DependencyMet(dependency))
{
<span title="Dependency not met." data-toggle="tooltip" class="fa fa-warning text-danger"></span>
<span title="Dependency not met." data-bs-toggle="tooltip" class="fa fa-warning text-danger"></span>
}
</li>
}
@ -300,7 +298,7 @@
}
<div class="mb-4">
<button class="btn btn-link text-secondary mb-2" type="button" data-toggle="collapse" data-target="#manual-upload">
<button class="btn btn-link text-secondary mb-2" type="button" data-bs-toggle="collapse" data-bs-target="#manual-upload">
Upload plugin
</button>
<div class="row collapse" id="manual-upload">
@ -309,16 +307,11 @@
<div class="card-body">
<h4 class="card-title">Add plugin manually</h4>
<div class="alert alert-warning my-3">
<h6 class="mr-1">This is an extremely dangerous operation!</h6>
<h6 class="me-1">This is an extremely dangerous operation!</h6>
Only upload plugins from trusted sources.
</div>
<form method="post" enctype="multipart/form-data" asp-action="UploadPlugin">
<div class="form-group">
<div class="custom-file">
<input type="file" class="custom-file-input form-control-file" required name="files" accept=".btcpay" id="files">
<label class="custom-file-label" for="files">Choose file</label>
</div>
</div>
<input type="file" class="form-control mb-3" required name="files" accept=".btcpay" id="files">
<button class="btn btn-primary" type="submit">Upload</button>
</form>
</div>
@ -330,7 +323,7 @@
@if (Model.Commands.Any())
{
<div class="mb-4">
<button class="btn btn-link text-secondary mb-2" type="button" data-toggle="collapse" data-target="#pending-actions">
<button class="btn btn-link text-secondary mb-2" type="button" data-bs-toggle="collapse" data-bs-target="#pending-actions">
Pending actions
</button>
<div class="row collapse" id="pending-actions">
@ -343,7 +336,7 @@
{
<li class="list-group-item px-0">
<div class="d-flex flex-wrap align-items-center justify-content-between">
<span class="my-2 mr-3">@extComm.Key</span>
<span class="my-2 me-3">@extComm.Key</span>
<form asp-action="CancelPluginCommands" asp-route-plugin="@extComm.Key">
<button type="submit" class="btn btn-outline-secondary">Cancel pending @extComm.Last().command</button>
</form>
@ -360,7 +353,7 @@
@if (Model.Disabled.Any())
{
<div class="mb-4">
<button class="btn btn-link text-secondary mb-2" type="button" data-toggle="collapse" data-target="#disabled-plugins">
<button class="btn btn-link text-secondary mb-2" type="button" data-bs-toggle="collapse" data-bs-target="#disabled-plugins">
Disabled plugins
</button>
<div class="row collapse" id="disabled-plugins">
@ -373,7 +366,7 @@
{
<li class="list-group-item px-0">
<div class="d-flex flex-wrap align-items-center justify-content-between">
<span class="my-2 mr-3">@d</span>
<span class="my-2 me-3">@d</span>
<form asp-action="UnInstallPlugin" asp-route-plugin="@d">
<button type="submit" class="btn btn-outline-secondary">Uninstall</button>
</form>
@ -387,20 +380,3 @@
</div>
</div>
}
@section Scripts {
<script>
$(document).ready(function () {
$(".custom-file-input").on("change", function () {
var label = $(this).next("label");
var el = $(this).get(0);
if (el.files.length > 0) {
var fileName = el.files[0].name;
label.addClass("selected").html(fileName);
} else {
label.removeClass("selected").html("Choose file");
}
});
});
</script>
}

View file

@ -35,11 +35,9 @@
>
<div class="input-group">
<input asp-for="SearchTerm" class="form-control" placeholder="Search by email..." />
<div class="input-group-append">
<button type="submit" class="btn btn-secondary" title="Search by email">
<span class="fa fa-search"></span> Search
</button>
</div>
<button type="submit" class="btn btn-secondary" title="Search by email">
<span class="fa fa-search"></span> Search
</button>
</div>
<span asp-validation-for="SearchTerm" class="text-danger"></span>
</form>
@ -60,7 +58,7 @@
</th>
<th>Created</th>
<th>Verified</th>
<th class="text-right">Actions</th>
<th class="text-end">Actions</th>
</tr>
</thead>
<tbody>
@ -79,7 +77,7 @@
<span class="text-danger fa fa-times"></span>
}
</td>
<td class="text-right">
<td class="text-end">
<a asp-action="User" asp-route-userId="@user.Id">Edit</a> <span> - </span> <a asp-action="DeleteUser" asp-route-userId="@user.Id">Remove</a>
</td>
</tr>

View file

@ -16,24 +16,20 @@
<a class="btn btn-primary @(Model.Removed ? "collapse" : "")" id="details" href="#">See confidential seed information</a>
<div class="form-group @(Model.Removed ? "" : "collapse")">
<div class="input-group">
<div class="input-group-prepend">
<label for="Seed" class="input-group-text"><span class="input-group-addon fa fa-eye"></span><span class="ml-2">Seed</span></label>
</div>
<textarea id="SeedTextArea" asp-for="Seed" onClick="this.select();" class="form-control" readonly rows="@(Model.Removed ? "1" : "3")"></textarea>
<label asp-for="Seed" class="input-group-text"><span class="input-group-addon fa fa-eye"></span><span class="ms-2">Seed</span></label>
<textarea asp-for="Seed" onClick="this.select();" class="form-control" readonly rows="@(Model.Removed ? "1" : "3")"></textarea>
</div>
</div>
@if (!Model.Removed)
{
<div class="form-group collapse">
<div class="input-group">
<div class="input-group-prepend">
<label for="WalletPassword" class="input-group-text"><span class="input-group-addon fa fa-lock"></span><span class="ml-2">Password</span></label>
</div>
<input id="PasswordInput" asp-for="WalletPassword" onClick="this.select();" class="form-control" readonly />
<label asp-for="WalletPassword" class="input-group-text"><span class="input-group-addon fa fa-lock"></span><span class="ms-2">Password</span></label>
<input asp-for="WalletPassword" onClick="this.select();" class="form-control" readonly />
</div>
</div>
<div class="form-group collapse">
<form method="get" asp-action="RemoveLndSeed" asp-route-serviceName="@this.Context.GetRouteValue("serviceName")" asp-route-cryptoCode="@this.Context.GetRouteValue("cryptoCode")">
<form method="get" asp-action="RemoveLndSeed" asp-route-serviceName="@Context.GetRouteValue("serviceName")" asp-route-cryptoCode="@Context.GetRouteValue("cryptoCode")">
<button id="delete" class="btn btn-primary" type="submit">Remove Seed from server</button>
</form>
</div>
@ -42,12 +38,12 @@
</div>
}
@section Scripts {
<script type="text/javascript">
$(function () {
$("#details").click(function () {
$(".collapse").removeClass("collapse");
$(this).addClass("collapse");
@section PageFootContent {
<script>
document.addEventListener("DOMContentLoaded", function () {
document.getElementById("details").addEventListener("click", function () {
document.querySelectorAll(".form-group.collapse").forEach(el => el.classList.remove("collapse"));
this.classList.add("collapse");
});
});
</script>

View file

@ -15,22 +15,22 @@
<div>
@if (Model.Uri == null) // if GRPC
{
<a href="https://www.pebble.indiesquare.me/" target="_blank" class="d-inline-block mr-3 text-center">
<a href="https://www.pebble.indiesquare.me/" target="_blank" class="d-inline-block me-3 text-center">
<img src="~/img/pebblewallet.jpg" width="100" height="100" asp-append-version="true" alt="Pebble" />
<div class="mt-2">Pebble</div>
</a>
<a href="https://zaphq.io/" target="_blank" class="d-inline-block mr-3 text-center">
<a href="https://zaphq.io/" target="_blank" class="d-inline-block me-3 text-center">
<img src="~/img/zapwallet.jpg" width="100" height="100" asp-append-version="true" alt="Zap" />
<div class="mt-2">Zap</div>
</a>
}
else
{
<a href="https://lightningjoule.com/" target="_blank" class="d-inline-block mr-3 mb-3 text-center">
<a href="https://lightningjoule.com/" target="_blank" class="d-inline-block me-3 mb-3 text-center">
<img src="~/img/joule.png" width="100" height="100" asp-append-version="true" alt="Joule" />
<div class="mt-2">Joule</div>
</a>
<a href="https://github.com/ZeusLN/zeus" target="_blank" class="d-inline-block mr-3 mb-3 text-center">
<a href="https://github.com/ZeusLN/zeus" target="_blank" class="d-inline-block me-3 mb-3 text-center">
<img src="~/img/zeus.jpg" width="100" height="100" asp-append-version="true" alt="Zeus" />
<div class="mt-2">Zeus</div>
</a>
@ -57,7 +57,7 @@
<div id="qrCode"></div>
<div id="qrCodeData" data-url="@Model.QRCode"></div>
</div>
<p>See QR Code information by clicking <a href="#detailsQR" data-toggle="collapse">here</a>.</p>
<p>See QR Code information by clicking <a href="#detailsQR" data-bs-toggle="collapse">here</a>.</p>
<div id="detailsQR" class="collapse">
<div class="form-group">
<label>QR Code data</label>
@ -70,7 +70,7 @@
}
<h4 class="mt-5 mb-3">More details</h4>
<p>Alternatively, you can see the settings by clicking <a href="#details" data-toggle="collapse">here</a>.</p>
<p>Alternatively, you can see the settings by clicking <a href="#details" data-bs-toggle="collapse">here</a>.</p>
<div id="details" class="collapse">
@if (Model.Uri == null)
@ -137,13 +137,13 @@
</div>
</div>
@section Scripts {
@section PageFootContent {
<partial name="_ValidationScriptsPartial" />
@if(Model.QRCode != null)
{
<script type="text/javascript" src="~/js/qrcode.js" asp-append-version="true"></script>
<script type="text/javascript">
<script src="~/js/qrcode.js" asp-append-version="true"></script>
<script>
new QRCode(document.getElementById("qrCode"), {
text: @Safe.Json(Model.QRCode),
width: 200,

View file

@ -15,7 +15,7 @@
</ul>
<nav aria-label="..." class="w-100">
<ul class="pagination float-left">
<ul class="pagination float-start">
<li class="page-item @(Model.LogFileOffset == 0 ? "disabled" : null)">
<a class="page-link" asp-action="LogsView" asp-route-offset="@(Model.LogFileOffset - 5)">&laquo;</a>
</li>
@ -40,6 +40,6 @@
}
@section Scripts {
@section PageFootContent {
<partial name="_ValidationScriptsPartial" />
}

View file

@ -11,14 +11,16 @@
<h4 class="mb-3">Change domain name</h4>
<p>You can change the domain name of your server by following <a href="https://docs.btcpayserver.org/ChangeDomain" target="_blank">this guide</a>.</p>
<div class="form-group">
<div class="form-inline">
<div class="row g-1">
<div class="col">
<input asp-for="DNSDomain" class="form-control flex-fill" disabled="@(Model.CanUseSSH ? null : "disabled")" />
<button name="command" type="submit" class="btn btn-primary mt-2 mt-sm-0 ml-sm-2" value="changedomain" title="Change domain" disabled="@(Model.CanUseSSH ? null : "disabled")">
<span asp-validation-for="DNSDomain" class="text-danger"></span>
</div>
<div class="col">
<button name="command" type="submit" class="btn btn-primary mt-2 mt-sm-0 ms-sm-2" value="changedomain" title="Change domain" disabled="@(Model.CanUseSSH ? null : "disabled")">
<span class="fa fa-check"></span> Confirm
</button>
</div>
<span asp-validation-for="DNSDomain" class="text-danger"></span>
</div>
<h4 class="mt-5 mb-3">Update</h4>
@ -48,6 +50,6 @@
</div>
</form>
@section Scripts {
@section PageFootContent {
<partial name="_ValidationScriptsPartial" />
}

View file

@ -8,7 +8,9 @@
@if (Model.ShowQR)
{
<div class="alert alert-warning alert-dismissible" role="alert">
<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close">
<vc:icon symbol="close" />
</button>
<div>
<span><b>CONFIDENTIAL:</b> This QR Code is confidential, close this window as soon as you don't need it anymore.<br /></span>
<span>A malicious actor with access to this QR Code can affect the performances of your server.</span>
@ -28,11 +30,11 @@
<h4 class="mb-3">Compatible wallets</h4>
<div>
<a href="https://play.google.com/store/apps/details?id=com.greenaddress.greenbits_android_wallet" target="_blank" class="d-inline-block mr-3 mb-3 text-center">
<a href="https://play.google.com/store/apps/details?id=com.greenaddress.greenbits_android_wallet" target="_blank" class="d-inline-block me-3 mb-3 text-center">
<img src="~/img/GreenWallet.png" width="100" height="100" asp-append-version="true" alt="Blockstream Green" />
<div class="mt-2">Blockstream Green</div>
</a>
<a href="https://www.wasabiwallet.io/" target="_blank" class="d-inline-block mr-3 mb-3 text-center">
<a href="https://www.wasabiwallet.io/" target="_blank" class="d-inline-block me-3 mb-3 text-center">
<img src="~/img/wasabi.png" width="100" height="100" asp-append-version="true" alt="Wasabi Wallet" />
<div class="mt-2">Wasabi Wallet</div>
</a>
@ -57,7 +59,7 @@
<div id="qrCode"></div>
<div id="qrCodeData" data-url="@Model.ServiceLink"></div>
</div>
<p>See QR Code information by clicking <a href="#detailsQR" data-toggle="collapse">here</a></p>
<p>See QR Code information by clicking <a href="#detailsQR" data-bs-toggle="collapse">here</a></p>
<div id="detailsQR" class="collapse">
<div class="form-group">
<label>QR Code data</label>
@ -69,15 +71,14 @@
</div>
</div>
@section Scripts {
@section PageFootContent {
<partial name="_ValidationScriptsPartial" />
@if (Model.ShowQR)
{
<script type="text/javascript" src="~/js/qrcode.js" asp-append-version="true"></script>
<script type="text/javascript">
new QRCode(document.getElementById("qrCode"),
{
<script src="~/js/qrcode.js" asp-append-version="true"></script>
<script>
new QRCode(document.getElementById("qrCode"), {
text: @Safe.Json(Model.ServiceLink),
width: 200,
height: 200,

View file

@ -117,8 +117,8 @@
<h4 class="mb-3">Customization Settings</h4>
<div class="form-group">
<label asp-for="RootAppId"></label>
<select asp-for="RootAppId" asp-items="@(new SelectList(ViewBag.AppsList, nameof(SelectListItem.Value), nameof(SelectListItem.Text), Model.RootAppId))" class="form-control w-auto"></select>
<label asp-for="RootAppId" class="form-label"></label>
<select asp-for="RootAppId" asp-items="@(new SelectList(ViewBag.AppsList, nameof(SelectListItem.Value), nameof(SelectListItem.Text), Model.RootAppId))" class="form-select w-auto"></select>
@if (!Model.DomainToAppMapping.Any())
{
<button type="submit" name="command" value="add-domain" class="btn btn-link px-0">Map specific domains to specific apps</button>
@ -131,24 +131,24 @@
<div class="list-group-item">
<h5 class="mb-1">
Domain to app mapping
<button type="submit" name="command" value="add-domain" class="ml-1 btn btn-secondary btn-sm ">Add domain mapping </button>
<button type="submit" name="command" value="add-domain" class="ms-1 btn btn-secondary btn-sm ">Add domain mapping </button>
</h5>
</div>
@for (var index = 0; index < Model.DomainToAppMapping.Count; index++)
{
<div class="list-group-item p-0 pl-lg-2">
<div class="list-group-item p-0 ps-lg-2">
<div class="row">
<div class="col-sm-12 col-md-12 col-lg-10 py-2 ">
<div class="form-group">
<label asp-for="DomainToAppMapping[index].Domain" class="control-label"></label>
<label asp-for="DomainToAppMapping[index].Domain" class="form-label"></label>
<input asp-for="DomainToAppMapping[index].Domain" class="form-control"/>
<span asp-validation-for="DomainToAppMapping[index].Domain" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="DomainToAppMapping[index].AppId"></label>
<label asp-for="DomainToAppMapping[index].AppId" class="form-label"></label>
<select asp-for="DomainToAppMapping[index].AppId"
asp-items="@(new SelectList(ViewBag.AppsList, nameof(SelectListItem.Value), nameof(SelectListItem.Text), Model.DomainToAppMapping[index].AppId))"
class="form-control">
class="form-select">
</select>
<span asp-validation-for="DomainToAppMapping[index].AppId" class="text-danger"></span>
@ -156,7 +156,7 @@
</div>
<div class="col-sm-12 col-md-12 col-lg-2 pull-right">
<button type="submit" title="Remove domain mapping" name="command" value="@($"remove-domain:{index}")"
class="d-block d-lg-none d-xl-none btn btn-danger mb-2 ml-2">
class="d-block d-lg-none d-xl-none btn btn-danger mb-2 ms-2">
Remove Destination
</button>
<button type="submit" title="Remove domain mapping" name="command" value="@($"remove-domain:{index}")"
@ -170,7 +170,7 @@
</div>
}
<button class="btn btn-link px-0" type="button" id="ExplorerLinksButton" data-toggle="collapse" data-target="#explorer-links" aria-expanded="false" aria-controls="explorer-links">
<button class="btn btn-link px-0" type="button" id="ExplorerLinksButton" data-bs-toggle="collapse" data-bs-target="#explorer-links" aria-expanded="false" aria-controls="explorer-links">
Override the block explorers used
</button>
@ -192,13 +192,11 @@
Model.BlockExplorerLinks.Add(new PoliciesSettings.BlockExplorerOverrideItem() {CryptoCode = network.CryptoCode, Link = network.BlockExplorerLinkDefault});
}
<li class="list-group-item">
<label > @network.DisplayName (@network.CryptoCode)</label>
<label class="form-label"> @network.DisplayName (@network.CryptoCode)</label>
<input type="hidden" asp-for="BlockExplorerLinks[i].CryptoCode" value="@network.CryptoCode"/>
<div class="input-group">
<input type="text" class="form-control" asp-for="BlockExplorerLinks[i].Link" value="@linkValue" data-default-link="@network.BlockExplorerLinkDefault"/>
<div class="input-group-btn only-for-js">
<button type="button" class="text-decoration-none btn btn-link revert-default fa fa-refresh " title="Revert to default"></button>
</div>
<button type="button" class="text-decoration-none btn btn-link revert-default fa fa-refresh only-for-js" title="Revert to default"></button>
</div>
</li>
}
@ -209,17 +207,15 @@
<button type="submit" class="btn btn-primary" name="command" value="Save">Save</button>
</form>
@section Scripts {
@section PageHeadContent {
<style>
.remove-domain-btn{
font-size: 1.5rem;
border-radius: 0;
}
.remove-domain-btn:hover{
background-color: #CCCCCC;
}
.remove-domain-btn { font-size: 1.5rem; border-radius: 0; }
.remove-domain-btn:hover { background-color: #CCCCCC; }
</style>
<script >
}
@section PageFootContent {
<script>
for (let element of document.getElementsByClassName("revert-default")) {
element.addEventListener("click", function (){
element.parentElement.previousElementSibling.value = element.parentElement.previousElementSibling.getAttribute("data-default-link")

View file

@ -8,7 +8,9 @@
@if (Model.ShowQR)
{
<div class="alert alert-warning alert-dismissible" role="alert">
<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close">
<vc:icon symbol="close" />
</button>
<div>
<span><b>CONFIDENTIAL:</b> This QR Code is confidential, close this window as soon as you don't need it anymore.<br /></span>
<span>A malicious actor with access to this QR Code can <b>affect the performances of your server</b> and <b>might steal your funds</b>.</span>
@ -28,11 +30,11 @@
<h4 class="mb-3">Compatible wallets</h4>
<div>
<a href="https://apps.apple.com/us/app/fully-noded/id1436425586" target="_blank" class="d-inline-block mr-3 text-center">
<a href="https://apps.apple.com/us/app/fully-noded/id1436425586" target="_blank" class="d-inline-block me-3 text-center">
<img src="~/img/fullynoded.png" width="100" height="100" asp-append-version="true" alt="Fully Noded" />
<div class="mt-2">Fully Noded</div>
</a>
<a href="https://github.com/cryptoadvance/specter-desktop" target="_blank" class="d-inline-block mr-3 text-center">
<a href="https://github.com/cryptoadvance/specter-desktop" target="_blank" class="d-inline-block me-3 text-center">
<img src="~/img/specter.png" width="100" height="100" asp-append-version="true" alt="Specter Desktop" />
<div class="mt-2">Specter Desktop</div>
</a>
@ -57,10 +59,10 @@
<div id="qrCode"></div>
<div id="qrCodeData" data-url="@Model.ServiceLink"></div>
</div>
<p>See QR Code information by clicking <a href="#detailsQR" data-toggle="collapse">here</a></p>
<p>See QR Code information by clicking <a href="#detailsQR" data-bs-toggle="collapse">here</a></p>
<div id="detailsQR" class="collapse">
<div class="form-group">
<label>QR Code data</label>
<label class="form-label">QR Code data</label>
<input asp-for="ServiceLink" readonly class="form-control"/>
</div>
</div>
@ -69,15 +71,14 @@
</div>
</div>
@section Scripts {
@section PageFootContent {
<partial name="_ValidationScriptsPartial" />
@if (Model.ShowQR)
{
<script type="text/javascript" src="~/js/qrcode.js" asp-append-version="true"></script>
<script type="text/javascript">
new QRCode(document.getElementById("qrCode"),
{
<script src="~/js/qrcode.js" asp-append-version="true"></script>
<script>
new QRCode(document.getElementById("qrCode"), {
text: @Safe.Json(Model.ServiceLink),
width: 200,
height: 200,

View file

@ -161,6 +161,6 @@
</div>
</div>
@section Scripts {
@section PageFootContent {
<partial name="_ValidationScriptsPartial" />
}

View file

@ -22,13 +22,13 @@
}
<div class="form-group">
<label asp-for="Provider"></label>
<select asp-for="Provider" asp-items="@Model.ProvidersList" class="form-control"></select>
<select asp-for="Provider" asp-items="@Model.ProvidersList" class="form-select"></select>
</div>
<button type="submit" class="btn btn-primary" name="command" value="Save">Next</button>
</form>
</div>
</div>
@section Scripts {
@section PageFootContent {
<partial name="_ValidationScriptsPartial" />
}

View file

@ -16,7 +16,7 @@
}
<div class="form-group">
<label asp-for="ThemeCssUri"></label>
<select asp-for="ThemeCssUri" class="form-control">
<select asp-for="ThemeCssUri" class="form-select">
<option value="/main/themes/default.css">Default (Light)</option>
<option value="/main/themes/default-dark.css">Default (Dark)</option>
<option value="/main/themes/classic.css">Classic</option>
@ -61,6 +61,6 @@
</div>
</div>
@section Scripts {
@section PageFootContent {
<partial name="_ValidationScriptsPartial" />
}

View file

@ -10,7 +10,7 @@
<form method="post">
<div class="form-group">
<label asp-for="IsAdmin">Is admin</label>
<input asp-for="IsAdmin" type="checkbox" class="btcpay-toggle ml-2"/>
<input asp-for="IsAdmin" type="checkbox" class="btcpay-toggle ms-2"/>
</div>
<button name="command" type="submit" class="btn btn-primary" value="Save">Save</button>
</form>

View file

@ -1,6 +1,6 @@
@using BTCPayServer.Configuration
@inject BTCPayServerOptions BTCPayServerOptions
<div class="nav flex-column mb-4">
<nav id="sideNav" class="nav flex-column mb-4">
<a asp-controller="Server" id="Server-@ServerNavPages.Users" class="nav-link @ViewData.IsActivePage(ServerNavPages.Users)" asp-action="ListUsers">Users</a>
<a asp-controller="Server" id="Server-@ServerNavPages.Emails" class="nav-link @ViewData.IsActivePage(ServerNavPages.Emails)" asp-action="Emails">Email server</a>
<a asp-controller="Server" id="Server-@ServerNavPages.Policies" class="nav-link @ViewData.IsActivePage(ServerNavPages.Policies)" asp-action="Policies">Policies</a>
@ -14,4 +14,4 @@
<a asp-controller="Server" id="Server-@ServerNavPages.Files" class="nav-link @ViewData.IsActivePage(ServerNavPages.Files)" asp-action="Files">Files</a>
<a asp-controller="Server" id="Server-@ServerNavPages.Plugins" class="nav-link @ViewData.IsActivePage(ServerNavPages.Plugins)" asp-action="ListPlugins">Plugins (experimental)</a>
<vc:ui-extension-point location="server-nav" />
</div>
</nav>

View file

@ -58,7 +58,7 @@
<th>Deposit address</th>
<th>Amount</th>
<th>Transaction Id</th>
<th class="text-right">Confirmations</th>
<th class="text-end">Confirmations</th>
</tr>
</thead>
<tbody>
@ -67,16 +67,16 @@
<tr style="@(payment.Replaced ? "text-decoration: line-through" : "")">
<td>@payment.Crypto</td>
<td>@(payment.CryptoPaymentData.KeyPath?.ToString()?? "Unknown")</td>
<td style="max-width:300px;" data-toggle="tooltip" class="text-truncate" title="@payment.DepositAddress">@payment.DepositAddress</td>
<td style="max-width:300px;" data-bs-toggle="tooltip" class="text-truncate" title="@payment.DepositAddress">@payment.DepositAddress</td>
<td class="payment-value">@payment.CryptoPaymentData.GetValue() @Safe.Raw(payment.AdditionalInformation is string i ? $"<br/>({i})" : string.Empty)</td>
<td style="max-width:300px;" data-toggle="tooltip" class="text-truncate" title="@payment.TransactionId">
<td style="max-width:300px;" data-bs-toggle="tooltip" class="text-truncate" title="@payment.TransactionId">
<div class="wraptextAuto">
<a href="@payment.TransactionLink" target="_blank">
@payment.TransactionId
</a>
</div>
</td>
<td class="text-right">@payment.Confirmations</td>
<td class="text-end">@payment.Confirmations</td>
</tr>
}
</tbody>

View file

@ -1,15 +1,15 @@
<template id="camera-qr-scanner-wrap">
<div v-if="modalId" :id="modalId" class="modal fade" data-backdrop="static">
<div v-if="modalId" :id="modalId" class="modal fade" data-bs-backdrop="static">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">
{{title}}
<h5 class="modal-title">
{{title}}
<span v-if="workload.length > 0">Animated QR detected: {{workload.length}} / {{workload[0].total}} scanned</span>
</h5>
<button type="button" class="close" aria-label="Close" v-on:click="close">
<span aria-hidden="true">&times;</span>
</button>
</h5>
<button type="button" class="btn-close" aria-label="Close" v-on:click="close">
<vc:icon symbol="close"/>
</button>
</div>
<div class="modal-body">
<slot/>
@ -36,12 +36,12 @@
<div v-if="errorMessage" class="alert alert-danger" role="alert">
{{errorMessage}}
</div>
<div class="text-break text-monospace">
<div class="text-break font-monospace">
{{qrData}}
</div>
<div class="mt-4">
<button type="button" class="btn btn-primary mr-1" v-if="qrData" v-on:click="submitData">Submit</button>
<button type="button" class="btn btn-secondary mr-1" v-on:click="retry">Retry</button>
<button type="button" class="btn btn-primary me-1" v-if="qrData" v-on:click="submitData">Submit</button>
<button type="button" class="btn btn-secondary me-1" v-on:click="retry">Retry</button>
<button type="button" class="btn btn-outline-secondary" v-if="isModal" v-on:click="close">Cancel</button>
</div>
</div>
@ -79,9 +79,9 @@ function initCameraScanningApp(title, onDataSubmit, modalId) {
},
mounted() {
if (this.isModal) {
const $modal = $("#" + this.modalId);
$modal.on("shown.bs.modal", () => { this.isLoaded = true; });
$modal.on("hide.bs.modal", () => { this.isLoaded = false; });
const modal = document.getElementById(this.modalId);
modal.addEventListener('shown.bs.modal', () => { this.isLoaded = true; });
modal.addEventListener('hide.bs.modal', () => { this.isLoaded = false; });
} else {
this.isLoaded = true;
}
@ -107,7 +107,8 @@ function initCameraScanningApp(title, onDataSubmit, modalId) {
},
close() {
if (this.modalId) {
$("#" + this.modalId).modal('hide');
const modal = bootstrap.Modal.getInstance(document.getElementById(this.modalId));
modal.hide();
}
this.reset();
},

View file

@ -5,22 +5,21 @@
<li class="list-group-item bg-tile ">
<div class="d-flex align-items-center">
<span class="d-flex flex-wrap flex-fill flex-column flex-sm-row">
<strong class="mr-3">
<strong class="me-3">
CoinSwitch
</strong>
<span title="" class="d-flex mr-3" >
<span class="text-secondary">Allows your customers to pay with altcoins that are not supported by BTC Pay Server.</span>
<span title="" class="d-flex me-3">
<span class="text-secondary">Allows your customers to pay with altcoins that are not supported by BTCPay Server.</span>
</span>
</span>
<span class="d-flex align-items-center fw-semibold">
@if (settings?.IsConfigured() is true && settings?.Enabled is true)
{
<span class="d-flex align-items-center text-success">
<span class="mr-2 btcpay-status btcpay-status--enabled"></span>
<span class="me-2 btcpay-status btcpay-status--enabled"></span>
Enabled
</span>
<span class="text-light ml-3 mr-2">|</span>
<span class="text-light ms-3 me-2">|</span>
<a lass="btn btn-link px-1 py-1 fw-semibold" asp-controller="CoinSwitch" asp-action="UpdateCoinSwitchSettings" asp-route-storeId="@Context.GetRouteValue("storeId")">
Modify
</a>
@ -28,10 +27,10 @@
else
{
<span class="d-flex align-items-center text-danger">
<span class="mr-2 btcpay-status btcpay-status--disabled"></span>
<span class="me-2 btcpay-status btcpay-status--disabled"></span>
Disabled
</span>
<a class="btn btn-primary btn-sm ml-4 px-3 py-1 fw-semibold" asp-controller="CoinSwitch" asp-action="UpdateCoinSwitchSettings" asp-route-storeId="@Context.GetRouteValue("storeId")">
<a class="btn btn-primary btn-sm ms-4 px-3 py-1 fw-semibold" asp-controller="CoinSwitch" asp-action="UpdateCoinSwitchSettings" asp-route-storeId="@Context.GetRouteValue("storeId")">
Setup
</a>
}

View file

@ -8,7 +8,7 @@
<!DOCTYPE html>
<html lang="en">
<head>
<partial name="Header" />
<partial name="LayoutHead" />
</head>
<body class="bg-light">
<div class="modal-dialog modal-dialog-centered min-vh-100">
@ -28,7 +28,7 @@
}
</div>
@if (!String.IsNullOrEmpty(Model.Action))
@if (!string.IsNullOrEmpty(Model.Action))
{
<form method="post" class="modal-footer justify-content-center" action="@Model.ActionUrl">
<button type="submit" class="btn @Model.ButtonClass xmx-2" id="continue" style="min-width:25%;">@Model.Action</button>
@ -37,5 +37,6 @@
}
</div>
</div>
<partial name="LayoutFoot" />
</body>
</html>

View file

@ -1,21 +1,19 @@
@model BTCPayServer.Models.ServerViewModels.EmailsViewModel
<partial name="_StatusMessage" />
<div class="row">
<div class="col-lg-6">
<div class="d-flex align-items-center justify-content-between mb-4">
<h2 class="mb-0">@ViewData["Title"]</h2>
<div class="dropdown quick-fill" style="display: none">
<button class="btn btn-primary dropdown-toggle" type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<div class="dropdown only-for-js" id="quick-fill">
<button class="btn btn-primary dropdown-toggle" type="button" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false" id="QuickFillDropdownToggle">
Quick fill settings for...
</button>
<div class="dropdown-menu" aria-labelledby="dropdownMenuButton">
<a class="dropdown-item" href="" data-Server="smtp.gmail.com" data-Port="587" data-EnableSSL="true">Gmail.com</a>
<a class="dropdown-item" href="" data-Server="mail.yahoo.com" data-Port="587" data-EnableSSL="true">Yahoo.com</a>
<a class="dropdown-item" href="" data-Server="smtp.mailgun.org" data-Port="587" data-EnableSSL="true">Mailgun</a>
<a class="dropdown-item" href="" data-Server="smtp.office365.com" data-Port="587" data-EnableSSL="true">Office365</a>
<a class="dropdown-item" href="" data-Server="smtp.sendgrid.net" data-Port="587" data-EnableSSL="true">SendGrid</a>
<div class="dropdown-menu" aria-labelledby="QuickFillDropdownToggle">
<a class="dropdown-item" href="" data-server="smtp.gmail.com" data-port="587" data-enablessl="true">Gmail.com</a>
<a class="dropdown-item" href="" data-server="mail.yahoo.com" data-port="587" data-enablessl="true">Yahoo.com</a>
<a class="dropdown-item" href="" data-server="smtp.mailgun.org" data-port="587" data-enablessl="true">Mailgun</a>
<a class="dropdown-item" href="" data-server="smtp.office365.com" data-port="587" data-enablessl="true">Office365</a>
<a class="dropdown-item" href="" data-server="smtp.sendgrid.net" data-port="587" data-enablessl="true">SendGrid</a>
</div>
</div>
</div>
@ -30,17 +28,17 @@
<div asp-validation-summary="All" class="text-danger"></div>
}
<div class="form-group">
<label asp-for="Settings.Server"></label>
<input asp-for="Settings.Server" class="form-control"/>
<label asp-for="Settings.Server" class="form-label"></label>
<input asp-for="Settings.Server" data-fill="server" class="form-control"/>
<span asp-validation-for="Settings.Server" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Settings.Port"></label>
<input asp-for="Settings.Port" class="form-control"/>
<label asp-for="Settings.Port" class="form-label"></label>
<input asp-for="Settings.Port" data-fill="port" class="form-control"/>
<span asp-validation-for="Settings.Port" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Settings.FromDisplay"></label>
<label asp-for="Settings.FromDisplay" class="form-label"></label>
<input asp-for="Settings.FromDisplay" class="form-control"/>
<small class="form-text text-muted">
Some email providers (like Gmail) don't allow you to set your display name, so this setting may not have any effect.
@ -48,12 +46,12 @@
<span asp-validation-for="Settings.FromDisplay" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Settings.From"></label>
<label asp-for="Settings.From" class="form-label"></label>
<input asp-for="Settings.From" class="form-control"/>
<span asp-validation-for="Settings.From" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Settings.Login"></label>
<label asp-for="Settings.Login" class="form-label"></label>
<input asp-for="Settings.Login" class="form-control"/>
<small class="form-text text-muted">
For many email providers (like Gmail) your login is your email address.
@ -64,24 +62,22 @@
@if (!Model.PasswordSet)
{
<label asp-for="Settings.Password"></label>
<label asp-for="Settings.Password" class="form-label"></label>
<input asp-for="Settings.Password" type="password" class="form-control"/>
<span asp-validation-for="Settings.Password" class="text-danger"></span>
}
else
{
<label asp-for="Settings.Password"></label>
<label asp-for="Settings.Password" class="form-label"></label>
<div class="input-group">
<input value="Configured" type="text" readonly class="form-control"/>
<div class="input-group-append">
<button type="submit" class="btn btn-danger" name="command" value="ResetPassword">Reset</button>
</div>
<button type="submit" class="btn btn-danger" name="command" value="ResetPassword">Reset</button>
</div>
}
</div>
<div class="form-group">
<div class="form-check">
<input asp-for="Settings.EnableSSL" type="checkbox" class="form-check-input"/>
<input asp-for="Settings.EnableSSL" type="checkbox" data-fill="enablessl" class="form-check-input"/>
<label asp-for="Settings.EnableSSL" class="form-check-label"></label>
</div>
</div>
@ -101,7 +97,7 @@
<br />
After a successful test, you can click "Save".
</p>
<label asp-for="TestEmail"></label>
<label asp-for="TestEmail" class="form-label"></label>
<input asp-for="TestEmail" class="form-control" />
<span asp-validation-for="TestEmail" class="text-danger"></span>
</div>
@ -111,32 +107,23 @@
</form>
<script>
$(document).ready(function () {
$('.dropdown.quick-fill').show();
$('.dropdown.quick-fill a').click(function (e) {
document.addEventListener("DOMContentLoaded", function () {
delegate('click', '#quick-fill .dropdown-menu a', function (e) {
e.preventDefault();
var aNode = $(this);
var data = aNode.data();
for (var key in data) {
var value = data[key];
var inputNodes = $('input[name*="Settings.' + key + '" i]');
if (inputNodes.length) {
inputNodes.each(function (i, input) {
input = $(input);
var type = input.attr('type');
if (type === 'checkbox') {
input.prop('checked', value);
} else {
input.val(value);
}
});
const data = e.target.dataset;
Object.keys(data).forEach(function (key) {
const value = data[key];
const input = document.querySelector('input[data-fill="' + key + '"]');
if (input) {
const type = input.getAttribute('type');
if (type === 'checkbox') {
input.checked = value;
} else {
input.value = value;
}
}
}
});
});
});
</script>

View file

@ -20,7 +20,7 @@
<div class="form-group">
<input type="hidden" asp-for="ChainId"/>
<div class="form-check">
<label asp-for="Web3ProviderUrl" class="form-control-label"></label>
<label asp-for="Web3ProviderUrl" class="form-label"></label>
<input asp-for="Web3ProviderUrl" type="text" class="form-control"/>
<span asp-validation-for="Web3ProviderUrl" class="text-danger"></span>
<div>
@ -34,12 +34,12 @@
</div>
</div>
<div class="form-check">
<label asp-for="Web3ProviderUsername" class="form-control-label"></label>
<label asp-for="Web3ProviderUsername" class="form-label"></label>
<input asp-for="Web3ProviderUsername" type="text" class="form-control"/>
<span asp-validation-for="Web3ProviderUsername" class="text-danger"></span>
</div>
<div class="form-check">
<label asp-for="Web3ProviderPassword" class="form-control-label"></label>
<label asp-for="Web3ProviderPassword" class="form-label"></label>
<input asp-for="Web3ProviderPassword" type="text" class="form-control"/>
<span asp-validation-for="Web3ProviderPassword" class="text-danger"></span>
</div>

View file

@ -0,0 +1,4 @@
@addTagHelper *, BundlerMinifier.TagHelpers
<bundle name="wwwroot/bundles/bootstrap-bundle.min.js" asp-append-version="true" />
<bundle name="wwwroot/bundles/main-bundle.min.js" asp-append-version="true" />

View file

@ -14,13 +14,11 @@
<link href="@Context.Request.GetRelativePathOrAbsolute(themeManager.BootstrapUri)" rel="stylesheet" asp-append-version="true" />
<link href="@Context.Request.GetRelativePathOrAbsolute(themeManager.CreativeStartUri)" rel="stylesheet" asp-append-version="true" />
<link href="@Context.Request.GetRelativePathOrAbsolute(themeManager.ThemeUri)" rel="stylesheet" asp-append-version="true" />
@if (!String.IsNullOrWhiteSpace(themeManager.CustomThemeUri))
@if (!string.IsNullOrWhiteSpace(themeManager.CustomThemeUri))
{
<link href="@Context.Request.GetRelativePathOrAbsolute(themeManager.CustomThemeUri)" rel="stylesheet" asp-append-version="true" />
}
<bundle name="wwwroot/bundles/main-bundle.min.css" asp-append-version="true" />
@* JS *@
<bundle name="wwwroot/bundles/main-bundle.min.js" asp-append-version="true" />
@* Non-JS *@
<noscript>
<style>

View file

@ -5,7 +5,7 @@
<!-- Modal -->
<div id="syncModal" class="modal-dialog">
<div class="modal-content">
<a class="modal-header btn-link border-0 text-decoration-none cursor-pointer align-items-center" data-toggle="collapse" data-target="#syncModalContent">
<a class="modal-header btn-link border-0 text-decoration-none cursor-pointer align-items-center" data-bs-toggle="collapse" data-bs-target="#syncModalContent">
<h4 class="modal-title">Your nodes are synching...</h4>
<span class="fa fa-chevron-down"></span>
</a>
@ -26,49 +26,54 @@
</div>
</div>
</div>
<script>
var syncModalContent = $('#syncModalContent');
var syncModal = $('#syncModal');
if (localStorage.getItem("sync-collapsed")){
syncModalContent.removeClass("show");
}
syncModalContent.on('hidden.bs.collapse', function () {
localStorage.setItem("sync-collapsed", "true");
}).on('shown.bs.collapse', function () {
localStorage.removeItem("sync-collapsed");
});
function handleFooterBottom() {
if (document.getElementsByTagName("footer")[0].getBoundingClientRect().top < window.innerHeight){
syncModal.stop().animate({"bottom":"40px"}, 200);
} else {
syncModal.stop().animate({"bottom":"10px"}, 200);
@section PageHeadContent {
<style type="text/css">
#syncModal {
position: fixed;
bottom: 40px;
right: 10px;
margin: 0;
z-index: 1000;
width: 500px;
max-width: 100%;
}
}
$(document).on("scroll", handleFooterBottom);
handleFooterBottom();
</script>
<style type="text/css">
#syncModal {
position: fixed;
bottom: 40px;
right: 10px;
margin: 0;
z-index: 1000;
width: 500px;
max-width: 100%;
}
#syncModal .modal-body {
max-height: 400px;
overflow-y: scroll;
}
#syncModal .fa-chevron-down {
font-size: 1em;
text-decoration: none;
transition: transform .35s;
}
#syncModal .collapsed .fa-chevron-down {
transform: rotate(-90deg);
}
</style>
#syncModal .modal-body {
max-height: 400px;
overflow-y: scroll;
}
#syncModal .fa-chevron-down {
font-size: 1em;
text-decoration: none;
transition: transform .35s;
}
#syncModal .collapsed .fa-chevron-down {
transform: rotate(-90deg);
}
</style>
}
@section PageFootContent {
<script>
var syncModalContent = $('#syncModalContent');
var syncModal = $('#syncModal');
if (localStorage.getItem("sync-collapsed")){
syncModalContent.removeClass("show");
}
syncModalContent.on('hidden.bs.collapse', function () {
localStorage.setItem("sync-collapsed", "true");
}).on('shown.bs.collapse', function () {
localStorage.removeItem("sync-collapsed");
});
function handleFooterBottom() {
if (document.getElementsByTagName("footer")[0].getBoundingClientRect().top < window.innerHeight){
syncModal.stop().animate({"bottom":"40px"}, 200);
} else {
syncModal.stop().animate({"bottom":"10px"}, 200);
}
}
$(document).on("scroll", handleFooterBottom);
handleFooterBottom();
</script>
}
}

View file

@ -1,5 +1,6 @@
<div class="alert alert-warning alert-dismissible">
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">&times;</span>
</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="Emails" asp-controller="Stores" asp-route-storeId="@Model" class="alert-link">Configure store email settings</a>
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="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="Emails" asp-controller="Stores" asp-route-storeId="@Model" class="alert-link">Configure store email settings</a>
</div>

View file

@ -13,7 +13,7 @@
<html lang="en">
<head>
<partial name="Header" />
<partial name="LayoutHead" />
<title>Post Redirect</title>
</head>
<body>
@ -41,5 +41,6 @@
<script type="text/javascript">
document.forms.item(0).submit();
</script>
<partial name="LayoutFoot" />
</body>
</html>

Some files were not shown because too many files have changed in this diff Show more