working filter system

This commit is contained in:
Sam 2024-09-23 20:11:25 +01:00
parent 5930fe90a1
commit eb3d17884a
7 changed files with 77 additions and 79 deletions

View File

@ -15,10 +15,10 @@ You can select the growth period of interest from the drop-down, which updates t
The chart always reflects the countries selected in the table.
<br/>
{{< dropdown_filter id="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" >}}
{{< table id="bitcoin_business_growth" endpoint="bitcoin_business_growth_percent_diff" headers="{'country_name': 'Country', 'date_range': 'Date Range', 'last_value': 'Previous #', 'first_value': 'Current #', 'difference': 'Diff', 'percent_difference': '% Diff'}" maxHeight="400px" sortable="true" valueId="country_name" selectableRows="multi" >}}
{{< 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', 'last_value': 'Previous #', 'first_value': 'Current #', 'difference': 'Diff', 'percent_difference': '% Diff'}" maxHeight="400px" sortable="true" valueId="country_name" selectableRows="multi" targets="bitcoin-business-growth-chart" >}}
{{< chart id="bitcoin_business_growth" endpoint="bitcoin_business_growth_timeseries" chartType="line" xAxisField="date" yAxisField="cumulative_value" scaleChart=true >}}
{{< chart id="bitcoin-business-growth-chart" endpoint="bitcoin_business_growth_timeseries" chartType="line" xAxisField="date" yAxisField="cumulative_value" scaleChart=true >}}
#### Attribution and License
Data obtained from © [OpenStreetMap](https://www.openstreetmap.org/copyright)

View File

@ -39,7 +39,7 @@
for (let objectId in chartData) {
chartDataMap.set(objectId, chartData[objectId]);
}
var chartDom = document.getElementById(`${id}--chart`);
var chartDom = document.getElementById(`${id}`);
var myChart = echarts.init(chartDom);
var option = {
@ -67,30 +67,29 @@
myChart.setOption(option, true);
}
document.addEventListener("rowSelected", (event) => {
console.log(
"Row selected:",
event.detail.row.offsetParent.id,
event.detail.row.value,
event.detail.valueId,
event.detail.selectableRows,
);
valueId = event.detail.valueId
// 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]: event.detail.row.value,
[valueId]: eventDetail.filterValue,
};
query = queryConstructor(selectedRow);
fetchDataForChart(query, valueId);
});
document.addEventListener("rowDeselected", (event) => {
console.log(
"Row deselected:",
event.detail.row.offsetParent.id,
event.detail.row.value,
);
delete chartData[event.detail.row.value];
} else {
delete chartData[eventDetail.filterValue];
updateChart();
}
}
}
});
}
</script>

View File

@ -7,6 +7,7 @@
sortable,
valueId,
selectableRows,
filterTargets
) {
async function fetchDataForTable(query) {
try {
@ -25,7 +26,7 @@
function generateTable(data) {
const jsonTableContainer = document.getElementById(
`${id}--table-container`,
`${id}--container`,
);
jsonTableContainer.className = "jsonTableContainer";
jsonTableContainer.innerHTML = "";
@ -35,7 +36,7 @@
tableHeaderKeys = Object.keys(headers);
const table = document.createElement("table");
table.id = `${id}--table`;
table.id = `${id}`;
const thead = document.createElement("thead");
const tbody = document.createElement("tbody");
const headerRow = document.createElement("tr");
@ -63,51 +64,43 @@
table.appendChild(thead);
table.appendChild(tbody);
// selectable rows
let currentlySelectedRow = null;
if (selectableRows === "multi" || selectableRows === "single") {
const rows = table.getElementsByTagName("tr");
for (let i = 1; i < rows.length; i++) {
// Skip the header row
rows[i].addEventListener("click", function () {
if (selectableRows === "single") {
// Deselect the currently selected row, if any
if (currentlySelectedRow && currentlySelectedRow !== this) {
currentlySelectedRow.classList.remove("selected");
const deselectEvent = new CustomEvent("rowDeselected", {
detail: { row: currentlySelectedRow },
});
document.dispatchEvent(deselectEvent);
}
// Toggle the selected class on the clicked row
if (selectableRows === "multi") {
this.classList.toggle("selected");
// Update the currently selected row
currentlySelectedRow = this.classList.contains("selected")
? this
: null;
} else {
// Multi-select behavior
this.classList.toggle("selected");
}
const event = new CustomEvent(
this.classList.contains("selected")
? "rowSelected"
: "rowDeselected",
{
if (this.classList.contains("selected")) {
const event = new CustomEvent("filterChange", {
detail: {
row: this,
selectableRows: selectableRows,
valueId: valueId,
filterId: valueId,
filterValue: this.value,
filterActions: ["selected"],
filterTargets: filterTargets
},
},
);
});
document.dispatchEvent(event);
} else {
const event = new CustomEvent("filterChange", {
detail: {
filterId: valueId,
filterValue: this.value,
filterActions: ["deselected"],
filterTargets: filterTargets
},
});
document.dispatchEvent(event);
}
} else if (selectableRows === "single") {
if (this.classList.contains("selected")) {
this.classList.remove("selected");
} else {
for (let j = 1; j < rows.length; j++) {
rows[j].classList.remove("selected");
}
this.classList.add("selected");
}
}
});
}
}
@ -116,16 +109,20 @@
// sortable
if (sortable == "true") {
table.className = "sortable";
sorttable.makeSortable(document.getElementById(`${id}--table`));
sorttable.makeSortable(document.getElementById(`${id}`));
}
}
// listen for filter events for this target
document.addEventListener("filterChange", function (event) {
query = queryConstructor()
tableId = document.getElementById(id).id
if (event.detail.filterTargets.includes(tableId)) {
query = queryConstructor();
fetchDataForTable(query);
}
});
query = queryConstructor()
query = queryConstructor();
fetchDataForTable(query);
}
</script>

View File

@ -1,6 +1,6 @@
{{ partial "chart.html" }}
<section class = 'chart-container'>
<div class = "chart" id='{{ .Get "id" }}--chart'>
<div class = "chart" id='{{ .Get "id" }}'>
<script>
document.addEventListener("DOMContentLoaded", function () {
createChart(id={{ .Get "id" }}, endpoint={{ .Get "endpoint" }}, chartType={{ .Get "chartType" }}, xAxisField={{ .Get "xAxisField" }}, yAxisField={{ .Get "yAxisField" }}, sortField={{ .Get "sortField" }}, scaleChart={{ .Get "scaleChart" }})

View File

@ -5,7 +5,7 @@
{{ $options_split := split $options "," }}
<div class="dropdown-filter-container">
<select class="filter dropdown-filter" id="{{ $id }}" onchange="dispatchDropdownEvent(this)">
<select class="filter dropdown-filter" id="{{ $id }}" idFilter='{{ .Get "id_filter" }}' onchange="dispatchDropdownEvent(this)">
{{ range $options_split }}
{{ $parts := split . ":" }}
{{ $key := index $parts 0 }}
@ -17,8 +17,10 @@
function dispatchDropdownEvent(selectElement) {
const event = new CustomEvent('filterChange', {
detail: {
filterId: selectElement.id,
filterId: '{{ .Get "id_filter" }}',
filterValue: selectElement.value,
filterActions: ["refresh"],
filterTargets: '{{ .Get "targets" }}'.split(" ")
}
});
document.dispatchEvent(event);

View File

@ -1,8 +1,8 @@
{{ partial "table.html" }}
<div id = '{{ .Get "id" }}--table-container'>
<div id = '{{ .Get "id" }}--container'>
<script>
document.addEventListener("DOMContentLoaded", function () {
createTable({{ .Get "endpoint" }}, {{ .Get "id" }}, {{ .Get "headers" | safeJS }}, {{ .Get "maxHeight" }}, {{ .Get "sortable" }}, {{ .Get "valueId" }}, {{ .Get "selectableRows" }})
createTable({{ .Get "endpoint" }}, {{ .Get "id" }}, {{ .Get "headers" | safeJS }}, {{ .Get "maxHeight" }}, {{ .Get "sortable" }}, {{ .Get "valueId" }}, {{ .Get "selectableRows" }}, '{{ .Get "targets" }}'.split(" "))
});
</script>
</div>

View File

@ -5,7 +5,7 @@ function queryConstructor(customFilters = {}) {
Object.assign(queryObject, customFilters);
filters.forEach((filter) => {
const filterId = filter.id;
const filterId = filter.getAttribute("idFilter");
const filterValue = filter.value;
queryObject[filterId] = filterValue;
});