mirror of
https://github.com/btcpayserver/btcpayserver.git
synced 2025-02-22 14:22:40 +01:00
Merge pull request #1990 from btcpayserver/feat/store-hints
Store hints/warnings
This commit is contained in:
commit
b430afe3e1
18 changed files with 379 additions and 274 deletions
|
@ -42,18 +42,19 @@ namespace BTCPayServer.Tests
|
|||
{
|
||||
await Server.StartAsync();
|
||||
ChromeOptions options = new ChromeOptions();
|
||||
var isDebug = !Server.PayTester.InContainer;
|
||||
if (Server.PayTester.InContainer)
|
||||
{
|
||||
// this must be first option https://stackoverflow.com/questions/53073411/selenium-webdriverexceptionchrome-failed-to-start-crashed-as-google-chrome-is#comment102570662_53073789
|
||||
options.AddArgument("no-sandbox");
|
||||
}
|
||||
|
||||
var isDebug = !Server.PayTester.InContainer;
|
||||
if (!isDebug)
|
||||
{
|
||||
options.AddArguments("headless"); // Comment to view browser
|
||||
options.AddArguments("window-size=1200x1000"); // Comment to view browser
|
||||
}
|
||||
options.AddArgument("shm-size=2g");
|
||||
if (Server.PayTester.InContainer)
|
||||
{
|
||||
options.AddArgument("no-sandbox");
|
||||
}
|
||||
Driver = new ChromeDriver(Server.PayTester.InContainer ? "/usr/bin" : Directory.GetCurrentDirectory(), options);
|
||||
if (isDebug)
|
||||
{
|
||||
|
@ -228,7 +229,11 @@ namespace BTCPayServer.Tests
|
|||
Driver.FindElement(By.Id("Email")).SendKeys(user);
|
||||
Driver.FindElement(By.Id("Password")).SendKeys(password);
|
||||
Driver.FindElement(By.Id("LoginButton")).Click();
|
||||
}
|
||||
|
||||
public void GoToStores()
|
||||
{
|
||||
Driver.FindElement(By.Id("Stores")).Click();
|
||||
}
|
||||
|
||||
public void GoToStore(string storeId, StoreNavPages storeNavPage = StoreNavPages.Index)
|
||||
|
@ -303,7 +308,7 @@ namespace BTCPayServer.Tests
|
|||
public string CreateInvoice(string storeName, decimal amount = 100, string currency = "USD", string refundEmail = "")
|
||||
{
|
||||
GoToInvoices();
|
||||
Driver.FindElement(By.Id("CreateNewInvoice")).Click();
|
||||
Driver.FindElement(By.Id("CreateNewInvoice")).Click(); // ocassionally gets stuck for some reason, tried force click and wait for element
|
||||
Driver.FindElement(By.Id("Amount")).SendKeys(amount.ToString(CultureInfo.InvariantCulture));
|
||||
var currencyEl = Driver.FindElement(By.Id("Currency"));
|
||||
currencyEl.Clear();
|
||||
|
|
|
@ -300,14 +300,30 @@ namespace BTCPayServer.Tests
|
|||
{
|
||||
await s.StartAsync();
|
||||
var alice = s.RegisterNewUser();
|
||||
var store = s.CreateNewStore().storeName;
|
||||
s.AddDerivationScheme();
|
||||
var storeData = s.CreateNewStore();
|
||||
// verify that hints are displayed on the store page
|
||||
Assert.True(s.Driver.PageSource.Contains("Wallet not setup for the store, please provide Derviation Scheme"),
|
||||
"Wallet hint not present");
|
||||
Assert.True(s.Driver.PageSource.Contains("Review settings if you want to receive Lightning payments"),
|
||||
"Lightning hint not present");
|
||||
|
||||
s.GoToStores();
|
||||
Assert.True(s.Driver.PageSource.Contains("warninghint_" + storeData.storeId),
|
||||
"Warning hint on list not present");
|
||||
|
||||
s.GoToStore(storeData.storeId);
|
||||
s.AddDerivationScheme(); // wallet hint should be dismissed
|
||||
s.Driver.AssertNoError();
|
||||
Assert.Contains(store, s.Driver.PageSource);
|
||||
Assert.False(s.Driver.PageSource.Contains("Wallet not setup for the store, please provide Derviation Scheme"),
|
||||
"Wallet hint not dismissed on derivation scheme add");
|
||||
|
||||
s.Driver.FindElement(By.Id("dismissLightningHint")).Click(); // dismiss lightning hint
|
||||
|
||||
Assert.Contains(storeData.storeName, s.Driver.PageSource);
|
||||
var storeUrl = s.Driver.Url;
|
||||
s.ClickOnAllSideMenus();
|
||||
s.GoToInvoices();
|
||||
var invoiceId = s.CreateInvoice(store);
|
||||
var invoiceId = s.CreateInvoice(storeData.storeName);
|
||||
s.AssertHappyMessage();
|
||||
s.Driver.FindElement(By.ClassName("invoice-details-link")).Click();
|
||||
var invoiceUrl = s.Driver.Url;
|
||||
|
@ -362,6 +378,11 @@ namespace BTCPayServer.Tests
|
|||
s.Logout();
|
||||
LogIn(s, alice);
|
||||
s.Driver.FindElement(By.Id("Stores")).Click();
|
||||
|
||||
// there shouldn't be any hints now
|
||||
Assert.False(s.Driver.PageSource.Contains("Review settings if you want to receive Lightning payments"),
|
||||
"Lightning hint should be dismissed at this point");
|
||||
|
||||
s.Driver.FindElement(By.LinkText("Remove")).Click();
|
||||
s.Driver.FindElement(By.Id("continue")).Click();
|
||||
s.Driver.FindElement(By.Id("Stores")).Click();
|
||||
|
|
|
@ -167,7 +167,7 @@ namespace BTCPayServer.Controllers
|
|||
(vm.Confirmation && !string.IsNullOrWhiteSpace(vm.HintAddress)) ||
|
||||
// - The user is clicking on continue after changing the config
|
||||
(!vm.Confirmation && oldConfig != vm.Config) ||
|
||||
// - The user is clickingon continue without changing config nor enabling/disabling
|
||||
// - The user is clicking on continue without changing config nor enabling/disabling
|
||||
(!vm.Confirmation && oldConfig == vm.Config && willBeExcluded == wasExcluded);
|
||||
|
||||
showAddress = showAddress && strategy != null;
|
||||
|
@ -179,6 +179,7 @@ namespace BTCPayServer.Controllers
|
|||
await wallet.TrackAsync(strategy.AccountDerivation);
|
||||
store.SetSupportedPaymentMethod(paymentMethodId, strategy);
|
||||
storeBlob.SetExcluded(paymentMethodId, willBeExcluded);
|
||||
storeBlob.Hints.Wallet = false;
|
||||
store.SetStoreBlob(storeBlob);
|
||||
}
|
||||
catch
|
||||
|
@ -202,6 +203,7 @@ namespace BTCPayServer.Controllers
|
|||
{
|
||||
TempData[WellKnownTempData.SuccessMessage] = $"Derivation settings for {network.CryptoCode} has been modified.";
|
||||
}
|
||||
// This is success case when derivation scheme is added to the store
|
||||
return RedirectToAction(nameof(UpdateStore), new { storeId = storeId });
|
||||
}
|
||||
else if (!string.IsNullOrEmpty(vm.HintAddress))
|
||||
|
|
|
@ -137,6 +137,7 @@ namespace BTCPayServer.Controllers
|
|||
case "save":
|
||||
var storeBlob = store.GetStoreBlob();
|
||||
storeBlob.SetExcluded(paymentMethodId, !vm.Enabled);
|
||||
storeBlob.Hints.Lightning = false;
|
||||
store.SetStoreBlob(storeBlob);
|
||||
store.SetSupportedPaymentMethod(paymentMethodId, paymentMethod);
|
||||
await _Repo.UpdateStore(store);
|
||||
|
|
|
@ -372,8 +372,8 @@ namespace BTCPayServer.Controllers
|
|||
new PaymentMethodCriteriaViewModel()
|
||||
{
|
||||
PaymentMethod = criteria.PaymentMethod.ToString(),
|
||||
Type = criteria.Above? PaymentMethodCriteriaViewModel.CriteriaType.GreaterThan : PaymentMethodCriteriaViewModel.CriteriaType.LessThan,
|
||||
Value = criteria.Value?.ToString()?? ""
|
||||
Type = criteria.Above ? PaymentMethodCriteriaViewModel.CriteriaType.GreaterThan : PaymentMethodCriteriaViewModel.CriteriaType.LessThan,
|
||||
Value = criteria.Value?.ToString() ?? ""
|
||||
}).ToList();
|
||||
vm.CustomCSS = storeBlob.CustomCSS;
|
||||
vm.CustomLogo = storeBlob.CustomLogo;
|
||||
|
@ -394,7 +394,9 @@ namespace BTCPayServer.Controllers
|
|||
.Select(o =>
|
||||
new CheckoutExperienceViewModel.Format()
|
||||
{
|
||||
Name = o.ToPrettyString(), Value = o.ToString(), PaymentId = o
|
||||
Name = o.ToPrettyString(),
|
||||
Value = o.ToString(),
|
||||
PaymentId = o
|
||||
}).ToArray();
|
||||
|
||||
var defaultPaymentId = storeData.GetDefaultPaymentId(_NetworkProvider);
|
||||
|
@ -439,7 +441,7 @@ namespace BTCPayServer.Controllers
|
|||
.Where(viewModel => !string.IsNullOrEmpty(viewModel.Value)).Select(viewModel =>
|
||||
{
|
||||
CurrencyValue.TryParse(viewModel.Value, out var cv);
|
||||
return new PaymentMethodCriteria() {Above = viewModel.Type == PaymentMethodCriteriaViewModel.CriteriaType.GreaterThan, Value = cv, PaymentMethod = PaymentMethodId.Parse(viewModel.PaymentMethod)};
|
||||
return new PaymentMethodCriteria() { Above = viewModel.Type == PaymentMethodCriteriaViewModel.CriteriaType.GreaterThan, Value = cv, PaymentMethod = PaymentMethodId.Parse(viewModel.PaymentMethod) };
|
||||
}).ToList();
|
||||
#pragma warning disable 612
|
||||
blob.LightningMaxValue = null;
|
||||
|
@ -471,32 +473,6 @@ namespace BTCPayServer.Controllers
|
|||
});
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
[Route("{storeId}")]
|
||||
public IActionResult UpdateStore()
|
||||
{
|
||||
var store = HttpContext.GetStoreData();
|
||||
if (store == null)
|
||||
return NotFound();
|
||||
|
||||
var storeBlob = store.GetStoreBlob();
|
||||
var vm = new StoreViewModel();
|
||||
vm.Id = store.Id;
|
||||
vm.StoreName = store.StoreName;
|
||||
vm.StoreWebsite = store.StoreWebsite;
|
||||
vm.NetworkFeeMode = storeBlob.NetworkFeeMode;
|
||||
vm.AnyoneCanCreateInvoice = storeBlob.AnyoneCanInvoice;
|
||||
vm.SpeedPolicy = store.SpeedPolicy;
|
||||
vm.CanDelete = _Repo.CanDeleteStores();
|
||||
AddPaymentMethods(store, storeBlob, vm);
|
||||
vm.MonitoringExpiration = (int)storeBlob.MonitoringExpiration.TotalMinutes;
|
||||
vm.InvoiceExpiration = (int)storeBlob.InvoiceExpiration.TotalMinutes;
|
||||
vm.LightningDescriptionTemplate = storeBlob.LightningDescriptionTemplate;
|
||||
vm.PaymentTolerance = storeBlob.PaymentTolerance;
|
||||
vm.PayJoinEnabled = storeBlob.PayJoinEnabled;
|
||||
return View(vm);
|
||||
}
|
||||
|
||||
|
||||
private void AddPaymentMethods(StoreData store, StoreBlob storeBlob, StoreViewModel vm)
|
||||
{
|
||||
|
@ -556,6 +532,36 @@ namespace BTCPayServer.Controllers
|
|||
}
|
||||
|
||||
|
||||
|
||||
[HttpGet]
|
||||
[Route("{storeId}")]
|
||||
public IActionResult UpdateStore()
|
||||
{
|
||||
var store = HttpContext.GetStoreData();
|
||||
if (store == null)
|
||||
return NotFound();
|
||||
|
||||
var storeBlob = store.GetStoreBlob();
|
||||
var vm = new StoreViewModel();
|
||||
vm.Id = store.Id;
|
||||
vm.StoreName = store.StoreName;
|
||||
vm.StoreWebsite = store.StoreWebsite;
|
||||
vm.NetworkFeeMode = storeBlob.NetworkFeeMode;
|
||||
vm.AnyoneCanCreateInvoice = storeBlob.AnyoneCanInvoice;
|
||||
vm.SpeedPolicy = store.SpeedPolicy;
|
||||
vm.CanDelete = _Repo.CanDeleteStores();
|
||||
AddPaymentMethods(store, storeBlob, vm);
|
||||
vm.MonitoringExpiration = (int)storeBlob.MonitoringExpiration.TotalMinutes;
|
||||
vm.InvoiceExpiration = (int)storeBlob.InvoiceExpiration.TotalMinutes;
|
||||
vm.LightningDescriptionTemplate = storeBlob.LightningDescriptionTemplate;
|
||||
vm.PaymentTolerance = storeBlob.PaymentTolerance;
|
||||
vm.PayJoinEnabled = storeBlob.PayJoinEnabled;
|
||||
vm.HintWallet = storeBlob.Hints.Wallet;
|
||||
vm.HintLightning = storeBlob.Hints.Lightning;
|
||||
return View(vm);
|
||||
}
|
||||
|
||||
|
||||
[HttpPost]
|
||||
[Route("{storeId}")]
|
||||
public async Task<IActionResult> UpdateStore(StoreViewModel model, string command = null)
|
||||
|
@ -625,7 +631,6 @@ namespace BTCPayServer.Controllers
|
|||
{
|
||||
storeId = CurrentStore.Id
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
|
@ -974,10 +979,30 @@ namespace BTCPayServer.Controllers
|
|||
{
|
||||
storeId = CurrentStore.Id
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[Route("{storeId}/dismissHint")]
|
||||
[IgnoreAntiforgeryToken]
|
||||
public async Task<IActionResult> DismissHint(string id)
|
||||
{
|
||||
var blob = CurrentStore.GetStoreBlob();
|
||||
if (id == "Wallet" || id == "Lightning")
|
||||
{
|
||||
try
|
||||
{
|
||||
var prop = blob.Hints.GetType().GetProperty(id);
|
||||
prop.SetValue(blob.Hints, false);
|
||||
}
|
||||
// disregard parse errors
|
||||
catch { }
|
||||
|
||||
|
||||
if (CurrentStore.SetStoreBlob(blob))
|
||||
{
|
||||
await _Repo.UpdateStore(CurrentStore);
|
||||
}
|
||||
}
|
||||
return Content("ack");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ using BTCPayServer.Models;
|
|||
using BTCPayServer.Models.StoreViewModels;
|
||||
using BTCPayServer.Security;
|
||||
using BTCPayServer.Services.Stores;
|
||||
using ExchangeSharp;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
@ -37,6 +38,23 @@ namespace BTCPayServer.Controllers
|
|||
return View();
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[Route("create")]
|
||||
public async Task<IActionResult> CreateStore(CreateStoreViewModel vm)
|
||||
{
|
||||
if (!ModelState.IsValid)
|
||||
{
|
||||
return View(vm);
|
||||
}
|
||||
var store = await _Repo.CreateStore(GetUserId(), vm.Name);
|
||||
CreatedStoreId = store.Id;
|
||||
TempData[WellKnownTempData.SuccessMessage] = "Store successfully created";
|
||||
return RedirectToAction(nameof(StoresController.UpdateStore), "Stores", new
|
||||
{
|
||||
storeId = store.Id
|
||||
});
|
||||
}
|
||||
|
||||
public string CreatedStoreId
|
||||
{
|
||||
get; set;
|
||||
|
@ -108,34 +126,20 @@ namespace BTCPayServer.Controllers
|
|||
for (int i = 0; i < stores.Length; i++)
|
||||
{
|
||||
var store = stores[i];
|
||||
var blob = store.GetStoreBlob();
|
||||
result.Stores.Add(new StoresViewModel.StoreViewModel()
|
||||
{
|
||||
Id = store.Id,
|
||||
|
||||
Name = store.StoreName,
|
||||
WebSite = store.StoreWebsite,
|
||||
IsOwner = store.Role == StoreRoles.Owner
|
||||
IsOwner = store.Role == StoreRoles.Owner,
|
||||
HintWalletWarning = blob.Hints.Wallet
|
||||
});
|
||||
}
|
||||
return View(result);
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[Route("create")]
|
||||
public async Task<IActionResult> CreateStore(CreateStoreViewModel vm)
|
||||
{
|
||||
if (!ModelState.IsValid)
|
||||
{
|
||||
return View(vm);
|
||||
}
|
||||
var store = await _Repo.CreateStore(GetUserId(), vm.Name);
|
||||
CreatedStoreId = store.Id;
|
||||
TempData[WellKnownTempData.SuccessMessage] = "Store successfully created";
|
||||
return RedirectToAction(nameof(StoresController.UpdateStore), "Stores", new
|
||||
{
|
||||
storeId = store.Id
|
||||
});
|
||||
}
|
||||
|
||||
private string GetUserId()
|
||||
{
|
||||
return _UserManager.GetUserId(User);
|
||||
|
|
|
@ -188,6 +188,13 @@ namespace BTCPayServer.Data
|
|||
public bool RedirectAutomatically { get; set; }
|
||||
public bool PayJoinEnabled { get; set; }
|
||||
|
||||
public StoreHints Hints { get; set; }
|
||||
public class StoreHints
|
||||
{
|
||||
public bool Wallet { get; set; }
|
||||
public bool Lightning { get; set; }
|
||||
}
|
||||
|
||||
public IPaymentFilter GetExcludedPaymentMethods()
|
||||
{
|
||||
#pragma warning disable CS0618 // Type or member is obsolete
|
||||
|
|
|
@ -46,6 +46,9 @@ namespace BTCPayServer.Data
|
|||
var result = storeData.StoreBlob == null ? new StoreBlob() : new Serializer(null).ToObject<StoreBlob>(Encoding.UTF8.GetString(storeData.StoreBlob));
|
||||
if (result.PreferredExchange == null)
|
||||
result.PreferredExchange = CoinGeckoRateProvider.CoinGeckoName;
|
||||
|
||||
if (result.Hints == null)
|
||||
result.Hints = new StoreBlob.StoreHints();
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@ using System.Collections.Generic;
|
|||
using System.ComponentModel.DataAnnotations;
|
||||
using BTCPayServer.Client.Models;
|
||||
using BTCPayServer.Validation;
|
||||
using static BTCPayServer.Data.StoreBlob;
|
||||
|
||||
namespace BTCPayServer.Models.StoreViewModels
|
||||
{
|
||||
|
@ -90,6 +91,9 @@ namespace BTCPayServer.Models.StoreViewModels
|
|||
[Display(Name = "Enable Payjoin/P2EP")]
|
||||
public bool PayJoinEnabled { get; set; }
|
||||
|
||||
public bool HintWallet { get; set; }
|
||||
public bool HintLightning { get; set; }
|
||||
|
||||
public class LightningNode
|
||||
{
|
||||
public string CryptoCode { get; set; }
|
||||
|
|
|
@ -4,32 +4,15 @@ namespace BTCPayServer.Models.StoreViewModels
|
|||
{
|
||||
public class StoresViewModel
|
||||
{
|
||||
public List<StoreViewModel> Stores
|
||||
{
|
||||
get; set;
|
||||
} = new List<StoreViewModel>();
|
||||
public List<StoreViewModel> Stores { get; set; } = new List<StoreViewModel>();
|
||||
|
||||
public class StoreViewModel
|
||||
{
|
||||
public string Name
|
||||
{
|
||||
get; set;
|
||||
}
|
||||
|
||||
public string WebSite
|
||||
{
|
||||
get; set;
|
||||
}
|
||||
|
||||
public string Id
|
||||
{
|
||||
get; set;
|
||||
}
|
||||
public bool IsOwner
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
public string Id { get; set; }
|
||||
public string Name { get; set; }
|
||||
public string WebSite { get; set; }
|
||||
public bool IsOwner { get; set; }
|
||||
public bool HintWalletWarning { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -171,7 +171,7 @@ namespace BTCPayServer.Services.Stores
|
|||
{
|
||||
StoreDataId = storeData.Id,
|
||||
ApplicationUserId = ownerId,
|
||||
Role = StoreRoles.Owner
|
||||
Role = StoreRoles.Owner,
|
||||
};
|
||||
ctx.Add(storeData);
|
||||
ctx.Add(userStore);
|
||||
|
@ -182,6 +182,13 @@ namespace BTCPayServer.Services.Stores
|
|||
public async Task<StoreData> CreateStore(string ownerId, string name)
|
||||
{
|
||||
var store = new StoreData() { StoreName = name };
|
||||
var blob = store.GetStoreBlob();
|
||||
blob.Hints = new Data.StoreBlob.StoreHints
|
||||
{
|
||||
Wallet = true,
|
||||
Lightning = true
|
||||
};
|
||||
store.SetStoreBlob(blob);
|
||||
await CreateStore(ownerId, store);
|
||||
return store;
|
||||
}
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
|
||||
<div class="row">
|
||||
<div class="col-12 col-sm-4 col-lg-6 mb-3">
|
||||
<a asp-action="CreateInvoice" class="btn btn-primary mb-1" role="button" id="CreateNewInvoice">
|
||||
<a id="CreateNewInvoice" asp-action="CreateInvoice" class="btn btn-primary mb-1">
|
||||
<span class="fa fa-plus"></span>
|
||||
Create an invoice
|
||||
</a>
|
||||
|
|
|
@ -109,19 +109,19 @@
|
|||
<a class="btn btn-secondary" asp-route-id="@this.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="@this.Context.GetRouteValue("id")" asp-controller="PaymentRequest" asp-action="TogglePaymentRequestArchival">Archive</a>
|
||||
<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="@this.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="@this.Context.GetRouteValue("id")" asp-controller="PaymentRequest" asp-action="TogglePaymentRequestArchival" >Unarchive</a>
|
||||
<a class="btn btn-secondary" data-toggle="tooltip" title="Unarchive this payment request" asp-route-id="@this.Context.GetRouteValue("id")" asp-controller="PaymentRequest" asp-action="TogglePaymentRequestArchival">Unarchive</a>
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
<a class="btn btn-secondary" target="_blank" asp-action="GetPaymentRequests">Back to list</a>
|
||||
</div>
|
||||
</form>
|
||||
<a asp-action="GetPaymentRequests">Back to List</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
@{
|
||||
@{
|
||||
Layout = "/Views/Shared/_Layout.cshtml";
|
||||
ViewBag.ShowMenu = ViewBag.ShowMenu ?? true;
|
||||
if (!ViewData.ContainsKey("NavPartialName"))
|
||||
{
|
||||
ViewData["NavPartialName"] = "_Nav";
|
||||
}
|
||||
var title = $"{(ViewData.ContainsKey("MainTitle")? $"{ViewData["MainTitle"]}:" : String.Empty)} {ViewData["Title"]}";
|
||||
var title = $"{(ViewData.ContainsKey("MainTitle") ? $"{ViewData["MainTitle"]}:" : String.Empty)} {ViewData["Title"]}";
|
||||
}
|
||||
|
||||
<section>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
@model BTCPayServer.Models.StoreViewModels.RatesViewModel
|
||||
@model BTCPayServer.Models.StoreViewModels.RatesViewModel
|
||||
@{
|
||||
Layout = "../Shared/_NavLayout.cshtml";
|
||||
ViewData.SetActivePageAndTitle(StoreNavPages.Rates, "Rates");
|
||||
|
@ -159,7 +159,7 @@
|
|||
<select asp-for="PreferredExchange" asp-items="Model.Exchanges" class="form-control"></select>
|
||||
<span asp-validation-for="PreferredExchange" class="text-danger"></span>
|
||||
<p id="PreferredExchangeHelpBlock" class="form-text text-muted">
|
||||
Current price source is <a href="@Model.RateSource" target="_blank">@Model.PreferredExchange</a>.
|
||||
Current Rates source is <a href="@Model.RateSource" target="_blank">@Model.PreferredExchange</a>.
|
||||
</p>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
|
|
|
@ -1,122 +1,44 @@
|
|||
@using System.Text.RegularExpressions
|
||||
@using System.Text.RegularExpressions
|
||||
@model StoreViewModel
|
||||
@{
|
||||
Layout = "../Shared/_NavLayout.cshtml";
|
||||
ViewData.SetActivePageAndTitle(StoreNavPages.Index, "Profile");
|
||||
ViewData.SetActivePageAndTitle(StoreNavPages.Index, Model.StoreName);
|
||||
}
|
||||
|
||||
<partial name="_StatusMessage" />
|
||||
|
||||
@if (!ViewContext.ModelState.IsValid)
|
||||
{
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div asp-validation-summary="All" class="text-danger"></div>
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div asp-validation-summary="All" class="text-danger"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-8">
|
||||
<form method="post">
|
||||
<div class="mb-5">
|
||||
<h4 class="mb-3">General</h4>
|
||||
<div class="form-group">
|
||||
<label asp-for="Id"></label>
|
||||
<input asp-for="Id" readonly class="form-control" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label asp-for="StoreName"></label>
|
||||
<input asp-for="StoreName" class="form-control" />
|
||||
<span asp-validation-for="StoreName" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label asp-for="StoreWebsite"></label>
|
||||
<input asp-for="StoreWebsite" class="form-control" />
|
||||
<span asp-validation-for="StoreWebsite" class="text-danger"></span>
|
||||
</div>
|
||||
|
||||
<h4 class="mt-5 mb-3">Payment</h4>
|
||||
<div class="form-group">
|
||||
<div class="form-check">
|
||||
<input asp-for="AnyoneCanCreateInvoice" type="checkbox" class="form-check-input" />
|
||||
<label asp-for="AnyoneCanCreateInvoice" class="form-check-label"></label>
|
||||
<a href="https://docs.btcpayserver.org/FAQ/FAQ-Stores/#allow-anyone-to-create-invoice" target="_blank"><span class="fa fa-question-circle-o" title="More information..."></span></a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="form-check">
|
||||
<input asp-for="PayJoinEnabled" type="checkbox" class="form-check-input"/>
|
||||
<label asp-for="PayJoinEnabled" class="form-check-label"></label>
|
||||
<a href="https://docs.btcpayserver.org/Payjoin/" target="_blank"><span class="fa fa-question-circle-o" title="More information..."></span></a>
|
||||
<span asp-validation-for="PayJoinEnabled" class="text-danger"></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label asp-for="NetworkFeeMode"></label>
|
||||
<a href="https://docs.btcpayserver.org/FAQ/FAQ-Stores/#add-network-fee-to-invoice-vary-with-mining-fees" target="_blank"><span class="fa fa-question-circle-o" title="More information..."></span></a>
|
||||
<select asp-for="NetworkFeeMode" class="form-control">
|
||||
<option value="MultiplePaymentsOnly">... only if the customer makes more than one payment for the invoice</option>
|
||||
<option value="Always">... on every payment</option>
|
||||
<option value="Never">Never add network fee</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="mb-2">
|
||||
<label asp-for="InvoiceExpiration" class="d-inline"></label>
|
||||
<a href="https://docs.btcpayserver.org/FAQ/FAQ-Stores/#invoice-expires-if-the-full-amount-has-not-been-paid-after-minutes" target="_blank"><span class="fa fa-question-circle-o" title="More information..."></span></a>
|
||||
</div>
|
||||
<div class="input-group">
|
||||
<input asp-for="InvoiceExpiration" class="form-control" style="max-width:10ch;"/>
|
||||
<div class="input-group-append">
|
||||
<span class="input-group-text">minutes</span>
|
||||
</div>
|
||||
</div>
|
||||
<span asp-validation-for="InvoiceExpiration" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="mb-2">
|
||||
<label asp-for="MonitoringExpiration" class="d-inline"></label>
|
||||
<a href="https://docs.btcpayserver.org/FAQ/FAQ-Stores/#payment-invalid-if-transactions-fails-to-confirm-minutes-after-invoice-expiration" target="_blank"><span class="fa fa-question-circle-o" title="More information..."></span></a>
|
||||
</div>
|
||||
<div class="input-group">
|
||||
<input asp-for="MonitoringExpiration" class="form-control" style="max-width:10ch;"/>
|
||||
<div class="input-group-append">
|
||||
<span class="input-group-text">minutes</span>
|
||||
</div>
|
||||
</div>
|
||||
<span asp-validation-for="MonitoringExpiration" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="mb-2">
|
||||
<label asp-for="PaymentTolerance" class="d-inline"></label>
|
||||
<a href="https://docs.btcpayserver.org/FAQ/FAQ-Stores/#consider-the-invoice-paid-even-if-the-paid-amount-is-less-than-expected" target="_blank"><span class="fa fa-question-circle-o" title="More information..."></span></a>
|
||||
</div>
|
||||
<div class="input-group">
|
||||
<input asp-for="PaymentTolerance" class="form-control" style="max-width:10ch;"/>
|
||||
<div class="input-group-append">
|
||||
<span class="input-group-text">percent</span>
|
||||
</div>
|
||||
</div>
|
||||
<span asp-validation-for="PaymentTolerance" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="mb-2">
|
||||
<label asp-for="SpeedPolicy" class="d-inline"></label>
|
||||
<a href="https://docs.btcpayserver.org/FAQ/FAQ-Stores/#consider-the-invoice-confirmed-when-the-payment-transaction" target="_blank"><span class="fa fa-question-circle-o" title="More information..."></span></a>
|
||||
</div>
|
||||
<select asp-for="SpeedPolicy" class="form-control w-auto">
|
||||
<option value="0">Is unconfirmed</option>
|
||||
<option value="1">Has at least 1 confirmation</option>
|
||||
<option value="3">Has at least 2 confirmations</option>
|
||||
<option value="2">Has at least 6 confirmations</option>
|
||||
</select>
|
||||
<span asp-validation-for="SpeedPolicy" class="text-danger"></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h4 class="mt-5 mb-3">Derivation Scheme</h4>
|
||||
<p>The Derivation Scheme represents the destination of the funds received by your invoice on chain.</p>
|
||||
<div>
|
||||
<h4 class="mb-3">Wallet <span class="text-muted small">On-chain payments</span></h4>
|
||||
@if (Model.HintWallet)
|
||||
{
|
||||
<p class="alert alert-warning">
|
||||
<span class="fa fa-warning"></span>
|
||||
Wallet not setup for the store, please provide Derviation Scheme
|
||||
<button type="button" class="close only-for-js" data-dismiss="alert" aria-label="Close"
|
||||
onclick="return dismissHint('Wallet', '@Model.Id');">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</p>
|
||||
}
|
||||
<p>
|
||||
The Derivation Scheme <a href="https://docs.btcpayserver.org/FAQ/FAQ-Wallet/#what-is-a-derivation-scheme" target="_blank"><span class="fa fa-question-circle-o" title="More information..."></span></a>
|
||||
facilitates generation of the destination addresses for your invoices so funds can be received on-chain.
|
||||
</p>
|
||||
<p>
|
||||
Until wallet is defined, no invoices can be created for this store.
|
||||
Optionally, you can have a store that only receives Lightning payments, see the next section for more details.
|
||||
</p>
|
||||
|
||||
<table class="table table-sm table-responsive-md mt-0 mb-5">
|
||||
<thead>
|
||||
|
@ -128,7 +50,7 @@
|
|||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach(var scheme in Model.DerivationSchemes.OrderBy(scheme => scheme.Collapsed))
|
||||
@foreach (var scheme in Model.DerivationSchemes.OrderBy(scheme => scheme.Collapsed))
|
||||
{
|
||||
<tr class="@(@scheme.Collapsed? "collapsed": "")">
|
||||
<td>@scheme.Crypto</td>
|
||||
|
@ -152,7 +74,7 @@
|
|||
}
|
||||
</td>
|
||||
<td style="text-align:center;">
|
||||
@if(scheme.Enabled)
|
||||
@if (scheme.Enabled)
|
||||
{
|
||||
<span class="text-success fa fa-check"></span>
|
||||
}
|
||||
|
@ -162,7 +84,7 @@
|
|||
}
|
||||
</td>
|
||||
<td style="text-align:right">
|
||||
@if(!string.IsNullOrWhiteSpace(scheme.Value) && scheme.WalletSupported)
|
||||
@if (!string.IsNullOrWhiteSpace(scheme.Value) && scheme.WalletSupported)
|
||||
{
|
||||
<a asp-action="WalletTransactions" asp-controller="Wallets" asp-route-walletId="@scheme.WalletId">Wallet</a><span> - </span>
|
||||
}
|
||||
|
@ -171,20 +93,29 @@
|
|||
</tr>
|
||||
}
|
||||
|
||||
@if (Model.DerivationSchemes.Any(scheme => scheme.Collapsed))
|
||||
{
|
||||
<tr class="only-for-js">
|
||||
<td colspan="4"><button class="btn btn-link" id="toggle-assets" type="button">Show additional assets</button></td>
|
||||
</tr>
|
||||
}
|
||||
@if (Model.DerivationSchemes.Any(scheme => scheme.Collapsed))
|
||||
{
|
||||
<tr class="only-for-js">
|
||||
<td colspan="4"><button class="btn btn-link" id="toggle-assets" type="button">Show additional assets</button></td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<h4 class="mt-5 mb-3">Lightning nodes (Experimental)</h4>
|
||||
<h4 class="mt-5 mb-3">Lightning <span class="text-muted small">Off-chain payments</span></h4>
|
||||
@if (Model.HintLightning)
|
||||
{
|
||||
<p class="alert alert-warning">
|
||||
<span class="fa fa-warning"></span>
|
||||
Review settings if you want to receive Lightning payments
|
||||
<button id="dismissLightningHint" type="button" class="close only-for-js" data-dismiss="alert" aria-label="Close"
|
||||
onclick="return dismissHint('Lightning', '@Model.Id');">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</p>
|
||||
}
|
||||
<p>
|
||||
A connection to a lightning charge node is required to generate lightning network enabled invoices.
|
||||
<br />
|
||||
This is experimental and not advised for production.
|
||||
A connection to a Lightning Node is required to generate Lightning Network enabled invoices.
|
||||
</p>
|
||||
|
||||
<table class="table table-sm table-responsive-md">
|
||||
|
@ -197,7 +128,7 @@
|
|||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach(var scheme in Model.LightningNodes)
|
||||
@foreach (var scheme in Model.LightningNodes)
|
||||
{
|
||||
<tr>
|
||||
<td>@scheme.CryptoCode</td>
|
||||
|
@ -218,15 +149,110 @@
|
|||
</tbody>
|
||||
</table>
|
||||
|
||||
<div class="form-group mb-5">
|
||||
<label asp-for="LightningDescriptionTemplate"></label>
|
||||
<input asp-for="LightningDescriptionTemplate" class="form-control" />
|
||||
<span asp-validation-for="LightningDescriptionTemplate" class="text-danger"></span>
|
||||
<p class="form-text text-muted">
|
||||
Available placeholders:
|
||||
<code>{StoreName} {ItemDescription} {OrderId}</code>
|
||||
</p>
|
||||
</div>
|
||||
<form method="post">
|
||||
<div class="form-group mb-5">
|
||||
<label asp-for="LightningDescriptionTemplate"></label>
|
||||
<input asp-for="LightningDescriptionTemplate" class="form-control" />
|
||||
<span asp-validation-for="LightningDescriptionTemplate" class="text-danger"></span>
|
||||
<p class="form-text text-muted">
|
||||
Available placeholders:
|
||||
<code>{StoreName} {ItemDescription} {OrderId}</code>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<h4 class="mt-5 mb-3">Store settings</h4>
|
||||
<div class="form-group">
|
||||
<label asp-for="Id"></label>
|
||||
<input asp-for="Id" readonly class="form-control" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label asp-for="StoreName"></label>
|
||||
<input asp-for="StoreName" class="form-control" />
|
||||
<span asp-validation-for="StoreName" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label asp-for="StoreWebsite"></label>
|
||||
<input asp-for="StoreWebsite" class="form-control" />
|
||||
<span asp-validation-for="StoreWebsite" class="text-danger"></span>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<div class="form-check">
|
||||
<input asp-for="AnyoneCanCreateInvoice" type="checkbox" class="form-check-input" />
|
||||
<label asp-for="AnyoneCanCreateInvoice" class="form-check-label"></label>
|
||||
<a href="https://docs.btcpayserver.org/FAQ/FAQ-Stores/#allow-anyone-to-create-invoice" target="_blank"><span class="fa fa-question-circle-o" title="More information..."></span></a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="form-check">
|
||||
<input asp-for="PayJoinEnabled" type="checkbox" class="form-check-input" />
|
||||
<label asp-for="PayJoinEnabled" class="form-check-label"></label>
|
||||
<a href="https://docs.btcpayserver.org/Payjoin/" target="_blank"><span class="fa fa-question-circle-o" title="More information..."></span></a>
|
||||
<span asp-validation-for="PayJoinEnabled" class="text-danger"></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label asp-for="NetworkFeeMode"></label>
|
||||
<a href="https://docs.btcpayserver.org/FAQ/FAQ-Stores/#add-network-fee-to-invoice-vary-with-mining-fees" target="_blank"><span class="fa fa-question-circle-o" title="More information..."></span></a>
|
||||
<select asp-for="NetworkFeeMode" class="form-control">
|
||||
<option value="MultiplePaymentsOnly">... only if the customer makes more than one payment for the invoice</option>
|
||||
<option value="Always">... on every payment</option>
|
||||
<option value="Never">Never add network fee</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="mb-2">
|
||||
<label asp-for="InvoiceExpiration" class="d-inline"></label>
|
||||
<a href="https://docs.btcpayserver.org/FAQ/FAQ-Stores/#invoice-expires-if-the-full-amount-has-not-been-paid-after-minutes" target="_blank"><span class="fa fa-question-circle-o" title="More information..."></span></a>
|
||||
</div>
|
||||
<div class="input-group">
|
||||
<input asp-for="InvoiceExpiration" class="form-control" style="max-width:10ch;" />
|
||||
<div class="input-group-append">
|
||||
<span class="input-group-text">minutes</span>
|
||||
</div>
|
||||
</div>
|
||||
<span asp-validation-for="InvoiceExpiration" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="mb-2">
|
||||
<label asp-for="MonitoringExpiration" class="d-inline"></label>
|
||||
<a href="https://docs.btcpayserver.org/FAQ/FAQ-Stores/#payment-invalid-if-transactions-fails-to-confirm-minutes-after-invoice-expiration" target="_blank"><span class="fa fa-question-circle-o" title="More information..."></span></a>
|
||||
</div>
|
||||
<div class="input-group">
|
||||
<input asp-for="MonitoringExpiration" class="form-control" style="max-width:10ch;" />
|
||||
<div class="input-group-append">
|
||||
<span class="input-group-text">minutes</span>
|
||||
</div>
|
||||
</div>
|
||||
<span asp-validation-for="MonitoringExpiration" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="mb-2">
|
||||
<label asp-for="PaymentTolerance" class="d-inline"></label>
|
||||
<a href="https://docs.btcpayserver.org/FAQ/FAQ-Stores/#consider-the-invoice-paid-even-if-the-paid-amount-is-less-than-expected" target="_blank"><span class="fa fa-question-circle-o" title="More information..."></span></a>
|
||||
</div>
|
||||
<div class="input-group">
|
||||
<input asp-for="PaymentTolerance" class="form-control" style="max-width:10ch;" />
|
||||
<div class="input-group-append">
|
||||
<span class="input-group-text">percent</span>
|
||||
</div>
|
||||
</div>
|
||||
<span asp-validation-for="PaymentTolerance" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="mb-2">
|
||||
<label asp-for="SpeedPolicy" class="d-inline"></label>
|
||||
<a href="https://docs.btcpayserver.org/FAQ/FAQ-Stores/#consider-the-invoice-confirmed-when-the-payment-transaction" target="_blank"><span class="fa fa-question-circle-o" title="More information..."></span></a>
|
||||
</div>
|
||||
<select asp-for="SpeedPolicy" class="form-control w-auto">
|
||||
<option value="0">Is unconfirmed</option>
|
||||
<option value="1">Has at least 1 confirmation</option>
|
||||
<option value="3">Has at least 2 confirmations</option>
|
||||
<option value="2">Has at least 6 confirmations</option>
|
||||
</select>
|
||||
<span asp-validation-for="SpeedPolicy" class="text-danger"></span>
|
||||
<button name="command" type="submit" class="btn btn-primary mt-3" value="Save" id="Save">Save Store Settings</button>
|
||||
</form>
|
||||
|
||||
<h4 class="mt-5 mb-3">Additional Payment methods</h4>
|
||||
<table class="table table-sm table-responsive-md mt-1 mb-5">
|
||||
|
@ -238,23 +264,23 @@
|
|||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach (var scheme in Model.ThirdPartyPaymentMethods)
|
||||
{
|
||||
<tr>
|
||||
<td>@scheme.Provider</td>
|
||||
<td class="text-center">
|
||||
@if (scheme.Enabled)
|
||||
{
|
||||
<span class="text-success fa fa-check"></span>
|
||||
}
|
||||
else
|
||||
{
|
||||
<span class="text-danger fa fa-times"></span>
|
||||
}
|
||||
</td>
|
||||
<td class="text-right"><a asp-action="@scheme.Action" id='Modify-@scheme.Provider' asp-route-storeId="@this.Context.GetRouteValue("storeId")">Modify</a></td>
|
||||
</tr>
|
||||
}
|
||||
@foreach (var scheme in Model.ThirdPartyPaymentMethods)
|
||||
{
|
||||
<tr>
|
||||
<td>@scheme.Provider</td>
|
||||
<td class="text-center">
|
||||
@if (scheme.Enabled)
|
||||
{
|
||||
<span class="text-success fa fa-check"></span>
|
||||
}
|
||||
else
|
||||
{
|
||||
<span class="text-danger fa fa-times"></span>
|
||||
}
|
||||
</td>
|
||||
<td class="text-right"><a asp-action="@scheme.Action" id='Modify-@scheme.Provider' asp-route-storeId="@this.Context.GetRouteValue("storeId")">Modify</a></td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
|
@ -265,8 +291,8 @@
|
|||
<th>Service</th>
|
||||
<th style="text-align:right">Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
Email
|
||||
|
@ -284,8 +310,7 @@
|
|||
<a class="btn btn-outline-danger mb-5" asp-action="DeleteStore" asp-route-storeId="@Model.Id">Delete this store</a>
|
||||
</div>
|
||||
}
|
||||
<button name="command" type="submit" class="btn btn-primary" value="Save" id="Save">Save</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@ -293,12 +318,12 @@
|
|||
@await Html.PartialAsync("_ValidationScriptsPartial")
|
||||
|
||||
<script>
|
||||
$(document).ready(function(){
|
||||
$(".collapsed").hide();
|
||||
$("#toggle-assets").click(function() {
|
||||
$(".collapsed").show();
|
||||
$(this).parents("tr").hide();
|
||||
});
|
||||
});
|
||||
$(document).ready(function () {
|
||||
$(".collapsed").hide();
|
||||
$("#toggle-assets").click(function () {
|
||||
$(".collapsed").show();
|
||||
$(this).parents("tr").hide();
|
||||
});
|
||||
});
|
||||
</script>
|
||||
}
|
||||
|
|
|
@ -13,3 +13,12 @@
|
|||
}
|
||||
</div>
|
||||
|
||||
<script type="text/javascript">
|
||||
function dismissHint(hintId, storeId) {
|
||||
var url = "@Url.Action("DismissHint", "Stores", new { storeId = "store_Id", id="hint_Id" })"
|
||||
.replace("hint_Id", hintId)
|
||||
.replace("store_Id", storeId);
|
||||
$.post(url);
|
||||
return true;
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
@model StoresViewModel
|
||||
@model StoresViewModel
|
||||
@{
|
||||
ViewData["Title"] = "Stores";
|
||||
var storeNameSortOrder = (string)ViewData["StoreNameSortOrder"];
|
||||
|
@ -11,11 +11,11 @@
|
|||
<div class="container">
|
||||
@if (TempData.HasStatusMessage())
|
||||
{
|
||||
<div class="row">
|
||||
<div class="col-lg-12 text-center">
|
||||
<partial name="_StatusMessage" />
|
||||
<div class="row">
|
||||
<div class="col-lg-12 text-center">
|
||||
<partial name="_StatusMessage" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
<div class="row">
|
||||
<div class="col-lg-12 section-heading">
|
||||
|
@ -37,25 +37,21 @@
|
|||
<thead>
|
||||
<tr>
|
||||
<th>
|
||||
<a
|
||||
asp-action="ListStores"
|
||||
asp-route-sortOrder="@(storeNameSortOrder ?? "asc")"
|
||||
asp-route-sortOrderColumn="StoreName"
|
||||
class="text-nowrap"
|
||||
title="@(storeNameSortOrder == "desc" ? sortByDesc : sortByAsc)"
|
||||
>
|
||||
<a asp-action="ListStores"
|
||||
asp-route-sortOrder="@(storeNameSortOrder ?? "asc")"
|
||||
asp-route-sortOrderColumn="StoreName"
|
||||
class="text-nowrap"
|
||||
title="@(storeNameSortOrder == "desc" ? sortByDesc : sortByAsc)">
|
||||
Name
|
||||
<span class="fa @(storeNameSortOrder == "asc" ? "fa-sort-alpha-desc" : storeNameSortOrder == "desc" ? "fa-sort-alpha-asc" : "fa-sort")" />
|
||||
</a>
|
||||
</th>
|
||||
<th>
|
||||
<a
|
||||
asp-action="ListStores"
|
||||
asp-route-sortOrder="@(storeWebsiteSortOrder ?? "asc")"
|
||||
asp-route-sortOrderColumn="StoreWebsite"
|
||||
class="text-nowrap"
|
||||
title="@(storeWebsiteSortOrder == "desc" ? sortByDesc : sortByAsc)"
|
||||
>
|
||||
<a asp-action="ListStores"
|
||||
asp-route-sortOrder="@(storeWebsiteSortOrder ?? "asc")"
|
||||
asp-route-sortOrderColumn="StoreWebsite"
|
||||
class="text-nowrap"
|
||||
title="@(storeWebsiteSortOrder == "desc" ? sortByDesc : sortByAsc)">
|
||||
Website
|
||||
<span class="fa @(storeWebsiteSortOrder == "asc" ? "fa-sort-alpha-desc" : storeWebsiteSortOrder == "desc" ? "fa-sort-alpha-asc" : "fa-sort")" />
|
||||
</a>
|
||||
|
@ -67,7 +63,20 @@
|
|||
@foreach (var store in Model.Stores)
|
||||
{
|
||||
<tr id="store-@store.Id">
|
||||
<td>@store.Name</td>
|
||||
<td>
|
||||
@if (store.IsOwner)
|
||||
{
|
||||
<a asp-action="UpdateStore" asp-controller="Stores" asp-route-storeId="@store.Id">@store.Name</a>
|
||||
}
|
||||
else
|
||||
{
|
||||
@store.Name
|
||||
}
|
||||
@if (store.HintWalletWarning)
|
||||
{
|
||||
<span class="fa fa-warning text-warning" title="Wallet not setup for this store" id="warninghint_@store.Id"></span>
|
||||
}
|
||||
</td>
|
||||
<td>
|
||||
@if (!string.IsNullOrEmpty(store.WebSite))
|
||||
{
|
||||
|
|
Loading…
Add table
Reference in a new issue