From 9c12ccadc5cd219bbde5e378f1d684b9d380d005 Mon Sep 17 00:00:00 2001 From: Sam Date: Fri, 10 Jan 2025 12:20:38 +0000 Subject: [PATCH] refactor chart shortcode to use static js instead --- content/data-lab/global-business-growth.md | 2 + content/data-lab/miner-rewards.md | 2 +- layouts/partials/chart.html | 10 +- layouts/shortcodes/chart.html | 19 +- static/css/charts.css | 11 +- static/js/bitcoin-business-growth-chart.js | 193 +++++++------- static/js/miner-rewards.js | 277 +++++++++------------ 7 files changed, 234 insertions(+), 280 deletions(-) diff --git a/content/data-lab/global-business-growth.md b/content/data-lab/global-business-growth.md index 84c92af..954aab9 100644 --- a/content/data-lab/global-business-growth.md +++ b/content/data-lab/global-business-growth.md @@ -18,6 +18,8 @@ The chart always reflects the countries selected in the table. {{< dropdown_filter id="days_ago_dropdown_filter" id_filter="days_ago" options="1 day:1,7 day:7,28 day:28,1 year:365,5 year:1826,10 year:3652,all time:10000" default_selection="7 day" targets="bitcoin-business-growth-chart bitcoin-business-growth-table" >}} {{< table id="bitcoin-business-growth-table" endpoint="bitcoin_business_growth_percent_diff" headers="{'country_name': 'Country', 'date_range': 'Date Range', 'first_value': 'Previous #', 'last_value': 'Current #', 'difference': 'Diff', 'percent_difference': '% Diff'}" maxHeight="400px" sortable="true" valueId="country_name" selectableRows="multi" targets="bitcoin-business-growth-chart" defaultFirstSelected="true" >}} +{{< chart id="bitcoin-business-growth-table" src="/js/bitcoin-business-growth-chart.js" >}} + {{< chart chartMethod="tableRowSelectChart" id="bitcoin-business-growth-chart" endpoint="bitcoin_business_growth_timeseries" chartType="line" xAxisField="date" yAxisField="cumulative_value" scaleChart=true xAxisType="category" >}} #### Attribution and License diff --git a/content/data-lab/miner-rewards.md b/content/data-lab/miner-rewards.md index 39ac8e1..e0e522e 100644 --- a/content/data-lab/miner-rewards.md +++ b/content/data-lab/miner-rewards.md @@ -13,4 +13,4 @@ The following chart shows daily miner revenue in USD for the period selected in {{< dropdown_filter id="days_ago_dropdown_filter" id_filter="days_ago" options="1 day:1,7 day:7,28 day:28,1 year:365,5 year:1826,10 year:3652,all time:10000" default_selection="7 day" targets="miner-rewards-chart" >}} -{{< chart chartMethod="simpleChart" id="miner-rewards-chart" endpoint="miner_rewards" chartType="line" xAxisField="date" yAxisField="total_reward_usd" scaleChart=true xAxisType="category" >}} +{{< chart id="miner-rewards" src="/js/miner-rewards.js" >}} diff --git a/layouts/partials/chart.html b/layouts/partials/chart.html index cf807a9..1e94b9e 100644 --- a/layouts/partials/chart.html +++ b/layouts/partials/chart.html @@ -97,18 +97,19 @@ }); } - chartData = []; function simpleChart( id, endpoint, chartType, xAxisField, yAxisField, + series, sortField = null, scaleChart = false, xAxisType = "time", formatValueDecimalPlaces = null, ) { + console.log(series); async function fetchDataForChart(query) { try { const apiEndpoint = `${apiURL}/${endpoint}?${query}`; @@ -145,12 +146,7 @@ scale: scaleChart, type: "value", }, - series: [ - { - data: chartData.map((item) => item.total_reward_usd), - type: "line", - }, - ], + series: JSON.parse(`{${series}}`), }; myChart.setOption(option, true); diff --git a/layouts/shortcodes/chart.html b/layouts/shortcodes/chart.html index d8c1813..4087315 100644 --- a/layouts/shortcodes/chart.html +++ b/layouts/shortcodes/chart.html @@ -1,20 +1,7 @@ -{{ partial "chart.html" }} +
+
- +
diff --git a/static/css/charts.css b/static/css/charts.css index 4102992..0bf82bc 100644 --- a/static/css/charts.css +++ b/static/css/charts.css @@ -2,7 +2,7 @@ .chart-container { display: flex; /* height: 600px; */ - aspect-ratio: 1 / 1; + aspect-ratio: 2 / 1; } .chart { @@ -10,3 +10,12 @@ height: 100%; width: 100%; } + +@media (max-width: 600px) { +.chart-container { + display: flex; + /* height: 600px; */ + aspect-ratio: 1 / 1; +} + +} diff --git a/static/js/bitcoin-business-growth-chart.js b/static/js/bitcoin-business-growth-chart.js index cc517d3..b1e94a2 100644 --- a/static/js/bitcoin-business-growth-chart.js +++ b/static/js/bitcoin-business-growth-chart.js @@ -1,109 +1,102 @@ -let chartData = []; -let myChart; - -let periodIndex = 3; - -const periods = ["1 day", "7 day", "28 day", "365 day"]; - -async function fetchDataForChart(str, period) { - try { - const apiEndpoint = `${apiURL}/bitcoin_business_growth_by_country?cumulative_period_type=${period}&countries=${str}`; - console.log("Fetching from " + apiEndpoint); - const response = await fetch(apiEndpoint); - if (!response.ok) { - throw new Error(`HTTP error! status: ${response.status}`); - } - const fetchedData = await response.json(); - const newData = fetchedData.reduce((acc, item) => { - const objectId = item.country_name; - if (!acc[objectId]) { - acc[objectId] = []; +var chartDom = document.getElementById(id); +var myChart = echarts.init(chartDom); +chartData = []; +function tableRowSelectChart( + endpoint, + xAxisField, + yAxisField, + chartType, + xAxisType, + scaleChart = false, + formatValueDecimalPlaces = null, +) { + async function fetchDataForChart(query, valueId) { + try { + const apiEndpoint = `${apiURL}/${endpoint}?${query}`; + const response = await fetch(apiEndpoint); + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`); } - acc[objectId].push([item.date, item.cumulative_current_value]); - return acc; - }, {}); - chartData = { ...chartData, ...newData }; - updateChart(); - } catch (error) { - console.error("Fetching data failed:", error); + const fetchedData = await response.json(); + console.log(fetchedData); + const newData = fetchedData.reduce((acc, item) => { + const objectId = item[valueId]; + if (!acc[objectId]) { + acc[objectId] = []; + } + acc[objectId].push([item[xAxisField], item[yAxisField]]); + return acc; + }, {}); + chartData = { ...chartData, ...newData }; + updateChart(); + } catch (error) { + console.error("Fetching data failed:", error); + } } -} -function updateChart() { - let chartDataMap = new Map(); - for (let objectId in chartData) { - chartDataMap.set(objectId, chartData[objectId]); - } - option = { - backgroundColor: backgroundColor, - grid: grid, - tooltip: tooltip, - toolbox: toolboxParams, - xAxis: { - axisTick: axisTick, - axisLabel: axisLabel, - axisLine: axisLine, - type: "category", - }, - yAxis: { - axisTick: axisTick, - scale: true, - splitLine: { - show: false, - }, - axisLabel: { - fontSize: 12 * fontScale, - color: textColor, - formatter(value, index) { - return nFormatter(value, 2); + function updateChart() { + let chartDataMap = new Map(); + for (let objectId in chartData) { + chartDataMap.set(objectId, chartData[objectId]); + } + + var option = { + tooltip: { + ...tooltip, + valueFormatter(value, index) { + return formatValueDecimalPlaces == null + ? value + : nFormatter(value, formatValueDecimalPlaces); }, }, - axisLine: axisLine, - }, - - series: Array.from(chartDataMap.entries()).map(([name, data]) => ({ - name, - type: "line", - data, - showSymbol: false, - })), - }; - myChart.setOption(option, true); -} - -function handleCheckboxChange(event) { - if (event.target.type === "checkbox") { - const boxChecked = event.target.checked; - const boxId = event.target.id; - let selectedPeriod = getPeriodFromDropdown(); - // Remove unchecked boxes - if (boxChecked === false) { - delete chartData[boxId]; - updateChart(); - // Add checked boxes - } else { - fetchDataForChart(boxId, selectedPeriod); - } + xAxis: { + type: xAxisType, + }, + yAxis: { + scale: scaleChart, + type: "value", + }, + series: Array.from(chartDataMap.entries()).map(([name, data]) => ({ + name, + type: chartType, + data, + showSymbol: false, + })), + }; + myChart.setOption(option, true); } -} -document.addEventListener("DOMContentLoaded", function () { - periodDropdown(periods, periodIndex); - document.addEventListener("reloadTable", () => { - myChart = echarts.init(document.getElementById("chart")); - jsonTableCheckedBoxes = document.querySelectorAll( - '#jsonTableContainer input[type="checkbox"]:checked', - ); - const checkedBoxes = Array.from(jsonTableCheckedBoxes).map( - (checkbox) => checkbox.id, - ); - const str = checkedBoxes.join(","); - let selectedPeriod = getPeriodFromDropdown(); - chartData = []; - fetchDataForChart(str, selectedPeriod); + // listen for filter events for this target + document.addEventListener("filterChange", function (event) { + tableId = document.getElementById(id).id; + console.log(event.detail); + eventDetail = event.detail; + if (eventDetail.filterActions.includes("refresh")) { + chartData = []; + updateChart(); + } else { + if (eventDetail.filterTargets.includes(tableId)) { + if (eventDetail.filterActions.includes("selected")) { + valueId = eventDetail.filterId; + let selectedRow = { + [valueId]: eventDetail.filterValue, + }; + query = queryConstructor(selectedRow); - jsonTable = document.getElementById("jsonTableContainer"); - jsonTable.removeEventListener("change", handleCheckboxChange); - jsonTable.addEventListener("change", handleCheckboxChange); + fetchDataForChart(query, valueId); + console.log(valueId) + } else { + delete chartData[eventDetail.filterValue]; + updateChart(); + } + } + } }); -}); +} +tableRowSelectChart( + endpoint = "bitcoin_business_growth_timeseries", + xAxisField = "date", + yAxisField = "cumulative_value", + chartType = "line", + xAxisType = "category", +); diff --git a/static/js/miner-rewards.js b/static/js/miner-rewards.js index ac47647..d0a88a9 100644 --- a/static/js/miner-rewards.js +++ b/static/js/miner-rewards.js @@ -1,169 +1,136 @@ -let dataArr = []; -const myChart = echarts.init(document.getElementById("chart")); -const filename = "final__miner_rewards.json"; -const periods = [ - "all time", - "last 7 days", - "last 28 days", - "last 365 days", - "last 2 years", -]; - -async function fetchDataForChart(selectedValue) { - try { - const apiEndpoint = `${apiURL}/get_json/${filename}?period=${selectedValue}`; - const response = await fetch(apiEndpoint); - if (!response.ok) { - throw new Error(`HTTP error! status: ${response.status}`); +var chartDom = document.getElementById(id); +var myChart = echarts.init(chartDom); +chartData = []; +function simpleChart( + endpoint, + formatValueDecimalPlaces = null, +) { + async function fetchDataForChart(query) { + try { + const apiEndpoint = `${apiURL}/${endpoint}?${query}`; + const response = await fetch(apiEndpoint); + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`); + } + chartData = await response.json(); + updateChart(); + console.log(chartData); + } catch (error) { + console.error("Fetching data failed:", error); } - const dataArr = await response.json(); - initEchart(dataArr); - } catch (error) { - console.error("Fetching data failed:", error); } -} -function initEchart(dataArr) { - console.log(dataArr); - const option = { - backgroundColor: backgroundColor, - tooltip: { - ...tooltip, - formatter: function (params) { - let colors = ["#ee6666", "#000000", "#b0da9d", "#8699d5"]; - let colorSpan = (color) => - ''; - let tooltip = "

" + params[0].axisValue + "

"; - params.reverse().forEach((item, index) => { - let color = colors[index % colors.length]; - let labels = - "

" + - colorSpan(color) + - " " + - item.seriesName + - ": " + - nFormatter(item.data, 3); - ("

"); - tooltip += labels; - }); - - return tooltip; - }, - valueFormatter(value, index) { - return nFormatter(value, 3); - }, - }, - toolbox: toolboxParams, - xAxis: { - data: dataArr.map((row) => row.date), - axisTick: axisTick, - axisLabel: axisLabel, - axisLine: axisLine, - }, - grid: grid, - dataZoom: dataZoom(0), - yAxis: [ - { - type: "value", - name: "Rewards (USD)", - nameLocation: "middle", - nameGap: 30, - nameTextStyle: textStyleMain, - position: "left", - alignTicks: true, - axisTick: axisTick, - axisLine: axisLine, - splitLine: { - show: false, + function updateChart() { + var option = { + tooltip: { + ...tooltip, + valueFormatter(value, index) { + return formatValueDecimalPlaces == null + ? value + : nFormatter(value, formatValueDecimalPlaces); }, - axisLabel: { - ...axisLabel, - formatter(value, index) { - return nFormatter(value, 0); + }, + xAxis: { + type: "category", + data: chartData.map((item) => item.date), + }, + yAxis: [ + { + type: "value", + name: "Rewards (USD)", + nameLocation: "middle", + nameGap: 30, + nameTextStyle: textStyleMain, + position: "left", + alignTicks: true, + axisTick: axisTick, + axisLine: axisLine, + splitLine: { + show: false, + }, + axisLabel: { + ...axisLabel, + formatter(value, index) { + return nFormatter(value, 0); + }, }, }, - }, - { - type: "value", - name: "Subsidy (BTC)", - nameLocation: "middle", - nameGap: 20, - nameTextStyle: { - fontSize: 12 * fontScale, - color: textColor, + { + type: "value", + name: "Subsidy (BTC)", + nameLocation: "middle", + nameGap: 20, + nameTextStyle: { + fontSize: 12 * fontScale, + color: textColor, + }, + axisTick: axisTick, + position: "right", + alignTicks: true, + axisLine: axisLine, + splitLine: { + show: false, + }, + axisLabel: { + fontSize: 12 * fontScale, + color: textColor, + }, }, - axisTick: axisTick, - position: "right", - alignTicks: true, - axisLine: axisLine, - splitLine: { - show: false, + ], + series: [ + { + type: "line", + name: "Subsidy (USD)", + stack: "Total", + areaStyle: {}, + symbol: "none", + lineStyle: { + width: 0, + }, + data: chartData.map((row) => row.subsidy_usd), }, - axisLabel: { - fontSize: 12 * fontScale, - color: textColor, + { + type: "line", + name: "Fees (USD)", + stack: "Total", + areaStyle: {}, + symbol: "none", + lineStyle: { + width: 0, + }, + data: chartData.map((row) => row.totalfee_usd), }, - }, - ], - series: [ - { - type: "line", - name: "Subsidy (USD)", - stack: "Total", - areaStyle: {}, - symbol: "none", - lineStyle: { - width: 0, + { + type: "line", + name: "Total (USD)", + symbol: "none", + lineStyle: { + width: 1, + color: textColor, + }, + data: chartData.map((row) => row.total_reward_usd), }, - data: dataArr.map((row) => row.subsidy_usd), - }, - { - type: "line", - name: "Fees (USD)", - stack: "Total", - areaStyle: {}, - symbol: "none", - lineStyle: { - width: 0, + { + type: "line", + yAxisIndex: 1, + name: "Block Subsidy (BTC)", + symbol: "none", + lineStyle: { + width: 3, + }, + data: chartData.map((row) => row.block_subsidy), }, - data: dataArr.map((row) => row.totalfee_usd), - }, - { - type: "line", - name: "Total (USD)", - symbol: "none", - lineStyle: { - width: 1, - color: textColor, - }, - data: dataArr.map((row) => row.total_reward_usd), - }, - { - type: "line", - yAxisIndex: 1, - name: "Block Subsidy (BTC)", - symbol: "none", - lineStyle: { - width: 3, - }, - data: dataArr.map((row) => row.block_subsidy), - }, - ], - }; + ], + }; - myChart.setOption(option); -} + myChart.setOption(option, true); + } -document.addEventListener("DOMContentLoaded", function () { - let periodIndex = 2; - periodDropdown(periods, periodIndex); - fetchDataForChart(periods[periodIndex]); - const selectElement = document.getElementById("select-period-dropdown"); - - selectElement.addEventListener("change", function (event) { - const selectedValue = event.target.value; - fetchDataForChart(selectedValue); + query = queryConstructor(); + fetchDataForChart(query); + document.addEventListener("filterChange", function (event) { + query = queryConstructor(); + fetchDataForChart(query); }); -}); +} +simpleChart((endpoint = "miner_rewards"));