diff --git a/basicswap/static/css/style.css b/basicswap/static/css/style.css index 4650ad0..c5c87ec 100644 --- a/basicswap/static/css/style.css +++ b/basicswap/static/css/style.css @@ -96,6 +96,17 @@ display: block; } +.blurred { + filter: blur(4px); + pointer-events: none; + user-select: none; +} + +.error-overlay.non-blurred { + filter: none; + pointer-events: auto; + user-select: auto; +} /* Disable opacity on disabled form elements in Chrome */ @media screen and (-webkit-min-device-pixel-ratio:0) { diff --git a/basicswap/templates/offers.html b/basicswap/templates/offers.html index b17eab5..9a4076b 100644 --- a/basicswap/templates/offers.html +++ b/basicswap/templates/offers.html @@ -59,27 +59,35 @@ {% include 'inc_messages.html' %} {% if show_chart %} -<section> - <div class="pl-6 pr-6 pt-0 pb-0 mt-5 h-full overflow-hidden"> - <div class="pb-6 border-coolGray-100"> - <div class="flex flex-wrap items-center justify-between -m-2"> - <div class="w-full pt-2"> - <div class="container mt-5 mx-auto"> - <div class="pt-6 pb-8 bg-coolGray-100 dark:bg-gray-500 rounded-xl"> - <div class="px-6"> - <div class="w-full mt-6 pb-6 overflow-x-auto"> - <div class="chart-container" style="max-width: 100%;"> - <canvas id="coin-chart" style="height: 280px;"></canvas> - </div> +<section class="relative"> + <div class="pl-6 pr-6 pt-0 pb-0 mt-5 h-full overflow-hidden"> + <div class="pb-6 border-coolGray-100"> + <div class="flex flex-wrap items-center justify-between -m-2"> + <div class="w-full pt-2"> + <div class="container mt-5 mx-auto relative"> + <div class="pt-6 pb-8 bg-coolGray-100 dark:bg-gray-500 rounded-xl container-to-blur"> + <div class="px-6"> + <div class="w-full mt-6 pb-6 overflow-x-auto"> + <div class="chart-container" style="max-width: 100%;"> + <canvas id="coin-chart" style="height: 280px;"></canvas> + </div> + </div> + </div> + </div> + <div id="error-overlay" class="error-overlay hidden absolute inset-0 flex items-center justify-center"> + <div id="error-content" class="error-content bg-coolGray-100 dark:bg-gray-500 rounded-md p-4 non-blurred"> + <p class="text-red-600 font-semibold text-center">Error:</p> + <p class="text-sm text-gray-700 dark:text-gray-300 mt-5 text-center">To review or update your Chart API Key, navigate to <a href="/settings">Settings & Tools > Settings > General (TAB).</a></p> + </div> + </div> + </div> + </div> + </div> + </div> </div> -</div> -</div> -</div> -</div> -</div> -</div> </section> -<section class="py-4 overflow-hidden"> + +<section class="py-4 overflow-hidden container-to-blur"> <div class="container px-4 mx-auto"> <div class="flex flex-wrap -m-3"> <div class="w-full sm:w-1/2 lg:w-1/5 p-3" id="btc-container"> @@ -302,11 +310,19 @@ window.addEventListener('load', function() { const coins = ['BTC', 'PART', 'XMR', 'LTC', 'FIRO', 'DASH', 'PIVX', 'DOGE']; coins.forEach(coin => { fetch(`https://min-api.cryptocompare.com/data/pricemultifull?fsyms=${coin}&tsyms=USD,BTC&api_key=${api_key}`) - .then(response => response.json()) + .then(response => { + if (!response.ok) { + throw new Error(`Error fetching data. Status: ${response.status}`); + } + return response.json(); + }) .then(data => { displayCoinData(coin, data); }) - .catch(error => console.error(`Error fetching ${coin} data:`, error)); + .catch(error => { + console.error(`Fetching ${coin} data:`, error); + displayErrorMessage(`Unable to fetch data. Please verify your API key or try again later.`); + }); }); updateChart('BTC'); }); @@ -329,6 +345,33 @@ function displayCoinData(coin, data) { priceChangeContainer.innerHTML = negativePriceChangeHTML(priceChange1h); } } + +function displayErrorMessage(message) { + const errorContainer = document.getElementById('error-container'); + if (errorContainer) { + errorContainer.innerHTML = `<div class="error-message">${message}</div>`; + } else { + document.body.innerHTML += `<div id="error-container" class="error-message">${message}</div>`; + } +} + +function displayErrorMessage(message) { + const errorOverlay = document.getElementById('error-overlay'); + const errorContent = document.getElementById('error-content'); + const containersToBlur = document.querySelectorAll('.container-to-blur'); + + if (errorOverlay && errorContent) { + errorOverlay.classList.remove('hidden'); + errorContent.querySelector('p').textContent = `Error: ${message}`; + + containersToBlur.forEach(container => { + container.classList.add('blurred'); + }); + + errorOverlay.classList.add('non-blurred'); + } +} + function positivePriceChangeHTML(value) { return ` <div class="flex flex-wrap items-center py-px px-1 border border-green-500 rounded-full"> diff --git a/basicswap/ui/page_offers.py b/basicswap/ui/page_offers.py index a8aee64..f2b9559 100644 --- a/basicswap/ui/page_offers.py +++ b/basicswap/ui/page_offers.py @@ -445,7 +445,7 @@ def page_newoffer(self, url_split, post_string): chart_api_key = swap_client.settings.get('chart_api_key', '') if chart_api_key == '': chart_api_key_enc = swap_client.settings.get('chart_api_key_enc', '') - chart_api_key = 'cd7600e7b5fdd99c6f900673ff0ee8f64d6d4219a4bb87191ad4a2e3fc65d7f4' if chart_api_key_enc == '' else bytes.fromhex(chart_api_key_enc).decode('utf-8') + chart_api_key = '95dd900af910656e0e17c41f2ddc5dba77d01bf8b0e7d2787634a16bd976c553' if chart_api_key_enc == '' else bytes.fromhex(chart_api_key_enc).decode('utf-8') return self.render_template(template, { 'messages': messages, diff --git a/tests/basicswap/selenium/test_settings.py b/tests/basicswap/selenium/test_settings.py index f821b52..c409861 100644 --- a/tests/basicswap/selenium/test_settings.py +++ b/tests/basicswap/selenium/test_settings.py @@ -77,7 +77,7 @@ def test_settings(driver): chart_api_key = bytes.fromhex(settings.get('chart_api_key_enc', '')).decode('utf-8') assert (chart_api_key == difficult_text) - hex_text = 'cd7600e7b5fdd99c6f900673ff0ee8f64d6d4219a4bb87191ad4a2e3fc65d7f4' + hex_text = '95dd900af910656e0e17c41f2ddc5dba77d01bf8b0e7d2787634a16bd976c553' el = driver.find_element(By.NAME, 'chartapikey') el.clear() el.send_keys(hex_text)