mirror of
https://github.com/aljazceru/btcpayserver.git
synced 2026-02-08 15:54:20 +01:00
Merge branch 'lepipele-dev-i18n'
This commit is contained in:
@@ -8,12 +8,16 @@
|
||||
<ItemGroup>
|
||||
<Compile Remove="Build\dockerfiles\**" />
|
||||
<Compile Remove="wwwroot\bundles\jqueryvalidate\**" />
|
||||
<Compile Remove="wwwroot\vendor\jquery-nice-select\**" />
|
||||
<Content Remove="Build\dockerfiles\**" />
|
||||
<Content Remove="wwwroot\bundles\jqueryvalidate\**" />
|
||||
<Content Remove="wwwroot\vendor\jquery-nice-select\**" />
|
||||
<EmbeddedResource Remove="Build\dockerfiles\**" />
|
||||
<EmbeddedResource Remove="wwwroot\bundles\jqueryvalidate\**" />
|
||||
<EmbeddedResource Remove="wwwroot\vendor\jquery-nice-select\**" />
|
||||
<None Remove="Build\dockerfiles\**" />
|
||||
<None Remove="wwwroot\bundles\jqueryvalidate\**" />
|
||||
<None Remove="wwwroot\vendor\jquery-nice-select\**" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Remove="Currencies.txt" />
|
||||
@@ -56,7 +60,7 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Include="wwwroot\js\core.js" />
|
||||
<None Include="wwwroot\js\checkout\core.js" />
|
||||
<None Include="wwwroot\js\creative.js" />
|
||||
<None Include="wwwroot\js\creative.min.js" />
|
||||
<None Include="wwwroot\js\site.js" />
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
"launchBrowser": true,
|
||||
"environmentVariables": {
|
||||
"BTCPAY_NETWORK": "regtest",
|
||||
"BTCPAY_BUNDLEJSCSS": "false",
|
||||
"BTCPAY_LTCEXPLORERURL": "http://127.0.0.1:32838/",
|
||||
"BTCPAY_BTCEXPLORERURL": "http://127.0.0.1:32838/",
|
||||
"ASPNETCORE_ENVIRONMENT": "Development",
|
||||
|
||||
561
BTCPayServer/Views/Invoice/Checkout-Body.cshtml
Normal file
561
BTCPayServer/Views/Invoice/Checkout-Body.cshtml
Normal file
@@ -0,0 +1,561 @@
|
||||
@model PaymentModel
|
||||
|
||||
<div class="top-header">
|
||||
<div class="header">
|
||||
<div class="header__icon">
|
||||
<img class="header__icon__img" src="~/img/logo-white.png" height="40">
|
||||
</div>
|
||||
</div>
|
||||
<div class="timer-row">
|
||||
<div class="timer-row__progress-bar" style="width: 0%;"></div>
|
||||
<div class="timer-row__spinner">
|
||||
@Html.Partial("Checkout-Spinner")
|
||||
</div>
|
||||
<div class="timer-row__message">
|
||||
<span v-if="srvModel.status === 'expired' || srvModel.status === 'invalid'">
|
||||
{{$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">@Model.TimeLeft</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="order-details">
|
||||
@if (Model.AvailableCryptos.Count > 1)
|
||||
{
|
||||
<div class="currency-selection">
|
||||
<div class="single-item-order__left">
|
||||
<div style="font-weight: 600;">
|
||||
{{$t("Pay with")}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="single-item-order__right">
|
||||
<div class="payment__currencies">
|
||||
@foreach (var crypto in Model.AvailableCryptos)
|
||||
{
|
||||
<a href="@crypto.Link" onclick="return changeCurrency('@crypto.PaymentMethodId');">
|
||||
<img style="height:32px; margin-left:5px;" alt="@crypto.PaymentMethodId" src="@crypto.CryptoImage" />
|
||||
</a>
|
||||
}
|
||||
</div>
|
||||
<div class="payment__spinner">
|
||||
@Html.Partial("Checkout-Spinner")
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
<div class="single-item-order buyerTotalLine">
|
||||
<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" id="buyerTotalBtcAmount">
|
||||
<span>{{ srvModel.btcDue }} {{ srvModel.cryptoCode }}</span>
|
||||
</div>
|
||||
<div class="single-item-order__right__ex-rate">
|
||||
1 {{ srvModel.cryptoCode }} = {{ srvModel.rate }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<span class="fa fa-angle-double-down"></span>
|
||||
<span class="fa fa-angle-double-up"></span>
|
||||
</div>
|
||||
<line-items>
|
||||
<div class="line-items">
|
||||
<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">
|
||||
<div class="line-items__item__label">
|
||||
<span>{{$t("Network Cost")}}</span>
|
||||
</div>
|
||||
<div class="line-items__item__value" i18n="">{{srvModel.networkFeeDescription }}</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>
|
||||
<div class="payment-tabs">
|
||||
<div class="payment-tabs__tab active" id="scan-tab">
|
||||
<span>{{$t("Scan")}}</span>
|
||||
</div>
|
||||
<div class="payment-tabs__tab" id="copy-tab">
|
||||
<span>{{$t("Copy")}}</span>
|
||||
</div>
|
||||
@if (Model.AllowCoinConversion)
|
||||
{
|
||||
<div class="payment-tabs__tab" id="altcoins-tab">
|
||||
<span>{{$t("Conversion")}}</span>
|
||||
</div>
|
||||
<div id="tabsSlider" class="payment-tabs__slider three-tabs"></div>
|
||||
}
|
||||
else
|
||||
{
|
||||
<div id="tabsSlider" class="payment-tabs__slider"></div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div adjust-height="" class="payment-box">
|
||||
<div class="bp-view payment manual-flow enter-contact-email active" id="emailAddressView">
|
||||
<form class="manual__step-one refund-address-form contact-email-form" id="emailAddressForm" name="emailAddressForm" novalidate="">
|
||||
<div class="manual__step-one__header">
|
||||
<span>{{$t("Contact and Refund Email")}}</span>
|
||||
</div>
|
||||
<div class="manual__step-one__instructions">
|
||||
<span class="initial-label">
|
||||
<span>{{$t("Contact_Body")}}</span>
|
||||
</span>
|
||||
<span class="submission-error-label">{{$t("Please enter a valid email address")}}</span>
|
||||
</div>
|
||||
<div class="input-wrapper">
|
||||
<input class="bp-input email-input ng-pristine ng-invalid ng-touched" id="emailAddressFormInput" v-bind:placeholder="$t('Your email')" type="email">
|
||||
<bp-loading-button>
|
||||
<button type="submit" class="action-button" style="margin-top: 15px;">
|
||||
<span class="button-text">{{$t("Continue")}}</span>
|
||||
<div class="loader-wrapper">
|
||||
@Html.Partial("Checkout-Spinner")
|
||||
</div>
|
||||
</button>
|
||||
</bp-loading-button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="bp-view payment scan" id="scan">
|
||||
<div class="payment__scan">
|
||||
<img v-bind:src="srvModel.cryptoImage" style="position: absolute; height:64px; width:64px; left:118px; top:96px;" />
|
||||
<qrcode v-bind:val="srvModel.invoiceBitcoinUrlQR" v-bind:size="256" bg-color="#f5f5f7" fg-color="#000">
|
||||
</qrcode>
|
||||
</div>
|
||||
<div class="payment__details__instruction__open-wallet">
|
||||
<a class="payment__details__instruction__open-wallet__btn action-button" v-bind:href="srvModel.invoiceBitcoinUrl">
|
||||
<span>{{$t("Open in wallet")}}</span>
|
||||
<span class="glyphicon glyphicon-new-window"></span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="bp-view payment manual-flow" id="copy">
|
||||
<div class="manual__step-two__instructions">
|
||||
<span i18n="">{{$t("CompletePay_Body", srvModel)}}</span>
|
||||
</div>
|
||||
<div class="manual-box flipped" style="margin-bottom: 30px;">
|
||||
<div class="manual-box__amount">
|
||||
<div class="manual-box__amount__label label">{{$t("Amount")}}</div>
|
||||
|
||||
<div class="manual-box__amount__value copy-cursor" ngxclipboard="">
|
||||
<span>{{srvModel.btcDue}}</span> {{ srvModel.cryptoCode }}
|
||||
<div class="copied-label">
|
||||
<span>{{$t("Copied")}}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="manual-box__address">
|
||||
<div class="flipper flipped-initially">
|
||||
<div class="back"></div>
|
||||
<div class="front">
|
||||
<div class="manual-box__address__arrow"></div>
|
||||
<div class="manual-box__address__label label">{{$t("Address")}}</div>
|
||||
|
||||
<div class="manual-box__address__value copy-cursor" ngxclipboard="">
|
||||
<div class="manual-box__address__wrapper">
|
||||
<div class="manual-box__address__wrapper__logo">
|
||||
<img :src="srvModel.cryptoImage" height="16" />
|
||||
</div>
|
||||
<div class="manual-box__address__wrapper__value" style="overflow:hidden;max-width:240px;">{{srvModel.btcAddress}}</div>
|
||||
</div>
|
||||
<div class="copied-label" style="top: 5px;">
|
||||
<span>{{$t("Copied")}}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@if (Model.AllowCoinConversion)
|
||||
{
|
||||
<div id="altcoins" class="bp-view payment manual-flow">
|
||||
<div v-if="srvModel.paymentMethodId != 'BTC_LightningLike'">
|
||||
<div class="manual__step-two__instructions">
|
||||
<span>
|
||||
{{$t("ConversionTab_BodyTop", srvModel)}}
|
||||
<br /><br />
|
||||
{{$t("ConversionTab_BodyDesc", srvModel)}}
|
||||
</span>
|
||||
</div>
|
||||
<center>
|
||||
<script>function shapeshift_click(a, e) { e.preventDefault(); var link = a.href; var shapeshiftWindow = window.open(link, '1418115287605', 'width=700,height=500,toolbar=0,menubar=0,location=0,status=1,scrollbars=1,resizable=0,left=0,top=0'); shapeshiftWindow.focus(); return false; }</script>
|
||||
<a onclick="shapeshift_click(this, event);" v-bind:href="srvModel.shapeshiftUrl">
|
||||
<img src="https://shapeshift.io/images/shifty/xs_light_altcoins.png" class="ss-button">
|
||||
</a>
|
||||
|
||||
@*Changelly doesn't have TO_AMOUNT support so we can't include it
|
||||
<script type="text/javascript">function open_widget(a, e) { e.preventDefault(); var link = a.href; var changellyWindow = window.open(link, 'Changelly', 'width=600,height=470,toolbar=0,menubar=0,location=0,status=1,scrollbars=1,resizable=0,left=0,top=0'); changellyWindow.focus(); return false; }</script>
|
||||
<a onclick="open_widget(this, event);" href="https://changelly.com/widget/v1?auth=email&from=DASH&to=BTC&address=&amount=1&merchant_id=&ref_id=">
|
||||
<img src="https://changelly.com/pay_button_pay_with.png" alt="Changelly" />
|
||||
</a>*@
|
||||
</center>
|
||||
</div>
|
||||
<div v-else>
|
||||
<div class="manual__step-two__instructions">
|
||||
<span>
|
||||
{{$t("ConversionTab_Lightning")}}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
<div class="bp-view pad" id="paid">
|
||||
<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">
|
||||
</div>
|
||||
<div class="status-icon__wrapper__outline"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="success-message">{{$t("This invoice has been paid")}}</div>
|
||||
<button class="action-button">
|
||||
<bp-done-text>
|
||||
<span>{{$t("Return to StoreName", srvModel)}}</span>
|
||||
</bp-done-text>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="button-wrapper refund-address-form-container" id="refund-overpayment-button">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="bp-view expired" id="archived">
|
||||
<div class="expired-icon">
|
||||
<img src="~/imlegacy/archived.svg">
|
||||
</div>
|
||||
<div class="archived__message">
|
||||
<div class="archived__message__header">
|
||||
<span>{{$t("This invoice has been archived")}}</span>
|
||||
</div>
|
||||
<div>
|
||||
<span>{{$t("Archived_Body")}}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="bp-view expired" id="expired">
|
||||
<div>
|
||||
<div class="expired__body">
|
||||
<div class="expired__header">{{$t("What happened?")}}</div>
|
||||
<div class="expired__text" i18n="">
|
||||
{{$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">
|
||||
<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 href="/invoices" class="action-button" style="margin-top: 20px;">
|
||||
<bp-done-text>
|
||||
<span>{{$t("Return to StoreName", srvModel)}}</span>
|
||||
</bp-done-text>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@* Obsolete? Start *@
|
||||
<div class="bp-view" id="link-expired" style="padding-top: 3.6rem;">
|
||||
<div class="manual__step-one refund-address-form" novalidate="">
|
||||
<div class="manual__step-one__header" i18n="">Link Expired</div>
|
||||
<div class="manual__step-one__instructions">
|
||||
<span class="initial-label" i18n="">Sorry, this link has expired. Please try requesting another refund by clicking the button below.</span>
|
||||
</div>
|
||||
<div class="input-wrapper">
|
||||
<bp-loading-button i18n="">
|
||||
<button class="action-button" style="margin-top: 15px;" type="submit">
|
||||
<span class="button-text" lcl="">Request Refund</span>
|
||||
<div class="loader-wrapper">
|
||||
@Html.Partial("Checkout-Spinner")
|
||||
</div>
|
||||
</button>
|
||||
</bp-loading-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="bp-view confirm-contact-email-view">
|
||||
<form class="manual__step-one refund-address-form contact-email-form ng-untouched ng-pristine" novalidate="">
|
||||
<div class="manual__step-one__header" i18n="">Contact & Refund Email</div>
|
||||
<div class="manual__step-one__instructions">
|
||||
<span class="initial-label" i18n="">If there is an issue with this payment, or a refund needs to be made, we will contact you at this address.</span>
|
||||
</div>
|
||||
<div class="input-wrapper">
|
||||
<input bp-focus="focusEmailInput" class="bp-input email-input ng-untouched ng-pristine" disabled="disabled" name="receiptEmail" placeholder="Your email"
|
||||
style="opacity: 1;" type="email">
|
||||
<button type="submit" class="action-button" style="margin-top: 15px;">
|
||||
<span i18n="">Confirm email address</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="refund-address-form__link" id="wrong-email-button" style="color: #a9a9a9;">
|
||||
<span i18n="">Wrong email?</span>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="bp-view wrong-email-view" id="compromised-invoice">
|
||||
<div class="manual__step-one refund-address-form" novalidate="" style="margin-top: -1rem;">
|
||||
<div class="manual__step-one__header">
|
||||
<span i18n="">There seems to be a problem</span>
|
||||
</div>
|
||||
<div class="manual__step-one__instructions">
|
||||
<span class="initial-label" i18n="">
|
||||
This invoice was previously opened, and the address <strong class="placeholder-refundEmail">{Entered email address}</strong> was submitted as your contact email. If you entered this email, you can still safely make your payment. <br> <br>
|
||||
If you did not submit the email address, it's possible a thief falsely
|
||||
submitted this address to steal refunds. Please contact the merchant
|
||||
about this security incident, and try your payment again.
|
||||
</span>
|
||||
</div>
|
||||
<div class="input-wrapper">
|
||||
<a class="action-button" style="margin-top: 15px;" target="_blank" href="mailto:@Model.StoreEmail">
|
||||
<span i18n="">Contact {{srvModel.storeName}}</span>
|
||||
</a>
|
||||
</div>
|
||||
<div class="refund-address-form__link">
|
||||
<span i18n="">I understand, continue to payment →</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="bp-view confirm-bitcoin-address-view" id="confirm-refund-address">
|
||||
<form class="manual__step-one refund-address-form ng-untouched ng-pristine ng-valid" novalidate="" style="padding-top: 1.6rem;">
|
||||
<div><img src="~/imlegacy/mail.svg"></div>
|
||||
<div class="manual__step-one__header">
|
||||
<span i18n="">Please confirm your address</span>
|
||||
</div>
|
||||
<div class="manual__step-one__instructions">
|
||||
<span class="initial-label" i18n="">You should receive an email from us in a moment at <strong class="placeholder-refundEmail">{enterd refund email}</strong>. To ensure your refund is sent to the correct address, please confirm your bitcoin address by clicking the link in the email. </span>
|
||||
</div>
|
||||
<bp-resend-link id="resend-link">
|
||||
<div class="bp-resend__link">
|
||||
<span class="link-text">
|
||||
|
||||
<span i18n="">Resend email</span>
|
||||
|
||||
</span>
|
||||
<div class="success-text">
|
||||
|
||||
<img src="~/imlegacy/circle-check.svg">
|
||||
|
||||
<div i18n="">Email resent</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</bp-resend-link>
|
||||
</form>
|
||||
</div>
|
||||
<div class="bp-view refund-address-view" id="enter-refund-address">
|
||||
<form class="manual__step-one refund-address-form ng-untouched ng-pristine ng-invalid" name="refundAddressForm" novalidate="" style="margin-top: 28px; margin-bottom: 4rem;">
|
||||
<div class="manual__step-one__header">
|
||||
|
||||
<span i18n="">Please provide a refund address.</span>
|
||||
|
||||
</div>
|
||||
<div class="manual__step-one__instructions">
|
||||
<span class="initial-label">
|
||||
|
||||
<span i18n="">
|
||||
To send your refund of {BTC to refund} BTC,
|
||||
we’ll need a bitcoin address from your wallet. Please open your bitcoin
|
||||
wallet, copy a receiving address, and paste it below.
|
||||
</span>
|
||||
|
||||
</span>
|
||||
<span class="submission-error-label" i18n="" id="invalid-bitcoin-address">Please enter a valid bitcoin address.</span>
|
||||
</div>
|
||||
<div class="input-wrapper">
|
||||
<bp-refund-address name="refundAddress" ngmodel="" class="ng-untouched ng-pristine ng-invalid">
|
||||
<div class="bp-refund-address">
|
||||
<div class="bitcoin-logo">
|
||||
<div><img src="@Model.CryptoImage"></div>
|
||||
</div>
|
||||
<input class="bp-input {'not-empty': addressValue.length > 0} ng-untouched ng-pristine ng-valid" id="refund-address-input" name="refundAddress" ngclass="{'not-empty': addressValue.length > 0}">
|
||||
</div>
|
||||
</bp-refund-address>
|
||||
<bp-loading-button i18n="" id="request-refund-button">
|
||||
<button class="action-button" style="margin-top: 15px;" type="submit">
|
||||
<span class="button-text" lcl="">Request Refund</span>
|
||||
<div class="loader-wrapper">
|
||||
@Html.Partial("Checkout-Spinner")
|
||||
</div>
|
||||
</button>
|
||||
</bp-loading-button>
|
||||
</div>
|
||||
<div class="refund-address-form__cancel">
|
||||
<span i18n="">Cancel</span>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="bp-view" id="refund-pending">
|
||||
<div class="status-block">
|
||||
<div class="pending-block" style="position: relative; padding-bottom: 1.6rem;">
|
||||
<img src="~/imlegacy/refund-pending.svg">
|
||||
<div class="pending-block__header" i18n="">Processing Refund</div>
|
||||
<span>
|
||||
<span class="pending-block__message" i18n="">The amount below will be refunded to you within 1-2 business days. </span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="manual-box" style="margin-bottom: 30px;">
|
||||
<div class="manual-box__amount amount-only">
|
||||
<div class="manual-box__amount__label label">
|
||||
<span class="initial-label"> </span>
|
||||
<span class="final-label" i18n="">Amount To Be Refunded</span>
|
||||
</div>
|
||||
<div class="manual-box__amount__value">{BTC Amount} BTC</div>
|
||||
</div>
|
||||
<div class="manual-box__address">
|
||||
<div class="flipper">
|
||||
<div class="back"></div>
|
||||
<div class="front">
|
||||
<div class="manual-box__address__arrow"></div>
|
||||
<div class="manual-box__address__label label" i18n="">Will Be Refunded To</div>
|
||||
<div class="manual-box__address__wrapper">
|
||||
<div class="manual-box__address__wrapper__logo">
|
||||
<img src="~/imlegacy/bitcoin-symbol.svg">
|
||||
</div>
|
||||
<div class="manual-box__address__wrapper__value">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="bp-view expired" id="low-fee">
|
||||
<div class="expired__body">
|
||||
<div class="expired__header" i18n="" style="font-weight: 400; font-size: 22px;">Payment Confirming</div>
|
||||
<div class="expired__text" i18n="">This payment was made with a low <a href="https://bitcoin.org/en/glossary/transaction-fee">bitcoin miner fee</a>, which may prevent it from being accepted by the Bitcoin network.</div>
|
||||
<div class="expired__text" i18n="">This is an issue with the configuration of your bitcoin wallet.</div>
|
||||
<div class="expired__text" i18n="">
|
||||
If the transaction
|
||||
doesn't confirm, the funds will be spendable again in your wallet.
|
||||
Depending on the wallet, this may take 48-72 hours.
|
||||
</div>
|
||||
<low-fee-timeline>
|
||||
<div class="timeline">
|
||||
<div class="timeline__item">
|
||||
<div class="timeline__item__icon timeline__item__icon--complete">
|
||||
<img src="~/imlegacy/checkmark-small.svg">
|
||||
</div>
|
||||
<div class="timeline__item__name" i18n="">Transaction created</div>
|
||||
</div>
|
||||
<div class="timeline__item">
|
||||
<div class="timeline__item__icon timeline__item__icon--pending">
|
||||
<img src="~/imlegacy/pending.svg">
|
||||
</div>
|
||||
<div class="timeline__item__name">
|
||||
<span i18n="">Transaction confirming — funds have not yet moved</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="timeline__item">
|
||||
<div class="timeline__item__icon"></div>
|
||||
<div class="timeline__item__name" i18n="">Payment received by {{srvModel.storeName}}</div>
|
||||
</div>
|
||||
</div>
|
||||
</low-fee-timeline>
|
||||
</div>
|
||||
<button class="action-button" style="margin-top: .75rem;">
|
||||
<bp-done-text>
|
||||
<span i18n="">Return to {{srvModel.storeName}}</span>
|
||||
</bp-done-text>
|
||||
</button>
|
||||
</div>
|
||||
<div class="bp-view" id="refund-complete">
|
||||
<div class="status-block">
|
||||
<div class="success-block" style="opacity: 1;">
|
||||
<div class="status-icon">
|
||||
<div class="status-icon__wrapper">
|
||||
<div class="inner-wrapper">
|
||||
<div class="status-icon__wrapper__icon">
|
||||
<img src="~/imlegacy/checkmark.svg">
|
||||
</div>
|
||||
<div class="status-icon__wrapper__outline" style="height: 117px; width: 117px;"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="success-message">
|
||||
<span>
|
||||
<span i18n="">Refund Complete</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="manual-box">
|
||||
<div class="manual-box__amount amount-only">
|
||||
<div class="manual-box__amount__label label">
|
||||
<span class="initial-label" i18n="">Overpaid By</span>
|
||||
<span class="final-label">
|
||||
<span i18n="">Amount Refunded</span>
|
||||
</span>
|
||||
</div>
|
||||
<div class="manual-box__amount__value">{BTC amount} BTC</div>
|
||||
</div>
|
||||
<div class="manual-box__address">
|
||||
<div class="flipper flipped-initially">
|
||||
<div class="back"></div>
|
||||
<div class="front">
|
||||
<div class="manual-box__address__arrow"></div>
|
||||
<div class="manual-box__address__label label" i18n="">Refunded To</div>
|
||||
<div class="manual-box__address__wrapper">
|
||||
<div class="manual-box__address__wrapper__logo">
|
||||
<img src="~/imlegacy/bitcoin-symbol.svg">
|
||||
</div>
|
||||
<div class="manual-box__address__wrapper__value">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<button class="action-button finished" style="margin-top: 23px;">
|
||||
<bp-done-text>
|
||||
<span>{{$t("Return to StoreName", srvModel)}}</span>
|
||||
</bp-done-text>
|
||||
</button>
|
||||
</div>
|
||||
<div class="footer-button enter-different-address-button">
|
||||
<bp-done-text>
|
||||
<span>{{$t("Return to StoreName", srvModel)}}</span>
|
||||
</bp-done-text>
|
||||
</div>
|
||||
@* Obsolete? End *@
|
||||
</div>
|
||||
5
BTCPayServer/Views/Invoice/Checkout-Spinner.cshtml
Normal file
5
BTCPayServer/Views/Invoice/Checkout-Spinner.cshtml
Normal file
@@ -0,0 +1,5 @@
|
||||
<bp-spinner>
|
||||
<svg xml:space="preserve" style="enable-background:new 0 0 50 50;" version="1.1" viewBox="0 0 50 50" x="0px" xmlns="http://www.w3.org/2000/svg" y="0px">
|
||||
<path d="M11.1,29.6c-0.5-1.5-0.8-3-0.8-4.6c0-8.1,6.6-14.7,14.7-14.7S39.7,16.9,39.7,25c0,1.6-0.3,3.2-0.8,4.6l6.1,2c0.7-2.1,1.1-4.3,1.1-6.6c0-11.7-9.5-21.2-21.2-21.2S3.8,13.3,3.8,25c0,2.3,0.4,4.5,1.1,6.6L11.1,29.6z"></path>
|
||||
</svg>
|
||||
</bp-spinner>
|
||||
@@ -2,7 +2,6 @@
|
||||
@model PaymentModel
|
||||
@{
|
||||
Layout = null;
|
||||
ViewData["Title"] = "Payment";
|
||||
}
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
@@ -46,632 +45,71 @@
|
||||
|
||||
<invoice>
|
||||
<div class="no-bounce" id="checkoutCtrl">
|
||||
@*<div class="modal-backdrop fade-in"></div>*@
|
||||
|
||||
<!---->
|
||||
<div class="modal page">
|
||||
<div class="modal-dialog open opened" role="document">
|
||||
<div class="modal-dialog open opened enter-purchaser-email" role="document">
|
||||
<div class="modal-content long">
|
||||
<div class="content">
|
||||
<div class="invoice">
|
||||
<div class="top-header">
|
||||
<div class="header">
|
||||
<div class="header__icon">
|
||||
<img class="header__icon__img" src="~/img/logo-white.png" height="40">
|
||||
</div>
|
||||
<!---->
|
||||
</div>
|
||||
<div class="timer-row">
|
||||
<div class="timer-row__progress-bar" style="width: 0%;"></div>
|
||||
<!---->
|
||||
<div class="timer-row__spinner">
|
||||
<bp-spinner>
|
||||
<svg xml:space="preserve" style="enable-background:new 0 0 50 50;" version="1.1" viewBox="0 0 50 50" x="0px" xmlns="http://www.w3.org/2000/svg" y="0px">
|
||||
<path d="M11.1,29.6c-0.5-1.5-0.8-3-0.8-4.6c0-8.1,6.6-14.7,14.7-14.7S39.7,16.9,39.7,25c0,1.6-0.3,3.2-0.8,4.6l6.1,2c0.7-2.1,1.1-4.3,1.1-6.6c0-11.7-9.5-21.2-21.2-21.2S3.8,13.3,3.8,25c0,2.3,0.4,4.5,1.1,6.6L11.1,29.6z"></path>
|
||||
</svg>
|
||||
</bp-spinner>
|
||||
</div>
|
||||
<div class="timer-row__message">
|
||||
<!---->
|
||||
<span>
|
||||
<!---->
|
||||
<span i18n="">Awaiting Payment...</span>
|
||||
<!---->
|
||||
</span>
|
||||
<!---->
|
||||
</div>
|
||||
<div class="timer-row__time-left">@Model.TimeLeft</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="order-details">
|
||||
@if (Model.AvailableCryptos.Count > 1)
|
||||
{
|
||||
<div class="currency-selection">
|
||||
<div class="single-item-order__left">
|
||||
<div style="font-weight: 600;">
|
||||
Pay with
|
||||
</div>
|
||||
</div>
|
||||
<div class="single-item-order__right">
|
||||
<div class="payment__currencies">
|
||||
@foreach (var crypto in Model.AvailableCryptos)
|
||||
{
|
||||
<a href="@crypto.Link" onclick="return changeCurrency('@crypto.PaymentMethodId');">
|
||||
<img style="height:32px; margin-left:5px;" alt="@crypto.PaymentMethodId" src="@crypto.CryptoImage" />
|
||||
</a>
|
||||
}
|
||||
</div>
|
||||
<div class="payment__spinner">
|
||||
<bp-spinner>
|
||||
<svg xml:space="preserve" style="enable-background:new 0 0 50 50;" version="1.1" viewBox="0 0 50 50" x="0px" xmlns="http://www.w3.org/2000/svg" y="0px">
|
||||
<path d="M11.1,29.6c-0.5-1.5-0.8-3-0.8-4.6c0-8.1,6.6-14.7,14.7-14.7S39.7,16.9,39.7,25c0,1.6-0.3,3.2-0.8,4.6l6.1,2c0.7-2.1,1.1-4.3,1.1-6.6c0-11.7-9.5-21.2-21.2-21.2S3.8,13.3,3.8,25c0,2.3,0.4,4.5,1.1,6.6L11.1,29.6z"></path>
|
||||
</svg>
|
||||
</bp-spinner>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
<!---->
|
||||
<div class="single-item-order buyerTotalLine">
|
||||
<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" id="buyerTotalBtcAmount">
|
||||
<span>{{ srvModel.btcDue }} {{ srvModel.cryptoCode }}</span>
|
||||
</div>
|
||||
<!---->
|
||||
<div class="single-item-order__right__ex-rate">
|
||||
1 {{ srvModel.cryptoCode }} = {{ srvModel.rate }}
|
||||
</div>
|
||||
<!---->
|
||||
</div>
|
||||
|
||||
<span class="fa fa-angle-double-down"></span>
|
||||
<span class="fa fa-angle-double-up"></span>
|
||||
</div>
|
||||
<!---->
|
||||
<line-items>
|
||||
<div class="line-items">
|
||||
<!---->
|
||||
<div class="line-items__item">
|
||||
<div class="line-items__item__label" i18n="">Order Amount</div>
|
||||
<div class="line-items__item__value">{{srvModel.orderAmount}} {{ srvModel.cryptoCode }}</div>
|
||||
</div>
|
||||
<div class="line-items__item">
|
||||
<div class="line-items__item__label">
|
||||
<span i18n="">Network Cost</span>
|
||||
</div>
|
||||
<div class="line-items__item__value" i18n="">{{srvModel.networkFeeDescription }}</div>
|
||||
</div>
|
||||
<div class="line-items__item">
|
||||
<div class="line-items__item__label">
|
||||
<span i18n="">Already Paid</span>
|
||||
</div>
|
||||
<div class="line-items__item__value" i18n="">-{{srvModel.btcPaid }} {{ srvModel.cryptoCode }}</div>
|
||||
</div>
|
||||
<div class="line-items__item line-items__item--total">
|
||||
<div class="line-items__item__label" i18n="">Due </div>
|
||||
<div class="line-items__item__value">{{srvModel.btcDue}} {{ srvModel.cryptoCode }}</div>
|
||||
</div>
|
||||
<!---->
|
||||
</div>
|
||||
</line-items>
|
||||
<div class="payment-tabs">
|
||||
<div class="payment-tabs__tab active" id="scan-tab">
|
||||
<span i18n="">Scan</span>
|
||||
</div>
|
||||
<div class="payment-tabs__tab" id="copy-tab">
|
||||
<span i18n="">Copy</span>
|
||||
</div>
|
||||
@if (Model.AllowCoinConversion)
|
||||
{
|
||||
<div class="payment-tabs__tab" id="altcoins-tab">
|
||||
<span i18n="">Conversion</span>
|
||||
</div>
|
||||
<div id="tabsSlider" class="payment-tabs__slider three-tabs"></div>
|
||||
}
|
||||
else
|
||||
{
|
||||
<div id="tabsSlider" class="payment-tabs__slider"></div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
<div adjust-height="" class="payment-box">
|
||||
<div class="bp-view payment manual-flow enter-contact-email active" id="emailAddressView">
|
||||
<form class="manual__step-one refund-address-form contact-email-form" id="emailAddressForm" name="emailAddressForm" novalidate="">
|
||||
<div class="manual__step-one__header">
|
||||
<!---->
|
||||
<span i18n="">Contact & Refund Email</span>
|
||||
<!---->
|
||||
</div>
|
||||
<div class="manual__step-one__instructions">
|
||||
<span class="initial-label">
|
||||
<!---->
|
||||
<span i18n="">Please provide an email address below. We’ll contact you at this address if there is an issue with your payment. </span>
|
||||
<!---->
|
||||
</span>
|
||||
<span class="submission-error-label" i18n="">Please enter a valid email address.</span>
|
||||
</div>
|
||||
<div class="input-wrapper">
|
||||
<input class="bp-input email-input ng-pristine ng-invalid ng-touched" id="emailAddressFormInput" placeholder="Your email" type="email">
|
||||
<bp-loading-button i18n="">
|
||||
<button class="action-button" style="margin-top: 15px;" type="button">
|
||||
<span class="button-text" lcl="">Continue</span>
|
||||
<div class="loader-wrapper">
|
||||
<bp-spinner>
|
||||
<svg xml:space="preserve" style="enable-background:new 0 0 50 50;" version="1.1" viewBox="0 0 50 50" x="0px" xmlns="http://www.w3.org/2000/svg" y="0px">
|
||||
<path d="M11.1,29.6c-0.5-1.5-0.8-3-0.8-4.6c0-8.1,6.6-14.7,14.7-14.7S39.7,16.9,39.7,25c0,1.6-0.3,3.2-0.8,4.6l6.1,2c0.7-2.1,1.1-4.3,1.1-6.6c0-11.7-9.5-21.2-21.2-21.2S3.8,13.3,3.8,25c0,2.3,0.4,4.5,1.1,6.6L11.1,29.6z"></path>
|
||||
</svg>
|
||||
</bp-spinner>
|
||||
</div>
|
||||
</button>
|
||||
</bp-loading-button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="bp-view payment scan" id="scan">
|
||||
<div class="payment__scan">
|
||||
<img v-bind:src="srvModel.cryptoImage" style="position: absolute; height:64px; width:64px; left:118px; top:96px;" />
|
||||
<qrcode v-bind:val="srvModel.invoiceBitcoinUrlQR" v-bind:size="256" bg-color="#f5f5f7" fg-color="#000">
|
||||
</qrcode>
|
||||
</div>
|
||||
<div class="payment__details__instruction__open-wallet">
|
||||
<a class="payment__details__instruction__open-wallet__btn action-button" v-bind:href="srvModel.invoiceBitcoinUrl">
|
||||
<span i18n="">Open in wallet</span>
|
||||
<span class="glyphicon glyphicon-new-window"></span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="bp-view payment manual-flow" id="copy">
|
||||
<div class="manual__step-two__instructions">
|
||||
<span i18n="">To complete your payment, please send {{ srvModel.btcDue }} {{ srvModel.cryptoCode }} to the address below.</span>
|
||||
</div>
|
||||
<div class="manual-box flipped" style="margin-bottom: 30px;">
|
||||
<div class="manual-box__amount">
|
||||
<div class="manual-box__amount__label label" i18n="">Amount</div>
|
||||
<!---->
|
||||
<div class="manual-box__amount__value copy-cursor" ngxclipboard="">
|
||||
<span>{{srvModel.btcDue}}</span> {{ srvModel.cryptoCode }}
|
||||
<div class="copied-label">
|
||||
<span i18n="">Copied</span>
|
||||
</div>
|
||||
</div>
|
||||
<!---->
|
||||
</div>
|
||||
<div class="manual-box__address">
|
||||
<div class="flipper flipped-initially">
|
||||
<div class="back"></div>
|
||||
<div class="front">
|
||||
<div class="manual-box__address__arrow"></div>
|
||||
<div class="manual-box__address__label label" i18n="">Address</div>
|
||||
<!---->
|
||||
<div class="manual-box__address__value copy-cursor" ngxclipboard="">
|
||||
<div class="manual-box__address__wrapper">
|
||||
<div class="manual-box__address__wrapper__logo">
|
||||
<img :src="srvModel.cryptoImage" height="16" />
|
||||
</div>
|
||||
<div class="manual-box__address__wrapper__value" style="overflow:hidden;max-width:240px;">{{srvModel.btcAddress}}</div>
|
||||
</div>
|
||||
<div class="copied-label" style="top: 5px;">
|
||||
<span i18n="">Copied</span>
|
||||
</div>
|
||||
</div>
|
||||
<!---->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@if (Model.AllowCoinConversion)
|
||||
{
|
||||
<div id="altcoins" class="bp-view payment manual-flow">
|
||||
<div v-if="srvModel.paymentMethodId != 'BTC_LightningLike'">
|
||||
<div class="manual__step-two__instructions">
|
||||
<span>
|
||||
You can pay {{ srvModel.btcDue }} {{ srvModel.cryptoCode }} using altcoins other than the ones merchant directly supports.
|
||||
<br /><br />
|
||||
This service is provided by 3rd party. Please keep in mind that
|
||||
<span style="font-weight: 900;">we have no control</span> over how providers will forward your funds.
|
||||
Invoice will only be marked paid once funds are received on {{srvModel.cryptoCode}} Blockchain.
|
||||
</span>
|
||||
</div>
|
||||
<center>
|
||||
<script>function shapeshift_click(a, e) { e.preventDefault(); var link = a.href; var shapeshiftWindow = window.open(link, '1418115287605', 'width=700,height=500,toolbar=0,menubar=0,location=0,status=1,scrollbars=1,resizable=0,left=0,top=0'); shapeshiftWindow.focus(); return false; }</script>
|
||||
<a onclick="shapeshift_click(this, event);" v-bind:href="srvModel.shapeshiftUrl">
|
||||
<img src="https://shapeshift.io/images/shifty/xs_light_altcoins.png" class="ss-button">
|
||||
</a>
|
||||
|
||||
@*Changelly doesn't have TO_AMOUNT support so we can't include it
|
||||
<script type="text/javascript">function open_widget(a, e) { e.preventDefault(); var link = a.href; var changellyWindow = window.open(link, 'Changelly', 'width=600,height=470,toolbar=0,menubar=0,location=0,status=1,scrollbars=1,resizable=0,left=0,top=0'); changellyWindow.focus(); return false; }</script>
|
||||
<a onclick="open_widget(this, event);" href="https://changelly.com/widget/v1?auth=email&from=DASH&to=BTC&address=&amount=1&merchant_id=&ref_id=">
|
||||
<img src="https://changelly.com/pay_button_pay_with.png" alt="Changelly" />
|
||||
</a>*@
|
||||
</center>
|
||||
</div>
|
||||
<div v-else>
|
||||
<div class="manual__step-two__instructions">
|
||||
<span>
|
||||
No conversion providers available for BTC Lightning Network payments.
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
<div class="bp-view" id="link-expired" style="padding-top: 3.6rem;">
|
||||
<div class="manual__step-one refund-address-form" novalidate="">
|
||||
<div class="manual__step-one__header" i18n="">Link Expired</div>
|
||||
<div class="manual__step-one__instructions">
|
||||
<span class="initial-label" i18n="">Sorry, this link has expired. Please try requesting another refund by clicking the button below.</span>
|
||||
</div>
|
||||
<div class="input-wrapper">
|
||||
<bp-loading-button i18n="">
|
||||
<button class="action-button" style="margin-top: 15px;" type="submit">
|
||||
<span class="button-text" lcl="">Request Refund</span>
|
||||
<div class="loader-wrapper">
|
||||
<bp-spinner>
|
||||
<svg xml:space="preserve" style="enable-background:new 0 0 50 50;" version="1.1" viewBox="0 0 50 50" x="0px" xmlns="http://www.w3.org/2000/svg" y="0px">
|
||||
<path d="M11.1,29.6c-0.5-1.5-0.8-3-0.8-4.6c0-8.1,6.6-14.7,14.7-14.7S39.7,16.9,39.7,25c0,1.6-0.3,3.2-0.8,4.6l6.1,2c0.7-2.1,1.1-4.3,1.1-6.6c0-11.7-9.5-21.2-21.2-21.2S3.8,13.3,3.8,25c0,2.3,0.4,4.5,1.1,6.6L11.1,29.6z"></path>
|
||||
</svg>
|
||||
</bp-spinner>
|
||||
</div>
|
||||
</button>
|
||||
</bp-loading-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="bp-view confirm-contact-email-view">
|
||||
<form class="manual__step-one refund-address-form contact-email-form ng-untouched ng-pristine" novalidate="">
|
||||
<div class="manual__step-one__header" i18n="">Contact & Refund Email</div>
|
||||
<div class="manual__step-one__instructions">
|
||||
<span class="initial-label" i18n="">If there is an issue with this payment, or a refund needs to be made, we will contact you at this address.</span>
|
||||
</div>
|
||||
<div class="input-wrapper">
|
||||
<input bp-focus="focusEmailInput" class="bp-input email-input ng-untouched ng-pristine" disabled="disabled" name="receiptEmail" placeholder="Your email" style="opacity: 1;" type="email">
|
||||
<button class="action-button" style="margin-top: 15px;">
|
||||
<span i18n="">Confirm email address</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="refund-address-form__link" id="wrong-email-button" style="color: #a9a9a9;">
|
||||
<span i18n="">Wrong email?</span>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="bp-view wrong-email-view" id="compromised-invoice">
|
||||
<div class="manual__step-one refund-address-form" novalidate="" style="margin-top: -1rem;">
|
||||
<div class="manual__step-one__header">
|
||||
<span i18n="">There seems to be a problem</span>
|
||||
</div>
|
||||
<div class="manual__step-one__instructions">
|
||||
<span class="initial-label" i18n="">
|
||||
This invoice was previously opened, and the address <strong class="placeholder-refundEmail">{Entered email address}</strong> was submitted as your contact email. If you entered this email, you can still safely make your payment. <br> <br>
|
||||
If you did not submit the email address, it's possible a thief falsely
|
||||
submitted this address to steal refunds. Please contact the merchant
|
||||
about this security incident, and try your payment again.
|
||||
</span>
|
||||
</div>
|
||||
<div class="input-wrapper">
|
||||
<a class="action-button" style="margin-top: 15px;" target="_blank" href="mailto:@Model.StoreEmail">
|
||||
<span i18n="">Contact {{srvModel.storeName}}</span>
|
||||
</a>
|
||||
</div>
|
||||
<div class="refund-address-form__link">
|
||||
<span i18n="">I understand, continue to payment →</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="bp-view confirm-bitcoin-address-view" id="confirm-refund-address">
|
||||
<form class="manual__step-one refund-address-form ng-untouched ng-pristine ng-valid" novalidate="" style="padding-top: 1.6rem;">
|
||||
<div><img src="~/imlegacy/mail.svg"></div>
|
||||
<div class="manual__step-one__header">
|
||||
<span i18n="">Please confirm your address</span>
|
||||
</div>
|
||||
<div class="manual__step-one__instructions">
|
||||
<span class="initial-label" i18n="">You should receive an email from us in a moment at <strong class="placeholder-refundEmail">{enterd refund email}</strong>. To ensure your refund is sent to the correct address, please confirm your bitcoin address by clicking the link in the email. </span>
|
||||
</div>
|
||||
<bp-resend-link id="resend-link">
|
||||
<div class="bp-resend__link">
|
||||
<span class="link-text">
|
||||
<!---->
|
||||
<span i18n="">Resend email</span>
|
||||
<!---->
|
||||
</span>
|
||||
<div class="success-text">
|
||||
<!---->
|
||||
<img src="~/imlegacy/circle-check.svg">
|
||||
<!---->
|
||||
<div i18n="">Email resent</div>
|
||||
<!---->
|
||||
</div>
|
||||
</div>
|
||||
</bp-resend-link>
|
||||
</form>
|
||||
</div>
|
||||
<div class="bp-view refund-address-view" id="enter-refund-address">
|
||||
<form class="manual__step-one refund-address-form ng-untouched ng-pristine ng-invalid" name="refundAddressForm" novalidate="" style="margin-top: 28px; margin-bottom: 4rem;">
|
||||
<div class="manual__step-one__header">
|
||||
<!---->
|
||||
<span i18n="">Please provide a refund address.</span>
|
||||
<!---->
|
||||
</div>
|
||||
<div class="manual__step-one__instructions">
|
||||
<span class="initial-label">
|
||||
<!---->
|
||||
<span i18n="">
|
||||
To send your refund of {BTC to refund} BTC,
|
||||
we’ll need a bitcoin address from your wallet. Please open your bitcoin
|
||||
wallet, copy a receiving address, and paste it below.
|
||||
</span>
|
||||
<!---->
|
||||
</span>
|
||||
<span class="submission-error-label" i18n="" id="invalid-bitcoin-address">Please enter a valid bitcoin address.</span>
|
||||
</div>
|
||||
<div class="input-wrapper">
|
||||
<bp-refund-address name="refundAddress" ngmodel="" class="ng-untouched ng-pristine ng-invalid">
|
||||
<div class="bp-refund-address">
|
||||
<div class="bitcoin-logo">
|
||||
<div><img src="@Model.CryptoImage"></div>
|
||||
</div>
|
||||
<input class="bp-input {'not-empty': addressValue.length > 0} ng-untouched ng-pristine ng-valid" id="refund-address-input" name="refundAddress" ngclass="{'not-empty': addressValue.length > 0}">
|
||||
</div>
|
||||
</bp-refund-address>
|
||||
<bp-loading-button i18n="" id="request-refund-button">
|
||||
<button class="action-button" style="margin-top: 15px;" type="submit">
|
||||
<span class="button-text" lcl="">Request Refund</span>
|
||||
<div class="loader-wrapper">
|
||||
<bp-spinner>
|
||||
<svg xml:space="preserve" style="enable-background:new 0 0 50 50;" version="1.1" viewBox="0 0 50 50" x="0px" xmlns="http://www.w3.org/2000/svg" y="0px">
|
||||
<path d="M11.1,29.6c-0.5-1.5-0.8-3-0.8-4.6c0-8.1,6.6-14.7,14.7-14.7S39.7,16.9,39.7,25c0,1.6-0.3,3.2-0.8,4.6l6.1,2c0.7-2.1,1.1-4.3,1.1-6.6c0-11.7-9.5-21.2-21.2-21.2S3.8,13.3,3.8,25c0,2.3,0.4,4.5,1.1,6.6L11.1,29.6z"></path>
|
||||
</svg>
|
||||
</bp-spinner>
|
||||
</div>
|
||||
</button>
|
||||
</bp-loading-button>
|
||||
</div>
|
||||
<div class="refund-address-form__cancel">
|
||||
<span i18n="">Cancel</span>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div class="bp-view pad" id="paid">
|
||||
<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">
|
||||
</div>
|
||||
<div class="status-icon__wrapper__outline"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!---->
|
||||
<div class="success-message" i18n="">This invoice has been paid.</div>
|
||||
<!---->
|
||||
<button class="action-button" style="margin-top: 0px;">
|
||||
<bp-done-text>
|
||||
<span i18n="" class="i18n-return-to-merchant">Return to {{srvModel.storeName}}</span>
|
||||
</bp-done-text>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<!---->
|
||||
<div class="button-wrapper refund-address-form-container" id="refund-overpayment-button">
|
||||
<!---->
|
||||
</div>
|
||||
<!---->
|
||||
</div>
|
||||
<div class="bp-view" id="refund-pending">
|
||||
<div class="status-block">
|
||||
<div class="pending-block" style="position: relative; padding-bottom: 1.6rem;">
|
||||
<img src="~/imlegacy/refund-pending.svg">
|
||||
<div class="pending-block__header" i18n="">Processing Refund</div>
|
||||
<span>
|
||||
<!---->
|
||||
<!---->
|
||||
<!---->
|
||||
<span class="pending-block__message" i18n="">The amount below will be refunded to you within 1-2 business days. </span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="manual-box" style="margin-bottom: 30px;">
|
||||
<div class="manual-box__amount amount-only">
|
||||
<div class="manual-box__amount__label label">
|
||||
<span class="initial-label"> </span>
|
||||
<span class="final-label" i18n="">Amount To Be Refunded</span>
|
||||
</div>
|
||||
<div class="manual-box__amount__value">{BTC Amount} BTC</div>
|
||||
</div>
|
||||
<div class="manual-box__address">
|
||||
<div class="flipper">
|
||||
<div class="back"></div>
|
||||
<div class="front">
|
||||
<div class="manual-box__address__arrow"></div>
|
||||
<div class="manual-box__address__label label" i18n="">Will Be Refunded To</div>
|
||||
<div class="manual-box__address__wrapper">
|
||||
<div class="manual-box__address__wrapper__logo">
|
||||
<img src="~/imlegacy/bitcoin-symbol.svg">
|
||||
</div>
|
||||
<div class="manual-box__address__wrapper__value">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!---->
|
||||
</div>
|
||||
<div class="bp-view expired" id="low-fee">
|
||||
<div class="expired__body">
|
||||
<div class="expired__header" i18n="" style="font-weight: 400; font-size: 22px;">Payment Confirming</div>
|
||||
<div class="expired__text" i18n="">This payment was made with a low <a href="https://bitcoin.org/en/glossary/transaction-fee">bitcoin miner fee</a>, which may prevent it from being accepted by the Bitcoin network.</div>
|
||||
<div class="expired__text" i18n="">This is an issue with the configuration of your bitcoin wallet.</div>
|
||||
<div class="expired__text" i18n="">
|
||||
If the transaction
|
||||
doesn't confirm, the funds will be spendable again in your wallet.
|
||||
Depending on the wallet, this may take 48-72 hours.
|
||||
</div>
|
||||
<low-fee-timeline>
|
||||
<div class="timeline">
|
||||
<div class="timeline__item">
|
||||
<div class="timeline__item__icon timeline__item__icon--complete">
|
||||
<img src="~/imlegacy/checkmark-small.svg">
|
||||
</div>
|
||||
<div class="timeline__item__name" i18n="">Transaction created</div>
|
||||
</div>
|
||||
<div class="timeline__item">
|
||||
<div class="timeline__item__icon timeline__item__icon--pending">
|
||||
<img src="~/imlegacy/pending.svg">
|
||||
</div>
|
||||
<div class="timeline__item__name">
|
||||
<span i18n="">Transaction confirming — funds have not yet moved</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="timeline__item">
|
||||
<div class="timeline__item__icon"></div>
|
||||
<div class="timeline__item__name" i18n="">Payment received by {{srvModel.storeName}}</div>
|
||||
</div>
|
||||
</div>
|
||||
</low-fee-timeline>
|
||||
</div>
|
||||
<!---->
|
||||
<!---->
|
||||
<button class="action-button" style="margin-top: .75rem;">
|
||||
<bp-done-text>
|
||||
<!---->
|
||||
<!---->
|
||||
<span i18n="" class="i18n-return-to-merchant">Return to {{srvModel.storeName}}</span>
|
||||
</bp-done-text>
|
||||
</button>
|
||||
</div>
|
||||
<div class="bp-view expired" id="expired">
|
||||
<!---->
|
||||
<div>
|
||||
<div class="expired__body">
|
||||
<div class="expired__header" i18n="">What happened?</div>
|
||||
<div class="expired__text" i18n="">This invoice has expired. An invoice is only valid for @Model.MaxTimeMinutes minutes. You can <div class="expired__text__link i18n-return-to-merchant">return to {{srvModel.storeName}}</div> if you would like to submit your payment again.</div>
|
||||
<div class="expired__text" i18n="">If you tried to send a payment, it has not yet been accepted by the Bitcoin network. We have not yet received your funds.</div>
|
||||
<div class="expired__text" i18n="">
|
||||
If the transaction
|
||||
is not accepted by the Bitcoin network, the funds will be spendable
|
||||
again in your wallet. Depending on your wallet, this may take 48-72
|
||||
hours.
|
||||
</div>
|
||||
<div class="expired__text">
|
||||
<span class="expired__text__bullet" i18n="">Invoice ID:</span> {{srvModel.invoiceId}}<br>
|
||||
<!---->
|
||||
<span>
|
||||
<span class="expired__text__bullet" i18n="">Order ID:</span> {{srvModel.orderId}}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<a href="/invoices" class="action-button" style="margin-top: 20px;">
|
||||
<bp-done-text>
|
||||
<!---->
|
||||
<!---->
|
||||
<span i18n="" class="i18n-return-to-merchant">Return to {{srvModel.storeName}}</span>
|
||||
</bp-done-text>
|
||||
</a>
|
||||
</div>
|
||||
<!---->
|
||||
<!---->
|
||||
</div>
|
||||
<div class="bp-view expired" id="archived">
|
||||
<div class="expired-icon">
|
||||
<img src="~/imlegacy/archived.svg">
|
||||
</div>
|
||||
<div class="archived__message">
|
||||
<div class="archived__message__header">
|
||||
<span i18n="">This invoice has been archived.</span>
|
||||
</div>
|
||||
<div>
|
||||
<span i18n="">Please contact the store for order information or assistance.</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="bp-view" id="refund-complete">
|
||||
<div class="status-block">
|
||||
<div class="success-block" style="opacity: 1;">
|
||||
<div class="status-icon">
|
||||
<div class="status-icon__wrapper">
|
||||
<div class="inner-wrapper">
|
||||
<div class="status-icon__wrapper__icon">
|
||||
<img src="~/imlegacy/checkmark.svg">
|
||||
</div>
|
||||
<div class="status-icon__wrapper__outline" style="height: 117px; width: 117px;"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="success-message">
|
||||
<!---->
|
||||
<span>
|
||||
<span i18n="">Refund Complete</span>
|
||||
</span>
|
||||
<!---->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="manual-box">
|
||||
<div class="manual-box__amount amount-only">
|
||||
<div class="manual-box__amount__label label">
|
||||
<span class="initial-label" i18n="">Overpaid By</span>
|
||||
<!---->
|
||||
<span class="final-label">
|
||||
<span i18n="">Amount Refunded</span>
|
||||
</span>
|
||||
<!---->
|
||||
</div>
|
||||
<div class="manual-box__amount__value">{BTC amount} BTC</div>
|
||||
</div>
|
||||
<div class="manual-box__address">
|
||||
<div class="flipper flipped-initially">
|
||||
<div class="back"></div>
|
||||
<div class="front">
|
||||
<div class="manual-box__address__arrow"></div>
|
||||
<div class="manual-box__address__label label" i18n="">Refunded To</div>
|
||||
<div class="manual-box__address__wrapper">
|
||||
<div class="manual-box__address__wrapper__logo">
|
||||
<img src="~/imlegacy/bitcoin-symbol.svg">
|
||||
</div>
|
||||
<div class="manual-box__address__wrapper__value">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<button class="action-button finished" style="margin-top: 23px;">
|
||||
<bp-done-text>
|
||||
<!---->
|
||||
<!---->
|
||||
<span i18n="" class="i18n-return-to-merchant">Return to {{srvModel.storeName}}</span>
|
||||
</bp-done-text>
|
||||
</button>
|
||||
</div>
|
||||
<div class="footer-button enter-different-address-button">
|
||||
<bp-done-text>
|
||||
<!---->
|
||||
<!---->
|
||||
<span i18n="" class="i18n-return-to-merchant">Return to {{srvModel.storeName}}</span>
|
||||
</bp-done-text>
|
||||
</div>
|
||||
</div>
|
||||
@Html.Partial("Checkout-Body")
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div style="margin-top: 10px; text-align: right;">
|
||||
@* Not working because of nsSeparator: false, keySeparator: false,
|
||||
{{$t("nested.lang")}} >>
|
||||
*@
|
||||
<select class="cmblang reverse invisible" onchange="changeLanguage($(this).val())">
|
||||
<option value="en-US">English</option>
|
||||
<option value="de-DE">Deutsch</option>
|
||||
<option value="ja-JP">日本語</option>
|
||||
<option value="fr-FR">Français</option>
|
||||
<option value="es-ES">Spanish</option>
|
||||
</select>
|
||||
<script>
|
||||
$(function () {
|
||||
if (urlParams.lang) {
|
||||
$(".cmblang").val(urlParams.lang);
|
||||
}
|
||||
|
||||
$('select').prettyDropdown({
|
||||
classic: false,
|
||||
height: 30,
|
||||
reverse: true,
|
||||
hoverIntent: 5000
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</invoice>
|
||||
<script type="text/javascript">
|
||||
// initialization
|
||||
i18next.init({
|
||||
lng: 'en',
|
||||
fallbackLng: 'en',
|
||||
nsSeparator: false,
|
||||
keySeparator: false,
|
||||
resources: {
|
||||
en: { translation: locales_en },
|
||||
de: { translation: locales_de },
|
||||
es: { translation: locales_es },
|
||||
ja: { translation: locales_ja },
|
||||
fr: { translation: locales_fr }
|
||||
},
|
||||
});
|
||||
|
||||
function changeLanguage(lang) {
|
||||
i18next.changeLanguage(lang);
|
||||
}
|
||||
|
||||
if (urlParams.lang) {
|
||||
changeLanguage(urlParams.lang);
|
||||
}
|
||||
|
||||
const i18n = new VueI18next(i18next);
|
||||
|
||||
// TODO: Move all logic from core.js to Vue controller
|
||||
Vue.config.ignoredElements = [
|
||||
'line-items',
|
||||
@@ -680,12 +118,14 @@
|
||||
/^bp-/
|
||||
];
|
||||
var checkoutCtrl = new Vue({
|
||||
i18n: i18n,
|
||||
el: '#checkoutCtrl',
|
||||
components: {
|
||||
qrcode: VueQr
|
||||
},
|
||||
data: {
|
||||
srvModel: srvModel
|
||||
srvModel: srvModel,
|
||||
expiringSoon: false
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -33,7 +33,8 @@
|
||||
"inputFiles": [
|
||||
"wwwroot/vendor/font-awesome/css/font-awesome.css",
|
||||
"wwwroot/css/css.css",
|
||||
"wwwroot/css/normalizer.css"
|
||||
"wwwroot/css/normalizer.css",
|
||||
"wwwroot/vendor/jquery-prettydropdowns/prettydropdowns.css"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -41,9 +42,12 @@
|
||||
"inputFiles": [
|
||||
"wwwroot/vendor/clipboard.js/clipboard.js",
|
||||
"wwwroot/vendor/jquery/jquery.js",
|
||||
"wwwroot/js/vue.min.js",
|
||||
"wwwroot/js/vue-qrcode.js",
|
||||
"wwwroot/js/core.js"
|
||||
"wwwroot/vendor/vuejs/vue.min.js",
|
||||
"wwwroot/vendor/vuejs/vue-qrcode.js",
|
||||
"wwwroot/vendor/i18next/i18next.js",
|
||||
"wwwroot/vendor/i18next/vue-i18next.js",
|
||||
"wwwroot/vendor/jquery-prettydropdowns/jquery.prettydropdowns.js",
|
||||
"wwwroot/js/checkout/**/*.js"
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
// TODO: Refactor... switch from jQuery to Vue.js
|
||||
// public methods
|
||||
function resetTabsSlider() {
|
||||
$("#tabsSlider").removeClass("slide-copy");
|
||||
$("#tabsSlider").removeClass("slide-altcoins");
|
||||
@@ -16,8 +18,11 @@ function resetTabsSlider() {
|
||||
$("#altcoins").removeClass("active");
|
||||
}
|
||||
|
||||
// public methods
|
||||
function onDataCallback(jsonData) {
|
||||
// extender properties used
|
||||
jsonData.shapeshiftUrl = "https://shapeshift.io/shifty.html?destination=" + jsonData.btcAddress + "&output=" + jsonData.paymentMethodId + "&amount=" + jsonData.btcDue;
|
||||
//
|
||||
|
||||
var newStatus = jsonData.status;
|
||||
|
||||
if (newStatus === "complete" ||
|
||||
@@ -44,7 +49,6 @@ function onDataCallback(jsonData) {
|
||||
|
||||
if (newStatus === "expired" || newStatus === "invalid") { //TODO: different state if the invoice is invalid (failed to confirm after timeout)
|
||||
$(".timer-row").removeClass("expiring-soon");
|
||||
$(".timer-row__message span").html("Invoice expired.");
|
||||
$(".timer-row__spinner").html("");
|
||||
$("#emailAddressView").removeClass("active");
|
||||
$(".modal-dialog").addClass("expired");
|
||||
@@ -63,7 +67,6 @@ function onDataCallback(jsonData) {
|
||||
$(".payment__spinner").hide();
|
||||
}
|
||||
|
||||
jsonData.shapeshiftUrl = "https://shapeshift.io/shifty.html?destination=" + jsonData.btcAddress + "&output=" + jsonData.paymentMethodId + "&amount=" + jsonData.btcDue;
|
||||
// updating ui
|
||||
checkoutCtrl.srvModel = jsonData;
|
||||
}
|
||||
@@ -125,7 +128,6 @@ $(document).ready(function () {
|
||||
|
||||
|
||||
function hideEmailForm() {
|
||||
$("[role=document]").removeClass("enter-purchaser-email");
|
||||
$("#emailAddressView").removeClass("active");
|
||||
$("placeholder-refundEmail").html(srvModel.customerEmail);
|
||||
|
||||
@@ -163,6 +165,8 @@ $(document).ready(function () {
|
||||
} else {
|
||||
$("#emailAddressForm").addClass("ng-touched ng-dirty ng-submitted ng-invalid");
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -282,23 +286,23 @@ $(document).ready(function () {
|
||||
}
|
||||
|
||||
function animateUpdate() {
|
||||
|
||||
var now = new Date();
|
||||
var timeDiff = end.getTime() - now.getTime();
|
||||
var perc = 100 - Math.round(timeDiff / timerMax * 100);
|
||||
var status = checkoutCtrl.srvModel.status;
|
||||
|
||||
if (perc === 75 && (status === "paidPartial" || status === "new")) {
|
||||
$(".timer-row").addClass("expiring-soon");
|
||||
$(".timer-row__message span").html("Invoice expiring soon ...");
|
||||
checkoutCtrl.expiringSoon = true;
|
||||
updateProgress(perc);
|
||||
}
|
||||
if (perc <= 100) {
|
||||
updateProgress(perc);
|
||||
setTimeout(animateUpdate, timeoutVal);
|
||||
}
|
||||
if (perc >= 100 && status === "expired") {
|
||||
onDataCallback(status);
|
||||
}
|
||||
//if (perc >= 100 && status === "expired") {
|
||||
// onDataCallback(status);
|
||||
//}
|
||||
}
|
||||
}
|
||||
|
||||
48
BTCPayServer/wwwroot/js/checkout/langs/de.js
Normal file
48
BTCPayServer/wwwroot/js/checkout/langs/de.js
Normal file
@@ -0,0 +1,48 @@
|
||||
const locales_de = {
|
||||
nested: {
|
||||
lang: 'Sprache',
|
||||
},
|
||||
"Awaiting Payment...": "Warten auf Zahlung...",
|
||||
"Pay with": "Bezahlen mit",
|
||||
"Contact and Refund Email": "Kontakt und Rückerstattungs Email",
|
||||
"Contact_Body": "Bitte geben Sie unten eine E-Mail-Adresse an. Wir werden Sie unter dieser Adresse kontaktieren, wenn ein Problem mit Ihrer Zahlung vorliegt.",
|
||||
"Your email": "Deine Email",
|
||||
"Continue": "Fortsetzen",
|
||||
"Please enter a valid email address": "Bitte geben Sie eine gültige E-Mail-Adresse ein",
|
||||
"Order Amount": "Bestellbetrag",
|
||||
"Network Cost": "Netzwerkkosten",
|
||||
"Already Paid": "Bereits bezahlt",
|
||||
"Due": "Fällig",
|
||||
// Tabs
|
||||
"Scan": "Scan",
|
||||
"Copy": "Kopieren",
|
||||
"Conversion": "Umwandlung",
|
||||
// Scan tab
|
||||
"Open in wallet": "In der Brieftasche öffnen",
|
||||
// Copy tab
|
||||
"CompletePay_Body": "Um Ihre Zahlung abzuschließen, senden Sie bitte {{btcDue}} {{cryptoCode}} an die unten angegebene Adresse.",
|
||||
"Amount": "Menge",
|
||||
"Address": "Adresse",
|
||||
"Copied": "Kopiert",
|
||||
// Conversion tab
|
||||
"ConversionTab_BodyTop": "Sie können {{btcDue}} {{cryptoCode}} mit altcoins bezahlen, die nicht direkt vom Händler unterstützt werden.",
|
||||
"ConversionTab_BodyDesc": "Dieser Service wird von Drittanbietern bereitgestellt. Bitte beachten Sie, dass wir keine Kontrolle darüber haben, wie die Anbieter Ihre Gelder weiterleiten. Die Rechnung wird erst bezahlt, wenn das Geld in {{cryptoCode}} Blockchain eingegangen ist.",
|
||||
"Shapeshift_Button_Text": "Bezahlen mit Altcoins",
|
||||
"ConversionTab_Lightning": "Für BTC Lightning Network-Zahlungen sind keine Conversion-Anbieter verfügbar.",
|
||||
// Invoice expired
|
||||
"Invoice expiring soon...": "Die Rechnung läuft bald ab...",
|
||||
"Invoice expired": "Die Rechnung ist abgelaufen",
|
||||
"What happened?": "Was ist passiert?",
|
||||
"InvoiceExpired_Body_1": "Diese Rechnung ist abgelaufen. Eine Rechnung ist nur für {{maxTimeMinutes}} Minuten gültig. \
|
||||
Sie können zu {{storeName}} zurückkehren, wenn Sie Ihre Zahlung erneut senden möchten.",
|
||||
"InvoiceExpired_Body_2": "Wenn Sie versucht haben, eine Zahlung zu senden, wurde sie vom Bitcoin-Netzwerk noch nicht akzeptiert. Wir haben Ihre Gelder noch nicht erhalten.",
|
||||
"InvoiceExpired_Body_3": "Wenn die Transaktion vom Bitcoin-Netzwerk nicht akzeptiert wird, ist das Geld wieder in Ihrer Brieftasche verfügbar. Abhängig von Ihrem Geldbeutel, kann dies 48-72 Stunden dauern.",
|
||||
"Invoice ID": "Rechnungs ID",
|
||||
"Order ID": "Auftrag ID",
|
||||
"Return to StoreName": "Zurück zu {{storeName}}",
|
||||
// Invoice paid
|
||||
"This invoice has been paid": "Diese Rechnung wurde bezahlt",
|
||||
// Invoice archived
|
||||
"This invoice has been archived": "Diese Rechnung wurde archiviert",
|
||||
"Archived_Body": "Bitte kontaktieren Sie den Shop für Bestellinformationen oder Hilfe"
|
||||
};
|
||||
48
BTCPayServer/wwwroot/js/checkout/langs/en.js
Normal file
48
BTCPayServer/wwwroot/js/checkout/langs/en.js
Normal file
@@ -0,0 +1,48 @@
|
||||
const locales_en = {
|
||||
nested: {
|
||||
lang: 'Language',
|
||||
},
|
||||
"Awaiting Payment...": "Awaiting Payment...",
|
||||
"Pay with": "Pay with",
|
||||
"Contact and Refund Email": "Contact & Refund Email",
|
||||
"Contact_Body": "Please provide an email address below. We’ll contact you at this address if there is an issue with your payment.",
|
||||
"Your email": "Your email",
|
||||
"Continue": "Continue",
|
||||
"Please enter a valid email address": "Please enter a valid email address",
|
||||
"Order Amount": "Order Amount",
|
||||
"Network Cost": "Network Cost",
|
||||
"Already Paid": "Already Paid",
|
||||
"Due": "Due",
|
||||
// Tabs
|
||||
"Scan": "Scan",
|
||||
"Copy": "Copy",
|
||||
"Conversion": "Conversion",
|
||||
// Scan tab
|
||||
"Open in wallet": "Open in wallet",
|
||||
// Copy tab
|
||||
"CompletePay_Body": "To complete your payment, please send {{btcDue}} {{cryptoCode}} to the address below.",
|
||||
"Amount": "Amount",
|
||||
"Address": "Address",
|
||||
"Copied": "Copied",
|
||||
// Conversion tab
|
||||
"ConversionTab_BodyTop": "You can pay {{btcDue}} {{cryptoCode}} using altcoins other than the ones merchant directly supports.",
|
||||
"ConversionTab_BodyDesc": "This service is provided by 3rd party. Please keep in mind that we have no control over how providers will forward your funds. Invoice will only be marked paid once funds are received on {{cryptoCode}} Blockchain.",
|
||||
"Shapeshift_Button_Text": "Pay with Altcoins",
|
||||
"ConversionTab_Lightning": "No conversion providers available for BTC Lightning Network payments.",
|
||||
// Invoice expired
|
||||
"Invoice expiring soon...": "Invoice expiring soon...",
|
||||
"Invoice expired": "Invoice expired",
|
||||
"What happened?": "What happened?",
|
||||
"InvoiceExpired_Body_1": "This invoice has expired. An invoice is only valid for {{maxTimeMinutes}} minutes. \
|
||||
You can return to {{storeName}} if you would like to submit your payment again.",
|
||||
"InvoiceExpired_Body_2": "If you tried to send a payment, it has not yet been accepted by the Bitcoin network. We have not yet received your funds.",
|
||||
"InvoiceExpired_Body_3": "If the transaction is not accepted by the Bitcoin network, the funds will be spendable again in your wallet. Depending on your wallet, this may take 48-72 hours.",
|
||||
"Invoice ID": "Invoice ID",
|
||||
"Order ID": "Order ID",
|
||||
"Return to StoreName": "Return to {{storeName}}",
|
||||
// Invoice paid
|
||||
"This invoice has been paid": "This invoice has been paid",
|
||||
// Invoice archived
|
||||
"This invoice has been archived": "This invoice has been archived",
|
||||
"Archived_Body": "Please contact the store for order information or assistance"
|
||||
};
|
||||
2
BTCPayServer/wwwroot/js/checkout/langs/es.js
Normal file
2
BTCPayServer/wwwroot/js/checkout/langs/es.js
Normal file
@@ -0,0 +1,2 @@
|
||||
const locales_es = {
|
||||
};
|
||||
2
BTCPayServer/wwwroot/js/checkout/langs/fr.js
Normal file
2
BTCPayServer/wwwroot/js/checkout/langs/fr.js
Normal file
@@ -0,0 +1,2 @@
|
||||
const locales_fr = {
|
||||
};
|
||||
2
BTCPayServer/wwwroot/js/checkout/langs/ja.js
Normal file
2
BTCPayServer/wwwroot/js/checkout/langs/ja.js
Normal file
@@ -0,0 +1,2 @@
|
||||
const locales_ja = {
|
||||
};
|
||||
12
BTCPayServer/wwwroot/js/checkout/querystring.js
Normal file
12
BTCPayServer/wwwroot/js/checkout/querystring.js
Normal file
@@ -0,0 +1,12 @@
|
||||
var urlParams;
|
||||
(window.onpopstate = function () {
|
||||
var match,
|
||||
pl = /\+/g, // Regex for replacing addition symbol with a space
|
||||
search = /([^&=]+)=?([^&]*)/g,
|
||||
decode = function (s) { return decodeURIComponent(s.replace(pl, " ")); },
|
||||
query = window.location.search.substring(1);
|
||||
|
||||
urlParams = {};
|
||||
while (match = search.exec(query))
|
||||
urlParams[decode(match[1])] = decode(match[2]);
|
||||
})();
|
||||
2122
BTCPayServer/wwwroot/vendor/i18next/i18next.js
vendored
Normal file
2122
BTCPayServer/wwwroot/vendor/i18next/i18next.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
2
BTCPayServer/wwwroot/vendor/i18next/vue-i18next.js
vendored
Normal file
2
BTCPayServer/wwwroot/vendor/i18next/vue-i18next.js
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define("VueI18next",[],t):"object"==typeof exports?exports.VueI18next=t():e.VueI18next=t()}(this,function(){return function(e){function t(i){if(n[i])return n[i].exports;var o=n[i]={i:i,l:!1,exports:{}};return e[i].call(o.exports,o,o.exports,t),o.l=!0,o.exports}var n={};return t.m=e,t.c=n,t.i=function(e){return e},t.d=function(e,n,i){t.o(e,n)||Object.defineProperty(e,n,{configurable:!1,enumerable:!0,get:i})},t.n=function(e){var n=e&&e.__esModule?function(){return e.default}:function(){return e};return t.d(n,"a",n),n},t.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},t.p="/dist/",t(t.s=2)}([function(e,t,n){"use strict";function i(e){i.installed||(i.installed=!0,t.Vue=u=e,u.mixin({computed:{$t:function(){var e=this;return function(t,n){return e.$i18n.t(t,n,e.$i18n.i18nLoadedAt)}}},beforeCreate:function(){var e=this.$options;e.i18n?this.$i18n=e.i18n:e.parent&&e.parent.$i18n&&(this.$i18n=e.parent.$i18n)}}),u.component(r.default.name,r.default))}Object.defineProperty(t,"__esModule",{value:!0}),t.Vue=void 0,t.install=i;var o=n(1),r=function(e){return e&&e.__esModule?e:{default:e}}(o),u=t.Vue=void 0},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default={name:"i18next",functional:!0,props:{tag:{type:String,default:"span"},path:{type:String,required:!0}},render:function(e,t){var n=t.props,i=t.data,o=t.children,r=t.parent,u=r.$i18n;if(!u)return o;var a=n.path,s=u.i18next.services.interpolator.regexp,f=u.t(a,{interpolation:{prefix:"#$?",suffix:"?$#"}}),d=[],c={};return o.forEach(function(e){e.data&&e.data.attrs&&e.data.attrs.tkey&&(c[e.data.attrs.tkey]=e)}),f.split(s).reduce(function(e,t,n){var i=void 0;if(n%2==0){if(0===t.length)return e;i=t}else i=o[parseInt(t,10)];return e.push(i),e},d),e(n.tag,i,d)}},e.exports=t.default},function(e,t,n){"use strict";function i(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}Object.defineProperty(t,"__esModule",{value:!0});var o="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},r=function(){function e(e,t){for(var n=0;n<t.length;n++){var i=t[n];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(e,i.key,i)}}return function(t,n,i){return n&&e(t.prototype,n),i&&e(t,i),t}}(),u=n(0),a=function(){function e(t){var n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};i(this,e);var o=n.bindI18n,r=void 0===o?"languageChanged loaded":o,u=n.bindStore,a=void 0===u?"added removed":u;this._vm=null,this.i18next=t,this.onI18nChanged=this.onI18nChanged.bind(this),r&&this.i18next.on(r,this.onI18nChanged),a&&this.i18next.store&&this.i18next.store.on(a,this.onI18nChanged),this.resetVM({i18nLoadedAt:new Date})}return r(e,[{key:"resetVM",value:function(e){var t=this._vm,n=u.Vue.config.silent;u.Vue.config.silent=!0,this._vm=new u.Vue({data:e}),u.Vue.config.silent=n,t&&u.Vue.nextTick(function(){return t.$destroy()})}},{key:"t",value:function(e,t){return this.i18next.t(e,t)}},{key:"onI18nChanged",value:function(){this.i18nLoadedAt=new Date}},{key:"i18nLoadedAt",get:function(){return this._vm.$data.i18nLoadedAt},set:function(e){this._vm.$set(this._vm,"i18nLoadedAt",e)}}]),e}();t.default=a,a.install=u.install,a.version="0.4.0",("undefined"==typeof window?"undefined":o(window))&&window.Vue&&window.Vue.use(a),e.exports=t.default}])});
|
||||
//# sourceMappingURL=vue-i18next.js.map
|
||||
490
BTCPayServer/wwwroot/vendor/jquery-prettydropdowns/jquery.prettydropdowns.js
vendored
Normal file
490
BTCPayServer/wwwroot/vendor/jquery-prettydropdowns/jquery.prettydropdowns.js
vendored
Normal file
@@ -0,0 +1,490 @@
|
||||
/*!
|
||||
* jQuery Pretty Dropdowns Plugin v4.11.0 by T. H. Doan (http://thdoan.github.io/pretty-dropdowns/)
|
||||
*
|
||||
* jQuery Pretty Dropdowns by T. H. Doan is licensed under the MIT License.
|
||||
* Read a copy of the license in the LICENSE file or at
|
||||
* http://choosealicense.com/licenses/mit
|
||||
*/
|
||||
|
||||
(function($) {
|
||||
$.fn.prettyDropdown = function(oOptions) {
|
||||
|
||||
// Default options
|
||||
oOptions = $.extend({
|
||||
classic: false,
|
||||
customClass: 'arrow',
|
||||
height: 50,
|
||||
hoverIntent: 200,
|
||||
multiDelimiter: '; ',
|
||||
multiVerbosity: 99,
|
||||
selectedMarker: '✓',
|
||||
reverse: false,
|
||||
afterLoad: function(){}
|
||||
}, oOptions);
|
||||
|
||||
oOptions.selectedMarker = '<span aria-hidden="true" class="checked"> ' + oOptions.selectedMarker + '</span>';
|
||||
// Validate options
|
||||
if (isNaN(oOptions.height) || oOptions.height<8) oOptions.height = 8;
|
||||
if (isNaN(oOptions.hoverIntent) || oOptions.hoverIntent<0) oOptions.hoverIntent = 200;
|
||||
if (isNaN(oOptions.multiVerbosity)) oOptions.multiVerbosity = 99;
|
||||
|
||||
// Translatable strings
|
||||
var MULTI_NONE = 'None selected',
|
||||
MULTI_PREFIX = 'Selected: ',
|
||||
MULTI_POSTFIX = ' selected';
|
||||
|
||||
// Globals
|
||||
var $current,
|
||||
aKeys = [
|
||||
'0','1','2','3','4','5','6','7','8','9',,,,,,,,
|
||||
'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'
|
||||
],
|
||||
nCount,
|
||||
nHoverIndex,
|
||||
nLastIndex,
|
||||
nTimer,
|
||||
nTimestamp,
|
||||
|
||||
// Initiate pretty drop-downs
|
||||
init = function(elSel) {
|
||||
var $select = $(elSel),
|
||||
nSize = elSel.size,
|
||||
sId = elSel.name || elSel.id || '',
|
||||
sLabelId;
|
||||
// Exit if widget has already been initiated
|
||||
if ($select.data('loaded')) return;
|
||||
// Remove 'size' attribute to it doesn't affect vertical alignment
|
||||
$select.data('size', nSize).removeAttr('size');
|
||||
// Set <select> height to reserve space for <div> container
|
||||
$select.css('visibility', 'hidden').outerHeight(oOptions.height);
|
||||
nTimestamp = +new Date();
|
||||
// Test whether to add 'aria-labelledby'
|
||||
if (elSel.id) {
|
||||
// Look for <label>
|
||||
var $label = $('label[for=' + elSel.id + ']');
|
||||
if ($label.length) {
|
||||
// Add 'id' to <label> if necessary
|
||||
if ($label.attr('id') && !/^menu\d{13,}$/.test($label.attr('id'))) sLabelId = $label.attr('id');
|
||||
else $label.attr('id', (sLabelId = 'menu' + nTimestamp));
|
||||
}
|
||||
}
|
||||
nCount = 0;
|
||||
var $items = $('optgroup, option', $select),
|
||||
$selected = $items.filter(':selected'),
|
||||
bMultiple = elSel.multiple,
|
||||
// Height - 2px for borders
|
||||
sHtml = '<ul' + (elSel.disabled ? '' : ' tabindex="0"') + ' role="listbox"'
|
||||
+ (elSel.title ? ' title="' + elSel.title + '" aria-label="' + elSel.title + '"' : '')
|
||||
+ (sLabelId ? ' aria-labelledby="' + sLabelId + '"' : '')
|
||||
+ ' aria-activedescendant="item' + nTimestamp + '-1" aria-expanded="false"'
|
||||
+ ' style="max-height:' + (oOptions.height-2) + 'px;margin:'
|
||||
// NOTE: $select.css('margin') returns an empty string in Firefox, so we have to get
|
||||
// each margin individually. See https://github.com/jquery/jquery/issues/3383
|
||||
+ $select.css('margin-top') + ' '
|
||||
+ $select.css('margin-right') + ' '
|
||||
+ $select.css('margin-bottom') + ' '
|
||||
+ $select.css('margin-left') + ';">';
|
||||
if (bMultiple) {
|
||||
sHtml += renderItem(null, 'selected');
|
||||
$items.each(function() {
|
||||
if (this.selected) {
|
||||
sHtml += renderItem(this, '', true)
|
||||
} else {
|
||||
sHtml += renderItem(this);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
if (oOptions.classic) {
|
||||
$items.each(function() {
|
||||
sHtml += renderItem(this);
|
||||
});
|
||||
} else {
|
||||
sHtml += renderItem($selected[0], 'selected');
|
||||
$items.filter(':not(:selected)').each(function() {
|
||||
sHtml += renderItem(this);
|
||||
});
|
||||
}
|
||||
}
|
||||
sHtml += '</ul>';
|
||||
$select.wrap('<div ' + (sId ? 'id="prettydropdown-' + sId + '" ' : '')
|
||||
+ 'class="prettydropdown '
|
||||
+ (oOptions.classic ? 'classic ' : '')
|
||||
+ (elSel.disabled ? 'disabled ' : '')
|
||||
+ (bMultiple ? 'multiple ' : '')
|
||||
+ oOptions.customClass + ' loading"'
|
||||
// NOTE: For some reason, the container height is larger by 1px if the <select> has the
|
||||
// 'multiple' attribute or 'size' attribute with a value larger than 1. To fix this, we
|
||||
// have to inline the height.
|
||||
+ ((bMultiple || nSize>1) ? ' style="height:' + oOptions.height + 'px;"' : '')
|
||||
+'></div>').before(sHtml).data('loaded', true);
|
||||
var $dropdown = $select.parent().children('ul'),
|
||||
nWidth = $dropdown.outerWidth(true),
|
||||
nOuterWidth;
|
||||
$items = $dropdown.children();
|
||||
// Update default selected values for multi-select menu
|
||||
if (bMultiple) updateSelected($dropdown);
|
||||
else if (oOptions.classic) $('[data-value="' + $selected.val() + '"]', $dropdown).addClass('selected').append(oOptions.selectedMarker);
|
||||
// Calculate width if initially hidden
|
||||
if ($dropdown.width()<=0) {
|
||||
var $clone = $dropdown.parent().clone().css({
|
||||
position: 'absolute',
|
||||
top: '-100%'
|
||||
});
|
||||
$('body').append($clone);
|
||||
nWidth = $clone.children('ul').outerWidth(true);
|
||||
$('li', $clone).width(nWidth);
|
||||
nOuterWidth = $clone.children('ul').outerWidth(true);
|
||||
$clone.remove();
|
||||
}
|
||||
// Set dropdown width and event handler
|
||||
// NOTE: Setting width using width(), then css() because width() only can return a float,
|
||||
// which can result in a missing right border when there is a scrollbar.
|
||||
$items.width(nWidth).css('width', $items.css('width')).click(function() {
|
||||
var $li = $(this),
|
||||
$selected = $dropdown.children('.selected');
|
||||
// Ignore disabled menu
|
||||
if ($dropdown.parent().hasClass('disabled')) return;
|
||||
// Only update if not disabled, not a label, and a different value selected
|
||||
if ($dropdown.hasClass('active') && !$li.hasClass('disabled') && !$li.hasClass('label') && $li.data('value')!==$selected.data('value')) {
|
||||
// Select highlighted item
|
||||
if (bMultiple) {
|
||||
if ($li.children('span.checked').length) $li.children('span.checked').remove();
|
||||
else $li.append(oOptions.selectedMarker);
|
||||
// Sync <select> element
|
||||
$dropdown.children(':not(.selected)').each(function(nIndex) {
|
||||
$('optgroup, option', $select).eq(nIndex).prop('selected', $(this).children('span.checked').length>0);
|
||||
});
|
||||
// Update selected values for multi-select menu
|
||||
updateSelected($dropdown);
|
||||
} else {
|
||||
$selected.removeClass('selected').children('span.checked').remove();
|
||||
$li.addClass('selected').append(oOptions.selectedMarker);
|
||||
if (!oOptions.classic) $dropdown.prepend($li);
|
||||
$dropdown.removeClass('reverse').attr('aria-activedescendant', $li.attr('id'));
|
||||
if ($selected.data('group') && !oOptions.classic) $dropdown.children('.label').filter(function() {
|
||||
return $(this).text()===$selected.data('group');
|
||||
}).after($selected);
|
||||
// Sync <select> element
|
||||
$('optgroup, option', $select).filter(function() {
|
||||
// NOTE: .data('value') can return numeric, so using == comparison instead.
|
||||
return this.value==$li.data('value') || this.text===$li.contents().filter(function() {
|
||||
// Filter out selected marker
|
||||
return this.nodeType===3;
|
||||
}).text();
|
||||
}).prop('selected', true);
|
||||
}
|
||||
$select.trigger('change');
|
||||
}
|
||||
if ($li.hasClass('selected') || !bMultiple) {
|
||||
$dropdown.toggleClass('active');
|
||||
$dropdown.attr('aria-expanded', $dropdown.hasClass('active'));
|
||||
}
|
||||
// Try to keep drop-down menu within viewport
|
||||
if ($dropdown.hasClass('active')) {
|
||||
// Close any other open menus
|
||||
if ($('.prettydropdown > ul.active').length>1) resetDropdown($('.prettydropdown > ul.active').not($dropdown)[0]);
|
||||
var nWinHeight = window.innerHeight,
|
||||
nMaxHeight,
|
||||
nOffsetTop = $dropdown.offset().top,
|
||||
nScrollTop = document.body.scrollTop,
|
||||
nDropdownHeight = $dropdown.outerHeight();
|
||||
if (nSize) {
|
||||
nMaxHeight = nSize*(oOptions.height-2);
|
||||
if (nMaxHeight<nDropdownHeight-2) nDropdownHeight = nMaxHeight+2;
|
||||
}
|
||||
var nDropdownBottom = nOffsetTop-nScrollTop+nDropdownHeight;
|
||||
if (nDropdownBottom > nWinHeight ||
|
||||
oOptions.reverse) {
|
||||
// Expand to direction that has the most space
|
||||
if (nOffsetTop - nScrollTop > nWinHeight - (nOffsetTop - nScrollTop + oOptions.height) ||
|
||||
oOptions.reverse) {
|
||||
$dropdown.addClass('reverse');
|
||||
if (!oOptions.classic) $dropdown.append($selected);
|
||||
if (nOffsetTop-nScrollTop+oOptions.height<nDropdownHeight) {
|
||||
$dropdown.outerHeight(nOffsetTop-nScrollTop+oOptions.height);
|
||||
// Ensure the selected item is in view
|
||||
$dropdown.scrollTop(nDropdownHeight);
|
||||
}
|
||||
} else {
|
||||
$dropdown.height($dropdown.height()-(nDropdownBottom-nWinHeight));
|
||||
}
|
||||
}
|
||||
if (nMaxHeight && nMaxHeight<$dropdown.height()) $dropdown.css('height', nMaxHeight + 'px');
|
||||
// Ensure the selected item is in view
|
||||
if (oOptions.classic) $dropdown.scrollTop($selected.index()*(oOptions.height-2));
|
||||
} else {
|
||||
$dropdown.data('clicked', true);
|
||||
resetDropdown($dropdown[0]);
|
||||
}
|
||||
});
|
||||
$dropdown.on({
|
||||
focusin: function() {
|
||||
// Unregister any existing handlers first to prevent duplicate firings
|
||||
$(window).off('keydown', handleKeypress).on('keydown', handleKeypress);
|
||||
},
|
||||
focusout: function() {
|
||||
$(window).off('keydown', handleKeypress);
|
||||
},
|
||||
mouseenter: function() {
|
||||
$dropdown.data('hover', true);
|
||||
},
|
||||
mouseleave: resetDropdown,
|
||||
mousemove: hoverDropdownItem
|
||||
});
|
||||
// Put focus on menu when user clicks on label
|
||||
if (sLabelId) $('#' + sLabelId).off('click', handleFocus).click(handleFocus);
|
||||
// Done with everything!
|
||||
$dropdown.parent().width(nOuterWidth||$dropdown.outerWidth(true)).removeClass('loading');
|
||||
oOptions.afterLoad();
|
||||
},
|
||||
|
||||
// Manage widget focusing
|
||||
handleFocus = function(e) {
|
||||
$('ul[aria-labelledby=' + e.target.id + ']').focus();
|
||||
},
|
||||
|
||||
// Manage keyboard navigation
|
||||
handleKeypress = function(e) {
|
||||
var $dropdown = $('.prettydropdown > ul.active, .prettydropdown > ul:focus');
|
||||
if (!$dropdown.length) return;
|
||||
if (e.which===9) { // Tab
|
||||
resetDropdown($dropdown[0]);
|
||||
return;
|
||||
} else {
|
||||
// Intercept non-Tab keys only
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
}
|
||||
var $items = $dropdown.children(),
|
||||
bOpen = $dropdown.hasClass('active'),
|
||||
nItemsHeight = $dropdown.height()/(oOptions.height-2),
|
||||
nItemsPerPage = nItemsHeight%1<0.5 ? Math.floor(nItemsHeight) : Math.ceil(nItemsHeight),
|
||||
sKey;
|
||||
nHoverIndex = Math.max(0, $dropdown.children('.hover').index());
|
||||
nLastIndex = $items.length-1;
|
||||
$current = $items.eq(nHoverIndex);
|
||||
$dropdown.data('lastKeypress', +new Date());
|
||||
switch (e.which) {
|
||||
case 13: // Enter
|
||||
if (!bOpen) {
|
||||
$current = $items.filter('.selected');
|
||||
toggleHover($current, 1);
|
||||
}
|
||||
$current.click();
|
||||
break;
|
||||
case 27: // Esc
|
||||
if (bOpen) resetDropdown($dropdown[0]);
|
||||
break;
|
||||
case 32: // Space
|
||||
if (bOpen) {
|
||||
sKey = ' ';
|
||||
} else {
|
||||
$current = $items.filter('.selected');
|
||||
toggleHover($current, 1);
|
||||
$current.click();
|
||||
}
|
||||
break;
|
||||
case 33: // Page Up
|
||||
if (bOpen) {
|
||||
toggleHover($current, 0);
|
||||
toggleHover($items.eq(Math.max(nHoverIndex-nItemsPerPage-1, 0)), 1);
|
||||
}
|
||||
break;
|
||||
case 34: // Page Down
|
||||
if (bOpen) {
|
||||
toggleHover($current, 0);
|
||||
toggleHover($items.eq(Math.min(nHoverIndex+nItemsPerPage-1, nLastIndex)), 1);
|
||||
}
|
||||
break;
|
||||
case 35: // End
|
||||
if (bOpen) {
|
||||
toggleHover($current, 0);
|
||||
toggleHover($items.eq(nLastIndex), 1);
|
||||
}
|
||||
break;
|
||||
case 36: // Home
|
||||
if (bOpen) {
|
||||
toggleHover($current, 0);
|
||||
toggleHover($items.eq(0), 1);
|
||||
}
|
||||
break;
|
||||
case 38: // Up
|
||||
if (bOpen) {
|
||||
toggleHover($current, 0);
|
||||
// If not already key-navigated or first item is selected, cycle to the last item; or
|
||||
// else select the previous item
|
||||
toggleHover(nHoverIndex ? $items.eq(nHoverIndex-1) : $items.eq(nLastIndex), 1);
|
||||
}
|
||||
break;
|
||||
case 40: // Down
|
||||
if (bOpen) {
|
||||
toggleHover($current, 0);
|
||||
// If last item is selected, cycle to the first item; or else select the next item
|
||||
toggleHover(nHoverIndex===nLastIndex ? $items.eq(0) : $items.eq(nHoverIndex+1), 1);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (bOpen) sKey = aKeys[e.which-48];
|
||||
}
|
||||
if (sKey) { // Alphanumeric key pressed
|
||||
clearTimeout(nTimer);
|
||||
$dropdown.data('keysPressed', $dropdown.data('keysPressed')===undefined ? sKey : $dropdown.data('keysPressed') + sKey);
|
||||
nTimer = setTimeout(function() {
|
||||
$dropdown.removeData('keysPressed');
|
||||
// NOTE: Windows keyboard repeat delay is 250-1000 ms. See
|
||||
// https://technet.microsoft.com/en-us/library/cc978658.aspx
|
||||
}, 300);
|
||||
// Build index of matches
|
||||
var aMatches = [],
|
||||
nCurrentIndex = $current.index();
|
||||
$items.each(function(nIndex) {
|
||||
if ($(this).text().toLowerCase().indexOf($dropdown.data('keysPressed'))===0) aMatches.push(nIndex);
|
||||
});
|
||||
if (aMatches.length) {
|
||||
// Cycle through items matching key(s) pressed
|
||||
for (var i=0; i<aMatches.length; ++i) {
|
||||
if (aMatches[i]>nCurrentIndex) {
|
||||
toggleHover($items, 0);
|
||||
toggleHover($items.eq(aMatches[i]), 1);
|
||||
break;
|
||||
}
|
||||
if (i===aMatches.length-1) {
|
||||
toggleHover($items, 0);
|
||||
toggleHover($items.eq(aMatches[0]), 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// Highlight menu item
|
||||
hoverDropdownItem = function(e) {
|
||||
var $dropdown = $(e.currentTarget);
|
||||
if (e.target.nodeName!=='LI' || !$dropdown.hasClass('active') || new Date()-$dropdown.data('lastKeypress')<200) return;
|
||||
toggleHover($dropdown.children(), 0, 1);
|
||||
toggleHover($(e.target), 1, 1);
|
||||
},
|
||||
|
||||
// Construct menu item
|
||||
// elOpt is null for first item in multi-select menus
|
||||
renderItem = function(elOpt, sClass, bSelected) {
|
||||
var sGroup = '',
|
||||
sText = '',
|
||||
sTitle;
|
||||
sClass = sClass || '';
|
||||
if (elOpt) {
|
||||
switch (elOpt.nodeName) {
|
||||
case 'OPTION':
|
||||
if (elOpt.parentNode.nodeName==='OPTGROUP') sGroup = elOpt.parentNode.getAttribute('label');
|
||||
sText = (elOpt.getAttribute('data-prefix') || '') + elOpt.text + (elOpt.getAttribute('data-suffix') || '');
|
||||
break;
|
||||
case 'OPTGROUP':
|
||||
sClass += ' label';
|
||||
sText = elOpt.getAttribute('label');
|
||||
break;
|
||||
}
|
||||
if (elOpt.disabled || (sGroup && elOpt.parentNode.disabled)) sClass += ' disabled';
|
||||
sTitle = elOpt.title;
|
||||
if (sGroup && !sTitle) sTitle = elOpt.parentNode.title;
|
||||
}
|
||||
++nCount;
|
||||
return '<li id="item' + nTimestamp + '-' + nCount + '"'
|
||||
+ (sGroup ? ' data-group="' + sGroup + '"' : '')
|
||||
+ (elOpt && elOpt.value ? ' data-value="' + elOpt.value + '"' : '')
|
||||
+ (elOpt && elOpt.nodeName==='OPTION' ? ' role="option"' : '')
|
||||
+ (sTitle ? ' title="' + sTitle + '" aria-label="' + sTitle + '"' : '')
|
||||
+ (sClass ? ' class="' + $.trim(sClass) + '"' : '')
|
||||
+ ((oOptions.height!==50) ? ' style="height:' + (oOptions.height-2)
|
||||
+ 'px;line-height:' + (oOptions.height-4) + 'px;"' : '') + '>' + sText
|
||||
+ ((bSelected || sClass==='selected') ? oOptions.selectedMarker : '') + '</li>';
|
||||
},
|
||||
|
||||
// Reset menu state
|
||||
// @param o Event or Element object
|
||||
resetDropdown = function(o) {
|
||||
var $dropdown = $(o.currentTarget||o);
|
||||
// NOTE: Sometimes it's possible for $dropdown to point to the wrong element when you
|
||||
// quickly hover over another menu. To prevent this, we need to check for .active as a
|
||||
// backup and manually reassign $dropdown. This also requires that it's not clicked on
|
||||
// because in rare cases the reassignment fails and the reverse menu will not get reset.
|
||||
if (o.type==='mouseleave' && !$dropdown.hasClass('active') && !$dropdown.data('clicked')) $dropdown = $('.prettydropdown > ul.active');
|
||||
$dropdown.data('hover', false);
|
||||
clearTimeout(nTimer);
|
||||
nTimer = setTimeout(function() {
|
||||
if ($dropdown.data('hover')) return;
|
||||
if ($dropdown.hasClass('reverse') && !oOptions.classic) $dropdown.prepend($dropdown.children(':last-child'));
|
||||
$dropdown.removeClass('active reverse').removeData('clicked').attr('aria-expanded', 'false').css('height', '');
|
||||
$dropdown.children().removeClass('hover nohover');
|
||||
}, (o.type==='mouseleave' && !$dropdown.data('clicked')) ? oOptions.hoverIntent : 0);
|
||||
},
|
||||
|
||||
// Set menu item hover state
|
||||
// bNoScroll set on hoverDropdownItem()
|
||||
toggleHover = function($li, bOn, bNoScroll) {
|
||||
if (bOn) {
|
||||
$li.removeClass('nohover').addClass('hover');
|
||||
if ($li.length===1 && $current && !bNoScroll) {
|
||||
// Ensure items are always in view
|
||||
var $dropdown = $li.parent(),
|
||||
nDropdownHeight = $dropdown.outerHeight(),
|
||||
nItemOffset = $li.offset().top-$dropdown.offset().top-1; // -1px for top border
|
||||
if ($li.index()===0) {
|
||||
$dropdown.scrollTop(0);
|
||||
} else if ($li.index()===nLastIndex) {
|
||||
$dropdown.scrollTop($dropdown.children().length*oOptions.height);
|
||||
} else {
|
||||
if (nItemOffset+oOptions.height>nDropdownHeight) $dropdown.scrollTop($dropdown.scrollTop()+oOptions.height+nItemOffset-nDropdownHeight);
|
||||
else if (nItemOffset<0) $dropdown.scrollTop($dropdown.scrollTop()+nItemOffset);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$li.removeClass('hover').addClass('nohover');
|
||||
}
|
||||
},
|
||||
|
||||
// Update selected values for multi-select menu
|
||||
updateSelected = function($dropdown) {
|
||||
var $select = $dropdown.parent().children('select'),
|
||||
aSelected = $('option', $select).map(function() {
|
||||
if (this.selected) return this.text;
|
||||
}).get(),
|
||||
sSelected;
|
||||
if (oOptions.multiVerbosity>=aSelected.length) sSelected = aSelected.join(oOptions.multiDelimiter) || MULTI_NONE;
|
||||
else sSelected = aSelected.length + '/' + $('option', $select).length + MULTI_POSTFIX;
|
||||
if (sSelected) {
|
||||
var sTitle = ($select.attr('title') ? $select.attr('title') : '') + (aSelected.length ? '\n' + MULTI_PREFIX + aSelected.join(oOptions.multiDelimiter) : '');
|
||||
$dropdown.children('.selected').text(sSelected);
|
||||
$dropdown.attr({
|
||||
'title': sTitle,
|
||||
'aria-label': sTitle
|
||||
});
|
||||
} else {
|
||||
$dropdown.children('.selected').empty();
|
||||
$dropdown.attr({
|
||||
'title': $select.attr('title'),
|
||||
'aria-label': $select.attr('title')
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Public Functions
|
||||
*/
|
||||
|
||||
// Resync the menu with <select> to reflect state changes
|
||||
this.refresh = function(oOptions) {
|
||||
return this.each(function() {
|
||||
var $select = $(this);
|
||||
$select.prevAll('ul').remove();
|
||||
$select.unwrap().data('loaded', false);
|
||||
this.size = $select.data('size');
|
||||
init(this);
|
||||
});
|
||||
};
|
||||
|
||||
return this.each(function() {
|
||||
init(this);
|
||||
});
|
||||
|
||||
};
|
||||
}(jQuery));
|
||||
206
BTCPayServer/wwwroot/vendor/jquery-prettydropdowns/prettydropdowns.css
vendored
Normal file
206
BTCPayServer/wwwroot/vendor/jquery-prettydropdowns/prettydropdowns.css
vendored
Normal file
@@ -0,0 +1,206 @@
|
||||
.prettydropdown {
|
||||
position: relative;
|
||||
min-width: 72px; /* 70px + borders */
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.prettydropdown.loading {
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.prettydropdown > ul {
|
||||
border-radius: 5px;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
background: #fff;
|
||||
border: 1px solid #a9a9a9;
|
||||
box-sizing: content-box;
|
||||
color: #000;
|
||||
cursor: pointer;
|
||||
font: normal 18px Calibri, sans-serif;
|
||||
list-style-type: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
text-align: left;
|
||||
-webkit-user-select: none; /* Chrome all / Safari all */
|
||||
-moz-user-select: none; /* Firefox all */
|
||||
-ms-user-select: none; /* IE 10+ */
|
||||
user-select: none; /* Likely future */
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.prettydropdown.loading > ul {
|
||||
visibility: hidden;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.prettydropdown > ul:focus, .prettydropdown:not(.disabled) > ul:hover {
|
||||
border-color: #7f7f7f;
|
||||
}
|
||||
|
||||
.prettydropdown:not(.disabled) > ul.active {
|
||||
width: auto;
|
||||
max-height: 400px !important;
|
||||
border-color: #1e90ff;
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
z-index: 99;
|
||||
}
|
||||
|
||||
.prettydropdown > ul.active:focus {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.prettydropdown > ul.active.reverse {
|
||||
top: auto;
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
.prettydropdown > ul > li {
|
||||
font-size: 14px;
|
||||
position: relative;
|
||||
min-width: 70px;
|
||||
height: 48px; /* 50px - borders */
|
||||
border-top: 1px solid transparent;
|
||||
border-bottom: 1px solid transparent;
|
||||
box-sizing: border-box;
|
||||
display: none;
|
||||
line-height: 46px; /* 48px - borders */
|
||||
margin: 0;
|
||||
padding-left: 0.8rem;
|
||||
}
|
||||
|
||||
.prettydropdown.loading > ul > li {
|
||||
min-width: 0;
|
||||
display: block;
|
||||
padding-right: 0.8rem;
|
||||
}
|
||||
|
||||
.prettydropdown > ul:not(.active) > li:not(.selected):first-child {
|
||||
color: transparent; /* Prevent FOUC */
|
||||
}
|
||||
|
||||
.prettydropdown > ul > li:first-child, .prettydropdown > ul.active > li {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.prettydropdown > ul.active > li:not(.label):hover, .prettydropdown > ul.active > li.hover:not(.label), .prettydropdown > ul.active > li:first-child:hover:after {
|
||||
background: #1e90ff;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.prettydropdown > ul.active > li.nohover {
|
||||
background: inherit !important;
|
||||
color: inherit !important;
|
||||
}
|
||||
|
||||
.prettydropdown > ul.active > li.hover:before, .prettydropdown > ul.active > li.nohover:after {
|
||||
border-top-color: #fff !important;
|
||||
}
|
||||
|
||||
.prettydropdown > ul.active > li.hover:after, .prettydropdown > ul.active > li.nohover:before {
|
||||
border-top-color: #1e90ff !important;
|
||||
}
|
||||
|
||||
.prettydropdown.arrow > ul > li.selected:before, .prettydropdown.arrow > ul > li.selected:after {
|
||||
position: absolute;
|
||||
top: 8px;
|
||||
bottom: 0;
|
||||
right: 8px;
|
||||
height: 16px;
|
||||
border: 8px solid transparent; /* Arrow size */
|
||||
box-sizing: border-box;
|
||||
content: '';
|
||||
display: block;
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
.prettydropdown.arrow.small > ul > li.selected:before, .prettydropdown.arrow.small > ul > li.selected:after {
|
||||
top: 4px;
|
||||
height: 8px;
|
||||
border-width: 4px;
|
||||
}
|
||||
|
||||
.prettydropdown.arrow > ul > li.selected:before {
|
||||
border-top-color: #a9a9a9; /* Arrow color */
|
||||
}
|
||||
|
||||
.prettydropdown.arrow > ul > li.selected:after {
|
||||
top: 4px; /* Chevron thickness */
|
||||
border-top-color: #fff; /* Match background colour */
|
||||
}
|
||||
|
||||
.prettydropdown.arrow.small > ul > li.selected:after {
|
||||
top: 2px; /* Chevron thickness */
|
||||
}
|
||||
|
||||
.prettydropdown.arrow.triangle > ul > li.selected:after {
|
||||
content: none;
|
||||
}
|
||||
|
||||
.prettydropdown > ul:hover > li.selected:before {
|
||||
border-top-color: #7f7f7f;
|
||||
}
|
||||
|
||||
.prettydropdown > ul.active > li.selected:before,
|
||||
.prettydropdown > ul.active > li.selected:after {
|
||||
border: none;
|
||||
}
|
||||
|
||||
.prettydropdown > ul:not(.active) > li > span.checked {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Multi-Select */
|
||||
.prettydropdown.multiple > ul > li.selected {
|
||||
overflow: hidden;
|
||||
padding-right: 2rem;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.prettydropdown > ul > li > span.checked {
|
||||
clear: both;
|
||||
float: right;
|
||||
font-weight: bold;
|
||||
margin-right: 0.8rem;
|
||||
}
|
||||
|
||||
/* Option Groups */
|
||||
.prettydropdown > ul > li.label {
|
||||
cursor: default;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.prettydropdown > ul > li.label:first-child,
|
||||
.prettydropdown.classic > ul > li.label ~ li.selected {
|
||||
border-top: none;
|
||||
}
|
||||
|
||||
.prettydropdown > ul > li.label ~ li:not(.label):not(.selected),
|
||||
.prettydropdown.classic > ul.active > li.label ~ li:not(.label) {
|
||||
padding-left: 1.6rem;
|
||||
}
|
||||
|
||||
/* Classic Behavior */
|
||||
.prettydropdown.classic > ul:not(.active) > li.selected:not(:first-child) {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
display: block;
|
||||
}
|
||||
|
||||
/* Disabled */
|
||||
.prettydropdown.disabled, .prettydropdown > ul > li.disabled {
|
||||
opacity: 0.3;
|
||||
}
|
||||
|
||||
.prettydropdown.disabled > ul > li, .prettydropdown > ul > li.disabled {
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
/* Divider Lines */
|
||||
.prettydropdown.multiple > ul > li.selected + li, .prettydropdown.multiple > ul.reverse > li.selected,
|
||||
.prettydropdown > ul > li.label, .prettydropdown > ul > li.label ~ li.selected {
|
||||
border-top-color: #dedede;
|
||||
}
|
||||
Reference in New Issue
Block a user