Fix Pay Button steps and range validation

There were numerous issues around different button types and the amount range validation. Also fixes #2503
This commit is contained in:
Kukks
2021-05-05 11:27:02 +02:00
parent 86092fc955
commit 200e8330d8
4 changed files with 29 additions and 13 deletions

View File

@@ -1015,7 +1015,7 @@ namespace BTCPayServer.Controllers
ButtonType = 0, ButtonType = 0,
Min = 1, Min = 1,
Max = 20, Max = 20,
Step = 1, Step = "1",
Apps = apps Apps = apps
}; };
return View(model); return View(model);

View File

@@ -21,7 +21,7 @@ namespace BTCPayServer.Models.StoreViewModels
// Slider properties (ButtonType = 2) // Slider properties (ButtonType = 2)
public decimal Min { get; set; } public decimal Min { get; set; }
public decimal Max { get; set; } public decimal Max { get; set; }
public decimal Step { get; set; } public string Step { get; set; }
// Custom Amount properties (ButtonType = 1) // Custom Amount properties (ButtonType = 1)
public bool SimpleInput { get; set; } public bool SimpleInput { get; set; }

View File

@@ -107,21 +107,21 @@
<label>Min</label> <label>Min</label>
<input name="min" type="text" class="form-control" <input name="min" type="text" class="form-control"
v-model="srvModel.min" v-on:change="inputChanges" v-model="srvModel.min" v-on:change="inputChanges"
v-validate="'required|decimal|min_value:1'" :class="{'is-invalid': errors.has('min') }"> v-validate="'required|decimal|min_value:0'" :class="{'is-invalid': errors.has('min') }">
<small class="text-danger">{{ errors.first('min') }}</small> <small class="text-danger">{{ errors.first('min') }}</small>
</div> </div>
<div class="form-group col-md-4"> <div class="form-group col-md-4">
<label>Max</label> <label>Max</label>
<input name="max" type="text" class="form-control" <input name="max" type="text" class="form-control"
v-model="srvModel.max" v-on:change="inputChanges" v-model="srvModel.max" v-on:change="inputChanges"
v-validate="'required|decimal|min_value:1'" :class="{'is-invalid': errors.has('max') }"> v-validate="'required|decimal'" :class="{'is-invalid': errors.has('max') }">
<small class="text-danger">{{ errors.first('max') }}</small> <small class="text-danger">{{ errors.first('max') }}</small>
</div> </div>
<div class="form-group col-md-4"> <div class="form-group col-md-4">
<label>Step</label> <label>Step</label>
<input name="step" type="text" class="form-control" <input name="step" type="text" class="form-control"
v-model="srvModel.step" v-on:change="inputChanges" v-model="srvModel.step" v-on:change="inputChanges"
v-validate="'required|decimal|min_value:1'" :class="{'is-invalid': errors.has('step') }"> v-validate="'required'" :class="{'is-invalid': errors.has('step') }">
<small class="text-danger">{{ errors.first('step') }}</small> <small class="text-danger">{{ errors.first('step') }}</small>
</div> </div>
</div> </div>

View File

@@ -156,9 +156,9 @@ function inputChanges(event, buttonSize) {
// Custom amount // Custom amount
else if (isCustomAmount) { else if (isCustomAmount) {
html += ' <div class="btcpay-custom-container">\n <div class="btcpay-custom">\n'; html += ' <div class="btcpay-custom-container">\n <div class="btcpay-custom">\n';
html += srvModel.simpleInput ? '' : addPlusMinusButton("-"); html += srvModel.simpleInput ? '' : addPlusMinusButton("-", srvModel.step, srvModel.min, srvModel.max);
html += ' ' + addInputPrice(priceInputName, srvModel.price, widthInput, "", srvModel.simpleInput ? "number": null, srvModel.min, srvModel.max, srvModel.step); html += ' ' + addInputPrice(priceInputName, srvModel.price, widthInput, "", "number", srvModel.min, srvModel.max, srvModel.step);
html += srvModel.simpleInput ? '' : addPlusMinusButton("+"); html += srvModel.simpleInput ? '' : addPlusMinusButton("+", srvModel.step, srvModel.min, srvModel.max);
html += ' </div>\n'; html += ' </div>\n';
if(allowCurrencySelection) { if(allowCurrencySelection) {
html += addSelectCurrency(srvModel.currency); html += addSelectCurrency(srvModel.currency);
@@ -167,8 +167,13 @@ function inputChanges(event, buttonSize) {
} }
// Slider // Slider
else if (isSlider) { else if (isSlider) {
var step = srvModel.step =="any"? 1: srvModel.step;
var min = srvModel.min == null? 1: parseInt(srvModel.min);
var max = srvModel.max == null? 1: parseInt(srvModel.max);
var onChange = "var el=document.querySelector(\'#btcpay-input-price\'); var price = parseInt(el.value); if(price< "+min+") { el.value = "+min+"} else if(price> "+max+") { el.value = "+max+"} document.querySelector(\'#btcpay-input-range\').value = el.value"
html += ' <div class="btcpay-custom-container">\n'; html += ' <div class="btcpay-custom-container">\n';
html += addInputPrice(priceInputName, srvModel.price, width, 'onchange="document.querySelector(\'#btcpay-input-range\').value = document.querySelector(\'#btcpay-input-price\').value"'); html += addInputPrice(priceInputName, srvModel.price, width, 'onchange= \"'+onChange+'\"');
if(allowCurrencySelection) { if(allowCurrencySelection) {
html += addSelectCurrency(srvModel.currency); html += addSelectCurrency(srvModel.currency);
} }
@@ -211,12 +216,23 @@ function addInput(name, value) {
return ' <input type="hidden" name="' + esc(name) + '" value="' + esc(value) + '" />\n'; return ' <input type="hidden" name="' + esc(name) + '" value="' + esc(value) + '" />\n';
} }
function addPlusMinusButton(type) { function addPlusMinusButton(type, step, min, max) {
return ' <button class="plus-minus" onclick="event.preventDefault(); var price = parseInt(document.querySelector(\'#btcpay-input-price\').value); if (\'' + type + '\' == \'-\' && (price - 1) < 1) { return; } document.querySelector(\'#btcpay-input-price\').value = parseInt(document.querySelector(\'#btcpay-input-price\').value) ' + type + ' 1;">' + type + '</button>\n'; step = step =="any"? 1: step;
min = min == null? 1: parseInt(min);
max = max == null? 1: parseInt(max);
var onChange = "event.preventDefault(); var el=document.querySelector(\'#btcpay-input-price\'); var price = parseInt(el.value);"
if(type == "-"){
onChange += " if((price - "+step+" )< "+min+") { el.value = "+min+"} else {el.value = parseInt(el.value) - "+step + " }";
} else if(type == "+"){
onChange += " if((price + "+step+" )> "+max+") { el.value = "+max+"} else {el.value = parseInt(el.value) + "+step + " }";
}
return ' <button class="plus-minus" onclick="'+onChange+'">' + type + '</button>\n';
} }
function addInputPrice(name, price, widthInput, customFn, type, min, max, step) { function addInputPrice(name, price, widthInput, customFn, type, min, max, step) {
return ' <input id="btcpay-input-price" name="'+name+'" type="' + (type || "text") + '" min="' + (min || 0) + '" max="' + (max || "none") + '" step="' + (step || "any") + '" value="' + price + '" style="width: ' + widthInput + ';" oninput="event.preventDefault();isNaN(event.target.value) || event.target.value <= 0 ? document.querySelector(\'#btcpay-input-price\').value = ' + price + ' : event.target.value" ' + (customFn || '') + ' />\n'; return ' <input id="btcpay-input-price" name="'+name+'" type="' + (type || "text") + '" min="' + (min || 0) + '" max="' + (max || "none") + '" step="' + (step || "any") + '" value="' + price + '" style="width: ' + widthInput + ';" oninput="event.preventDefault();isNaN(event.target.value)? document.querySelector(\'#btcpay-input-price\').value = ' + price + ' : event.target.value; console.log(this); if (this.value < '+min+') {this.value = '+min+'; } else if(this.value > '+max+'){ this.value = '+max+';}" ' + (customFn || '') + ' />\n';
} }
function addSelectCurrency(currency) { function addSelectCurrency(currency) {