Files
caprigis/webgis/js/controllers/search_controller.js

165 lines
5.0 KiB
JavaScript

import { Controller } from "@hotwired/stimulus";
import { GisState } from "../state.js";
import UI from "../ui.js";
import { INIT_ZOOM } from "../gis.js";
const html = String.raw;
export default class extends Controller {
static targets = [
'search',
'results',
'clear',
'container',
];
/**
*
* @param {Event} event
*/
async submitSearch(event) {
event.preventDefault();
const data = new FormData(event.target);
const body = {};
const map = GisState.map;
const techs = GisState.layers.buildingTechs;
const techsMarkers = GisState.markers.buildingTechs;
// Reset search for building techs...
for (const key of Object.keys(techsMarkers)) {
map.removeLayer(techsMarkers[key]);
}
for (const entry of data.entries()) {
body[entry[0]] = entry[1];
}
const response = await fetch(`${GisState.apiUrl}/search?` + new URLSearchParams(body));
const results = await response.json();
this.containerTarget.classList.remove('is-hidden');
if (results.count) {
this.#injectResults(results);
// Reset zoom level after successful search
map.setZoom(INIT_ZOOM);
this.#filterMap(results);
console.debug(results);
// Should technique always be shown after a search?
for (const key of Object.keys(techsMarkers)) {
for (const record of results.sites) {
// Adjust for non-site records!!
if (techsMarkers[key].options.site === record.label
&& techsMarkers[key].options.label === body.technique)
map.addLayer(techsMarkers[key]);
}
}
}
}
clearSearch() {
const map = GisState.map;
// Restore layer groups in map
for (const key of Object.keys(GisState.layers)) {
map.addLayer(GisState.layers[key]);
}
// Empty result set
this.resultsTarget.innerHTML = '';
this.containerTarget.classList.add('is-hidden');
// Reset map zoom
map.setZoom(INIT_ZOOM);
}
#injectResults(results) {
/**
* @type {HTMLOutputElement} output
*/
const output = this.resultsTarget;
output.innerHTML = '';
console.debug(results);
if (results.count === 0) {
output.innerHTML = html`
<p class="has-background-white-bis p-4 mt-0 has-text-centered">
Nessun risultato trovato per i parametri di ricerca
</p>
`;
}
delete results.count;
for (const group of Object.keys(results)) {
if (results[group].length) this.#populateResults(group, results[group], output);
}
}
/**
*
* @param {string} group
* @param {Array<Object>} resultGroup
* @param {HTMLOutputElement} output
*/
#populateResults(group, resultGroup, output) {
const markers = GisState.markers[group];
for (const result of resultGroup) {
let coordinates = '';
for (let key of Object.keys(markers)) {
if (markers[key].options.data.label === result.label) {
coordinates = key;
}
}
// TODO The group value should be dynamic!!
const item = html`
<tr>
<td class="pt-4">${result.label}</td>
<td>
<button class="button is-link"
data-controller="marker"
data-action="marker#go"
data-marker-zoom-param="17"
data-marker-coords-value="${coordinates}"
data-marker-group-value="${resultGroup}">
Vai
<span class="ml-1 icon">
<i class="fa fa-chevron-right"></i>
</span>
</button>
</td>
</tr>
`;
output.innerHTML += item;
}
}
/**
*
* @param {Object} results
*/
#filterMap(results) {
const map = GisState.map;
const labels = [];
results.sites.forEach(r => labels.push(r.label));
// Remove all layer groups first
for (const key of Object.keys(GisState.layers)) {
map.removeLayer(GisState.layers[key]);
}
const sites = GisState.markers.sites;
for (let key of Object.keys(sites)) {
// If map has layers from previous search results...
map.removeLayer(sites[key]);
for (const label of labels) {
if (sites[key].options.data.label === label) {
map.addLayer(sites[key]);
}
}
}
}
}