Checkout v2 fixes (#4705)

* Prevent duplicate titles on invoice view

* Fix text display of escaped values

Fixes #4696.

* Fix payment details re-rendering

Closes #4683. Closes #4684.

* Cleanup
This commit is contained in:
d11n 2023-02-25 14:28:02 +01:00 committed by GitHub
parent ff58301729
commit 4ef19e19cc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 52 additions and 46 deletions

View File

@ -38,7 +38,7 @@
<partial name="LayoutHeadStoreBranding" model="@(Model.BrandColor, Model.CssFileId, "", "")" /> <partial name="LayoutHeadStoreBranding" model="@(Model.BrandColor, Model.CssFileId, "", "")" />
</head> </head>
<body class="min-vh-100"> <body class="min-vh-100">
<div id="Checkout-v2" class="public-page-wrap" v-cloak v-waitForT> <div id="Checkout-v2" class="public-page-wrap" v-cloak>
<partial name="_StoreHeader" model="(Model.StoreName, Model.LogoFileId)" /> <partial name="_StoreHeader" model="(Model.StoreName, Model.LogoFileId)" />
<main class="shadow-lg"> <main class="shadow-lg">
<nav v-if="isModal"> <nav v-if="isModal">
@ -47,14 +47,17 @@
</button> </button>
</nav> </nav>
<section id="payment" v-if="isActive"> <section id="payment" v-if="isActive">
<h5 class="text-center mt-1 mb-3 fw-semibold" v-if="srvModel.itemDesc" v-text="srvModel.itemDesc">@Model.ItemDesc</h5> @if (!string.IsNullOrEmpty(Model.ItemDesc) && Model.ItemDesc != Model.StoreName)
{
<h5 class="text-center mt-1 mb-3 fw-semibold" v-if="srvModel.itemDesc" v-text="srvModel.itemDesc">@Model.ItemDesc</h5>
}
@if (Model.IsUnsetTopUp) @if (Model.IsUnsetTopUp)
{ {
<h2 id="AmountDue" class="text-center" v-t="'any_amount'"></h2> <h2 id="AmountDue" class="mt-1 text-center" v-t="'any_amount'"></h2>
} }
else else
{ {
<h2 id="AmountDue" class="text-center" v-text="`${srvModel.btcDue} ${srvModel.cryptoCode}`" :data-clipboard="srvModel.btcDue" :data-clipboard-confirm="$t('copy_confirm')" :data-amount-due="srvModel.btcDue">@Model.BtcDue @Model.CryptoCode</h2> <h2 id="AmountDue" class="mt-1 text-center" v-text="`${srvModel.btcDue} ${srvModel.cryptoCode}`" :data-clipboard="srvModel.btcDue" :data-clipboard-confirm="$t('copy_confirm')" :data-amount-due="srvModel.btcDue">@Model.BtcDue @Model.CryptoCode</h2>
} }
<div id="PaymentInfo" class="info mt-3 mb-2" v-collapsible="showInfo"> <div id="PaymentInfo" class="info mt-3 mb-2" v-collapsible="showInfo">
<div> <div>
@ -117,7 +120,7 @@
</div> </div>
<div class="buttons"> <div class="buttons">
<a v-if="srvModel.receiptLink" class="btn btn-primary rounded-pill w-100" :href="srvModel.receiptLink" :target="isModal ? '_top' : null" v-t="'view_receipt'" id="ReceiptLink"></a> <a v-if="srvModel.receiptLink" class="btn btn-primary rounded-pill w-100" :href="srvModel.receiptLink" :target="isModal ? '_top' : null" v-t="'view_receipt'" id="ReceiptLink"></a>
<a v-if="storeLink" class="btn btn-secondary rounded-pill w-100" :href="storeLink" :target="isModal ? '_top' : null" v-t="{ path: 'return_to_store', args: { storeName: srvModel.storeName }}" id="StoreLink"></a> <a v-if="storeLink" class="btn btn-secondary rounded-pill w-100" :href="storeLink" :target="isModal ? '_top' : null" v-html="$t('return_to_store', { storeName: srvModel.storeName })" id="StoreLink"></a>
<button v-else-if="isModal" class="btn btn-secondary rounded-pill w-100" v-on:click="close" v-t="'Close'"></button> <button v-else-if="isModal" class="btn btn-secondary rounded-pill w-100" v-on:click="close" v-t="'Close'"></button>
</div> </div>
</div> </div>
@ -147,7 +150,7 @@
<p class="text-center mt-3" v-html="replaceNewlines($t('invoice_expired_body', { storeName: srvModel.storeName, minutes: @Model.MaxTimeMinutes }))"></p> <p class="text-center mt-3" v-html="replaceNewlines($t('invoice_expired_body', { storeName: srvModel.storeName, minutes: @Model.MaxTimeMinutes }))"></p>
</div> </div>
<div class="buttons"> <div class="buttons">
<a v-if="storeLink" class="btn btn-primary rounded-pill w-100" :href="storeLink" :target="isModal ? '_top' : null" v-t="{ path: 'return_to_store', args: { storeName: srvModel.storeName }}" id="StoreLink"></a> <a v-if="storeLink" class="btn btn-primary rounded-pill w-100" :href="storeLink" :target="isModal ? '_top' : null" v-html="$t('return_to_store', { storeName: srvModel.storeName })" id="StoreLink"></a>
<button v-else-if="isModal" class="btn btn-primary rounded-pill w-100" v-on:click="close" v-t="'Close'"></button> <button v-else-if="isModal" class="btn btn-primary rounded-pill w-100" v-on:click="close" v-t="'Close'"></button>
</div> </div>
</div> </div>
@ -176,42 +179,44 @@
</p> </p>
</div> </div>
</noscript> </noscript>
<dl id="payment-details" v-cloak> <script type="text/x-template" id="payment-details">
<div v-if="orderAmount > 0"> <dl>
<dt v-t="'total_price'"></dt> <div v-if="orderAmount > 0">
<dd :data-clipboard="srvModel.orderAmount" :data-clipboard-confirm="$t('copy_confirm')">{{srvModel.orderAmount}} {{ srvModel.cryptoCode }}</dd> <dt v-t="'total_price'"></dt>
</div> <dd :data-clipboard="srvModel.orderAmount" :data-clipboard-confirm="$t('copy_confirm')">{{srvModel.orderAmount}} {{ srvModel.cryptoCode }}</dd>
<div v-if="orderAmount > 0 && srvModel.orderAmountFiat"> </div>
<dt v-t="'total_fiat'"></dt> <div v-if="orderAmount > 0 && srvModel.orderAmountFiat">
<dd :data-clipboard="srvModel.orderAmountFiat" :data-clipboard-confirm="$t('copy_confirm')">{{srvModel.orderAmountFiat}}</dd> <dt v-t="'total_fiat'"></dt>
</div> <dd :data-clipboard="srvModel.orderAmountFiat" :data-clipboard-confirm="$t('copy_confirm')">{{srvModel.orderAmountFiat}}</dd>
<div v-if="srvModel.rate && srvModel.cryptoCode"> </div>
<dt v-t="'exchange_rate'"></dt> <div v-if="srvModel.rate && srvModel.cryptoCode">
<dd :data-clipboard="srvModel.rate" :data-clipboard-confirm="$t('copy_confirm')"> <dt v-t="'exchange_rate'"></dt>
<template v-if="srvModel.cryptoCodeSrv === 'Sats'">1 Sat = {{ srvModel.rate }}</template> <dd :data-clipboard="srvModel.rate" :data-clipboard-confirm="$t('copy_confirm')">
<template v-else>1 {{ srvModel.cryptoCodeSrv }} = {{ srvModel.rate }}</template> <template v-if="srvModel.cryptoCodeSrv === 'Sats'">1 Sat = {{ srvModel.rate }}</template>
</dd> <template v-else>1 {{ srvModel.cryptoCodeSrv }} = {{ srvModel.rate }}</template>
</div> </dd>
<div v-if="srvModel.networkFee"> </div>
<dt v-t="'network_cost'"></dt> <div v-if="srvModel.networkFee">
<dd :data-clipboard="srvModel.networkFee" :data-clipboard-confirm="$t('copy_confirm')"> <dt v-t="'network_cost'"></dt>
<div v-if="srvModel.txCountForFee > 0" v-t="{ path: 'tx_count', args: { count: srvModel.txCount } }"></div> <dd :data-clipboard="srvModel.networkFee" :data-clipboard-confirm="$t('copy_confirm')">
<div v-text="`${srvModel.networkFee} ${srvModel.cryptoCode}`"></div> <div v-if="srvModel.txCountForFee > 0" v-t="{ path: 'tx_count', args: { count: srvModel.txCount } }"></div>
</dd> <div v-text="`${srvModel.networkFee} ${srvModel.cryptoCode}`"></div>
</div> </dd>
<div v-if="btcPaid > 0"> </div>
<dt v-t="'amount_paid'"></dt> <div v-if="btcPaid > 0">
<dd :data-clipboard="srvModel.btcPaid" :data-clipboard-confirm="$t('copy_confirm')" v-text="`${srvModel.btcPaid} ${srvModel.cryptoCode}`"></dd> <dt v-t="'amount_paid'"></dt>
</div> <dd :data-clipboard="srvModel.btcPaid" :data-clipboard-confirm="$t('copy_confirm')" v-text="`${srvModel.btcPaid} ${srvModel.cryptoCode}`"></dd>
<div v-if="btcDue > 0"> </div>
<dt v-t="'amount_due'"></dt> <div v-if="btcDue > 0">
<dd :data-clipboard="srvModel.btcDue" :data-clipboard-confirm="$t('copy_confirm')" v-text="`${srvModel.btcDue} ${srvModel.cryptoCode}`"></dd> <dt v-t="'amount_due'"></dt>
</div> <dd :data-clipboard="srvModel.btcDue" :data-clipboard-confirm="$t('copy_confirm')" v-text="`${srvModel.btcDue} ${srvModel.cryptoCode}`"></dd>
<div v-if="showRecommendedFee"> </div>
<dt v-t="'recommended_fee'"></dt> <div v-if="showRecommendedFee">
<dd :data-clipboard="srvModel.feeRate" :data-clipboard-confirm="$t('copy_confirm')" v-t="{ path: 'fee_rate', args: { feeRate: srvModel.feeRate } }"></dd> <dt v-t="'recommended_fee'"></dt>
</div> <dd :data-clipboard="srvModel.feeRate" :data-clipboard-confirm="$t('copy_confirm')" v-t="{ path: 'fee_rate', args: { feeRate: srvModel.feeRate } }"></dd>
</dl> </div>
</dl>
</script>
<script> <script>
const i18nUrl = @Safe.Json($"{Model.RootPath}locales/checkout/{{{{lng}}}}.json?v={Env.Version}"); const i18nUrl = @Safe.Json($"{Model.RootPath}locales/checkout/{{{{lng}}}}.json?v={Env.Version}");
const statusUrl = @Safe.Json(Url.Action("GetStatus", new { invoiceId = Model.InvoiceId })); const statusUrl = @Safe.Json(Url.Action("GetStatus", new { invoiceId = Model.InvoiceId }));

View File

@ -78,6 +78,7 @@ section dl > div dd {
text-align: right; text-align: right;
word-wrap: break-word; word-wrap: break-word;
word-break: break-word; word-break: break-word;
max-width: 62.5%;
} }
.info { .info {
color: var(--btcpay-neutral-700); color: var(--btcpay-neutral-700);

View File

@ -55,8 +55,8 @@ Vue.use(VueI18next);
const i18n = new VueI18next(i18next); const i18n = new VueI18next(i18next);
const eventBus = new Vue(); const eventBus = new Vue();
const PaymentDetails = Vue.component('payment-details', { const PaymentDetails = {
el: '#payment-details', template: '#payment-details',
props: { props: {
srvModel: Object, srvModel: Object,
isActive: Boolean isActive: Boolean
@ -75,14 +75,14 @@ const PaymentDetails = Vue.component('payment-details', {
return this.isActive && this.srvModel.showRecommendedFee && this.srvModel.feeRate; return this.isActive && this.srvModel.showRecommendedFee && this.srvModel.feeRate;
}, },
} }
}); }
function initApp() { function initApp() {
return new Vue({ return new Vue({
i18n, i18n,
el: '#Checkout-v2', el: '#Checkout-v2',
components: { components: {
PaymentDetails 'payment-details': PaymentDetails,
}, },
data () { data () {
const srvModel = initialSrvModel; const srvModel = initialSrvModel;