2022-06-15 04:32:46 +02:00
@using BTCPayServer.Views.Stores
2023-07-06 10:12:31 +02:00
@inject Security.ContentSecurityPolicies Csp
@inject BTCPayNetworkProvider NetworkProvider
2022-06-15 04:32:46 +02:00
@model BTCPayServer.Plugins.PayButton.Models.PayButtonViewModel
2018-08-10 20:26:51 +02:00
@{
2021-12-31 08:36:38 +01:00
ViewData.SetActivePage(StoreNavPages.PayButton, "Pay Button", Context.GetStoreData().Id);
2023-03-08 17:57:36 +09:00
Csp.UnsafeEval();
2018-08-10 20:26:51 +02:00
}
2021-05-19 04:39:27 +02:00
@section PageHeadContent {
<link rel="stylesheet" href="~/vendor/highlightjs/default.min.css" asp-append-version="true">
}
@section PageFootContent {
<script src="~/vendor/highlightjs/highlight.min.js" asp-append-version="true"></script>
2022-11-24 00:53:32 +01:00
<script src="~/vendor/vuejs/vue.min.js" asp-append-version="true"></script>
2021-05-19 04:39:27 +02:00
<script src="~/vendor/vuejs-vee-validate/vee-validate.js" asp-append-version="true"></script>
2023-07-06 10:12:31 +02:00
<script src="~/vendor/vue-qrcode/vue-qrcode.min.js" asp-append-version="true"></script>
2021-05-19 04:39:27 +02:00
<script src="~/paybutton/paybutton.js" asp-append-version="true"></script>
2022-01-21 03:11:08 +01:00
<template id="template-modal" csp-allow>
if (!window.btcpay) {
var script = document.createElement('script');
script.src = @(Safe.Json(Model.UrlRoot + "modal/btcpay.js"));
document.getElementsByTagName('head')[0].append(script);
}
2022-12-12 12:27:26 +01:00
function handleFormSubmit(event) {
2022-01-21 03:11:08 +01:00
event.preventDefault();
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200 && this.responseText) {
2022-09-08 21:21:39 -07:00
window.btcpay.appendInvoiceFrame(JSON.parse(this.responseText).invoiceId);
2022-01-21 03:11:08 +01:00
}
};
xhttp.open('POST', event.target.getAttribute('action'), true);
xhttp.send(new FormData(event.target));
}
2022-12-12 12:27:26 +01:00
document.querySelectorAll(".btcpay-form").forEach(function(el) {
if (!el.dataset.initialized) {
el.addEventListener('submit', handleFormSubmit);
el.dataset.initialized = true;
}
});
2022-01-21 03:11:08 +01:00
</template>
<template id="template-price-buttons" csp-allow>
function handlePlusMinus(event) {
event.preventDefault();
2022-01-24 20:05:22 +09:00
const root = event.target.closest('.btcpay-form');
const el = root.querySelector('.btcpay-input-price');
2022-01-21 03:11:08 +01:00
const step = parseInt(event.target.dataset.step) || 1;
const min = parseInt(event.target.dataset.min) || 1;
const max = parseInt(event.target.dataset.max);
const type = event.target.dataset.type;
const price = parseInt(el.value) || min;
if (type === '-') {
el.value = price - step < min ? min : price - step;
} else if (type === '+') {
el.value = price + step > max ? max : price + step;
2021-09-12 13:31:35 +02:00
}
2022-01-21 03:11:08 +01:00
}
2022-12-12 12:27:26 +01:00
document.querySelectorAll(".btcpay-form .plus-minus").forEach(function(el) {
if (!el.dataset.initialized) {
el.addEventListener('click', handlePlusMinus);
el.dataset.initialized = true;
}
});
2022-01-21 03:11:08 +01:00
</template>
<template id="template-price-input" csp-allow>
function handlePriceInput(event) {
event.preventDefault();
2022-01-24 20:05:22 +09:00
const root = event.target.closest('.btcpay-form');
2022-01-21 03:11:08 +01:00
const price = parseInt(event.target.dataset.price);
2022-01-24 20:05:22 +09:00
if (isNaN(event.target.value)) root.querySelector('.btcpay-input-price').value = price;
2022-01-21 03:11:08 +01:00
const min = parseInt(event.target.getAttribute('min')) || 1;
const max = parseInt(event.target.getAttribute('max'));
if (event.target.value < min) {
event.target.value = min;
} else if (event.target.value > max) {
event.target.value = max;
2021-09-12 13:31:35 +02:00
}
2022-01-21 03:11:08 +01:00
}
2022-12-12 12:27:26 +01:00
document.querySelectorAll(".btcpay-form .btcpay-input-price").forEach(function(el) {
if (!el.dataset.initialized) {
el.addEventListener('input', handlePriceInput);
el.dataset.initialized = true;
}
});
2021-09-12 13:31:35 +02:00
</template>
2022-01-21 03:11:08 +01:00
<template id="template-price-slider" csp-allow>
function handleSliderChange(event) {
event.preventDefault();
2022-01-24 20:05:22 +09:00
const root = event.target.closest('.btcpay-form');
const el = root.querySelector('.btcpay-input-price');
2022-01-21 03:11:08 +01:00
const price = parseInt(el.value);
const min = parseInt(event.target.getAttribute('min')) || 1;
const max = parseInt(event.target.getAttribute('max'));
if (price < min) {
el.value = min;
} else if (price > max) {
el.value = max;
}
2022-01-24 20:05:22 +09:00
root.querySelector('.btcpay-input-range').value = el.value;
2022-01-21 03:11:08 +01:00
}
function handleSliderInput(event) {
2022-01-24 20:05:22 +09:00
event.target.closest('.btcpay-form').querySelector('.btcpay-input-price').value = event.target.value;
2022-01-21 03:11:08 +01:00
}
2022-12-12 12:27:26 +01:00
document.querySelectorAll(".btcpay-form .btcpay-input-range").forEach(function(el) {
if (!el.dataset.initialized) {
el.addEventListener('input', handleSliderInput);
el.dataset.initialized = true;
}
});
document.querySelectorAll(".btcpay-form .btcpay-input-price").forEach(function(el) {
if (!el.dataset.initialized) {
el.addEventListener('change', handleSliderChange);
el.dataset.initialized = true;
}
});
2022-01-21 03:11:08 +01:00
</template>
2021-05-19 04:39:27 +02:00
<script>
2023-07-06 10:12:31 +02:00
window.lnurlEndpoint = @Safe.Json(Url.Action("GetLNUrlForStore", "UILNURL", new
{
storeId = Model.StoreId,
cryptoCode = NetworkProvider.DefaultNetwork.CryptoCode
}, "lnurlp", Context.Request.Host.ToString()));
2021-11-18 00:58:29 -08:00
const srvModel = @Safe.Json(Model);
const payButtonCtrl = new Vue({
2021-05-19 04:39:27 +02:00
el: '#payButtonCtrl',
2023-07-06 10:12:31 +02:00
components: {
qrcode: VueQrcode
},
2021-05-19 04:39:27 +02:00
data: {
srvModel: srvModel,
originalButtonImageUrl: srvModel.payButtonImageUrl,
2023-07-06 10:12:31 +02:00
buttonInlineTextMode: false,
previewLink: "",
lnurlLink: "",
alternativeMode: 'link',
qrOptions: {
width: 256,
height: 256,
margin: 1,
color: {
dark: '#000',
light: '#f5f5f7'
}
}
2021-05-19 04:39:27 +02:00
},
computed: {
2021-11-18 00:58:29 -08:00
imageUrlRequired() {
2021-05-19 04:39:27 +02:00
return !this.buttonInlineTextMode;
}
},
methods: {
2021-11-18 00:58:29 -08:00
inputChanges(event, buttonSize) {
2023-07-06 10:12:31 +02:00
inputChanges(payButtonCtrl, event, buttonSize, );
2021-05-19 04:39:27 +02:00
}
},
watch: {
2021-11-18 00:58:29 -08:00
buttonInlineTextMode(checked) {
if (!checked) {
this.srvModel.payButtonText = '';
this.srvModel.payButtonImageUrl = this.originalButtonImageUrl;
} else {
this.srvModel.payButtonText = 'Pay with';
2022-08-18 13:49:22 +02:00
this.srvModel.payButtonImageUrl = `${this.srvModel.urlRoot}img/paybutton/logo.svg`;
2021-11-18 00:58:29 -08:00
}
this.inputChanges();
2021-05-19 04:39:27 +02:00
}
2023-07-06 10:12:31 +02:00
},
2021-05-19 04:39:27 +02:00
});
2023-07-06 10:12:31 +02:00
inputChanges(payButtonCtrl);
2021-05-19 04:39:27 +02:00
</script>
}
2021-12-31 08:36:38 +01:00
<partial name="_StatusMessage" />
<h2 class="mt-1 mb-4">@ViewData["Title"]</h2>
2021-04-08 15:32:42 +02:00
<div id="payButtonCtrl">
2018-08-22 14:05:12 +02:00
<div class="row">
2022-01-27 03:56:46 +01:00
<div class="col-xl-8">
<div class="alert alert-warning alert-dismissible mb-4" role="alert">
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close">
<vc:icon symbol="close" />
</button>
2022-06-15 04:32:46 +02:00
<h5 class="alert-heading">Warning: Payment button should only be used for tips and donations</h5>
<p>
Using the payment button for e-commerce integrations is not recommended since order relevant information can be modified by the user.
For e-commerce, you should use our
<a href="https://docs.btcpayserver.org/API/Greenfield/v1/" class="alert-link" target="_blank" rel="noreferrer noopener">Greenfield API</a>.
If this store process commercial transactions, we advise you to
<a asp-controller="UIUserStores" asp-action="CreateStore" class="alert-link">create a separate store</a> before using the payment button.
</p>
2022-01-27 03:56:46 +01:00
<form asp-action="DisableAnyoneCanCreateInvoice" asp-route-storeId="@Context.GetRouteValue("storeId")" method="post">
<button name="command" id="disable-pay-button" type="submit" class="btn btn-danger mt-0" value="Save">Disable payment button</button>
</form>
</div>
<p>Configure your Pay Button, and the generated code will be displayed at the bottom of the page to copy into your project.</p>
<h4 class="mt-3 mb-3">General Settings</h4>
<div class="form-group col-md-8">
<label class="form-label" for="price">Price</label>
2022-03-30 00:58:50 -07:00
<input name="price" type="text" class="form-control" id="price" inputmode="decimal"
2022-01-27 03:56:46 +01:00
v-model="srvModel.price" v-on:change="inputChanges"
v-validate="'decimal|min_value:0'" :class="{'is-invalid': errors.has('price') }">
<small class="text-danger">{{ errors.first('price') }}</small>
</div>
<div class="form-group col-md-4" v-if="!srvModel.appIdEndpoint">
2022-04-16 18:38:51 +02:00
<label class="form-label" for="Currency">Currency</label>
2022-09-26 03:26:13 +02:00
<input asp-for="Currency" name="currency" class="form-control w-auto" currency-selection
2022-04-16 18:38:51 +02:00
v-model="srvModel.currency" v-on:change="inputChanges"
:class="{'is-invalid': errors.has('currency') }" />
2018-08-10 20:26:51 +02:00
</div>
2022-04-11 01:48:12 -07:00
<div class="form-group col-md-4" v-if="!srvModel.appIdEndpoint">
<label class="form-label" for="defaultPaymentMethod">Default Payment Method</label>
<select v-model="srvModel.defaultPaymentMethod" v-on:change="inputChanges" class="form-select" id="default-payment-method">
<option value="" selected>Use the store’ s default</option>
<option v-for="pm in srvModel.paymentMethods" v-bind:value="pm.value">{{pm.name}}</option>
</select>
</div>
2021-06-06 13:44:54 +02:00
<div class="form-group" v-if="!srvModel.appIdEndpoint">
2021-11-18 00:58:29 -08:00
<label class="form-label" for="description">Checkout Description</label>
<input name="checkoutDesc" type="text" class="form-control" id="description"
2018-08-22 14:05:12 +02:00
v-model="srvModel.checkoutDesc" v-on:change="inputChanges">
2018-08-10 20:26:51 +02:00
</div>
2018-08-22 14:05:12 +02:00
<div class="form-group">
2021-11-18 00:58:29 -08:00
<label class="form-label" for="order-id">Order ID</label>
<input name="orderId" type="text" class="form-control" id="order-id"
2018-08-22 14:05:12 +02:00
v-model="srvModel.orderId" v-on:change="inputChanges">
</div>
2019-11-03 09:53:09 -08:00
</div>
</div>
2021-04-08 15:32:42 +02:00
2021-11-18 00:58:29 -08:00
<h4 class="mt-5 mb-3">Display Options</h4>
2019-11-03 09:53:09 -08:00
<div class="row">
2022-01-27 03:56:46 +01:00
<div class="col-xl-8 col-xxl-constrain">
2020-02-24 13:29:29 +01:00
<div class="form-group">
2021-06-06 13:44:54 +02:00
<div class="form-check" v-if="!srvModel.appIdEndpoint">
<input id="useModal" type="checkbox" v-model="srvModel.useModal" v-on:change="inputChanges" class="form-check-input"/>
<label for="useModal" class="form-check-label">Use Modal</label>
</div>
<div class="form-check">
<input id="buttonInlineTextMode" type="checkbox" v-model="buttonInlineTextMode" v-on:change="inputChanges" class="form-check-input"/>
2021-11-18 00:58:29 -08:00
<label for="buttonInlineTextMode" class="form-check-label">Customize Pay Button Text</label>
2021-06-06 13:44:54 +02:00
</div>
2020-02-24 13:29:29 +01:00
</div>
2021-06-06 13:44:54 +02:00
2020-02-24 13:29:29 +01:00
<div class="form-group" v-show="buttonInlineTextMode">
2021-11-18 00:58:29 -08:00
<label class="form-label" for="pb-text">Pay Button Text</label>
<input name="payButtonText" type="text" class="form-control" id="pb-text"
2020-02-24 13:29:29 +01:00
v-model="srvModel.payButtonText" v-on:change="inputChanges">
</div>
2021-11-18 00:58:29 -08:00
<div class="form-group mb-4">
<label class="form-label" for="pb-image-url">Pay Button Image Url</label>
<input name="payButtonImageUrl" type="text" class="form-control" id="pb-image-url"
2018-08-22 14:05:12 +02:00
v-model="srvModel.payButtonImageUrl" v-on:change="inputChanges"
2020-02-24 13:29:29 +01:00
v-validate="{ required: this.imageUrlRequired, url: {require_tld:false} }"
:class="{'is-invalid': errors.has('payButtonImageUrl') }">
2018-08-22 14:05:12 +02:00
<small class="text-danger">{{ errors.first('payButtonImageUrl') }}</small>
2018-08-11 13:34:52 +02:00
</div>
2021-11-18 00:58:29 -08:00
<div class="form-group mb-4">
2021-06-06 13:44:54 +02:00
<label class="form-label">Image Size</label>
2021-11-18 00:58:29 -08:00
<div class="btn-group d-flex" role="group">
<button type="button" class="btn btn-outline-secondary"
v-on:click="inputChanges($event, 0)">146 x 40 px</button>
<button type="button" class="btn btn-outline-secondary"
v-on:click="inputChanges($event, 1)">168 x 46 px</button>
<button type="button" class="btn btn-outline-secondary"
v-on:click="inputChanges($event, 2)">209 x 57 px</button>
2018-08-22 14:05:12 +02:00
</div>
2018-08-11 13:34:52 +02:00
</div>
2019-04-03 21:43:53 +02:00
<div class="form-group">
2021-06-06 13:44:54 +02:00
<label class="form-label">Button Type</label>
<div class="form-check">
<input class="form-check-input" type="radio" name="button-type" id="btn-fixed" value="0" v-model="srvModel.buttonType" v-on:change="inputChanges" checked/>
<label for="btn-fixed" class="form-check-label">Fixed amount</label>
2019-04-03 21:43:53 +02:00
</div>
2021-06-06 13:44:54 +02:00
<div class="form-check">
<input class="form-check-input" type="radio" name="button-type" id="btn-custom" value="1" v-model="srvModel.buttonType" v-on:change="inputChanges"/>
<label for="btn-custom" class="form-check-label">Custom amount</label>
2019-04-03 21:43:53 +02:00
</div>
2021-06-06 13:44:54 +02:00
<div class="form-check">
<input class="form-check-input" type="radio" name="button-type" id="btn-slider" value="2" v-model="srvModel.buttonType" v-on:change="inputChanges"/>
<label for="btn-slider" class="form-check-label">Slider</label>
2019-04-04 20:56:12 +02:00
</div>
2019-04-03 21:43:53 +02:00
</div>
2022-01-21 03:11:08 +01:00
<div class="row" v-if="srvModel.buttonType === '1' ||srvModel.buttonType === '2'">
2019-04-06 13:47:22 +02:00
<div class="form-group col-md-4">
2021-11-18 00:58:29 -08:00
<label class="form-label" for="pb-min">Min</label>
<input name="min" type="text" class="form-control" id="pb-min"
2019-04-06 13:47:22 +02:00
v-model="srvModel.min" v-on:change="inputChanges"
2021-05-05 11:27:02 +02:00
v-validate="'required|decimal|min_value:0'" :class="{'is-invalid': errors.has('min') }">
2019-04-06 13:47:22 +02:00
<small class="text-danger">{{ errors.first('min') }}</small>
</div>
<div class="form-group col-md-4">
2021-11-18 00:58:29 -08:00
<label class="form-label" for="pb-max">Max</label>
<input name="max" type="text" class="form-control" id="pb-max"
2019-04-06 13:47:22 +02:00
v-model="srvModel.max" v-on:change="inputChanges"
2021-05-05 11:27:02 +02:00
v-validate="'required|decimal'" :class="{'is-invalid': errors.has('max') }">
2019-04-06 13:47:22 +02:00
<small class="text-danger">{{ errors.first('max') }}</small>
</div>
<div class="form-group col-md-4">
2021-11-18 00:58:29 -08:00
<label class="form-label" for="pb-step">Step</label>
<input name="step" type="text" class="form-control" id="pb-step"
2019-04-06 13:47:22 +02:00
v-model="srvModel.step" v-on:change="inputChanges"
2021-05-05 11:27:02 +02:00
v-validate="'required'" :class="{'is-invalid': errors.has('step') }">
2019-04-06 13:47:22 +02:00
<small class="text-danger">{{ errors.first('step') }}</small>
</div>
</div>
2022-01-21 03:11:08 +01:00
<template v-if="srvModel.buttonType === '1'">
2019-11-03 09:53:09 -08:00
<div class="form-check">
<input name="simpleInput"
id="simpleInput"
type="checkbox"
class="form-check-input"
v-model="srvModel.simpleInput"
v-on:change="inputChanges"
2019-07-31 15:58:04 +02:00
:class="{'is-invalid': errors.has('simpleInput') }">
2019-11-03 09:53:09 -08:00
<label class="form-check-label" for="simpleInput">Use a simple input style</label>
2019-07-31 15:58:04 +02:00
<small class="text-danger">{{ errors.first('simpleInput') }}</small>
</div>
2019-11-03 09:53:09 -08:00
<div class="form-check">
2020-02-24 13:29:29 +01:00
<input name="fitButtonInline"
id="fitButtonInline"
type="checkbox"
class="form-check-input"
v-model="srvModel.fitButtonInline"
v-on:change="inputChanges"
:class="{'is-invalid': errors.has('fitButtonInline') }">
<label class="form-check-label" for="fitButtonInline">Fit button inline</label>
<small class="text-danger">{{ errors.first('fitButtonInline') }}</small>
2019-07-31 15:58:04 +02:00
</div>
2021-06-06 13:44:54 +02:00
</template>
2018-08-11 13:34:52 +02:00
</div>
2022-01-27 03:56:46 +01:00
<div class="col-xl-4 mt-4 mt-xl-0">
2021-04-08 15:32:42 +02:00
<h5 class="mb-3">Preview</h5>
2019-11-03 09:53:09 -08:00
<div id="preview"></div>
2018-08-22 14:05:12 +02:00
</div>
</div>
2021-04-08 15:32:42 +02:00
<h4 class="mt-5 mb-3">Payment Notifications</h4>
2018-08-22 14:05:12 +02:00
<div class="row">
2022-01-27 03:56:46 +01:00
<div class="col-xl-8 col-xxl-constrain">
2018-08-22 14:05:12 +02:00
<div class="form-group">
2021-11-18 00:58:29 -08:00
<label class="form-label" for="server-ipn">Server IPN</label>
<input name="serverIpn" type="text" class="form-control" id="server-ipn"
2018-08-22 14:05:12 +02:00
v-model="srvModel.serverIpn" v-on:change="inputChanges"
2018-08-23 11:12:25 +09:00
v-validate="'url'" :class="{'is-invalid': errors.has('serverIpn') }">
2018-08-22 14:05:12 +02:00
<small class="text-danger">{{ errors.first('serverIpn') }}</small>
2022-12-04 10:01:38 +01:00
<div class="form-text">The URL to post purchase data.</div>
2018-08-11 13:34:52 +02:00
</div>
2021-11-18 00:58:29 -08:00
<div class="form-group" v-if="!srvModel.appIdEndpoint">
<label class="form-label" for="email-notifications">Email Notifications</label>
<input name="notifyEmail" type="text" class="form-control" id="email-notifications"
placeholder="name@domain.com"
2018-08-22 14:05:12 +02:00
v-model="srvModel.notifyEmail" v-on:change="inputChanges"
v-validate="'email'" :class="{'is-invalid': errors.has('notifyEmail') }">
<small class="text-danger">{{ errors.first('notifyEmail') }}</small>
2022-12-04 10:01:38 +01:00
<div class="form-text">Receive email notification updates.</div>
2018-08-11 13:34:52 +02:00
</div>
2018-08-22 14:05:12 +02:00
<div class="form-group">
2021-11-18 00:58:29 -08:00
<label class="form-label" for="browser-redirect">Browser Redirect</label>
<input name="browserRedirect" type="text" class="form-control" id="browser-redirect"
2018-08-22 14:05:12 +02:00
v-model="srvModel.browserRedirect" v-on:change="inputChanges"
v-validate="'url'" :class="{'is-invalid': errors.has('browserRedirect') }">
<small class="text-danger">{{ errors.first('browserRedirect') }}</small>
2022-12-04 10:01:38 +01:00
<div class="form-text">Where to redirect the customer after payment is complete</div>
2018-08-16 21:55:24 +02:00
</div>
</div>
2018-08-22 14:05:12 +02:00
</div>
2019-10-29 20:59:28 +01:00
2021-11-18 00:58:29 -08:00
<h4 class="mt-5 mb-3">Advanced Options</h4>
2021-04-08 15:32:42 +02:00
<div class="row" v-if="!srvModel.appIdEndpoint">
2022-01-27 03:56:46 +01:00
<div class="col-xl-8 col-xxl-constrain">
2021-11-18 00:58:29 -08:00
<p>
Specify additional query string parameters that should be appended to the checkout page once the invoice is created.
For example, <code>lang=da-DK</code> would load the checkout page in Danish by default.
</p>
2021-04-08 15:32:42 +02:00
<div class="form-group">
2021-11-18 00:58:29 -08:00
<label class="form-label" for="query-string">Checkout Additional Query String</label>
<input name="checkoutQueryString" type="text" class="form-control" id="query-string"
2021-04-08 15:32:42 +02:00
v-model="srvModel.checkoutQueryString" v-on:change="inputChanges"
:class="{'is-invalid': errors.has('checkoutQueryString') }">
<small class="text-danger">{{ errors.first('checkoutQueryString') }}</small>
2020-03-15 10:51:57 +01:00
</div>
2021-04-08 15:32:42 +02:00
</div>
</div>
<div class="row">
2022-01-27 03:56:46 +01:00
<div class="col-xl-8 col-xxl-constrain">
2021-11-18 00:58:29 -08:00
<p>Link this Pay Button to an app instead. Some features are disabled due to the different endpoint capabilities. You can set which perk/item this button should be targeting.</p>
2021-04-08 15:32:42 +02:00
<div class="form-group">
2021-11-18 00:58:29 -08:00
<label class="form-label" for="app-as-endpoint">Use App As Endpoint</label>
<select v-model="srvModel.appIdEndpoint" v-on:change="inputChanges" class="form-select" id="app-as-endpoint">
2021-04-08 15:32:42 +02:00
<option value="">Use default pay button endpoint</option>
<option v-for="app in srvModel.apps" v-bind:value="app.id" >{{app.appName}} ({{app.appType}})</option>
</select>
<small class="text-danger">{{ errors.first('appIdEndpoint') }}</small>
</div>
<div class="form-group" v-if="srvModel.appIdEndpoint">
2021-11-18 00:58:29 -08:00
<label class="form-label" for="app-item">App Item/Perk</label>
<input name="appChoiceKey" type="text" class="form-control" id="app-item"
2021-04-08 15:32:42 +02:00
v-model="srvModel.appChoiceKey" v-on:change="inputChanges"
:class="{'is-invalid': errors.has('appChoiceKey') }">
<small class="text-danger">{{ errors.first('appChoiceKey') }}</small>
2019-06-25 21:01:37 +02:00
</div>
</div>
2021-04-08 15:32:42 +02:00
</div>
2021-11-18 00:58:29 -08:00
<h4 class="mt-5 mb-3">Generated Code</h4>
2018-08-22 14:05:12 +02:00
<div class="row" v-show="!errors.any()">
2022-01-27 03:56:46 +01:00
<div class="col-xxl-8">
2018-08-22 14:05:12 +02:00
<pre><code id="mainCode" class="html"></code></pre>
2023-03-19 21:43:38 +01:00
<button class="btn btn-outline-secondary" data-clipboard-target="#mainCode">
<vc:icon symbol="copy"/> Copy Code
2018-08-22 14:05:12 +02:00
</button>
</div>
</div>
<div class="row" v-show="errors.any()">
2022-01-27 03:56:46 +01:00
<div class="col-xl-8 col-xxl-constrain text-danger">
2018-08-22 14:05:12 +02:00
Please fix errors shown in order for code generation to successfully execute.
</div>
2018-08-10 20:26:51 +02:00
</div>
2023-07-06 10:12:31 +02:00
<div v-if="!srvModel.appIdEndpoint && (previewLink || lnurlLink)">
<h4 class="mt-4 mb-3">Alternatives</h4>
<p>You can also share the link/LNURL or encode it in a QR code.</p>
<div class="align-items-center" style="width:256px">
<ul class="nav my-3 btcpay-pills align-items-center gap-2">
<li class="nav-item" v-if="previewLink">
<a class="btcpay-pill" :class="{ active: alternativeMode === 'link' }" data-bs-toggle="tab" data-bs-target="#Alternative-Link" role="tab" href="#Alternative-Link">
Link
</a>
</li>
<li class="nav-item" v-if="previewLink">
<a class="btcpay-pill" :class="{ active: alternativeMode === 'lnurl' }" data-bs-toggle="tab" data-bs-target="#Alternative-LNURL" role="tab" href="#Alternative-LNURL">
LNURL
</a>
</li>
</ul>
<div class="tab-content">
<div class="tab-pane" :class="{ active: alternativeMode === 'link' }" id="Alternative-Link" role="tabpanel">
<a class="qr-container d-inline-block" :class="{ active: true }" :href="previewLink">
<qrcode :value="previewLink" :options="qrOptions" tag="img"></qrcode>
</a>
<div class="input-group mt-3">
<div class="form-floating">
<vc:truncate-center text="previewLink" is-vue="true" padding="15" elastic="true" classes="form-control-plaintext" />
<label>Link URL</label>
</div>
</div>
</div>
<div class="tab-pane" :class="{ active: alternativeMode === 'lnurl' }" id="Alternative-LNURL" role="tabpanel">
<a class="qr-container d-inline-block" :href="lnurlLink">
<qrcode :value="lnurlLink" :options="qrOptions" tag="img"></qrcode>
</a>
<div class="input-group mt-3">
<div class="form-floating">
<vc:truncate-center text="lnurlLink" is-vue="true" padding="15" elastic="true" classes="form-control-plaintext" />
<label>LNURL</label>
</div>
</div>
</div>
</div>
</div>
</div>
2019-04-06 15:02:02 +02:00
</div>
2018-09-04 00:00:20 -05:00
2019-10-31 11:31:30 +01:00
<script id="template-paybutton-styles" type="text/template">
2021-12-04 21:12:15 +01:00
<style>
2019-10-31 11:31:30 +01:00
.btcpay-form {
display: inline-flex;
align-items: center;
justify-content: center;
}
.btcpay-form--inline {
flex-direction: row;
}
.btcpay-form--block {
flex-direction: column;
}
.btcpay-form--inline .submit {
margin-left: 15px;
}
.btcpay-form--block select {
margin-bottom: 10px;
}
2020-03-15 10:51:57 +01:00
.btcpay-form .btcpay-custom-container{
text-align: center;
}
.btcpay-custom {
2019-10-31 11:31:30 +01:00
display: flex;
align-items: center;
justify-content: center;
}
.btcpay-form .plus-minus {
cursor:pointer;
font-size:25px;
line-height: 25px;
2019-11-15 11:08:10 +01:00
background: #DFE0E1;
2019-10-31 11:31:30 +01:00
height: 30px;
width: 45px;
border:none;
border-radius: 60px;
2019-11-15 11:08:10 +01:00
margin: auto 5px;
display: inline-flex;
justify-content: center;
2019-10-31 11:31:30 +01:00
}
.btcpay-form select {
-moz-appearance: none;
-webkit-appearance: none;
appearance: none;
2019-11-15 11:08:10 +01:00
color: currentColor;
2019-10-31 11:31:30 +01:00
background: transparent;
border:1px solid transparent;
display: block;
padding: 1px;
margin-left: auto;
margin-right: auto;
font-size: 11px;
cursor: pointer;
}
.btcpay-form select:hover {
border-color: #ccc;
}
2022-01-24 20:05:22 +09:00
.btcpay-form option {
color: #000;
background: rgba(0,0,0,.1);
}
.btcpay-input-price {
2022-01-21 03:11:08 +01:00
-moz-appearance: textfield;
2019-10-31 11:31:30 +01:00
border: none;
box-shadow: none;
text-align: center;
font-size: 25px;
margin: auto;
border-radius: 5px;
line-height: 35px;
background: #fff;
}
2022-01-21 03:11:08 +01:00
2022-01-24 20:05:22 +09:00
.btcpay-input-price::-webkit-outer-spin-button,
.btcpay-input-price::-webkit-inner-spin-button {
2020-11-16 23:18:50 -08:00
-webkit-appearance: none;
margin: 0;
}
2019-10-31 11:31:30 +01:00
</style>
</script>
<script id="template-slider-styles" type="text/template">
2021-12-04 21:12:15 +01:00
<style>
2019-10-31 11:31:30 +01:00
input[type=range].btcpay-input-range {
-webkit-appearance:none;
width:100%;
2019-11-15 11:08:10 +01:00
background: transparent;
2019-10-31 11:31:30 +01:00
}
input[type=range].btcpay-input-range:focus {
outline:0;
}
input[type=range].btcpay-input-range::-webkit-slider-runnable-track {
width:100%;
height:3.1px;
cursor:pointer;
box-shadow:0 0 1.7px #020,0 0 0 #003c00;
background:#f3f3f3;
border-radius:1px;
2019-11-15 11:08:10 +01:00
border:0;
2019-10-31 11:31:30 +01:00
}
input[type=range].btcpay-input-range::-webkit-slider-thumb {
2019-11-15 11:08:10 +01:00
box-shadow:none;
2019-10-31 11:31:30 +01:00
border:2.5px solid #cedc21;
height:22px;
width:22px;
border-radius:50%;
background:#0f3723;
cursor:pointer;
-webkit-appearance:none;
margin-top:-9.45px
}
input[type=range].btcpay-input-range:focus::-webkit-slider-runnable-track {
background:#fff;
}
input[type=range].btcpay-input-range::-moz-range-track {
width:100%;
height:3.1px;
cursor:pointer;
box-shadow:0 0 1.7px #020,0 0 0 #003c00;
background:#f3f3f3;
border-radius:1px;
2019-11-15 11:08:10 +01:00
border:0;
2019-10-31 11:31:30 +01:00
}
input[type=range].btcpay-input-range::-moz-range-thumb {
2019-11-15 11:08:10 +01:00
box-shadow:none;
2019-10-31 11:31:30 +01:00
border:2.5px solid #cedc21;
height:22px;
width:22px;
border-radius:50%;
background:#0f3723;
cursor:pointer;
}
input[type=range].btcpay-input-range::-ms-track {
width:100%;
height:3.1px;
cursor:pointer;
background:0 0;
border-color:transparent;
color:transparent;
}
input[type=range].btcpay-input-range::-ms-fill-lower {
background:#e6e6e6;
2019-11-15 11:08:10 +01:00
border:0;
2019-10-31 11:31:30 +01:00
border-radius:2px;
box-shadow:0 0 1.7px #020,0 0 0 #003c00;
}
input[type=range].btcpay-input-range::-ms-fill-upper {
background:#f3f3f3;
2019-11-15 11:08:10 +01:00
border:0;
2019-10-31 11:31:30 +01:00
border-radius:2px;
box-shadow:0 0 1.7px #020,0 0 0 #003c00;
}
input[type=range].btcpay-input-range::-ms-thumb {
2019-11-15 11:08:10 +01:00
box-shadow:none;
2019-10-31 11:31:30 +01:00
border:2.5px solid #cedc21;
height:22px;
width:22px;
border-radius:50%;
background:#0f3723;
cursor:pointer;
height:3.1px;
}
input[type=range].btcpay-input-range:focus::-ms-fill-lower {
background:#f3f3f3;
}
input[type=range].btcpay-input-range:focus::-ms-fill-upper {
background:#fff;
}
</style>
2019-04-06 15:02:02 +02:00
</script>