Mostly working state
This commit is contained in:
@@ -18,180 +18,6 @@
|
||||
.bg-pale-orange { background-color: #FCE4D6; }
|
||||
</style>
|
||||
|
||||
<!-- <script> -->
|
||||
<!-- document.addEventListener("DOMContentLoaded", () => { -->
|
||||
<!-- let manifest = {}; -->
|
||||
<!-- let currentSelections = {}; -->
|
||||
<!-- -->
|
||||
<!-- async function init() { -->
|
||||
<!-- const resp = await fetch('/dashboard'); -->
|
||||
<!-- manifest = await resp.json(); -->
|
||||
<!-- renderRootFilters(); -->
|
||||
<!-- } -->
|
||||
<!-- -->
|
||||
<!-- function renderRootFilters() { -->
|
||||
<!-- const rootFilters = manifest.filters.filter(f => f.depends_on === null); -->
|
||||
<!-- rootFilters.forEach(f => createDropdown(f)); -->
|
||||
<!-- } -->
|
||||
<!-- -->
|
||||
<!-- function createDropdown(config) { -->
|
||||
<!-- const container = document.createElement("div"); -->
|
||||
<!-- container.id = `container_${config.id}`; -->
|
||||
<!-- -->
|
||||
<!-- const label = document.createElement("label"); -->
|
||||
<!-- label.textContent = config.label + ": "; -->
|
||||
<!-- label.style.fontWeight = "bold"; -->
|
||||
<!-- -->
|
||||
<!-- const select = document.createElement("select"); -->
|
||||
<!-- select.id = config.id; -->
|
||||
<!-- select.innerHTML = `<option value="">Select...</option>`; -->
|
||||
<!-- -->
|
||||
<!-- select.addEventListener("change", async (e) => { -->
|
||||
<!-- const val = e.target.value; -->
|
||||
<!-- currentSelections[config.id] = val; -->
|
||||
<!-- -->
|
||||
<!-- // 1. Clear dependent filters and data -->
|
||||
<!-- clearDependents(config.id); -->
|
||||
<!-- -->
|
||||
<!-- // 2. Load options for children -->
|
||||
<!-- const children = manifest.filters.filter(f => f.depends_on === config.id); -->
|
||||
<!-- children.forEach(child => { -->
|
||||
<!-- const options = await fetchOptions(child, val); -->
|
||||
<!-- populateDropdown(child.id, options); -->
|
||||
<!-- }); -->
|
||||
<!-- -->
|
||||
<!-- // 3. Update data grid -->
|
||||
<!-- updateGrid(); -->
|
||||
<!-- }); -->
|
||||
<!-- -->
|
||||
<!-- container.appendChild(label); -->
|
||||
<!-- container.appendChild(select); -->
|
||||
<!-- document.getElementById("filter-area").appendChild(container); -->
|
||||
<!-- } -->
|
||||
<!-- -->
|
||||
<!-- async function fetchOptions(config, value) { -->
|
||||
<!-- const params = new URLSearchParams({ -->
|
||||
<!-- table: config.table, -->
|
||||
<!-- pluck_column: config.pluck_column, -->
|
||||
<!-- filter_col: config.filter_column, -->
|
||||
<!-- value: value -->
|
||||
<!-- }); -->
|
||||
<!-- const resp = await fetch(`/dashboard/options?${params.toString()}`); -->
|
||||
<!-- return await resp.json(); -->
|
||||
<!-- } -->
|
||||
<!-- -->
|
||||
<!-- function populateDropdown(id, options) { -->
|
||||
<!-- const select = document.getElementById(id) || createMissingDropdown(id); -->
|
||||
<!-- select.innerHTML = `<option value="">Select...</option>`; -->
|
||||
<!-- options.forEach(opt => { -->
|
||||
<!-- select.innerHTML += `<option value="${opt}">${opt}</option>`; -->
|
||||
<!-- }); -->
|
||||
<!-- // If this is the last dropdown, it should be visible now -->
|
||||
<!-- const container = document.getElementById(`container_${id}`); -->
|
||||
<!-- if(container) container.style.display = "block"; -->
|
||||
<!-- } -->
|
||||
<!-- -->
|
||||
<!-- function createMissingDropdown(id) { -->
|
||||
<!-- const config = manifest.filters.find(f => f.id === id); -->
|
||||
<!-- const container = document.createElement("div"); -->
|
||||
<!-- container.id = `container_${id}`; -->
|
||||
<!-- container.style.display = "none"; // Hidden until parent is selected -->
|
||||
<!-- -->
|
||||
<!-- const label = document.createElement("label"); -->
|
||||
<!-- label.textContent = config.label + ": "; -->
|
||||
<!-- -->
|
||||
<!-- const select = document.createElement("select"); -->
|
||||
<!-- select.id = id; -->
|
||||
<!-- -->
|
||||
<!-- select.addEventListener("change", async (e) => { -->
|
||||
<!-- currentSelections[id] = e.target.value; -->
|
||||
<!-- clearDependents(id); -->
|
||||
<!-- const children = manifest.filters.filter(f => f.depends_on === id); -->
|
||||
<!-- children.forEach(child => { -->
|
||||
<!-- const opts = await fetchOptions(child, e.target.value); -->
|
||||
<!-- populateDropdown(child.id, opts); -->
|
||||
<!-- }); -->
|
||||
<!-- updateGrid(); -->
|
||||
<!-- }); -->
|
||||
<!-- -->
|
||||
<!-- container.appendChild(label); -->
|
||||
<!-- container.appendChild(select); -->
|
||||
<!-- document.getElementById("filter-area").appendChild(container); -->
|
||||
<!-- return select; -->
|
||||
<!-- } -->
|
||||
<!-- -->
|
||||
<!-- function clearDependents(id) { -->
|
||||
<!-- // Recursively find all filters that depend on this ID and reset them -->
|
||||
<!-- manifest.filters.forEach(f => { -->
|
||||
<!-- if (f.depends_on === id) { -->
|
||||
<!-- const select = document.getElementById(f.id); -->
|
||||
<!-- if (select) select.innerHTML = `<option value="">Select...</option>`; -->
|
||||
<!-- const container = document.getElementById(`container_${f.id}`); -->
|
||||
<!-- if (container) container.style.display = "none"; -->
|
||||
<!-- delete currentSelections[f.id]; -->
|
||||
<!-- clearDependents(f.id); -->
|
||||
<!-- } -->
|
||||
<!-- }); -->
|
||||
<!-- } -->
|
||||
<!-- -->
|
||||
<!-- async function updateGrid() { -->
|
||||
<!-- const params = new URLSearchParams(currentSelections); -->
|
||||
<!-- const resp = await fetch(`/dashboard/data?${params.toString()}`); -->
|
||||
<!-- const data = await resp.json(); -->
|
||||
<!-- renderLayout(data); -->
|
||||
<!-- } -->
|
||||
<!-- -->
|
||||
<!-- function renderLayout(data) { -->
|
||||
<!-- const area = document.getElementById("results-area"); -->
|
||||
<!-- area.innerHTML = ""; -->
|
||||
<!-- -->
|
||||
<!-- // Group layout by grid name (defaults to 'main') -->
|
||||
<!-- const grids = {}; -->
|
||||
<!-- manifest.layout.forEach(item => { -->
|
||||
<!-- const gridId = item.grid || 'main'; -->
|
||||
<!-- if (!grids[gridId]) grids[gridId] = []; -->
|
||||
<!-- grids[gridId].push(item); -->
|
||||
<!-- }); -->
|
||||
<!-- -->
|
||||
<!-- Object.keys(grids).forEach(gridId => { -->
|
||||
<!-- const table = document.createElement("table"); -->
|
||||
<!-- table.className = "dyn-grid"; -->
|
||||
<!-- -->
|
||||
<!-- // Find max rows/cols to initialize table structure if needed, -->
|
||||
<!-- // but we can just build rows dynamically. -->
|
||||
<!-- const layoutItems = grids[gridId]; -->
|
||||
<!-- const maxRow = Math.max(...layoutItems.map(i => i.row)); -->
|
||||
<!-- -->
|
||||
<!-- for (let r = 0; r <= maxRow; r++) { -->
|
||||
<!-- const tr = document.createElement("tr"); -->
|
||||
<!-- const rowItems = layoutItems.filter(i => i.row === r); -->
|
||||
<!-- -->
|
||||
<!-- rowItems.forEach(item => { -->
|
||||
<!-- const td = document.createElement("td"); -->
|
||||
<!-- td.className = item.class; -->
|
||||
<!-- td.colSpan = item.colspan || 1; -->
|
||||
<!-- td.rowSpan = item.rowspan || 1; -->
|
||||
<!-- -->
|
||||
<!-- if (item.text) { -->
|
||||
<!-- td.textContent = item.text; -->
|
||||
<!-- } else if (item.value) { -->
|
||||
<!-- // Resolve nested JSON path (e.g., "main_info.joint") -->
|
||||
<!-- const parts = item.value.split('.'); -->
|
||||
<!-- const val = parts.reduce((obj, key) => (obj && obj[key] !== undefined) ? obj[key] : '', data); -->
|
||||
<!-- td.textContent = val; -->
|
||||
<!-- } -->
|
||||
<!-- tr.appendChild(td); -->
|
||||
<!-- }); -->
|
||||
<!-- table.appendChild(tr); -->
|
||||
<!-- } -->
|
||||
<!-- area.appendChild(table); -->
|
||||
<!-- }); -->
|
||||
<!-- } -->
|
||||
<!-- -->
|
||||
<!-- init(); -->
|
||||
<!-- }); -->
|
||||
<!-- </script> -->
|
||||
|
||||
|
||||
<script>
|
||||
document.addEventListener("DOMContentLoaded", () => {
|
||||
@@ -261,7 +87,8 @@ document.addEventListener("DOMContentLoaded", () => {
|
||||
|
||||
async function fetchOptions(config, value) {
|
||||
var params
|
||||
if (config.filter_col == undefined) {
|
||||
if (config.filter_column == undefined) {
|
||||
console.log(config + "Undefined filter col");
|
||||
params = new URLSearchParams({
|
||||
table: config.table,
|
||||
pluck_column: config.pluck_column,
|
||||
@@ -270,7 +97,7 @@ document.addEventListener("DOMContentLoaded", () => {
|
||||
params = new URLSearchParams({
|
||||
table: config.table,
|
||||
pluck_column: config.pluck_column,
|
||||
filter_col: config.filter_column,
|
||||
filter_column: config.filter_column,
|
||||
value: value
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user