Refactor with sites from DB...

This commit is contained in:
Nicolò P 2025-03-26 16:44:48 +01:00
parent 1067d108e5
commit 1911c0ce9f
2 changed files with 69 additions and 215 deletions

View File

@ -63,20 +63,6 @@ const optionsFabbricati = {
fillColor: '#5b5d5f', fillColor: '#5b5d5f',
fillOpacity: 0.8 fillOpacity: 0.8
}; };
const MARKER_NAMES = {
sites: {
'gradola' : 'Villa di Gradola',
'damecuta' : 'Villa di Damecuta',
'matermania' : 'Grotta di Matermania',
'arsenale' : 'Grotta dell\'Arsenale',
'tiberio' : 'Bagni di Tiberio',
'mura' : 'Mura greche',
'san_michele' : 'Villa San Michele',
'scala_fenicia' : 'Scala Fenicia',
'grotta_azzurra' : 'Grotta Azzurra',
'lopozzo' : 'Località Lo Pozzo',
},
};
const clusterOptions = { const clusterOptions = {
spiderfyOnMaxZoom: false, spiderfyOnMaxZoom: false,
showCoverageOnHover: false, showCoverageOnHover: false,
@ -110,16 +96,6 @@ function capitalize(text) {
* @returns {Map} * @returns {Map}
*/ */
GIS.initMap = async function (mapId, zoomLevel = this.INIT_ZOOM) { GIS.initMap = async function (mapId, zoomLevel = this.INIT_ZOOM) {
L.LayerGroup.include({
customGetLayer : function (id) {
for (let l in this._layers) {
if (this._layers[l].id === id) {
return this._layers[l];
}
}
}
});
let map = L.map(mapId, { let map = L.map(mapId, {
//attributionControl: false, //attributionControl: false,
minZoom: GIS.MIN_ZOOM, minZoom: GIS.MIN_ZOOM,
@ -127,16 +103,20 @@ GIS.initMap = async function (mapId, zoomLevel = this.INIT_ZOOM) {
map.crs = L.CRS.EPSG4326; map.crs = L.CRS.EPSG4326;
const {baseMap, sitesGroup} = await this.initLayers(map); const baseMap = await this.initLayers(map);
// Add scale and ruler controls // Add scale and ruler controls
L.control.scale({imperial: false}).addTo(map); L.control.scale({imperial: false}).addTo(map);
L.control.graphicScale({fill: 'hollow', position: 'bottomright'}).addTo(map); L.control.graphicScale({fill: 'hollow', position: 'bottomright'}).addTo(map);
let layerVincoli = await this.loadLayer('vincoli.geojson', optionsVincoli); let layerVincoli = await this.loadGeoJSON('vincoli.geojson', optionsVincoli);
let layerPaesistici = await this.loadLayer('paesistici.geojson', optionsPaesistici); let layerPaesistici = await this.loadGeoJSON('paesistici.geojson', optionsPaesistici);
// Refactor with separate function... // Refactor with separate function...
this.sitesMarkers(sitesGroup).then(group => {group.addTo(map); window.Sites = group}); this.sites().then(data => {
data.markers.addTo(map);
data.geom.addTo(map);
window.Sites = data.markers;
});
this.notConserved().then(group => {group.addTo(map); window.NotConserved = group}); this.notConserved().then(group => {group.addTo(map); window.NotConserved = group});
this.findings().then(group => {group.addTo(map); window.Findings = group}); this.findings().then(group => {group.addTo(map); window.Findings = group});
this.prehistoric().then(group => {group.addTo(map); window.Prehistoric = group}); this.prehistoric().then(group => {group.addTo(map); window.Prehistoric = group});
@ -145,55 +125,39 @@ GIS.initMap = async function (mapId, zoomLevel = this.INIT_ZOOM) {
'Vincoli archeologici' : layerVincoli, 'Vincoli archeologici' : layerVincoli,
'Vincoli paesistici' : layerPaesistici, 'Vincoli paesistici' : layerPaesistici,
}; };
// TEMP!! Remove point for Lo Pozzo...
sitesGroup.removeLayer(sitesGroup.customGetLayer('lopozzo'));
sitesGroup.addTo(map);
L.control.layers(baseMap, archeo).addTo(map); L.control.layers(baseMap, archeo).addTo(map);
return map; return map;
} }
/** /**
* Create markers for sites * Create markers for sites
* @param {L.LayerGroup} sitesGroup * @returns {{markers: L.markerClusterGroup, geom: L.LayerGroup}}
* @returns {L.markerClusterGroup}
*/ */
GIS.sitesMarkers = async function (sitesGroup) { GIS.sites = async function () {
let sitesMarkers = L.markerClusterGroup( let sitesData = await fetch(`${API_URL}/sites`)
clusterOptions .then(data => data.json());
let sites = L.markerClusterGroup(clusterOptions);
let geom = [];
for (let record of sitesData) {
if (record.geojson) {
const options = record.gisId === 'grotta_azzurra' ?
optionsGrotta : optionsSiti;
geom.push(await this.loadSiteLayer(record, options));
}
sites.addLayer(L.marker(
record.coordinates,
{icon: Icons.site}
).bindTooltip(record.label + '<br>(Clicca per aprire scheda)')
.on(
'click',
() => UI.openSiteModal(record, '#site-data')
)
); );
for (let id in MARKER_NAMES.sites) {
let layer = sitesGroup.customGetLayer(id);
let coords = layer?.getBounds().getCenter();
const fromStorage = localStorage.getItem(id);
let data = {};
if (fromStorage !== 'undefined') {
try {
data = JSON.parse(fromStorage);
const lat = data?.coordinates[0] ?? coords.lat;
const lon = data?.coordinates[1] ?? coords.lng;
coords = [lat, lon];
} catch (error) {
console.log(error);
}
} else {
data = await GIS._fetchData('site/' + id);
} }
const marker = L.marker(coords, { icon: Icons.site }) return {markers: sites, geom: L.layerGroup(geom)};
.bindTooltip(MARKER_NAMES.sites[id] + '<br>(Clicca per aprire scheda)');
marker.id = id;
marker.on('click', () => UI.openSiteModal(data, '#site-data'));
sitesMarkers.addLayer(marker);
}
return sitesMarkers;
} }
/** /**
* Create not conserved group * Create not conserved group
@ -272,103 +236,15 @@ GIS.prehistoric = async function () {
} }
return prehistoric; return prehistoric;
/*
const geo = await fetch(`${BASE_URL}/geojson/preistorici.geojson`)
.then(res => res.json());
let prehistoric = L.markerClusterGroup(
clusterOptions
);
L.geoJSON(geo, {
pointToLayer: function(geoJsonPoint, latlng) {
prehistoric.addLayer(
L.marker(latlng, {
icon: Icons.prehistoric
}).bindTooltip(geoJsonPoint.properties.denominazione)
.bindPopup(`
<table class="table is-striped is-size-6 m-2">
<tr><th>Denominazione:</th><td>${geoJsonPoint.properties.denominazione}</td></tr>
<tr><th>Oggetto:</th><td>${geoJsonPoint.properties.oggetto}</td></tr>
</table>
`)
);
},
});
return prehistoric;
*/
} }
/*
GIS._prepareLayers = async function(layer) {
const fromStorage = localStorage.getItem(layer.id);
let data = {};
let coords = layer.getBounds().getCenter();
if (fromStorage !== 'undefined') {
try {
data = JSON.parse(fromStorage);
const lat = data?.lat ?? coords[0];
const lon = data?.lon ?? coords[1];
coords = [lat, lon];
} catch (error) {
console.log(error);
}
} else {
data = await GIS._fetchData(layer.id);
}
// TODO: terrible!
if (!layer.id.includes('area')) {
const marker = L.marker(coords)
.addTo(map)
.bindTooltip(
Object.keys(archeo).find(k => archeo[k] === layer)
.replace(/\s\(.*$/, '')
)
.openTooltip();
if (typeof data === 'object') {
marker.on('click', () => UI.openModal(data, '#site-data'));
}
}
}
*/
/** /**
* Adds layers to map and returns an object * Adds layers to map and returns an object
* with {baseMap, archeoLayers, sitesLayerGroup} * with {baseMap, archeoLayers, sitesLayerGroup}
* @todo Load areas for sites that have them!!
* @param {L.Map} map * @param {L.Map} map
* @returns {{baseMap: {"OpenStreetMap": L.TileLayer}, archeo: object, sitesGroup: L.LayerGroup}} * @returns {{baseMap: {"OpenStreetMap": L.TileLayer}}}
*/ */
GIS.initLayers = async function(map) { GIS.initLayers = async function(map) {
// TODO Move all this to separate array / object!
let layerMater = await this.loadLayer('matermania.geojson', optionsSiti, false);
let layerMaterArea = await this.loadLayer('matermania_area.geojson', optionsSiti, false);
let layerArsenale = await this.loadLayer('arsenale.geojson', optionsSiti, false);
let layerArsenaleArea = await this.loadLayer('arsenale_area.geojson', optionsSiti, false);
let layerGradola = await this.loadLayer('gradola.geojson', optionsSiti, false);
let layerGradolaArea = await this.loadLayer('gradola_area.geojson', optionsSiti, false);
let layerMura = await this.loadLayer('mura.geojson', optionsSiti, false);
let layerSanMichele = await this.loadLayer('san_michele.geojson', optionsSiti, false);
let layerDamecuta = await this.loadLayer('damecuta.geojson', optionsSiti, false);
let layerTiberio = await this.loadLayer('tiberio.geojson', optionsSiti, false);
let layerScala = await this.loadLayer('scala_fenicia.geojson', optionsSiti, false);
let layerGrotta = await this.loadLayer('grotta_azzurra.geojson', optionsGrotta, false);
let layerLopozzo = await this.loadLayer('lopozzo.geojson', optionsSiti, false);
layerMater.id = 'matermania';
layerMaterArea.id = 'matermania_area';
layerGradola.id = 'gradola';
layerGradolaArea.id = 'gradola_area';
layerArsenale.id = 'arsenale';
layerArsenaleArea.id = 'arsenale_area';
layerMura.id = 'mura';
layerSanMichele.id = 'san_michele';
layerDamecuta.id = 'damecuta';
layerTiberio.id = 'tiberio';
layerScala.id = 'scala_fenicia';
layerGrotta.id = 'grotta_azzurra';
layerLopozzo.id = 'lopozzo';
let osmap = new L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', { let osmap = new L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', {
maxNativeZoom : GIS.MAX_ZOOM, maxNativeZoom : GIS.MAX_ZOOM,
@ -383,25 +259,10 @@ GIS.initLayers = async function(map) {
maxZoom: GIS.MAX_ZOOM, maxZoom: GIS.MAX_ZOOM,
attribution: '&copy; Mapbox' attribution: '&copy; Mapbox'
}); });
let boundaries = await this.loadLayer('confini.geojson', {}, false); let boundaries = await this.loadGeoJSON('confini.geojson', {}, false);
let buildings = await this.loadLayer('fabbricati.geojson', optionsFabbricati, false); let buildings = await this.loadGeoJSON('fabbricati.geojson', optionsFabbricati, false);
let baseCatasto = new L.LayerGroup([buildings, boundaries]); let baseCatasto = new L.LayerGroup([buildings, boundaries]);
const sitesGroup = new L.LayerGroup([
layerMater,
layerMaterArea,
layerGradola,
layerGradolaArea,
layerArsenale,
layerArsenaleArea,
layerMura,
layerSanMichele,
layerDamecuta,
layerTiberio,
layerScala,
layerGrotta,
layerLopozzo
]);
const baseGroup = new L.LayerGroup([osmap]); const baseGroup = new L.LayerGroup([osmap]);
baseGroup.addTo(map); baseGroup.addTo(map);
const baseMap = { const baseMap = {
@ -410,7 +271,7 @@ GIS.initLayers = async function(map) {
"Cartografia catastale" : baseCatasto, "Cartografia catastale" : baseCatasto,
}; };
return {baseMap, sitesGroup}; return baseMap;
} }
/** /**
* Toggle spherical photos on the map * Toggle spherical photos on the map
@ -458,18 +319,43 @@ GIS.toggleSpherical = async function(map) {
}); });
} }
/** /**
* @param {string} geoJSON * @param {string} geoJSON geoJSON filename
* @param {{color, opacity, weight, fillColor, fillOpacity}} options Style options for features * @param {{color, opacity, weight, fillColor, fillOpacity}} options Style options for features
* @param {boolean} popup Should the features have a popup? * @param {boolean} popup Should the features have a popup?
* @returns {L.Layer}
*/ */
GIS.loadLayer = async function (geoJSON, options, popup = true) { GIS.loadGeoJSON = async function (geoJSON, options, popup = true) {
const geo = await fetch(`${BASE_URL}/geojson/${geoJSON}`) const geo = await fetch(`${BASE_URL}/geojson/${geoJSON}`)
.then(res => res.json()) .then(res => res.json())
.catch(error => console.error(`Can't load layer ${geoJSON}. Reason: ${error}`)); .catch(error => console.error(`Can't load layer ${geoJSON}. Reason: ${error}`));
const layerId = geoJSON.replace('.geojson', ''); // Show data from feature in popUp?
const layer = new L.geoJson(geo, {
style: function () {
return options;
},
onEachFeature: function (feature, layer) {
if (popup) {
layer.bindPopup(GIS.featurePopup(geoJSON, feature));
}
}
});
this.cacheDBData(layerId); return layer;
}
/**
* @param {object} site Site record from DB
* @param {{color, opacity, weight, fillColor, fillOpacity}} options Style options for features
* @param {boolean} popup Should the features have a popup?
* @returns {L.Layer}
*/
GIS.loadSiteLayer = async function (site, options, popup = true) {
const geoJSON = `${site.gisId}.geojson`;
const geo = await fetch(`${BASE_URL}/geojson/${geoJSON}`)
.then(res => res.json())
.catch(error => console.error(`Can't load layer ${geoJSON}. Reason: ${error}`));
this.cacheDBData(site.gisId, site.id);
// Show data from feature in popUp? // Show data from feature in popUp?
const layer = new L.geoJson(geo, { const layer = new L.geoJson(geo, {
@ -482,7 +368,7 @@ GIS.loadLayer = async function (geoJSON, options, popup = true) {
} }
else { else {
layer.on("click", async () => { layer.on("click", async () => {
let data = GIS.layerData(layerId); let data = GIS.layerData(site.gisId, site.id);
if (typeof data === 'object') { if (typeof data === 'object') {
UI.openSiteModal(data); UI.openSiteModal(data);
@ -497,9 +383,10 @@ GIS.loadLayer = async function (geoJSON, options, popup = true) {
/** /**
* Retrieves data for a given layer * Retrieves data for a given layer
* @param {string} layerId * @param {string} layerId
* @param {string} dbId
* @returns {object} Data for this layer from DB or cache * @returns {object} Data for this layer from DB or cache
*/ */
GIS.layerData = async function (layerId) { GIS.layerData = async function (layerId, dbId) {
const fromStorage = localStorage.getItem(layerId); const fromStorage = localStorage.getItem(layerId);
let data = {}; let data = {};
@ -510,7 +397,7 @@ GIS.layerData = async function (layerId) {
console.log(error); console.log(error);
} }
} else { } else {
data = await GIS._fetchData('site/' + layerId); data = await GIS._fetchData('sites/' + dbId);
} }
return data; return data;
@ -528,8 +415,8 @@ GIS.getSpherical = async function (siteId) {
* for a given layer * for a given layer
* @param {string} layerId * @param {string} layerId
*/ */
GIS.cacheDBData = async function (layerId) { GIS.cacheDBData = async function (layerId, dbId) {
const data = await this._fetchData('site/' + layerId); const data = await this._fetchData('sites/' + dbId);
localStorage.setItem(layerId, JSON.stringify(data)); localStorage.setItem(layerId, JSON.stringify(data));
} }
/** /**

View File

@ -208,39 +208,6 @@ UI.openPrehistModal = function (data, selector) {
prehistoric.render().then(html => modal.querySelector('#prehist-sheet').innerHTML = html); prehistoric.render().then(html => modal.querySelector('#prehist-sheet').innerHTML = html);
modal.classList.add('is-active'); modal.classList.add('is-active');
} }
/**
* @param {string} menuListSel Menu list selector
* @param {L.Map} map
* @param {L.LayerGroup} sites
*/
UI.sitesMenu = function (menuListSel, map, sites) {
// Close menu if arrow button is clicked...
let markers = [];
map.eachLayer(layer => {
if (layer instanceof L.Marker) {
markers.push(layer);
}
})
const menu = document.querySelector(menuListSel);
menu.addEventListener('click', async event => {
if (event.target.nodeName === 'A') {
const layerId = event.target.id;
const marker = markers.filter(m => m.id === layerId)[0];
// zoom to layer...
const layer = sites.customGetLayer(layerId);
map.setView(
layer.getBounds().getCenter(),
19,
{animate: true, duration: 1, easeLinearity: 0.25}
);
marker.openTooltip();
}
});
}
/** /**
* Open Spotlight gallery * Open Spotlight gallery
* @param {string} galleryId The id of the trigger element * @param {string} galleryId The id of the trigger element