Unify delete confirmation confirm dialog (#6965)

This commit is contained in:
Nicolas Dorier
2025-10-26 12:37:55 +09:00
committed by GitHub
parent 3697790c81
commit ff02c0f5d7
28 changed files with 72 additions and 73 deletions

View File

@@ -762,5 +762,11 @@ namespace BTCPayServer.Tests
});
return await new StreamReader(await download.CreateReadStreamAsync()).ReadToEndAsync();
}
public async Task ConfirmDeleteModal()
{
await Page.FillAsync("#ConfirmInput", "DELETE");
await Page.ClickAsync("#ConfirmContinue");
}
}
}

View File

@@ -144,8 +144,7 @@ namespace BTCPayServer.Tests
await s.GoToStore(StoreNavPages.Forms);
Assert.Contains("Custom Form 1", await s.Page.ContentAsync());
await s.Page.GetByRole(AriaRole.Link, new() { Name = "Remove" }).ClickAsync();
await s.Page.FillAsync("#ConfirmInput", "DELETE");
await s.Page.ClickAsync("#ConfirmContinue");
await s.ConfirmDeleteModal();
Assert.DoesNotContain("Custom Form 1", await s.Page.ContentAsync());
await s.ClickPagePrimary();
await s.Page.FillAsync("[name='Name']", "Custom Form 2");
@@ -491,8 +490,7 @@ namespace BTCPayServer.Tests
//let's test delete user quickly while we're at it
await s.GoToProfile();
await s.Page.ClickAsync("#delete-user");
await s.Page.FillAsync("#ConfirmInput", "DELETE");
await s.Page.ClickAsync("#ConfirmContinue");
await s.ConfirmDeleteModal();
Assert.Contains("/login", s.Page.Url);
}
@@ -1488,16 +1486,14 @@ namespace BTCPayServer.Tests
Assert.Equal(2, await deleteLinks.CountAsync());
await deleteLinks.First.ClickAsync();
await s.Page.FillAsync("#ConfirmInput", "REMOVE");
await s.Page.ClickAsync("#ConfirmContinue");
await s.ConfirmDeleteModal();
await s.FindAlertMessage();
deleteLinks = s.Page.GetByRole(AriaRole.Link, new() { Name = "Remove" });
Assert.Equal(1, await deleteLinks.CountAsync());
await deleteLinks.First.ClickAsync();
await s.Page.FillAsync("#ConfirmInput", "REMOVE");
await s.Page.ClickAsync("#ConfirmContinue");
await s.ConfirmDeleteModal();
await s.FindAlertMessage();
Assert.Contains("There are no rules yet.", await s.Page.ContentAsync());
@@ -1712,8 +1708,7 @@ namespace BTCPayServer.Tests
Assert.Contains(await passEl.TextContentAsync(), "hellorockstar", StringComparison.OrdinalIgnoreCase);
await s.Page.ClickAsync("#delete");
await s.Page.WaitForSelectorAsync("#ConfirmInput");
await s.Page.FillAsync("#ConfirmInput", "DELETE");
await s.Page.ClickAsync("#ConfirmContinue");
await s.ConfirmDeleteModal();
await s.FindAlertMessage();
seedEl = s.Page.Locator("#Seed");
Assert.Contains("Seed removed", await seedEl.TextContentAsync(), StringComparison.OrdinalIgnoreCase);
@@ -2131,8 +2126,7 @@ namespace BTCPayServer.Tests
var deleteLinks = await s.Page.Locator("a:has-text('Delete')").AllAsync();
Assert.Equal(2, deleteLinks.Count);
await deleteLinks[0].ClickAsync();
await s.Page.FillAsync("#ConfirmInput", "DELETE");
await s.Page.ClickAsync("#ConfirmContinue");
await s.ConfirmDeleteModal();
deleteLinks = await s.Page.Locator("a:has-text('Delete')").AllAsync();
Assert.Single(deleteLinks);
await s.FindAlertMessage();
@@ -2213,8 +2207,7 @@ namespace BTCPayServer.Tests
TestLogs.LogInformation("Let's see if we can delete store with some webhooks inside");
await s.GoToStore();
await s.Page.ClickAsync("#DeleteStore");
await s.Page.FillAsync("#ConfirmInput", "DELETE");
await s.Page.ClickAsync("#ConfirmContinue");
await s.ConfirmDeleteModal();
await s.FindAlertMessage();
}

View File

@@ -41,7 +41,7 @@ namespace BTCPayServer
return View("Confirm",
new ConfirmModel(StringLocalizer["Remove LNURL Auth link"],
StringLocalizer["Your account will no longer have this Lightning wallet as an option for two-factor authentication."],
StringLocalizer["Remove"]));
StringLocalizer["Delete"]));
}
[HttpPost("{id}/delete")]

View File

@@ -309,7 +309,7 @@ namespace BTCPayServer.Controllers
StringLocalizer["Delete"]));
}
return View("Confirm", new ConfirmModel(StringLocalizer["Delete user"], $"The user <strong>{Html.Encode(user.Email)}</strong> will be permanently deleted. Are you sure?", "Delete"));
return View("Confirm", new ConfirmModel(StringLocalizer["Delete user"], $"The user <strong>{Html.Encode(user.Email)}</strong> will be permanently deleted. Are you sure?", StringLocalizer["Delete"]));
}
[HttpPost("server/users/{userId}/delete")]
@@ -337,7 +337,7 @@ namespace BTCPayServer.Controllers
return View("Confirm", new ConfirmModel(StringLocalizer["Disable admin"],
$"Unable to proceed: As the user <strong>{Html.Encode(user.Email)}</strong> is the last enabled admin, it cannot be disabled."));
}
return View("Confirm", new ConfirmModel($"{(enable ? "Enable" : "Disable")} user", $"The user <strong>{Html.Encode(user.Email)}</strong> will be {(enable ? "enabled" : "disabled")}. Are you sure?", (enable ? "Enable" : "Disable")));
return View("Confirm", new ConfirmModel($"{(enable ? "Enable" : "Disable")} user", $"The user <strong>{Html.Encode(user.Email)}</strong> will be {(enable ? "enabled" : "disabled")}. Are you sure?", (enable ? StringLocalizer["Enable"] : StringLocalizer["Disable"])));
}
[HttpPost("server/users/{userId}/toggle")]
@@ -366,7 +366,7 @@ namespace BTCPayServer.Controllers
if (user == null)
return NotFound();
return View("Confirm", new ConfirmModel($"{(approved ? "Approve" : "Unapprove")} user", $"The user <strong>{Html.Encode(user.Email)}</strong> will be {(approved ? "approved" : "unapproved")}. Are you sure?", (approved ? "Approve" : "Unapprove")));
return View("Confirm", new ConfirmModel($"{(approved ? StringLocalizer["Approve"] : StringLocalizer["Unapprove"])} user", $"The user <strong>{Html.Encode(user.Email)}</strong> will be {(approved ? "approved" : "unapproved")}. Are you sure?", (approved ? StringLocalizer["Approve"] : StringLocalizer["Unapprove"])));
}
[HttpPost("server/users/{userId}/approve")]
@@ -392,7 +392,7 @@ namespace BTCPayServer.Controllers
if (user == null)
return NotFound();
return View("Confirm", new ConfirmModel(StringLocalizer["Send verification email"], $"This will send a verification email to <strong>{Html.Encode(user.Email)}</strong>.", "Send"));
return View("Confirm", new ConfirmModel(StringLocalizer["Send verification email"], $"This will send a verification email to <strong>{Html.Encode(user.Email)}</strong>.", StringLocalizer["Send"]));
}
[HttpPost("server/users/{userId}/verification-email")]

View File

@@ -919,7 +919,7 @@ namespace BTCPayServer.Controllers
return NotFound();
return View("Confirm",
new ConfirmModel("Delete dynamic DNS service",
$"Deleting the dynamic DNS service for <strong>{Html.Encode(hostname)}</strong> means your BTCPay Server will stop updating the associated DNS record periodically.", "Delete"));
$"Deleting the dynamic DNS service for <strong>{Html.Encode(hostname)}</strong> means your BTCPay Server will stop updating the associated DNS record periodically.", StringLocalizer["Delete"]));
}
[HttpPost("server/services/dynamic-dns/{hostname}/delete")]
@@ -1054,7 +1054,7 @@ namespace BTCPayServer.Controllers
[HttpGet("server/services/ssh/disable")]
public IActionResult SSHServiceDisable()
{
return View("Confirm", new ConfirmModel("Disable modification of SSH settings", "This action is permanent and will remove the ability to change the SSH settings via the BTCPay Server user interface.", "Disable"));
return View("Confirm", new ConfirmModel(StringLocalizer["Disable modification of SSH settings"], StringLocalizer["This action is permanent and will remove the ability to change the SSH settings via the BTCPay Server user interface."], StringLocalizer["Disable"]));
}
[HttpPost("server/services/ssh/disable")]

View File

@@ -76,7 +76,7 @@ namespace BTCPayServer.Controllers
_payoutProcessorService = payoutProcessorService;
_payoutProcessorFactories = payoutProcessorFactories;
}
[HttpGet("stores/{storeId}/pull-payments/new")]
[Authorize(Policy = Policies.CanCreateNonApprovedPullPayments, AuthenticationSchemes = AuthenticationSchemes.Cookie)]
public IActionResult NewPullPayment(string storeId)
@@ -119,7 +119,7 @@ namespace BTCPayServer.Controllers
model.PayoutMethods ??= new List<string>();
if (!model.PayoutMethods.Any())
{
// Since we assign all payment methods to be selected by default above we need to update
// Since we assign all payment methods to be selected by default above we need to update
// them here to reflect user's selection so that they can correct their mistake
model.PayoutMethodsItem =
paymentMethodOptions.Select(id => new SelectListItem(id.ToString(), id.ToString(), false));
@@ -263,7 +263,7 @@ namespace BTCPayServer.Controllers
string pullPaymentId)
{
return View("Confirm",
new ConfirmModel(StringLocalizer["Archive pull payment"], StringLocalizer["Do you really want to archive the pull payment?"], "Archive"));
new ConfirmModel(StringLocalizer["Archive pull payment"], StringLocalizer["Do you really want to archive the pull payment?"], StringLocalizer["Archive"]));
}
[HttpPost("stores/{storeId}/pull-payments/{pullPaymentId}/archive")]

View File

@@ -651,7 +651,7 @@ public partial class UIStoresController
{
Title = StringLocalizer["Remove {0} wallet", network.CryptoCode],
Description = WalletRemoveWarning(derivation.IsHotWallet, network.CryptoCode),
Action = StringLocalizer["Remove"]
Action = StringLocalizer["Delete"]
});
}

View File

@@ -125,7 +125,7 @@ namespace BTCPayServer.Controllers
var store = HttpContext.GetStoreData();
if (store == null)
return NotFound();
return View("Confirm", new ConfirmModel(StringLocalizer["Delete store {0}", store.StoreName], StringLocalizer["This store will still be accessible to users sharing it"], "Delete"));
return View("Confirm", new ConfirmModel(StringLocalizer["Delete store {0}", store.StoreName], StringLocalizer["This store will still be accessible to users sharing it"], StringLocalizer["Delete"]));
}
[HttpPost("{storeId}/me/delete")]

View File

@@ -33,7 +33,7 @@ namespace BTCPayServer.Fido2
[HttpGet("{id}/delete")]
public IActionResult Remove(string id)
{
return View("Confirm", new ConfirmModel(StringLocalizer["Remove security device"], StringLocalizer["Your account will no longer have this security device as an option for two-factor authentication."], StringLocalizer["Remove"]));
return View("Confirm", new ConfirmModel(StringLocalizer["Remove security device"], StringLocalizer["Your account will no longer have this security device as an option for two-factor authentication."], StringLocalizer["Delete"]));
}
[HttpPost("{id}/delete")]

View File

@@ -49,7 +49,7 @@
<td class="actions-col" permission="@Policies.CanModifyStoreSettings">
<div class="d-inline-flex align-items-center gap-3">
<a asp-action="StoreEmailRulesEdit" asp-route-storeId="@storeId" asp-route-ruleId="@rule.Data.Id">Edit</a>
<a asp-action="StoreEmailRulesDelete" asp-route-storeId="@storeId" asp-route-ruleId="@rule.Data.Id" data-bs-toggle="modal" data-bs-target="#ConfirmModal" data-description="@ViewLocalizer["This action will remove the rule with the trigger <b>{0}</b>.", Html.Encode(rule.Trigger)]" data-confirm-input="@StringLocalizer["REMOVE"]" text-translate="true">Remove</a>
<a asp-action="StoreEmailRulesDelete" asp-route-storeId="@storeId" asp-route-ruleId="@rule.Data.Id" data-bs-toggle="modal" data-bs-target="#ConfirmModal" data-description="@ViewLocalizer["This action will remove the rule with the trigger <b>{0}</b>.", Html.Encode(rule.Trigger)]" data-confirm-input="@StringLocalizer["Delete"]" text-translate="true">Remove</a>
</div>
</td>
</tr>

View File

@@ -53,7 +53,7 @@
<td class="d-block text-break">@wh.Url</td>
<td class="actions-col text-md-nowrap" permission="@Policies.CanModifyStoreSettings">
<a asp-action="ModifyWebhook" asp-route-storeId="@Context.GetRouteValue("storeId")" asp-route-webhookId="@wh.Id" text-translate="true">Modify</a> -
<a asp-action="DeleteWebhook" asp-route-storeId="@Context.GetRouteValue("storeId")" asp-route-webhookId="@wh.Id" data-bs-toggle="modal" data-bs-target="#ConfirmModal" data-confirm-input="DELETE" text-translate="true">Delete</a>
<a asp-action="DeleteWebhook" asp-route-storeId="@Context.GetRouteValue("storeId")" asp-route-webhookId="@wh.Id" data-bs-toggle="modal" data-bs-target="#ConfirmModal" data-confirm-input="@StringLocalizer["Delete"]" text-translate="true">Delete</a>
</td>
</tr>
}

View File

@@ -165,7 +165,7 @@
<span asp-validation-for="StartDate" class="text-danger"></span>
<span asp-validation-for="EndDate" class="text-danger"></span>
</div>
<div class="form-group mt-4" id="ResetRow" hidden="@(Model.StartDate == null)">
<div class="d-flex align-items-center mb-3">
<input asp-for="IsRecurring" type="checkbox" class="btcpay-toggle me-3" data-bs-toggle="collapse" data-bs-target="#ResetEverySettings" aria-expanded="@(Model.IsRecurring)" aria-controls="ResetEverySettings" />
@@ -175,7 +175,7 @@
<div class="text-muted" text-translate="true">Reset goal after a specific period of time, based on your crowdfund's start date.</div>
</div>
</div>
<div class="collapse @(Model.IsRecurring ? "show" : "")" id="ResetEverySettings">
<div class="form-group mb-0 pt-2 w-250px">
<label asp-for="ResetEveryAmount" class="form-label"></label>
@@ -222,14 +222,14 @@
<label asp-for="EnforceTargetAmount" class="form-check-label"></label>
<span asp-validation-for="EnforceTargetAmount" class="text-danger"></span>
</div>
<h3 class="mt-5 mb-4" text-translate="true">Crowdfund Behavior</h3>
<div class="d-flex">
<input asp-for="UseAllStoreInvoices" type="checkbox" class="btcpay-toggle me-3" />
<label asp-for="UseAllStoreInvoices" class="form-check-label"></label>
<span asp-validation-for="UseAllStoreInvoices" class="text-danger"></span>
</div>
<h3 class="mt-5 mb-4" text-translate="true">Checkout</h3>
<div class="form-group">
<label asp-for="FormId" class="form-label"></label>
@@ -384,8 +384,8 @@ Please insert valid HTML here. Only meta tags accepted.'>
}
</button>
</form>
<a id="DeleteApp" class="btn btn-outline-danger" asp-controller="UIApps" asp-action="DeleteApp" asp-route-appId="@Model.AppId" data-bs-toggle="modal" data-bs-target="#ConfirmModal" data-description="The app <strong>@Html.Encode(Model.AppName)</strong> and its settings will be permanently deleted." data-confirm-input="DELETE" permission="@Policies.CanModifyStoreSettings">Delete this app</a>
<a id="DeleteApp" class="btn btn-outline-danger" asp-controller="UIApps" asp-action="DeleteApp" asp-route-appId="@Model.AppId" data-bs-toggle="modal" data-bs-target="#ConfirmModal" data-description="The app <strong>@Html.Encode(Model.AppName)</strong> and its settings will be permanently deleted." data-confirm-input="@StringLocalizer["Delete"]" permission="@Policies.CanModifyStoreSettings">Delete this app</a>
</div>
<partial name="_Confirm" model="@(new ConfirmModel("Delete app", "This app will be removed from this store.", "Delete"))" permission="@Policies.CanModifyStoreSettings" />
<partial name="_Confirm" model="@(new ConfirmModel(StringLocalizer["Delete app"], StringLocalizer["This app will be removed from this store."], StringLocalizer["Delete"]))" permission="@Policies.CanModifyStoreSettings" />

View File

@@ -39,15 +39,15 @@
if (confirmInput) {
$text.removeAttribute('hidden')
$continue.setAttribute('disabled', 'disabled')
$inputText.textContent = confirmInput
$inputText.textContent = confirmInput.toUpperCase()
$input.setAttribute("autocomplete", "off")
$input.addEventListener('input', event => {
event.target.value.trim() === confirmInput
event.target.value.trim().toLowerCase() === confirmInput.toLowerCase()
? $continue.removeAttribute('disabled')
: $continue.setAttribute('disabled', 'disabled')
})
$form.addEventListener('submit', event => {
if ($input.value.trim() !== confirmInput) {
if ($input.value.trim().toLowerCase() !== confirmInput.toLowerCase()) {
event.preventDefault()
}
})

View File

@@ -136,4 +136,4 @@
}
</div>
<partial name="_Confirm" model="@(new ConfirmModel("Delete app", "This app will be removed from this store.", "Delete"))" />
<partial name="_Confirm" model="@(new ConfirmModel("Delete app", "This app will be removed from this store.", StringLocalizer["Delete"]))" />

View File

@@ -41,7 +41,7 @@
<a asp-action="ViewPublicForm" asp-route-formId="@item.Id" id="View-@item.Name" not-permission="@Policies.CanModifyStoreSettings">@item.Name</a>
</td>
<td class="actions-col" permission="@Policies.CanModifyStoreSettings">
<a asp-action="Remove" asp-route-storeId="@item.StoreId" asp-route-id="@item.Id" id="Remove-@item.Id" data-bs-toggle="modal" data-bs-target="#ConfirmModal" data-confirm-input="DELETE" text-translate="true">Remove</a> -
<a asp-action="Remove" asp-route-storeId="@item.StoreId" asp-route-id="@item.Id" id="Remove-@item.Id" data-bs-toggle="modal" data-bs-target="#ConfirmModal" data-confirm-input="@StringLocalizer["Delete"]" text-translate="true">Remove</a> -
<a asp-action="ViewPublicForm" asp-route-formId="@item.Id" id="View-@item.Name" text-translate="true">View</a>
</td>
</tr>
@@ -59,4 +59,4 @@
</div>
</div>
<partial name="_Confirm" model="@(new ConfirmModel("Delete form", "This form will be removed from this store.", "Delete"))" permission="@Policies.CanModifyStoreSettings" />
<partial name="_Confirm" model="@(new ConfirmModel("Delete form", "This form will be removed from this store.", StringLocalizer["Delete"]))" permission="@Policies.CanModifyStoreSettings" />

View File

@@ -15,8 +15,8 @@
@section PageFootContent {
<script>
delegate('click', '.remove', event => {
event.preventDefault()
delegate('click', '.remove', event => {
event.preventDefault()
const { name, value } = event.target
const confirmButton = document.getElementById('ConfirmContinue')
confirmButton.setAttribute('name', name)
@@ -48,7 +48,7 @@
var showAddForm = !ViewContext.ViewData.ModelState.IsValid || !string.IsNullOrEmpty(Model.Add?.Username) || Model.Add?.Max != null || Model.Add?.Min != null || !string.IsNullOrEmpty(Model.Add?.CurrencyCode);
var showAdvancedOptions = !string.IsNullOrEmpty(Model.Add?.CurrencyCode) || !string.IsNullOrEmpty(Model.Add?.InvoiceMetadata) || Model.Add?.Min != null || Model.Add?.Max != null;
}
<div class="collapse @(showAddForm ? "show": "")" id="AddAddress">
<div class="form-group">
<label asp-for="Add.Username" class="form-label"></label>
@@ -97,12 +97,12 @@
</div>
</div>
</div>
<div class="form-group">
<button type="submit" name="command" value="add" class="btn btn-primary">Save</button>
</div>
</div>
@if (Model.Items.Any())
{
<table class="table table-hover">
@@ -151,7 +151,7 @@
}
</td>
<td class="text-end">
<button type="submit" title="Remove" name="command" value="@($"remove:{Model.Items[index].Username}")" class="btn btn-link px-0 remove" data-bs-toggle="modal" data-bs-target="#ConfirmModal" data-description="The Lightning Address <strong>@Html.Encode(address)</strong> will be removed." data-confirm-input="REMOVE" text-translate="true">
<button type="submit" title="Remove" name="command" value="@($"remove:{Model.Items[index].Username}")" class="btn btn-link px-0 remove" data-bs-toggle="modal" data-bs-target="#ConfirmModal" data-description="The Lightning Address <strong>@Html.Encode(address)</strong> will be removed." data-confirm-input="@StringLocalizer["Delete"]" text-translate="true">
Remove
</button>
</td>
@@ -168,4 +168,4 @@
}
</form>
<partial name="_Confirm" model="@(new ConfirmModel("Remove Lightning Address", "This Lightning Address will be removed.", "Remove"))" />
<partial name="_Confirm" model="@(new ConfirmModel(StringLocalizer["Remove Lightning Address"], StringLocalizer["This Lightning Address will be removed."], StringLocalizer["Delete"]))" />

View File

@@ -77,7 +77,7 @@
</td>
<td>
<div class="d-flex align-items-center justify-content-end gap-1">
<a asp-action="DeleteAPIKey" asp-route-id="@keyData.Id" asp-controller="UIManage" data-bs-toggle="modal" data-bs-target="#ConfirmModal" data-description="Any application using the API key <strong>@Html.Encode(keyData.Label ?? keyData.Id)</strong> will immediately lose access." data-confirm-input="DELETE" text-translate="true">Delete</a>
<a asp-action="DeleteAPIKey" asp-route-id="@keyData.Id" asp-controller="UIManage" data-bs-toggle="modal" data-bs-target="#ConfirmModal" data-description="Any application using the API key <strong>@Html.Encode(keyData.Label ?? keyData.Id)</strong> will immediately lose access." data-confirm-input="@StringLocalizer["Delete"]" text-translate="true">Delete</a>
<span>-</span>
<button type="button" class="btn btn-link only-for-js p-0" data-qr="@index" text-translate="true">Show QR</button>
</div>
@@ -91,7 +91,7 @@
</div>
</div>
<partial name="_Confirm" model="@(new ConfirmModel("Delete API key", "Any application using the API key will immediately lose access.", "Delete"))" />
<partial name="_Confirm" model="@(new ConfirmModel(StringLocalizer["Delete API key"], StringLocalizer["Any application using the API key will immediately lose access."], StringLocalizer["Delete"]))" />
<partial name="ShowQR" />

View File

@@ -70,7 +70,7 @@
}
<h3 class="mt-5 mb-4" text-translate="true">Delete Account</h3>
<div id="danger-zone">
<a id="delete-user" class="btn btn-outline-danger mb-5" data-confirm-input="DELETE" data-bs-toggle="modal" data-bs-target="#ConfirmModal" asp-action="DeleteUserPost" data-description="@StringLocalizer["This action will also delete all stores, invoices, apps and data associated with the user."]" text-translate="true">Delete Account</a>
<a id="delete-user" class="btn btn-outline-danger mb-5" data-confirm-input="@StringLocalizer["Delete"]" data-bs-toggle="modal" data-bs-target="#ConfirmModal" asp-action="DeleteUserPost" data-description="@StringLocalizer["This action will also delete all stores, invoices, apps and data associated with the user."]" text-translate="true">Delete Account</a>
</div>
</div>
</form>

View File

@@ -115,11 +115,11 @@
@if (device.Type == Fido2Credential.CredentialType.FIDO2)
{
<a asp-controller="UIFido2" asp-action="Remove" asp-route-id="@device.Id" class="btn btn-outline-danger" data-bs-toggle="modal" data-bs-target="#ConfirmModal" data-title="@StringLocalizer["Remove security device"]" data-description="@ViewLocalizer["Your account will no longer have the security device <strong>{0}</strong> as an option for two-factor authentication.", Html.Encode(name)]" data-confirm="@StringLocalizer["Remove"]" data-confirm-input="@StringLocalizer["REMOVE"]" text-translate="true">Remove</a>
<a asp-controller="UIFido2" asp-action="Remove" asp-route-id="@device.Id" class="btn btn-outline-danger" data-bs-toggle="modal" data-bs-target="#ConfirmModal" data-title="@StringLocalizer["Remove security device"]" data-description="@ViewLocalizer["Your account will no longer have the security device <strong>{0}</strong> as an option for two-factor authentication.", Html.Encode(name)]" data-confirm="@StringLocalizer["Delete"]" data-confirm-input="@StringLocalizer["Delete"]" text-translate="true">Remove</a>
}
else if (device.Type == Fido2Credential.CredentialType.LNURLAuth)
{
<a asp-controller="UILNURLAuth" asp-action="Remove" asp-route-id="@device.Id" class="btn btn-outline-danger" data-bs-toggle="modal" data-bs-target="#ConfirmModal" data-title="@StringLocalizer["Remove Lightning security"]" data-description="@ViewLocalizer["Your account will no longer be linked to the lightning node <strong>{0}</strong> as an option for two-factor authentication.", Html.Encode(name)]" data-confirm="@StringLocalizer["Remove"]" data-confirm-input="@StringLocalizer["REMOVE"]" text-translate="true">Remove</a>
<a asp-controller="UILNURLAuth" asp-action="Remove" asp-route-id="@device.Id" class="btn btn-outline-danger" data-bs-toggle="modal" data-bs-target="#ConfirmModal" data-title="@StringLocalizer["Remove Lightning security"]" data-description="@ViewLocalizer["Your account will no longer be linked to the lightning node <strong>{0}</strong> as an option for two-factor authentication.", Html.Encode(name)]" data-confirm="@StringLocalizer["Delete"]" data-confirm-input="@StringLocalizer["Delete"]" text-translate="true">Remove</a>
}
</div>
}
@@ -131,7 +131,7 @@
<input type="text" class="form-control" name="Name" placeholder="@StringLocalizer["Security device name"]"/>
<select asp-items="@Html.GetEnumSelectList<Fido2Credential.CredentialType>()" class="form-select w-auto" name="type"></select>
<button id="btn-add" type="submit" class="btn btn-primary" text-translate="true">
Add
Add
</button>
</div>
</form>

View File

@@ -44,7 +44,7 @@
else
{
<a id="Configure-@conf.Key" href="@processorsView.Factory.ConfigureLink(storeId, conf.Key, Context.Request)" text-translate="true">Modify</a>
@if (await processorsView.Factory.CanRemove())
{
<span>-</span>
@@ -67,7 +67,7 @@
</div>
</div>
<partial name="_Confirm" model="@(new ConfirmModel("Delete payout processor", "This payout processor will be removed from this store.", "Delete"))" permission="@Policies.CanModifyStoreSettings" />
<partial name="_Confirm" model="@(new ConfirmModel("Delete payout processor", "This payout processor will be removed from this store.", StringLocalizer["Delete"]))" permission="@Policies.CanModifyStoreSettings" />
@section PageFootContent {
<partial name="_ValidationScriptsPartial"/>
}

View File

@@ -32,11 +32,11 @@
<div class="form-group">
<p text-translate="true">Dynamic DNS allows you to have a stable DNS name pointing to your server, even if your IP address changes regularly. This is recommended if you are hosting BTCPay Server at home and wish to have a clearnet domain to access your server.</p>
<p>
Note that you need to properly configure your NAT and BTCPay Server installation to get the HTTPS certificate.
Note that you need to properly configure your NAT and BTCPay Server installation to get the HTTPS certificate.
See the documentation for <a href="https://docs.btcpayserver.org/Deployment/DynamicDNS/" target="_blank" rel="noreferrer noopener">more information</a>.
</p>
</div>
@if (Model.Any())
{
<div class="table-responsive-md">
@@ -68,7 +68,7 @@
<td class="text-end">
<a asp-action="DynamicDnsService" asp-route-hostname="@service.Settings.Hostname" text-translate="true">Edit</a>
<span> - </span>
<a asp-action="DeleteDynamicDnsService" asp-route-hostname="@service.Settings.Hostname" data-bs-toggle="modal" data-bs-target="#ConfirmModal" data-description="Deleting the dynamic DNS service for <strong>@Html.Encode(service.Settings.Hostname)</strong> means your BTCPay Server will stop updating the associated DNS record periodically." data-confirm-input="DELETE" text-translate="true">Delete</a>
<a asp-action="DeleteDynamicDnsService" asp-route-hostname="@service.Settings.Hostname" data-bs-toggle="modal" data-bs-target="#ConfirmModal" data-description="Deleting the dynamic DNS service for <strong>@Html.Encode(service.Settings.Hostname)</strong> means your BTCPay Server will stop updating the associated DNS record periodically." data-confirm-input="@StringLocalizer["Delete"]" text-translate="true">Delete</a>
</td>
</tr>
}
@@ -85,5 +85,5 @@
</div>
</div>
<partial name="_Confirm" model="@(new ConfirmModel("Delete dynamic DNS service", "Deleting the dynamic DNS service means your BTCPay Server will stop updating the associated DNS record periodically.", "Delete"))" />
<partial name="_Confirm" model="@(new ConfirmModel("Delete dynamic DNS service", "Deleting the dynamic DNS service means your BTCPay Server will stop updating the associated DNS record periodically.", StringLocalizer["Delete"]))" />

View File

@@ -55,7 +55,7 @@
}
@if (v.Editable && !v.IsSelected)
{
<a id="Delete-@v.DictionaryName" asp-action="DeleteDictionary" asp-route-dictionary="@v.DictionaryName" data-bs-toggle="modal" data-bs-target="#ConfirmModal" data-description="The dictionary <b>@Html.Encode(v.DictionaryName)</b> will be removed from this server." data-confirm-input="DELETE" text-translate="true">Remove</a>
<a id="Delete-@v.DictionaryName" asp-action="DeleteDictionary" asp-route-dictionary="@v.DictionaryName" data-bs-toggle="modal" data-bs-target="#ConfirmModal" data-description="The dictionary <b>@Html.Encode(v.DictionaryName)</b> will be removed from this server." data-confirm-input="@StringLocalizer["Delete"]" text-translate="true">Remove</a>
}
</div>
</td>
@@ -63,5 +63,5 @@
}
</tbody>
</table>
<partial name="_Confirm" model="@(new ConfirmModel("Delete dictionary", "This dictionary will be removed from this server.", "Delete"))" />
<partial name="_Confirm" model="@(new ConfirmModel(StringLocalizer["Delete dictionary"], StringLocalizer["This dictionary will be removed from this server."], StringLocalizer["Delete"]))" />
</div>

View File

@@ -166,5 +166,5 @@
<vc:pager view-model="Model"></vc:pager>
<partial name="_Confirm" model="@(new ConfirmModel("Send verification email", $"This will send a verification email to the user.", "Send"))" />
<partial name="_Confirm" model="@(new ConfirmModel(StringLocalizer["Send verification email"], StringLocalizer["This will send a verification email to the user."], StringLocalizer["Send"]))" />
<partial name="ShowQR" />

View File

@@ -74,7 +74,7 @@
</div>
</div>
<partial name="_Confirm" model="@(new ConfirmModel("Disable modification of SSH settings", "This action is permanent and will remove the ability to change the SSH settings via the BTCPay Server user interface.", "Disable"))"/>
<partial name="_Confirm" model="@(new ConfirmModel(StringLocalizer["Disable modification of SSH settings"], StringLocalizer["This action is permanent and will remove the ability to change the SSH settings via the BTCPay Server user interface."], StringLocalizer["Disable"]))"/>
@section PageFootContent {
<script>

View File

@@ -32,7 +32,7 @@
<span text-translate="true">To generate Greenfield API keys, please</span>
<a asp-controller="UIManage" asp-action="APIKeys" text-translate="true">click here</a>.
</p>
<div class="d-flex align-items-center justify-content-between mt-5 mb-3">
<h3 class="mb-0">@ViewData["Title"]</h3>
<a id="CreateNewToken" asp-action="CreateToken" class="btn btn-primary" role="button" asp-route-storeId="@Context.GetRouteValue("storeId")" permission="@Policies.CanModifyStoreSettings" text-translate="true">
@@ -102,4 +102,4 @@
</div>
</div>
<partial name="_Confirm" model="@(new ConfirmModel("Revoke access token", "The access token will be revoked. Do you wish to continue?", "Revoke"))" permission="@Policies.CanModifyStoreSettings" />
<partial name="_Confirm" model="@(new ConfirmModel(StringLocalizer["Revoke access token"], StringLocalizer["The access token will be revoked. Do you wish to continue?"], StringLocalizer["Revoke"]))" permission="@Policies.CanModifyStoreSettings" />

View File

@@ -24,7 +24,7 @@
<div class="row">
<div class="col-xxl-constrain col-xl-8">
<p>@ViewLocalizer["Give other registered BTCPay Server users access to your store. See the {0} for granted permissions.", Html.ActionLink(StringLocalizer["roles"], "ListRoles", "UIStores", new { storeId })]</p>
@if (!ViewContext.ModelState.IsValid)
{
<div asp-validation-summary="All" class="@(ViewContext.ModelState.ErrorCount.Equals(1) ? "no-marker" : "")"></div>
@@ -56,7 +56,7 @@
<td class="actions-col" permission="@Policies.CanModifyStoreSettings">
<div class="d-inline-flex align-items-center gap-3">
<a asp-action="UpdateStoreUser" asp-route-storeId="@Model.StoreId" asp-route-userId="@user.Id" data-bs-toggle="modal" data-bs-target="#EditModal" data-user-email="@user.Email" data-user-role="@user.Role" text-translate="true">Change Role</a>
<a asp-action="DeleteStoreUser" asp-route-storeId="@Model.StoreId" asp-route-userId="@user.Id" data-bs-toggle="modal" data-bs-target="#ConfirmModal" data-description="@StringLocalizer["This action will prevent {0} from accessing this store and its settings.", Html.Encode(user.Email)]" data-confirm-input="@StringLocalizer["REMOVE"]" text-translate="true">Remove</a>
<a asp-action="DeleteStoreUser" asp-route-storeId="@Model.StoreId" asp-route-userId="@user.Id" data-bs-toggle="modal" data-bs-target="#ConfirmModal" data-description="@StringLocalizer["This action will prevent {0} from accessing this store and its settings.", Html.Encode(user.Email)]" data-confirm-input="@StringLocalizer["Delete"]" text-translate="true">Remove</a>
</div>
</td>
</tr>
@@ -104,7 +104,7 @@
const action = $target.dataset.action || ($target.nodeName === 'A'
? $target.getAttribute('href')
: $target.form.getAttribute('action'))
if ($form && !$form.hasAttribute('action')) $form.setAttribute('action', action)
if (userEmail) $email.textContent = userEmail
if (userRole) $role.value = userRole

View File

@@ -67,8 +67,8 @@
data-bs-target="#ConfirmModal"
data-title="@StringLocalizer["Remove {0} wallet", Model.CryptoCode]"
data-description="@ViewData["RemoveDescription"]"
data-confirm="@StringLocalizer["Remove"]"
data-confirm-input="@StringLocalizer["REMOVE"]"
data-confirm="@StringLocalizer["Delete"]"
data-confirm-input="@StringLocalizer["Delete"]"
text-translate="true">Remove wallet</button>
</form>
</div>
@@ -176,7 +176,7 @@
}
</form>
<partial name="_Confirm" model="@(new ConfirmModel(StringLocalizer["{0} wallet", Model.CryptoCode], StringLocalizer["Change"], "Update"))" />
<partial name="_Confirm" model="@(new ConfirmModel(StringLocalizer["{0} wallet", Model.CryptoCode], StringLocalizer["Change"], StringLocalizer["Update"]))" />
<partial name="ShowQR"/>
@section PageFootContent {

View File

@@ -49,7 +49,7 @@
</tbody>
</table>
</div>
<partial name="_Confirm" model="@(new ConfirmModel(StringLocalizer["Remove label"], StringLocalizer["This label will be removed from this wallet and its associated transactions."], StringLocalizer["Remove"]))" />
<partial name="_Confirm" model="@(new ConfirmModel(StringLocalizer["Remove label"], StringLocalizer["This label will be removed from this wallet and its associated transactions."], StringLocalizer["Delete"]))" />
}
else
{