mirror of
https://github.com/aljazceru/btcpayserver.git
synced 2025-12-17 14:04:26 +01:00
use more concrete types for price type in app items
This commit is contained in:
@@ -146,7 +146,7 @@ namespace BTCPayServer.Controllers
|
|||||||
if (choice == null)
|
if (choice == null)
|
||||||
return NotFound();
|
return NotFound();
|
||||||
title = choice.Title;
|
title = choice.Title;
|
||||||
if (choice.Custom == "topup")
|
if (choice.Price.Type == ViewPointOfSaleViewModel.Item.ItemPrice.ItemPriceType.Topup)
|
||||||
{
|
{
|
||||||
price = null;
|
price = null;
|
||||||
}
|
}
|
||||||
@@ -323,7 +323,7 @@ namespace BTCPayServer.Controllers
|
|||||||
return NotFound("Incorrect option provided");
|
return NotFound("Incorrect option provided");
|
||||||
title = choice.Title;
|
title = choice.Title;
|
||||||
|
|
||||||
if (choice.Custom == "topup")
|
if (choice.Price.Type == ViewPointOfSaleViewModel.Item.ItemPrice.ItemPriceType.Topup)
|
||||||
{
|
{
|
||||||
price = null;
|
price = null;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,14 +6,18 @@ using System.Threading.Tasks;
|
|||||||
using BTCPayServer.Abstractions.Contracts;
|
using BTCPayServer.Abstractions.Contracts;
|
||||||
using BTCPayServer.Client.Models;
|
using BTCPayServer.Client.Models;
|
||||||
using BTCPayServer.Configuration;
|
using BTCPayServer.Configuration;
|
||||||
|
using BTCPayServer.Controllers;
|
||||||
using BTCPayServer.Data;
|
using BTCPayServer.Data;
|
||||||
using BTCPayServer.Fido2;
|
using BTCPayServer.Fido2;
|
||||||
using BTCPayServer.Fido2.Models;
|
using BTCPayServer.Fido2.Models;
|
||||||
using BTCPayServer.Logging;
|
using BTCPayServer.Logging;
|
||||||
|
using BTCPayServer.Models.AppViewModels;
|
||||||
using BTCPayServer.Payments;
|
using BTCPayServer.Payments;
|
||||||
using BTCPayServer.Payments.Lightning;
|
using BTCPayServer.Payments.Lightning;
|
||||||
using BTCPayServer.Services;
|
using BTCPayServer.Services;
|
||||||
|
using BTCPayServer.Services.Apps;
|
||||||
using BTCPayServer.Services.Stores;
|
using BTCPayServer.Services.Stores;
|
||||||
|
using ExchangeSharp;
|
||||||
using Fido2NetLib.Objects;
|
using Fido2NetLib.Objects;
|
||||||
using Microsoft.AspNetCore.Identity;
|
using Microsoft.AspNetCore.Identity;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
@@ -31,6 +35,7 @@ namespace BTCPayServer.Hosting
|
|||||||
private readonly StoreRepository _StoreRepository;
|
private readonly StoreRepository _StoreRepository;
|
||||||
private readonly BTCPayNetworkProvider _NetworkProvider;
|
private readonly BTCPayNetworkProvider _NetworkProvider;
|
||||||
private readonly SettingsRepository _Settings;
|
private readonly SettingsRepository _Settings;
|
||||||
|
private readonly AppService _appService;
|
||||||
private readonly UserManager<ApplicationUser> _userManager;
|
private readonly UserManager<ApplicationUser> _userManager;
|
||||||
|
|
||||||
public IOptions<LightningNetworkOptions> LightningOptions { get; }
|
public IOptions<LightningNetworkOptions> LightningOptions { get; }
|
||||||
@@ -41,12 +46,14 @@ namespace BTCPayServer.Hosting
|
|||||||
ApplicationDbContextFactory dbContextFactory,
|
ApplicationDbContextFactory dbContextFactory,
|
||||||
UserManager<ApplicationUser> userManager,
|
UserManager<ApplicationUser> userManager,
|
||||||
IOptions<LightningNetworkOptions> lightningOptions,
|
IOptions<LightningNetworkOptions> lightningOptions,
|
||||||
SettingsRepository settingsRepository)
|
SettingsRepository settingsRepository,
|
||||||
|
AppService appService)
|
||||||
{
|
{
|
||||||
_DBContextFactory = dbContextFactory;
|
_DBContextFactory = dbContextFactory;
|
||||||
_StoreRepository = storeRepository;
|
_StoreRepository = storeRepository;
|
||||||
_NetworkProvider = networkProvider;
|
_NetworkProvider = networkProvider;
|
||||||
_Settings = settingsRepository;
|
_Settings = settingsRepository;
|
||||||
|
_appService = appService;
|
||||||
_userManager = userManager;
|
_userManager = userManager;
|
||||||
LightningOptions = lightningOptions;
|
LightningOptions = lightningOptions;
|
||||||
}
|
}
|
||||||
@@ -134,6 +141,12 @@ namespace BTCPayServer.Hosting
|
|||||||
settings.MigrateHotwalletProperty = true;
|
settings.MigrateHotwalletProperty = true;
|
||||||
await _Settings.UpdateSetting(settings);
|
await _Settings.UpdateSetting(settings);
|
||||||
}
|
}
|
||||||
|
if (!settings.MigrateAppCustomOption)
|
||||||
|
{
|
||||||
|
await MigrateAppCustomOption();
|
||||||
|
settings.MigrateAppCustomOption = true;
|
||||||
|
await _Settings.UpdateSetting(settings);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
@@ -142,6 +155,42 @@ namespace BTCPayServer.Hosting
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task MigrateAppCustomOption()
|
||||||
|
{
|
||||||
|
await using var ctx = _DBContextFactory.CreateContext();
|
||||||
|
foreach (var app in await ctx.Apps.AsQueryable().ToArrayAsync())
|
||||||
|
{
|
||||||
|
ViewPointOfSaleViewModel.Item[] items;
|
||||||
|
string newTemplate;
|
||||||
|
switch (app.AppType)
|
||||||
|
{
|
||||||
|
case nameof(AppType.Crowdfund):
|
||||||
|
var settings1 = app.GetSettings<CrowdfundSettings>();
|
||||||
|
items = _appService.Parse(settings1.PerksTemplate, settings1.TargetCurrency);
|
||||||
|
newTemplate = _appService.SerializeTemplate(items);
|
||||||
|
if (settings1.PerksTemplate != newTemplate)
|
||||||
|
{
|
||||||
|
settings1.PerksTemplate = newTemplate;
|
||||||
|
app.SetSettings(settings1);
|
||||||
|
};
|
||||||
|
break;
|
||||||
|
|
||||||
|
case nameof(AppType.PointOfSale):
|
||||||
|
|
||||||
|
var settings2 = app.GetSettings<AppsController.PointOfSaleSettings>();
|
||||||
|
items = _appService.Parse(settings2.Template, settings2.Currency);
|
||||||
|
newTemplate = _appService.SerializeTemplate(items);
|
||||||
|
if (settings2.Template != newTemplate)
|
||||||
|
{
|
||||||
|
settings2.Template = newTemplate;
|
||||||
|
app.SetSettings(settings2);
|
||||||
|
};
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
await ctx.SaveChangesAsync();
|
||||||
|
}
|
||||||
|
|
||||||
private async Task MigrateHotwalletProperty()
|
private async Task MigrateHotwalletProperty()
|
||||||
{
|
{
|
||||||
await using var ctx = _DBContextFactory.CreateContext();
|
await using var ctx = _DBContextFactory.CreateContext();
|
||||||
|
|||||||
@@ -9,15 +9,22 @@ namespace BTCPayServer.Models.AppViewModels
|
|||||||
{
|
{
|
||||||
public class ItemPrice
|
public class ItemPrice
|
||||||
{
|
{
|
||||||
|
public enum ItemPriceType
|
||||||
|
{
|
||||||
|
Topup,
|
||||||
|
Minimum,
|
||||||
|
Fixed
|
||||||
|
}
|
||||||
|
|
||||||
|
public ItemPriceType Type { get; set; }
|
||||||
public string Formatted { get; set; }
|
public string Formatted { get; set; }
|
||||||
public decimal Value { get; set; }
|
public decimal? Value { get; set; }
|
||||||
}
|
}
|
||||||
public string Description { get; set; }
|
public string Description { get; set; }
|
||||||
public string Id { get; set; }
|
public string Id { get; set; }
|
||||||
public string Image { get; set; }
|
public string Image { get; set; }
|
||||||
public ItemPrice Price { get; set; }
|
public ItemPrice Price { get; set; }
|
||||||
public string Title { get; set; }
|
public string Title { get; set; }
|
||||||
public string Custom { get; set; }
|
|
||||||
public string BuyButtonText { get; set; }
|
public string BuyButtonText { get; set; }
|
||||||
public int? Inventory { get; set; } = null;
|
public int? Inventory { get; set; } = null;
|
||||||
public string[] PaymentMethods { get; set; }
|
public string[] PaymentMethods { get; set; }
|
||||||
|
|||||||
@@ -289,7 +289,7 @@ namespace BTCPayServer.Services.Apps
|
|||||||
{
|
{
|
||||||
var itemNode = new YamlMappingNode();
|
var itemNode = new YamlMappingNode();
|
||||||
itemNode.Add("title", new YamlScalarNode(item.Title));
|
itemNode.Add("title", new YamlScalarNode(item.Title));
|
||||||
if(item.Custom!= "topup")
|
if(item.Price.Type!= ViewPointOfSaleViewModel.Item.ItemPrice.ItemPriceType.Topup)
|
||||||
itemNode.Add("price", new YamlScalarNode(item.Price.Value.ToStringInvariant()));
|
itemNode.Add("price", new YamlScalarNode(item.Price.Value.ToStringInvariant()));
|
||||||
if (!string.IsNullOrEmpty(item.Description))
|
if (!string.IsNullOrEmpty(item.Description))
|
||||||
{
|
{
|
||||||
@@ -302,7 +302,7 @@ namespace BTCPayServer.Services.Apps
|
|||||||
{
|
{
|
||||||
itemNode.Add("image", new YamlScalarNode(item.Image));
|
itemNode.Add("image", new YamlScalarNode(item.Image));
|
||||||
}
|
}
|
||||||
itemNode.Add("custom", new YamlScalarNode(item.Custom.ToStringLowerInvariant()));
|
itemNode.Add("price_type", new YamlScalarNode(item.Price.Type.ToStringLowerInvariant()));
|
||||||
itemNode.Add("disabled", new YamlScalarNode(item.Disabled.ToStringLowerInvariant()));
|
itemNode.Add("disabled", new YamlScalarNode(item.Disabled.ToStringLowerInvariant()));
|
||||||
if (item.Inventory.HasValue)
|
if (item.Inventory.HasValue)
|
||||||
{
|
{
|
||||||
@@ -336,26 +336,50 @@ namespace BTCPayServer.Services.Apps
|
|||||||
.Children
|
.Children
|
||||||
.Select(kv => new PosHolder(_HtmlSanitizer) { Key = _HtmlSanitizer.Sanitize((kv.Key as YamlScalarNode)?.Value), Value = kv.Value as YamlMappingNode })
|
.Select(kv => new PosHolder(_HtmlSanitizer) { Key = _HtmlSanitizer.Sanitize((kv.Key as YamlScalarNode)?.Value), Value = kv.Value as YamlMappingNode })
|
||||||
.Where(kv => kv.Value != null)
|
.Where(kv => kv.Value != null)
|
||||||
.Select(c => new ViewPointOfSaleViewModel.Item()
|
.Select(c =>
|
||||||
{
|
{
|
||||||
Description = c.GetDetailString("description"),
|
ViewPointOfSaleViewModel.Item.ItemPrice price = new ViewPointOfSaleViewModel.Item.ItemPrice();
|
||||||
Id = c.Key,
|
var pValue = c.GetDetail("price")?.FirstOrDefault();
|
||||||
Image = c.GetDetailString("image"),
|
|
||||||
Title = c.GetDetailString("title") ?? c.Key,
|
switch (c.GetDetailString("custom")??c.GetDetailString("price_type")?.ToLowerInvariant())
|
||||||
Custom = c.GetDetailString("custom"),
|
{
|
||||||
Price =
|
case "topup":
|
||||||
c.GetDetailString("custom") == "topup"
|
case null when pValue is null:
|
||||||
? null
|
price.Type = ViewPointOfSaleViewModel.Item.ItemPrice.ItemPriceType.Topup;
|
||||||
: c.GetDetail("price")
|
break;
|
||||||
.Select(cc => new ViewPointOfSaleViewModel.Item.ItemPrice()
|
case "true":
|
||||||
{
|
case "minimum":
|
||||||
Value = decimal.Parse(cc.Value.Value, CultureInfo.InvariantCulture),
|
price.Type = ViewPointOfSaleViewModel.Item.ItemPrice.ItemPriceType.Minimum;
|
||||||
Formatted = Currencies.FormatCurrency(cc.Value.Value, currency)
|
if (pValue != null)
|
||||||
}).Single(),
|
{
|
||||||
BuyButtonText = c.GetDetailString("buyButtonText"),
|
price.Value = decimal.Parse(pValue.Value.Value, CultureInfo.InvariantCulture);
|
||||||
Inventory = string.IsNullOrEmpty(c.GetDetailString("inventory")) ? (int?)null : int.Parse(c.GetDetailString("inventory"), CultureInfo.InvariantCulture),
|
price.Formatted = Currencies.FormatCurrency(pValue.Value.Value, currency);
|
||||||
PaymentMethods = c.GetDetailStringList("payment_methods"),
|
}
|
||||||
Disabled = c.GetDetailString("disabled") == "true"
|
break;
|
||||||
|
case "fixed":
|
||||||
|
case "false":
|
||||||
|
case null:
|
||||||
|
price.Type = ViewPointOfSaleViewModel.Item.ItemPrice.ItemPriceType.Fixed;
|
||||||
|
price.Value = decimal.Parse(pValue.Value.Value, CultureInfo.InvariantCulture);
|
||||||
|
price.Formatted = Currencies.FormatCurrency(pValue.Value.Value, currency);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new ViewPointOfSaleViewModel.Item()
|
||||||
|
{
|
||||||
|
Description = c.GetDetailString("description"),
|
||||||
|
Id = c.Key,
|
||||||
|
Image = c.GetDetailString("image"),
|
||||||
|
Title = c.GetDetailString("title") ?? c.Key,
|
||||||
|
Price = price,
|
||||||
|
BuyButtonText = c.GetDetailString("buyButtonText"),
|
||||||
|
Inventory =
|
||||||
|
string.IsNullOrEmpty(c.GetDetailString("inventory"))
|
||||||
|
? (int?)null
|
||||||
|
: int.Parse(c.GetDetailString("inventory"), CultureInfo.InvariantCulture),
|
||||||
|
PaymentMethods = c.GetDetailStringList("payment_methods"),
|
||||||
|
Disabled = c.GetDetailString("disabled") == "true"
|
||||||
|
};
|
||||||
})
|
})
|
||||||
.ToArray();
|
.ToArray();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,5 +25,6 @@ namespace BTCPayServer.Services
|
|||||||
|
|
||||||
// Done in DbMigrationsHostedService
|
// Done in DbMigrationsHostedService
|
||||||
public int? MigratedInvoiceTextSearchPages { get; set; }
|
public int? MigratedInvoiceTextSearchPages { get; set; }
|
||||||
|
public bool MigrateAppCustomOption { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -64,7 +64,8 @@
|
|||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-sm-3" v-show="editingItem.custom !== 'topup'">
|
<div class="col-sm-3" v-show="editingItem.custom !== 'topup'">
|
||||||
<label class="form-label" data-required>Price</label>
|
|
||||||
|
<label class="form-label"> </label>
|
||||||
<input class="form-control mb-2"
|
<input class="form-control mb-2"
|
||||||
inputmode="numeric"
|
inputmode="numeric"
|
||||||
pattern="\d*"
|
pattern="\d*"
|
||||||
@@ -121,8 +122,8 @@ document.addEventListener("DOMContentLoaded", function () {
|
|||||||
items: [],
|
items: [],
|
||||||
editingItem: null,
|
editingItem: null,
|
||||||
customPriceOptions: [
|
customPriceOptions: [
|
||||||
{ text: 'Fixed', value: false },
|
{ text: 'Fixed', value: "fixed" },
|
||||||
{ text: 'Minimum', value: true },
|
{ text: 'Minimum', value: "minimum" },
|
||||||
{ text: 'Topup', value: 'topup' },
|
{ text: 'Topup', value: 'topup' },
|
||||||
],
|
],
|
||||||
elementId: "@Model.templateId"
|
elementId: "@Model.templateId"
|
||||||
@@ -207,8 +208,8 @@ document.addEventListener("DOMContentLoaded", function () {
|
|||||||
if (productProperty.indexOf('image:') !== -1) {
|
if (productProperty.indexOf('image:') !== -1) {
|
||||||
image = productProperty.replace('image:', '').trim();
|
image = productProperty.replace('image:', '').trim();
|
||||||
}
|
}
|
||||||
if (productProperty.indexOf('custom:') !== -1) {
|
if (productProperty.indexOf('price_type:') !== -1) {
|
||||||
custom = productProperty.replace('custom:', '').trim();
|
custom = productProperty.replace('price_type:', '').trim();
|
||||||
}
|
}
|
||||||
if (productProperty.indexOf('buyButtonText:') !== -1) {
|
if (productProperty.indexOf('buyButtonText:') !== -1) {
|
||||||
buyButtonText = productProperty.replace('buyButtonText:', '').trim();
|
buyButtonText = productProperty.replace('buyButtonText:', '').trim();
|
||||||
@@ -232,7 +233,7 @@ document.addEventListener("DOMContentLoaded", function () {
|
|||||||
price: price,
|
price: price,
|
||||||
image: image || null,
|
image: image || null,
|
||||||
description: description || '',
|
description: description || '',
|
||||||
custom: custom === "topup"? "topup": custom === "true",
|
custom: custom,
|
||||||
buyButtonText: buyButtonText,
|
buyButtonText: buyButtonText,
|
||||||
inventory: isNaN(inventory)? null: inventory,
|
inventory: isNaN(inventory)? null: inventory,
|
||||||
paymentMethods: paymentMethods,
|
paymentMethods: paymentMethods,
|
||||||
@@ -271,7 +272,7 @@ document.addEventListener("DOMContentLoaded", function () {
|
|||||||
itemTemplate += ' inventory: ' + inventory + '\n';
|
itemTemplate += ' inventory: ' + inventory + '\n';
|
||||||
}
|
}
|
||||||
if (custom != null) {
|
if (custom != null) {
|
||||||
itemTemplate += ' custom: ' + (custom === "topup"? '"topup"': custom) + '\n';
|
itemTemplate += ' price_type: "' + custom + '" \n';
|
||||||
}
|
}
|
||||||
if (buyButtonText != null && buyButtonText.length > 0) {
|
if (buyButtonText != null && buyButtonText.length > 0) {
|
||||||
itemTemplate += ' buyButtonText: ' + buyButtonText + '\n';
|
itemTemplate += ' buyButtonText: ' + buyButtonText + '\n';
|
||||||
@@ -293,7 +294,7 @@ document.addEventListener("DOMContentLoaded", function () {
|
|||||||
editItem: function(index){
|
editItem: function(index){
|
||||||
this.errors = [];
|
this.errors = [];
|
||||||
if(index < 0){
|
if(index < 0){
|
||||||
this.editingItem = {index:-1, id:"", title: "", price: 0, image: "", description: "", custom: false, inventory: null, paymentMethods: [], disabled: false};
|
this.editingItem = {index:-1, id:"", title: "", price: 0, image: "", description: "", custom: "fixed", inventory: null, paymentMethods: [], disabled: false};
|
||||||
}else{
|
}else{
|
||||||
this.editingItem = {...this.items[index], index};
|
this.editingItem = {...this.items[index], index};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
@using BTCPayServer.Models.AppViewModels
|
||||||
@model BTCPayServer.Models.AppViewModels.ContributeToCrowdfund
|
@model BTCPayServer.Models.AppViewModels.ContributeToCrowdfund
|
||||||
|
|
||||||
@{ var vm = Model.ViewCrowdfundViewModel; }
|
@{ var vm = Model.ViewCrowdfundViewModel; }
|
||||||
@@ -26,20 +27,20 @@
|
|||||||
@(string.IsNullOrEmpty(item.Title) ? item.Id : item.Title)
|
@(string.IsNullOrEmpty(item.Title) ? item.Id : item.Title)
|
||||||
</label>
|
</label>
|
||||||
<span class="text-muted">
|
<span class="text-muted">
|
||||||
@if (item.Price?.Value > 0)
|
@if (item.Price.Value > 0)
|
||||||
{
|
{
|
||||||
<span>@item.Price.Value</span>
|
<span>@item.Price.Value</span>
|
||||||
<span>@vm.TargetCurrency</span>
|
<span>@vm.TargetCurrency</span>
|
||||||
|
|
||||||
if (item.Custom == "true")
|
if (item.Price.Type == ViewPointOfSaleViewModel.Item.ItemPrice.ItemPriceType.Minimum)
|
||||||
{
|
{
|
||||||
@Safe.Raw("or more")
|
@Safe.Raw("or more")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (item.Custom == "topup" || item.Custom == "true" )
|
else if (item.Price.Type != ViewPointOfSaleViewModel.Item.ItemPrice.ItemPriceType.Fixed )
|
||||||
{
|
{
|
||||||
@Safe.Raw("Any amount")
|
@Safe.Raw("Any amount")
|
||||||
}else if (item.Custom == "false")
|
}else if (item.Price.Type == ViewPointOfSaleViewModel.Item.ItemPrice.ItemPriceType.Fixed)
|
||||||
{
|
{
|
||||||
@Safe.Raw("Free")
|
@Safe.Raw("Free")
|
||||||
}
|
}
|
||||||
@@ -54,7 +55,7 @@
|
|||||||
{
|
{
|
||||||
case null:
|
case null:
|
||||||
break;
|
break;
|
||||||
case int i when i <= 0:
|
case var i when i <= 0:
|
||||||
<span>Sold out</span>
|
<span>Sold out</span>
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
@using BTCPayServer.Models.AppViewModels
|
||||||
@model BTCPayServer.Models.AppViewModels.ViewPointOfSaleViewModel
|
@model BTCPayServer.Models.AppViewModels.ViewPointOfSaleViewModel
|
||||||
@{
|
@{
|
||||||
Layout = "_LayoutPos";
|
Layout = "_LayoutPos";
|
||||||
@@ -232,8 +233,8 @@
|
|||||||
|
|
||||||
<span class="text-muted small">
|
<span class="text-muted small">
|
||||||
@{
|
@{
|
||||||
var buttonText = string.IsNullOrEmpty(item.BuyButtonText) ? (item.Custom == "true" || item.Custom == "topup") ? Model.CustomButtonText : Model.ButtonText : item.BuyButtonText;
|
var buttonText = string.IsNullOrEmpty(item.BuyButtonText) ? item.Price.Type != ViewPointOfSaleViewModel.Item.ItemPrice.ItemPriceType.Fixed ? Model.CustomButtonText : Model.ButtonText : item.BuyButtonText;
|
||||||
if (item.Custom != "topup")
|
if (item.Price.Type != ViewPointOfSaleViewModel.Item.ItemPrice.ItemPriceType.Topup)
|
||||||
{
|
{
|
||||||
buttonText = buttonText.Replace("{0}",item.Price.Formatted)
|
buttonText = buttonText.Replace("{0}",item.Price.Formatted)
|
||||||
?.Replace("{Price}",item.Price.Formatted);
|
?.Replace("{Price}",item.Price.Formatted);
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
@using BTCPayServer.Models.AppViewModels
|
||||||
@model BTCPayServer.Models.AppViewModels.ViewPointOfSaleViewModel
|
@model BTCPayServer.Models.AppViewModels.ViewPointOfSaleViewModel
|
||||||
@{
|
@{
|
||||||
Layout = "_LayoutPos";
|
Layout = "_LayoutPos";
|
||||||
@@ -19,12 +20,9 @@
|
|||||||
@for (int x = 0; x < Model.Items.Length; x++)
|
@for (int x = 0; x < Model.Items.Length; x++)
|
||||||
{
|
{
|
||||||
var item = Model.Items[x];
|
var item = Model.Items[x];
|
||||||
var buttonText = string.IsNullOrEmpty(item.BuyButtonText) ? (item.Custom == "true" || item.Custom == "topup") ? Model.CustomButtonText : Model.ButtonText : item.BuyButtonText;
|
var buttonText = string.IsNullOrEmpty(item.BuyButtonText) ? item.Price.Type != ViewPointOfSaleViewModel.Item.ItemPrice.ItemPriceType.Fixed ? Model.CustomButtonText : Model.ButtonText : item.BuyButtonText;
|
||||||
if (item.Custom != "topup")
|
buttonText = buttonText.Replace("{0}",item.Price.Formatted)
|
||||||
{
|
?.Replace("{Price}",item.Price.Formatted);
|
||||||
buttonText = buttonText.Replace("{0}",item.Price.Formatted)
|
|
||||||
?.Replace("{Price}",item.Price.Formatted);
|
|
||||||
}
|
|
||||||
|
|
||||||
<div class="card px-0" data-id="@x">
|
<div class="card px-0" data-id="@x">
|
||||||
@if (!String.IsNullOrWhiteSpace(item.Image))
|
@if (!String.IsNullOrWhiteSpace(item.Image))
|
||||||
@@ -35,7 +33,7 @@
|
|||||||
<div class="card-footer bg-transparent border-0 pb-3">
|
<div class="card-footer bg-transparent border-0 pb-3">
|
||||||
@if (!item.Inventory.HasValue || item.Inventory.Value > 0)
|
@if (!item.Inventory.HasValue || item.Inventory.Value > 0)
|
||||||
{
|
{
|
||||||
@if (item.Custom == "true")
|
@if (item.Price.Type == ViewPointOfSaleViewModel.Item.ItemPrice.ItemPriceType.Fixed)
|
||||||
{
|
{
|
||||||
<form method="post" asp-controller="AppsPublic" asp-action="ViewPointOfSale" asp-route-appId="@Model.AppId" asp-antiforgery="false" data-buy>
|
<form method="post" asp-controller="AppsPublic" asp-action="ViewPointOfSale" asp-route-appId="@Model.AppId" asp-antiforgery="false" data-buy>
|
||||||
<input type="hidden" name="choicekey" value="@item.Id"/>
|
<input type="hidden" name="choicekey" value="@item.Id"/>
|
||||||
|
|||||||
@@ -112,7 +112,7 @@ Cart.prototype.getTotalProducts = function() {
|
|||||||
typeof this.content[key] != 'undefined' &&
|
typeof this.content[key] != 'undefined' &&
|
||||||
!this.content[key].disabled
|
!this.content[key].disabled
|
||||||
) {
|
) {
|
||||||
var price = this.toCents(this.content[key].price?.value??0);
|
const price = this.toCents(this.content[key].price.value ||0);
|
||||||
amount += (this.content[key].count * price);
|
amount += (this.content[key].count * price);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -439,7 +439,7 @@ Cart.prototype.listItems = function() {
|
|||||||
'title': this.escape(item.title),
|
'title': this.escape(item.title),
|
||||||
'count': this.escape(item.count),
|
'count': this.escape(item.count),
|
||||||
'inventory': this.escape(item.inventory < 0? 99999: item.inventory),
|
'inventory': this.escape(item.inventory < 0? 99999: item.inventory),
|
||||||
'price': this.escape(item.price?.formatted??0)
|
'price': this.escape(item.price.formatted || 0)
|
||||||
});
|
});
|
||||||
list.push($(tableTemplate));
|
list.push($(tableTemplate));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ document.addEventListener("DOMContentLoaded",function (ev) {
|
|||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
canExpand: function(){
|
canExpand: function(){
|
||||||
return !this.expanded && this.active && (this.perk.custom=="topup" || this.perk.price.value || this.perk.custom == "true") && (this.perk.inventory==null || this.perk.inventory > 0)
|
return !this.expanded && this.active && (this.perk.custom !== "fixed" || this.perk.price.value) && (this.perk.inventory==null || this.perk.inventory > 0)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
@@ -45,14 +45,14 @@ document.addEventListener("DOMContentLoaded",function (ev) {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
setAmount: function (amount) {
|
setAmount: function (amount) {
|
||||||
this.amount = this.perk.custom == "topup"? null : (amount || 0).noExponents();
|
this.amount = this.perk.custom === "topup"? null : (amount || 0).noExponents();
|
||||||
this.expanded = false;
|
this.expanded = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
},
|
},
|
||||||
mounted: function () {
|
mounted: function () {
|
||||||
this.setAmount(this.perk.price?.value);
|
this.setAmount(this.perk.price.value);
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
perk: function (newValue, oldValue) {
|
perk: function (newValue, oldValue) {
|
||||||
|
|||||||
Reference in New Issue
Block a user