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. The chart always reflects the countries selected in the table.
<br/> <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" >}} {{< 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" 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" >}} {{< 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 #### Attribution and License
Data obtained from © [OpenStreetMap](https://www.openstreetmap.org/copyright) Data obtained from © [OpenStreetMap](https://www.openstreetmap.org/copyright)

View File

@ -39,7 +39,7 @@
for (let objectId in chartData) { for (let objectId in chartData) {
chartDataMap.set(objectId, chartData[objectId]); chartDataMap.set(objectId, chartData[objectId]);
} }
var chartDom = document.getElementById(`${id}--chart`); var chartDom = document.getElementById(`${id}`);
var myChart = echarts.init(chartDom); var myChart = echarts.init(chartDom);
var option = { var option = {
@ -67,30 +67,29 @@
myChart.setOption(option, true); myChart.setOption(option, true);
} }
document.addEventListener("rowSelected", (event) => { // listen for filter events for this target
console.log( document.addEventListener("filterChange", function (event) {
"Row selected:", tableId = document.getElementById(id).id;
event.detail.row.offsetParent.id, console.log(event.detail);
event.detail.row.value, eventDetail = event.detail;
event.detail.valueId, if (eventDetail.filterActions.includes("refresh")) {
event.detail.selectableRows, chartData = [];
); updateChart();
valueId = event.detail.valueId } else {
if (eventDetail.filterTargets.includes(tableId)) {
if (eventDetail.filterActions.includes("selected")) {
valueId = eventDetail.filterId;
let selectedRow = { let selectedRow = {
[valueId]: event.detail.row.value, [valueId]: eventDetail.filterValue,
}; };
query = queryConstructor(selectedRow); query = queryConstructor(selectedRow);
fetchDataForChart(query, valueId); fetchDataForChart(query, valueId);
}); } else {
delete chartData[eventDetail.filterValue];
document.addEventListener("rowDeselected", (event) => {
console.log(
"Row deselected:",
event.detail.row.offsetParent.id,
event.detail.row.value,
);
delete chartData[event.detail.row.value];
updateChart(); updateChart();
}
}
}
}); });
} }
</script> </script>

View File

@ -7,6 +7,7 @@
sortable, sortable,
valueId, valueId,
selectableRows, selectableRows,
filterTargets
) { ) {
async function fetchDataForTable(query) { async function fetchDataForTable(query) {
try { try {
@ -25,7 +26,7 @@
function generateTable(data) { function generateTable(data) {
const jsonTableContainer = document.getElementById( const jsonTableContainer = document.getElementById(
`${id}--table-container`, `${id}--container`,
); );
jsonTableContainer.className = "jsonTableContainer"; jsonTableContainer.className = "jsonTableContainer";
jsonTableContainer.innerHTML = ""; jsonTableContainer.innerHTML = "";
@ -35,7 +36,7 @@
tableHeaderKeys = Object.keys(headers); tableHeaderKeys = Object.keys(headers);
const table = document.createElement("table"); const table = document.createElement("table");
table.id = `${id}--table`; table.id = `${id}`;
const thead = document.createElement("thead"); const thead = document.createElement("thead");
const tbody = document.createElement("tbody"); const tbody = document.createElement("tbody");
const headerRow = document.createElement("tr"); const headerRow = document.createElement("tr");
@ -63,51 +64,43 @@
table.appendChild(thead); table.appendChild(thead);
table.appendChild(tbody); table.appendChild(tbody);
// selectable rows
let currentlySelectedRow = null;
if (selectableRows === "multi" || selectableRows === "single") { if (selectableRows === "multi" || selectableRows === "single") {
const rows = table.getElementsByTagName("tr"); const rows = table.getElementsByTagName("tr");
for (let i = 1; i < rows.length; i++) { for (let i = 1; i < rows.length; i++) {
// Skip the header row
rows[i].addEventListener("click", function () { rows[i].addEventListener("click", function () {
if (selectableRows === "single") { if (selectableRows === "multi") {
// 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
this.classList.toggle("selected"); this.classList.toggle("selected");
if (this.classList.contains("selected")) {
// Update the currently selected row const event = new CustomEvent("filterChange", {
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",
{
detail: { detail: {
row: this, filterId: valueId,
selectableRows: selectableRows, filterValue: this.value,
valueId: valueId, filterActions: ["selected"],
filterTargets: filterTargets
}, },
}, });
);
document.dispatchEvent(event); 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 // sortable
if (sortable == "true") { if (sortable == "true") {
table.className = "sortable"; 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) { document.addEventListener("filterChange", function (event) {
query = queryConstructor() tableId = document.getElementById(id).id
if (event.detail.filterTargets.includes(tableId)) {
query = queryConstructor();
fetchDataForTable(query); fetchDataForTable(query);
}
}); });
query = queryConstructor() query = queryConstructor();
fetchDataForTable(query); fetchDataForTable(query);
} }
</script> </script>

View File

@ -1,6 +1,6 @@
{{ partial "chart.html" }} {{ partial "chart.html" }}
<section class = 'chart-container'> <section class = 'chart-container'>
<div class = "chart" id='{{ .Get "id" }}--chart'> <div class = "chart" id='{{ .Get "id" }}'>
<script> <script>
document.addEventListener("DOMContentLoaded", function () { 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" }}) 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 "," }} {{ $options_split := split $options "," }}
<div class="dropdown-filter-container"> <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 }} {{ range $options_split }}
{{ $parts := split . ":" }} {{ $parts := split . ":" }}
{{ $key := index $parts 0 }} {{ $key := index $parts 0 }}
@ -17,8 +17,10 @@
function dispatchDropdownEvent(selectElement) { function dispatchDropdownEvent(selectElement) {
const event = new CustomEvent('filterChange', { const event = new CustomEvent('filterChange', {
detail: { detail: {
filterId: selectElement.id, filterId: '{{ .Get "id_filter" }}',
filterValue: selectElement.value, filterValue: selectElement.value,
filterActions: ["refresh"],
filterTargets: '{{ .Get "targets" }}'.split(" ")
} }
}); });
document.dispatchEvent(event); document.dispatchEvent(event);

View File

@ -1,8 +1,8 @@
{{ partial "table.html" }} {{ partial "table.html" }}
<div id = '{{ .Get "id" }}--table-container'> <div id = '{{ .Get "id" }}--container'>
<script> <script>
document.addEventListener("DOMContentLoaded", function () { 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> </script>
</div> </div>

View File

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