mirror of
https://github.com/btcpayserver/btcpayserver.git
synced 2025-02-23 14:40:36 +01:00
Cache static assets for one year and set the correct cache control header. Adds the cache busting version based on file content to asset references to invalidate the cache on change. ([further details on the approach](https://andrewlock.net/adding-cache-control-headers-to-static-files-in-asp-net-core/) and [why one year](https://ashton.codes/set-cache-control-max-age-1-year/)) Most of the changes are the additions of the `asp-append-version="true"` attribute, the main configuration change is in `Startup.cs`.
247 lines
12 KiB
Text
247 lines
12 KiB
Text
@model PaymentModel
|
|
|
|
<div class="top-header">
|
|
<div class="header">
|
|
@if (!string.IsNullOrEmpty(Model.CustomLogoLink))
|
|
{
|
|
<div class="header__icon">
|
|
<img class="header__icon__img" src="@Model.CustomLogoLink" height="40" asp-append-version="true">
|
|
</div>
|
|
}
|
|
else
|
|
{
|
|
<div class="header__iconcentered">
|
|
<img class="header__iconcentered__img">
|
|
</div>
|
|
}
|
|
<div class="close-icon close-action" v-on:click="close">
|
|
✖
|
|
</div>
|
|
</div>
|
|
<div class="timer-row" v-bind:class="{ 'expiring-soon': expiringSoon }">
|
|
<div class="timer-row__progress-bar" v-bind:style="{ 'width': expirationPercentage+ '%' }"></div>
|
|
<div class="timer-row__spinner" v-if="!invoiceUnpayable && !invoicePaid">
|
|
<partial name="Checkout-Spinner" />
|
|
</div>
|
|
<div class="timer-row__message">
|
|
<span v-if="invoiceUnpayable">
|
|
{{$t("Invoice expired")}}
|
|
</span>
|
|
<span v-else-if="expiringSoon">
|
|
{{$t("Invoice expiring soon...")}}
|
|
</span>
|
|
<span v-else>
|
|
{{$t("Awaiting Payment...")}}
|
|
</span>
|
|
</div>
|
|
<div class="timer-row__time-left">{{timerText}}</div>
|
|
</div>
|
|
</div>
|
|
<div class="order-details">
|
|
<div class="currency-selection">
|
|
<div class="single-item-order__left">
|
|
<div style="font-weight: 600;" id="pay-with-text">
|
|
{{$t("Pay with")}}
|
|
</div>
|
|
</div>
|
|
<div class="single-item-order__right">
|
|
@if (Model.AvailableCryptos.Count > 1)
|
|
{
|
|
<div class="paywithRowRight cursorPointer" v-on:click="openPaymentMethodDialog">
|
|
<span class="payment__currencies " v-show="!changingCurrencies">
|
|
<img v-bind:src="srvModel.cryptoImage" />
|
|
<span>{{srvModel.paymentMethodName}} ({{srvModel.cryptoCodeSrv}})</span>
|
|
<span v-show="srvModel.isLightning">⚡</span>
|
|
<span class="clickable_indicator fa fa-angle-right"></span>
|
|
</span>
|
|
</div>
|
|
<div id="vexPopupDialog">
|
|
<ul class="vexmenu">
|
|
@foreach (var crypto in Model.AvailableCryptos)
|
|
{
|
|
<li class="vexmenuitem">
|
|
<a href="@crypto.Link" onclick="closePaymentMethodDialog('@crypto.PaymentMethodId');return false;">
|
|
<img alt="@crypto.PaymentMethodName" src="@crypto.CryptoImage" asp-append-version="true" />
|
|
@crypto.PaymentMethodName
|
|
@(crypto.IsLightning ? Html.Raw("⚡") : null)
|
|
<span>@crypto.CryptoCode</span>
|
|
</a>
|
|
</li>
|
|
}
|
|
</ul>
|
|
</div>
|
|
}
|
|
else
|
|
{
|
|
<div class="payment__currencies_noborder">
|
|
<img v-bind:src="srvModel.cryptoImage" />
|
|
<span>{{srvModel.paymentMethodName}} ({{srvModel.cryptoCodeSrv}})</span>
|
|
<span v-show="srvModel.isLightning">⚡</span>
|
|
</div>
|
|
}
|
|
<div class="payment__spinner" v-show="changingCurrencies || loading">
|
|
<partial name="Checkout-Spinner" />
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="single-item-order buyerTotalLine" v-on:click="toggleLineItems" v-bind:class="{ 'expanded': lineItemsExpanded}">
|
|
<div class="single-item-order__left">
|
|
<div class="single-item-order__left__name">
|
|
{{ srvModel.storeName }}
|
|
</div>
|
|
<div class="single-item-order__left__description">
|
|
{{ srvModel.itemDesc }}
|
|
</div>
|
|
</div>
|
|
<div class="single-item-order__right">
|
|
<div class="single-item-order__right__btc-price" v-if="srvModel.status === 'paid'">
|
|
<span>{{ srvModel.btcPaid }} {{ srvModel.cryptoCode }}</span>
|
|
</div>
|
|
<div class="single-item-order__right__btc-price" v-else>
|
|
<span>{{ srvModel.btcDue }} {{ srvModel.cryptoCode }}</span>
|
|
</div>
|
|
<div class="single-item-order__right__ex-rate" v-if="srvModel.orderAmountFiat && srvModel.cryptoCode">
|
|
<span v-if="srvModel.cryptoCodeSrv === 'Sats'">1 Sat = {{ srvModel.rate }}</span>
|
|
<span v-else>1 {{ srvModel.cryptoCodeSrv }} = {{ srvModel.rate }}</span>
|
|
</div>
|
|
</div>
|
|
<span class="fa fa-angle-double-down"></span>
|
|
<span class="fa fa-angle-double-up"></span>
|
|
</div>
|
|
<line-items>
|
|
<div class="extraPayment" v-if="srvModel.status === 'new' && srvModel.txCount > 1">
|
|
{{$t("NotPaid_ExtraTransaction")}}
|
|
</div>
|
|
<div class="line-items" v-bind:class="{ 'expanded': lineItemsExpanded}">
|
|
<div class="line-items__item">
|
|
<div class="line-items__item__label">{{$t("Order Amount")}}</div>
|
|
<div class="line-items__item__value">{{srvModel.orderAmount}} {{ srvModel.cryptoCode }}</div>
|
|
</div>
|
|
<div class="line-items__item line-items_fiatvalue" v-if="srvModel.orderAmountFiat">
|
|
<div class="line-items__item__label"> </div>
|
|
<div class="line-items__item__value single-item-order__right__ex-rate">
|
|
{{srvModel.orderAmountFiat}}
|
|
</div>
|
|
</div>
|
|
<div class="line-items__item" v-show="srvModel.networkFee > 0">
|
|
<div class="line-items__item__label">
|
|
<span>{{$t("Network Cost")}}</span>
|
|
</div>
|
|
<div class="line-items__item__value">
|
|
<span v-if="srvModel.isMultiCurrency">
|
|
{{ srvModel.networkFee }} {{ srvModel.cryptoCode }}
|
|
</span>
|
|
<span v-else>
|
|
{{$t("txCount", {count: srvModel.txCount})}} x {{ srvModel.networkFee }} {{ srvModel.cryptoCode }}
|
|
</span>
|
|
</div>
|
|
</div>
|
|
<div class="line-items__item">
|
|
<div class="line-items__item__label">
|
|
<span>{{$t("Already Paid")}}</span>
|
|
</div>
|
|
<div class="line-items__item__value">-{{srvModel.btcPaid }} {{ srvModel.cryptoCode }}</div>
|
|
</div>
|
|
<div class="line-items__item line-items__item--total">
|
|
<div class="line-items__item__label">{{$t("Due")}}</div>
|
|
<div class="line-items__item__value">{{srvModel.btcDue}} {{ srvModel.cryptoCode }}</div>
|
|
</div>
|
|
</div>
|
|
</line-items>
|
|
<component v-if="srvModel.uiSettings && srvModel.uiSettings.checkoutHeaderVueComponentName"
|
|
v-bind:srv-model="srvModel"
|
|
v-bind:is="srvModel.uiSettings.checkoutHeaderVueComponentName">
|
|
</component>
|
|
</div>
|
|
|
|
<div class="payment-box" v-bind:class="{ 'with-recommended-fee': showRecommendedFee && !showEmailForm }">
|
|
<div class="bp-view enter-contact-email" id="emailAddressView" v-bind:class="{ 'active': showEmailForm}">
|
|
<form class="manual__step-one refund-address-form contact-email-form" id="emailAddressForm" name="emailAddressForm" novalidate="" v-on:submit.prevent="onEmailSubmit">
|
|
<div class="manual__step-one__header">
|
|
<span>{{$t("Contact and Refund Email")}}</span>
|
|
</div>
|
|
<div class="manual__step-one__instructions">
|
|
<span class="initial-label" v-show="!emailAddressInputInvalid">
|
|
<span>{{$t("Contact_Body")}}</span>
|
|
</span>
|
|
<span class="submission-error-label" v-show="emailAddressInputInvalid">{{$t("Please enter a valid email address")}}</span>
|
|
</div>
|
|
<div class="input-wrapper">
|
|
<input class="bp-input email-input "
|
|
v-bind:class="{ 'ng-pristine ng-submitted ng-touched': !emailAddressInputDirty, 'ng-invalid form-input-invalid': emailAddressInputInvalid }" id="emailAddressFormInput"
|
|
v-bind:placeholder="$t('Your email')" type="email" v-model="emailAddressInput"
|
|
v-on:change="onEmailChange">
|
|
<bp-loading-button>
|
|
<button type="submit" class="action-button" style="margin-top: 15px;" v-bind:disabled="emailAddressFormSubmitting" v-bind:class="{ 'loading': emailAddressFormSubmitting }">
|
|
<span class="button-text">{{$t("Continue")}}</span>
|
|
<div class="loader-wrapper">
|
|
<partial name="Checkout-Spinner" />
|
|
</div>
|
|
</button>
|
|
</bp-loading-button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
<div v-if="showPaymentUI">
|
|
<component v-if="srvModel.uiSettings && srvModel.uiSettings.checkoutBodyVueComponentName"
|
|
v-bind:srv-model="srvModel"
|
|
v-bind:is="srvModel.uiSettings.checkoutBodyVueComponentName">
|
|
</component>
|
|
</div>
|
|
|
|
<div class="bp-view" id="paid" v-bind:class="{ 'active': invoicePaid && !showEmailForm}">
|
|
<div class="status-block">
|
|
<div class="success-block">
|
|
<div class="status-icon">
|
|
<div class="status-icon__wrapper">
|
|
<div class="inner-wrapper">
|
|
<div class="status-icon__wrapper__icon">
|
|
<img src="~/imlegacy/checkmark.svg" asp-append-version="true">
|
|
</div>
|
|
<div class="status-icon__wrapper__outline"></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="success-message">{{$t("This invoice has been paid")}}</div>
|
|
<a class="action-button" :href="srvModel.merchantRefLink" v-show="!isModal">
|
|
<span v-html="$t('Return to StoreName', srvModel)"></span>
|
|
</a>
|
|
<button class="action-button close-action" v-show="isModal" v-on:click="close">
|
|
<span v-html="$t('Close')"></span>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
<div class="button-wrapper refund-address-form-container" id="refund-overpayment-button">
|
|
</div>
|
|
</div>
|
|
|
|
<div class="bp-view expired" id="expired" v-bind:class="{ 'active': invoiceUnpayable}">
|
|
<div>
|
|
<div class="expired__body" style="margin-bottom: 20px;">
|
|
<div class="expired__header">{{$t("What happened?")}}</div>
|
|
<div class="expired__text" v-html="$t('InvoiceExpired_Body_1', {storeName: srvModel.storeName, maxTimeMinutes: @Model.MaxTimeMinutes})">
|
|
</div>
|
|
<div class="expired__text">
|
|
{{$t("InvoiceExpired_Body_2")}}
|
|
</div>
|
|
<div class="expired__text">
|
|
{{$t("InvoiceExpired_Body_3")}}
|
|
</div>
|
|
<div class="expired__text expired__text__smaller">
|
|
<span class="expired__text__bullet">{{$t("Invoice ID")}}</span>:
|
|
{{srvModel.invoiceId}}
|
|
<br />
|
|
<span class="expired__text__bullet">{{$t("Order ID")}}</span>:
|
|
{{srvModel.orderId}}
|
|
</div>
|
|
</div>
|
|
<a class="action-button" :href="srvModel.merchantRefLink" v-show="!isModal">
|
|
<span v-html="$t('Return to StoreName', srvModel)"></span>
|
|
</a>
|
|
<button class="action-button close-action" v-show="isModal" v-on:click="close">
|
|
<span v-html="$t('Close')"></span>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|