refactor chart shortcode to use static js instead

This commit is contained in:
Sam 2025-01-10 12:20:38 +00:00
parent eb6f97f54a
commit 9c12ccadc5
7 changed files with 234 additions and 280 deletions

View File

@ -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

View File

@ -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" >}}

View File

@ -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);

View File

@ -1,20 +1,7 @@
{{ partial "chart.html" }}
<script src="https://cdn.jsdelivr.net/npm/echarts@5.5.1/dist/echarts.js"></script>
<section class = 'chart-container'>
<script>let id = '{{ .Get "id" }}'</script>
<div class = "chart" id='{{ .Get "id" }}'>
<script>
document.addEventListener("DOMContentLoaded", function () {
{{ .Get "chartMethod" | safeJS }}(
id={{ .Get "id" }},
endpoint={{ .Get "endpoint" }},
chartType={{ .Get "chartType" }},
xAxisField={{ .Get "xAxisField" }},
yAxisField={{ .Get "yAxisField" }},
sortField={{ .Get "sortField" }},
scaleChart={{ .Get "scaleChart" }},
xAxisType={{ .Get "xAxisType" }})
});
</script>
<script src={{ .Get "src" }}></script>
</div>
</section>

View File

@ -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;
}
}

View File

@ -1,25 +1,30 @@
let chartData = [];
let myChart;
let periodIndex = 3;
const periods = ["1 day", "7 day", "28 day", "365 day"];
async function fetchDataForChart(str, period) {
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}/bitcoin_business_growth_by_country?cumulative_period_type=${period}&countries=${str}`;
console.log("Fetching from " + apiEndpoint);
const apiEndpoint = `${apiURL}/${endpoint}?${query}`;
const response = await fetch(apiEndpoint);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const fetchedData = await response.json();
console.log(fetchedData);
const newData = fetchedData.reduce((acc, item) => {
const objectId = item.country_name;
const objectId = item[valueId];
if (!acc[objectId]) {
acc[objectId] = [];
}
acc[objectId].push([item.date, item.cumulative_current_value]);
acc[objectId].push([item[xAxisField], item[yAxisField]]);
return acc;
}, {});
chartData = { ...chartData, ...newData };
@ -34,36 +39,26 @@ function updateChart() {
for (let objectId in chartData) {
chartDataMap.set(objectId, chartData[objectId]);
}
option = {
backgroundColor: backgroundColor,
grid: grid,
tooltip: tooltip,
toolbox: toolboxParams,
var option = {
tooltip: {
...tooltip,
valueFormatter(value, index) {
return formatValueDecimalPlaces == null
? value
: nFormatter(value, formatValueDecimalPlaces);
},
},
xAxis: {
axisTick: axisTick,
axisLabel: axisLabel,
axisLine: axisLine,
type: "category",
type: xAxisType,
},
yAxis: {
axisTick: axisTick,
scale: true,
splitLine: {
show: false,
scale: scaleChart,
type: "value",
},
axisLabel: {
fontSize: 12 * fontScale,
color: textColor,
formatter(value, index) {
return nFormatter(value, 2);
},
},
axisLine: axisLine,
},
series: Array.from(chartDataMap.entries()).map(([name, data]) => ({
name,
type: "line",
type: chartType,
data,
showSymbol: false,
})),
@ -71,39 +66,37 @@ function updateChart() {
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);
}
}
}
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();
// 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 = [];
fetchDataForChart(str, selectedPeriod);
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",
);

View File

@ -1,69 +1,39 @@
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) {
var chartDom = document.getElementById(id);
var myChart = echarts.init(chartDom);
chartData = [];
function simpleChart(
endpoint,
formatValueDecimalPlaces = null,
) {
async function fetchDataForChart(query) {
try {
const apiEndpoint = `${apiURL}/get_json/${filename}?period=${selectedValue}`;
const apiEndpoint = `${apiURL}/${endpoint}?${query}`;
const response = await fetch(apiEndpoint);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const dataArr = await response.json();
initEchart(dataArr);
chartData = await response.json();
updateChart();
console.log(chartData);
} catch (error) {
console.error("Fetching data failed:", error);
}
}
function initEchart(dataArr) {
console.log(dataArr);
const option = {
backgroundColor: backgroundColor,
function updateChart() {
var option = {
tooltip: {
...tooltip,
formatter: function (params) {
let colors = ["#ee6666", "#000000", "#b0da9d", "#8699d5"];
let colorSpan = (color) =>
'<span style="display:inline-block;margin-right:1px;border-radius:5px;width:9px;height:9px;background-color:' +
color +
'"></span>';
let tooltip = "<p>" + params[0].axisValue + "</p>";
params.reverse().forEach((item, index) => {
let color = colors[index % colors.length];
let labels =
"<p>" +
colorSpan(color) +
" " +
item.seriesName +
": " +
nFormatter(item.data, 3);
("</p>");
tooltip += labels;
});
return tooltip;
},
valueFormatter(value, index) {
return nFormatter(value, 3);
return formatValueDecimalPlaces == null
? value
: nFormatter(value, formatValueDecimalPlaces);
},
},
toolbox: toolboxParams,
xAxis: {
data: dataArr.map((row) => row.date),
axisTick: axisTick,
axisLabel: axisLabel,
axisLine: axisLine,
type: "category",
data: chartData.map((item) => item.date),
},
grid: grid,
dataZoom: dataZoom(0),
yAxis: [
{
type: "value",
@ -117,7 +87,7 @@ function initEchart(dataArr) {
lineStyle: {
width: 0,
},
data: dataArr.map((row) => row.subsidy_usd),
data: chartData.map((row) => row.subsidy_usd),
},
{
type: "line",
@ -128,7 +98,7 @@ function initEchart(dataArr) {
lineStyle: {
width: 0,
},
data: dataArr.map((row) => row.totalfee_usd),
data: chartData.map((row) => row.totalfee_usd),
},
{
type: "line",
@ -138,7 +108,7 @@ function initEchart(dataArr) {
width: 1,
color: textColor,
},
data: dataArr.map((row) => row.total_reward_usd),
data: chartData.map((row) => row.total_reward_usd),
},
{
type: "line",
@ -148,22 +118,19 @@ function initEchart(dataArr) {
lineStyle: {
width: 3,
},
data: dataArr.map((row) => row.block_subsidy),
data: chartData.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"));