From 03a0044745507d1395b2b5f75a4af6e9392e0a83 Mon Sep 17 00:00:00 2001 From: lepipele Date: Fri, 2 Mar 2018 23:42:17 -0600 Subject: [PATCH 1/7] Currency selection moved to top of the form --- BTCPayServer/Views/Invoice/Checkout.cshtml | 36 +++++++++++++--------- BTCPayServer/wwwroot/css/normalizer.css | 11 +++++++ BTCPayServer/wwwroot/js/core.js | 6 ++++ 3 files changed, 38 insertions(+), 15 deletions(-) diff --git a/BTCPayServer/Views/Invoice/Checkout.cshtml b/BTCPayServer/Views/Invoice/Checkout.cshtml index 044feb294..35a4eb4a9 100644 --- a/BTCPayServer/Views/Invoice/Checkout.cshtml +++ b/BTCPayServer/Views/Invoice/Checkout.cshtml @@ -72,7 +72,7 @@ - +
@@ -87,6 +87,26 @@
@Model.TimeLeft
+ @if (Model.AvailableCryptos.Count > 1) + { +
+
+
+ Currency Selection +
+
+
+
+ @foreach (var crypto in Model.AvailableCryptos) + { + + @crypto.PaymentMethodId + + } +
+
+
+ }
@@ -600,20 +620,6 @@
- diff --git a/BTCPayServer/wwwroot/css/normalizer.css b/BTCPayServer/wwwroot/css/normalizer.css index 4ea32122b..c37d4dc0f 100644 --- a/BTCPayServer/wwwroot/css/normalizer.css +++ b/BTCPayServer/wwwroot/css/normalizer.css @@ -8411,6 +8411,17 @@ strong { float: right; } +.currency-selection { + border-bottom: 1px solid #E9E9E9; + position: relative; + padding: 4px 15px; + display: flex; + font-weight: 300; + color: #565D6E; + letter-spacing: .45px; + background: #fff; +} + .single-item-order { position: relative; padding: 15px; diff --git a/BTCPayServer/wwwroot/js/core.js b/BTCPayServer/wwwroot/js/core.js index bdd0ac4f3..7f808a2f5 100644 --- a/BTCPayServer/wwwroot/js/core.js +++ b/BTCPayServer/wwwroot/js/core.js @@ -197,6 +197,12 @@ function onDataCallback(jsonData) { checkoutCtrl.srvModel = jsonData; } +function changeCurrency(currency) { + srvModel.paymentMethodId = currency; + fetchStatus(); + return false; +} + function fetchStatus() { var path = srvModel.serverUrl + "/i/" + srvModel.invoiceId + "/" + srvModel.paymentMethodId + "/status"; $.ajax({ From b0c810398c41f8bed184f69c5f2d2b3f6f1378b5 Mon Sep 17 00:00:00 2001 From: lepipele Date: Fri, 2 Mar 2018 23:49:51 -0600 Subject: [PATCH 2/7] Moving currency selection to order details This way state transitions of form are now properly preserved --- BTCPayServer/Views/Invoice/Checkout.cshtml | 40 +++++++++++----------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/BTCPayServer/Views/Invoice/Checkout.cshtml b/BTCPayServer/Views/Invoice/Checkout.cshtml index 35a4eb4a9..9f8ff1c02 100644 --- a/BTCPayServer/Views/Invoice/Checkout.cshtml +++ b/BTCPayServer/Views/Invoice/Checkout.cshtml @@ -87,27 +87,27 @@
@Model.TimeLeft
- @if (Model.AvailableCryptos.Count > 1) - { -
-
-
- Currency Selection -
-
-
-
- @foreach (var crypto in Model.AvailableCryptos) - { - - @crypto.PaymentMethodId - - } -
-
-
- }
+ @if (Model.AvailableCryptos.Count > 1) + { +
+
+
+ Currency Selection +
+
+
+
+ @foreach (var crypto in Model.AvailableCryptos) + { + + @crypto.PaymentMethodId + + } +
+
+
+ }
From acd98aad32476e8b6a0cf7eb2964fb09dd402a62 Mon Sep 17 00:00:00 2001 From: lepipele Date: Sat, 3 Mar 2018 00:11:08 -0600 Subject: [PATCH 3/7] Showing loader for better UX when switching currencies --- BTCPayServer/Views/Invoice/Checkout.cshtml | 7 +++++++ BTCPayServer/wwwroot/css/normalizer.css | 14 ++++++++++++++ BTCPayServer/wwwroot/js/core.js | 14 ++++++++++++-- 3 files changed, 33 insertions(+), 2 deletions(-) diff --git a/BTCPayServer/Views/Invoice/Checkout.cshtml b/BTCPayServer/Views/Invoice/Checkout.cshtml index 9f8ff1c02..abdcdcaec 100644 --- a/BTCPayServer/Views/Invoice/Checkout.cshtml +++ b/BTCPayServer/Views/Invoice/Checkout.cshtml @@ -183,6 +183,13 @@
+
+ + + + + +
diff --git a/BTCPayServer/wwwroot/css/normalizer.css b/BTCPayServer/wwwroot/css/normalizer.css index c37d4dc0f..d7d139328 100644 --- a/BTCPayServer/wwwroot/css/normalizer.css +++ b/BTCPayServer/wwwroot/css/normalizer.css @@ -10892,6 +10892,20 @@ bp-spinner { display: flex; } +.payment__spinner { + margin-top: 140px; + display: none; +} + + .payment__spinner > bp-spinner > svg { + margin: auto auto; + height: 60px; + width: 60px; + fill: gray; + animation: spin 0.55s linear infinite; + opacity: .85; + } + bp-refund-address.ng-valid .bitcoin-logo { opacity: 1; margin-left: 0; diff --git a/BTCPayServer/wwwroot/js/core.js b/BTCPayServer/wwwroot/js/core.js index 7f808a2f5..87a3b6c7d 100644 --- a/BTCPayServer/wwwroot/js/core.js +++ b/BTCPayServer/wwwroot/js/core.js @@ -193,13 +193,23 @@ function onDataCallback(jsonData) { window.parent.postMessage({ "invoiceId": srvModel.invoiceId, "status": newStatus }, "*"); } + // restoring qr code view only when currency is switched + if (jsonData.paymentMethodId == srvModel.paymentMethodId) { + $("#scan").show(); + $(".payment__spinner").hide(); + } + // updating ui checkoutCtrl.srvModel = jsonData; } function changeCurrency(currency) { - srvModel.paymentMethodId = currency; - fetchStatus(); + if (srvModel.paymentMethodId != currency) { + $("#scan").hide(); + $(".payment__spinner").show(); + srvModel.paymentMethodId = currency; + fetchStatus(); + } return false; } From f1e971d047a113d423234d4e29a421633639acb4 Mon Sep 17 00:00:00 2001 From: lepipele Date: Sat, 3 Mar 2018 00:32:04 -0600 Subject: [PATCH 4/7] Refactoring core.js in preparation for bundling Moving Vue registration to body for quick update of page Removing defer dependancy for core.js --- BTCPayServer/Views/Invoice/Checkout.cshtml | 20 +- BTCPayServer/wwwroot/js/core.js | 633 ++++++++++----------- 2 files changed, 327 insertions(+), 326 deletions(-) diff --git a/BTCPayServer/Views/Invoice/Checkout.cshtml b/BTCPayServer/Views/Invoice/Checkout.cshtml index abdcdcaec..a96a6175f 100644 --- a/BTCPayServer/Views/Invoice/Checkout.cshtml +++ b/BTCPayServer/Views/Invoice/Checkout.cshtml @@ -23,7 +23,7 @@ - +
+ diff --git a/BTCPayServer/wwwroot/js/core.js b/BTCPayServer/wwwroot/js/core.js index 87a3b6c7d..916642bfb 100644 --- a/BTCPayServer/wwwroot/js/core.js +++ b/BTCPayServer/wwwroot/js/core.js @@ -1,347 +1,330 @@ +$(document).ready(function () { + /* TAF + + - Version mobile + + - Réparer le décallage par timer + + - Preparer les variables de l'API + + - Gestion des differents evenements en fonction du status de l'invoice + + - sécuriser les CDN + + */ -/* TAF + var display = $(".timer-row__time-left"); // Timer container -- Version mobile + // check if the Document expired + if (srvModel.expirationSeconds > 0) { + progressStart(srvModel.maxTimeSeconds); // Progress bar + startTimer(srvModel.expirationSeconds, display); // Timer -- Réparer le décallage par timer - -- Preparer les variables de l'API - -- Gestion des differents evenements en fonction du status de l'invoice - -- sécuriser les CDN - -*/ - -// TODO: Vue controller... complete migrate to it for binding, animations can stay in jQuery -Vue.config.ignoredElements = [ - 'line-items', - 'low-fee-timeline', - // Ignoring custom HTML5 elements, eg: bp-spinner - /^bp-/ -]; -var checkoutCtrl = new Vue({ - el: '#checkoutCtrl', - components: { - qrcode: VueQr - }, - data: { - srvModel: srvModel - } -}); - -var display = $(".timer-row__time-left"); // Timer container - -// check if the Document expired -if (srvModel.expirationSeconds > 0) { - - progressStart(srvModel.maxTimeSeconds); // Progress bar - startTimer(srvModel.expirationSeconds, display); // Timer - - if (!validateEmail(srvModel.customerEmail)) - emailForm(); // Email form Display - else - hideEmailForm(); -} - - -function hideEmailForm() { - $("[role=document]").removeClass("enter-purchaser-email"); - $("#emailAddressView").removeClass("active"); - $("placeholder-refundEmail").html(srvModel.customerEmail); - - // Remove Email mode - $(".modal-dialog").removeClass("enter-purchaser-email"); - $("#scan").addClass("active"); -} -// Email Form -// Setup Email mode -function emailForm() { - - $(".modal-dialog").addClass("enter-purchaser-email"); - - $("#emailAddressForm .action-button").click(function () { - var emailAddress = $("#emailAddressFormInput").val(); - if (validateEmail(emailAddress)) { - $("#emailAddressForm .input-wrapper bp-loading-button .action-button").addClass("loading"); - // Push the email to a server, once the reception is confirmed move on - srvModel.customerEmail = emailAddress; - - var path = srvModel.serverUrl + "/i/" + srvModel.invoiceId + "/UpdateCustomer"; - - $.ajax({ - url: path, - type: "POST", - data: JSON.stringify({ Email: srvModel.customerEmail }), - contentType: "application/json; charset=utf-8" - }).done(function () { - hideEmailForm(); - }) - .fail(function (jqXHR, textStatus, errorThrown) { - - }) - .always(function () { - $("#emailAddressForm .input-wrapper bp-loading-button .action-button").removeClass("loading"); - }); - } else { - - $("#emailAddressForm").addClass("ng-touched ng-dirty ng-submitted ng-invalid"); - - } - }); -} - -/* =============== Even listeners =============== */ - -// Email -$("#emailAddressFormInput").change(function () { - if ($("#emailAddressForm").hasClass("ng-submitted")) { - $("#emailAddressForm").removeClass("ng-submitted"); - } -}); - - -// Scan/Copy Transitions -// Scan Tab -$("#scan-tab").click(function () { - if (!$(this).is(".active")) { - $(this).addClass("active"); + if (!validateEmail(srvModel.customerEmail)) + emailForm(); // Email form Display + else + hideEmailForm(); } - if ($("#copy-tab").is(".active")) { - $("#copy-tab").removeClass("active"); - } - $(".payment-tabs__slider").removeClass("slide-right"); + function hideEmailForm() { + $("[role=document]").removeClass("enter-purchaser-email"); + $("#emailAddressView").removeClass("active"); + $("placeholder-refundEmail").html(srvModel.customerEmail); - if (!$("#scan").is(".active")) { - $("#copy").hide(); - $("#copy").removeClass("active"); - - $("#scan").show(); + // Remove Email mode + $(".modal-dialog").removeClass("enter-purchaser-email"); $("#scan").addClass("active"); } -}); + // Email Form + // Setup Email mode + function emailForm() { + $(".modal-dialog").addClass("enter-purchaser-email"); -// Main Copy tab -$("#copy-tab").click(function () { - if (!$(this).is(".active")) { - $(this).addClass("active"); + $("#emailAddressForm .action-button").click(function () { + var emailAddress = $("#emailAddressFormInput").val(); + if (validateEmail(emailAddress)) { + $("#emailAddressForm .input-wrapper bp-loading-button .action-button").addClass("loading"); + // Push the email to a server, once the reception is confirmed move on + srvModel.customerEmail = emailAddress; + + var path = srvModel.serverUrl + "/i/" + srvModel.invoiceId + "/UpdateCustomer"; + + $.ajax({ + url: path, + type: "POST", + data: JSON.stringify({ Email: srvModel.customerEmail }), + contentType: "application/json; charset=utf-8" + }).done(function () { + hideEmailForm(); + }) + .fail(function (jqXHR, textStatus, errorThrown) { + + }) + .always(function () { + $("#emailAddressForm .input-wrapper bp-loading-button .action-button").removeClass("loading"); + }); + } else { + + $("#emailAddressForm").addClass("ng-touched ng-dirty ng-submitted ng-invalid"); + + } + }); } - if ($("#scan-tab").is(".active")) { - $("#scan-tab").removeClass("active"); - } - if (!$(".payment-tabs__slider").is("slide-right")) { - $(".payment-tabs__slider").addClass("slide-right"); - } + /* =============== Even listeners =============== */ - if (!$("#copy").is(".active")) { - $("#copy").show(); - $("#copy").addClass("active"); - - $("#scan").hide(); - $("#scan").removeClass("active"); - } -}); - -// Payment received -// Should connect using webhook ? -// If notification received - -onDataCallback(srvModel); - -function onDataCallback(jsonData) { - var newStatus = jsonData.status; - - if (newStatus === "complete" || - newStatus === "confirmed" || - newStatus === "paid") { - if ($(".modal-dialog").hasClass("expired")) { - $(".modal-dialog").removeClass("expired"); + // Email + $("#emailAddressFormInput").change(function () { + if ($("#emailAddressForm").hasClass("ng-submitted")) { + $("#emailAddressForm").removeClass("ng-submitted"); } - - if (srvModel.merchantRefLink !== "") { - $(".action-button").click(function () { - window.location.href = srvModel.merchantRefLink; - }); - } - else { - $(".action-button").hide(); - } - - $(".modal-dialog").addClass("paid"); - - if ($("#scan").hasClass("active")) { - $("#scan").removeClass("active"); - } else if ($("#copy").hasClass("active")) { - $("#copy").removeClass("active"); - } - $("#paid").addClass("active"); - } - - 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"); - $("#expired").addClass("active"); - } - - if (checkoutCtrl.srvModel.status !== newStatus) { - window.parent.postMessage({ "invoiceId": srvModel.invoiceId, "status": newStatus }, "*"); - } - - // restoring qr code view only when currency is switched - if (jsonData.paymentMethodId == srvModel.paymentMethodId) { - $("#scan").show(); - $(".payment__spinner").hide(); - } - - // updating ui - checkoutCtrl.srvModel = jsonData; -} - -function changeCurrency(currency) { - if (srvModel.paymentMethodId != currency) { - $("#scan").hide(); - $(".payment__spinner").show(); - srvModel.paymentMethodId = currency; - fetchStatus(); - } - return false; -} - -function fetchStatus() { - var path = srvModel.serverUrl + "/i/" + srvModel.invoiceId + "/" + srvModel.paymentMethodId + "/status"; - $.ajax({ - url: path, - type: "GET" - }).done(function (data) { - onDataCallback(data); - }).fail(function (jqXHR, textStatus, errorThrown) { - }); -} -var supportsWebSockets = 'WebSocket' in window && window.WebSocket.CLOSING === 2; -if (supportsWebSockets) { - var path = srvModel.serverUrl + "/i/" + srvModel.invoiceId + "/status/ws"; - path = path.replace("https://", "wss://"); - path = path.replace("http://", "ws://"); - try { - var socket = new WebSocket(path); - socket.onmessage = function (e) { + + // Scan/Copy Transitions + // Scan Tab + $("#scan-tab").click(function () { + if (!$(this).is(".active")) { + $(this).addClass("active"); + } + + if ($("#copy-tab").is(".active")) { + $("#copy-tab").removeClass("active"); + } + + $(".payment-tabs__slider").removeClass("slide-right"); + + if (!$("#scan").is(".active")) { + $("#copy").hide(); + $("#copy").removeClass("active"); + + $("#scan").show(); + $("#scan").addClass("active"); + } + }); + + // Main Copy tab + $("#copy-tab").click(function () { + if (!$(this).is(".active")) { + $(this).addClass("active"); + } + + if ($("#scan-tab").is(".active")) { + $("#scan-tab").removeClass("active"); + } + if (!$(".payment-tabs__slider").is("slide-right")) { + $(".payment-tabs__slider").addClass("slide-right"); + } + + if (!$("#copy").is(".active")) { + $("#copy").show(); + $("#copy").addClass("active"); + + $("#scan").hide(); + $("#scan").removeClass("active"); + } + }); + + // Payment received + // Should connect using webhook ? + // If notification received + + onDataCallback(srvModel); + + function onDataCallback(jsonData) { + var newStatus = jsonData.status; + + if (newStatus === "complete" || + newStatus === "confirmed" || + newStatus === "paid") { + if ($(".modal-dialog").hasClass("expired")) { + $(".modal-dialog").removeClass("expired"); + } + + if (srvModel.merchantRefLink !== "") { + $(".action-button").click(function () { + window.location.href = srvModel.merchantRefLink; + }); + } + else { + $(".action-button").hide(); + } + + $(".modal-dialog").addClass("paid"); + + if ($("#scan").hasClass("active")) { + $("#scan").removeClass("active"); + } else if ($("#copy").hasClass("active")) { + $("#copy").removeClass("active"); + } + $("#paid").addClass("active"); + } + + 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"); + $("#expired").addClass("active"); + } + + if (checkoutCtrl.srvModel.status !== newStatus) { + window.parent.postMessage({ "invoiceId": srvModel.invoiceId, "status": newStatus }, "*"); + } + + // restoring qr code view only when currency is switched + if (jsonData.paymentMethodId == srvModel.paymentMethodId) { + $("#scan").show(); + $(".payment__spinner").hide(); + } + + // updating ui + checkoutCtrl.srvModel = jsonData; + } + + function changeCurrency(currency) { + if (srvModel.paymentMethodId != currency) { + $("#scan").hide(); + $(".payment__spinner").show(); + srvModel.paymentMethodId = currency; fetchStatus(); - }; + } + return false; } - catch (e) { - console.error("Error while connecting to websocket for invoice notifications"); + + function fetchStatus() { + var path = srvModel.serverUrl + "/i/" + srvModel.invoiceId + "/" + srvModel.paymentMethodId + "/status"; + $.ajax({ + url: path, + type: "GET" + }).done(function (data) { + onDataCallback(data); + }).fail(function (jqXHR, textStatus, errorThrown) { + + }); } -} -var watcher = setInterval(function () { - fetchStatus(); -}, 2000); + var supportsWebSockets = 'WebSocket' in window && window.WebSocket.CLOSING === 2; + if (supportsWebSockets) { + var path = srvModel.serverUrl + "/i/" + srvModel.invoiceId + "/status/ws"; + path = path.replace("https://", "wss://"); + path = path.replace("http://", "ws://"); + try { + var socket = new WebSocket(path); + socket.onmessage = function (e) { + fetchStatus(); + }; + } + catch (e) { + console.error("Error while connecting to websocket for invoice notifications"); + } + } + + var watcher = setInterval(function () { + fetchStatus(); + }, 2000); + + $(".menu__item").click(function () { + $(".menu__scroll .menu__item").removeClass("selected"); + $(this).addClass("selected"); + language(); + $(".selector span").text($(".selected").text()); + // function to load contents in different language should go there + }); + + // Validate Email address + function validateEmail(email) { + var re = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/; + return re.test(email); + } + + // Expand Line-Items + $(".buyerTotalLine").click(function () { + $("line-items").toggleClass("expanded"); + $(".buyerTotalLine").toggleClass("expanded"); + $(".single-item-order__right__btc-price__chevron").toggleClass("expanded"); + }); + + // Timer Countdown + function startTimer(duration, display) { + var timer = duration, minutes, seconds; + var timeout = setInterval(function () { + minutes = parseInt(timer / 60, 10); + seconds = parseInt(timer % 60, 10); + + minutes = minutes < 10 ? "0" + minutes : minutes; + seconds = seconds < 10 ? "0" + seconds : seconds; + + display.text(minutes + ":" + seconds); + + if (--timer < 0) { + clearInterval(timeout); + } + }, 1000); + } + + // Progress bar + function progressStart(timerMax) { + var end = new Date(); // Setup Time Variable, should come from server + end.setSeconds(end.getSeconds() + srvModel.expirationSeconds); + timerMax *= 1000; // Usually 15 minutes = 9000 second= 900000 ms + var timeoutVal = Math.floor(timerMax / 100); // Timeout calc + animateUpdate(); //Launch it + + function updateProgress(percentage) { + $('.timer-row__progress-bar').css("width", percentage + "%"); + } + + function animateUpdate() { + + var now = new Date(); + var timeDiff = end.getTime() - now.getTime(); + var perc = 100 - Math.round(timeDiff / timerMax * 100); + + if (perc === 75 && (status === "paidPartial" || status === "new")) { + $(".timer-row").addClass("expiring-soon"); + $(".timer-row__message span").html("Invoice expiring soon ..."); + updateProgress(perc); + } + if (perc <= 100) { + updateProgress(perc); + setTimeout(animateUpdate, timeoutVal); + } + if (perc >= 100 && status === "expired") { + onDataCallback(status); + } + } + } + + // Manual Copy + // Amount + var copyAmount = new Clipboard('.manual-box__amount__value', { + target: function () { + var $el = $(".manual-box__amount__value"); + $el.removeClass("copy-cursor").addClass("copied"); + setTimeout(function () { $el.removeClass("copied").addClass("copy-cursor"); }, 500); + return document.querySelector('.manual-box__amount__value span'); + } + }); + // Address + var copyAddress = new Clipboard('.manual-box__address__value', { + target: function () { + var $elm = $(".manual-box__address__value"); + $elm.removeClass("copy-cursor").addClass("copied"); + setTimeout(function () { $elm.removeClass("copied").addClass("copy-cursor"); }, 500); + return document.querySelector('.manual-box__address__value .manual-box__address__wrapper .manual-box__address__wrapper__value'); + } + }); + + // Disable enter key + $(document).keypress( + function (event) { + if (event.which === '13') { + event.preventDefault(); + } + } + ); -$(".menu__item").click(function () { - $(".menu__scroll .menu__item").removeClass("selected"); - $(this).addClass("selected"); - language(); - $(".selector span").text($(".selected").text()); - // function to load contents in different language should go there }); - -// Validate Email address -function validateEmail(email) { - var re = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/; - return re.test(email); -} - -// Expand Line-Items -$(".buyerTotalLine").click(function () { - $("line-items").toggleClass("expanded"); - $(".buyerTotalLine").toggleClass("expanded"); - $(".single-item-order__right__btc-price__chevron").toggleClass("expanded"); -}); - -// Timer Countdown -function startTimer(duration, display) { - var timer = duration, minutes, seconds; - var timeout = setInterval(function () { - minutes = parseInt(timer / 60, 10); - seconds = parseInt(timer % 60, 10); - - minutes = minutes < 10 ? "0" + minutes : minutes; - seconds = seconds < 10 ? "0" + seconds : seconds; - - display.text(minutes + ":" + seconds); - - if (--timer < 0) { - clearInterval(timeout); - } - }, 1000); -} - -// Progress bar -function progressStart(timerMax) { - var end = new Date(); // Setup Time Variable, should come from server - end.setSeconds(end.getSeconds() + srvModel.expirationSeconds); - timerMax *= 1000; // Usually 15 minutes = 9000 second= 900000 ms - var timeoutVal = Math.floor(timerMax / 100); // Timeout calc - animateUpdate(); //Launch it - - function updateProgress(percentage) { - $('.timer-row__progress-bar').css("width", percentage + "%"); - } - - function animateUpdate() { - - var now = new Date(); - var timeDiff = end.getTime() - now.getTime(); - var perc = 100 - Math.round(timeDiff / timerMax * 100); - - if (perc === 75 && (status === "paidPartial" || status === "new")) { - $(".timer-row").addClass("expiring-soon"); - $(".timer-row__message span").html("Invoice expiring soon ..."); - updateProgress(perc); - } - if (perc <= 100) { - updateProgress(perc); - setTimeout(animateUpdate, timeoutVal); - } - if (perc >= 100 && status === "expired") { - onDataCallback(status); - } - } -} - -// Manual Copy -// Amount -var copyAmount = new Clipboard('.manual-box__amount__value', { - target: function () { - var $el = $(".manual-box__amount__value"); - $el.removeClass("copy-cursor").addClass("copied"); - setTimeout(function () { $el.removeClass("copied").addClass("copy-cursor"); }, 500); - return document.querySelector('.manual-box__amount__value span'); - } -}); -// Address -var copyAddress = new Clipboard('.manual-box__address__value', { - target: function () { - var $elm = $(".manual-box__address__value"); - $elm.removeClass("copy-cursor").addClass("copied"); - setTimeout(function () { $elm.removeClass("copied").addClass("copy-cursor"); }, 500); - return document.querySelector('.manual-box__address__value .manual-box__address__wrapper .manual-box__address__wrapper__value'); - } -}); - -// Disable enter key -$(document).keypress( - function (event) { - if (event.which === '13') { - event.preventDefault(); - } - } -); From de6d3198ffb533864e27493182440ebef938031f Mon Sep 17 00:00:00 2001 From: lepipele Date: Sat, 3 Mar 2018 00:32:51 -0600 Subject: [PATCH 5/7] Bundling JS and CSS files for Checkout.cshtml Now we'll finally have versioning so when those JS/CSS files update, clients will properly request new bundle --- BTCPayServer/Views/Invoice/Checkout.cshtml | 14 +++++--------- BTCPayServer/bundleconfig.json | 18 ++++++++++++++++++ 2 files changed, 23 insertions(+), 9 deletions(-) diff --git a/BTCPayServer/Views/Invoice/Checkout.cshtml b/BTCPayServer/Views/Invoice/Checkout.cshtml index a96a6175f..5ad74970b 100644 --- a/BTCPayServer/Views/Invoice/Checkout.cshtml +++ b/BTCPayServer/Views/Invoice/Checkout.cshtml @@ -1,4 +1,5 @@ -@model PaymentModel +@addTagHelper *, Meziantou.AspNetCore.BundleTagHelpers +@model PaymentModel @{ Layout = null; ViewData["Title"] = "Payment"; @@ -12,18 +13,13 @@ BTCPay Invoice - - - + - - - - - + +