caprigis/webgis/js/ui.js
2024-11-30 18:37:01 +01:00

264 lines
8.0 KiB
JavaScript

'use strict';
import Spotlight from './vendor/spotlight.js/src/js/spotlight.js';
import { SiteSheet } from './components/SiteSheet.js';
import { SiteDocuments } from './components/SiteDocuments.js';
import { SiteSurveys } from './components/SiteSurveys.js';
import { SiteMedia } from './components/SiteMedia.js';
import { NotConservedSheet } from './components/NotConservedSheet.js';
import GIS from './gis.js';
import { Finding } from './components/Finding.js';
/**
* @namespace UI
*/
const UI = {};
/**
* Add a Leaflet control to center the map
* @param {Map} map The Leaflet map object
* @param {LatLngExpression} centerCoords The coordinates to center the map
* @param {number} zoom Zoom level
*/
UI.addCenterMapControl = function (map, centerCoords, zoom) {
L.Control.CenterControl = L.Control.extend({
options: {
position: 'topleft'
},
onAdd: function (map) {
let controlDiv = L.DomUtil.create('div', 'leaflet-draw-toolbar leaflet-bar');
L.DomEvent
.addListener(controlDiv, 'click', L.DomEvent.stopPropagation)
.addListener(controlDiv, 'click', L.DomEvent.preventDefault)
.addListener(controlDiv, 'click', function () {
map.setView(centerCoords, zoom, {animate: true});
}
);
let controlUI = L.DomUtil.create('a', 'leaflet-draw-edit-remove', controlDiv);
controlUI.title = 'Centra la mappa';
controlUI.href = '#';
controlUI.innerHTML = `
<span class="icon is-medium">
<i>
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="currentColor" class="pt-2" viewBox="0 0 16 16">
<path fill-rule="evenodd" d="M8 3a5 5 0 1 1-4.546 2.914.5.5 0 0 0-.908-.417A6 6 0 1 0 8 2z"/>
<path d="M8 4.466V.534a.25.25 0 0 0-.41-.192L5.23 2.308a.25.25 0 0 0 0 .384l2.36 1.966A.25.25 0 0 0 8 4.466"/>
</svg>
</i>
</span>
`;
return controlDiv;
}
});
let centerCtr = new L.Control.CenterControl();
map.addControl(centerCtr);
}
/**
* Toggle burger menu for small screens
* @param {string} burgerClass The CSS class of the burger element
*/
UI.toggleBurger = function(burgerClass) {
const burger = document.querySelector(`.${burgerClass}`);
burger.addEventListener('click', () => {
burger.classList.toggle('is-active');
const menuId = burger.getAttribute('data-target');
document.querySelector(`#${menuId}`).classList.toggle('is-active');
});
}
/**
* Toggle side menu
* @param {string} triggerId The ID of the trigger element
* @param {?string} listId The ID of the menu list to open (if any)
*/
UI.toggleMenu = function (triggerId, listId = null) {
const trigger = document.querySelector(`#${triggerId}`);
const menu = document.querySelector('#menu');
trigger.addEventListener('click', () => {
menu.classList.remove('is-hidden');
//menu.classList.add('is-3');
const lists = menu.querySelectorAll('ul');
if (listId !== null) {
const list = document.querySelector(`#${listId}`);
list.classList.remove('is-hidden');
for (let ul of lists) {
if (ul.id !== listId && !ul.id.includes('sub')) {
ul.classList.add('is-hidden');
}
}
}
});
}
/**
* Open a modal with DB site data
* @param {object} data The data retrieved from the DB to display as modal content
* @param {string} selector The modal selector
*/
UI.openSiteModal = async function (data, selector) {
const modal = document.querySelector(selector);
let dataTabs = modal.querySelectorAll('.data-tabs');
// Reset data tabs content
for (let tab of dataTabs) {
tab.innerHTML = '';
}
let siteSheet = new SiteSheet();
siteSheet.siteData = data;
window.Biblio = siteSheet;
modal.querySelector('#short-sheet').innerHTML = siteSheet.renderShort();
if (data.description) {
modal.querySelector('#site-sheet').innerHTML = siteSheet.render();
}
let images = modal.querySelector('#photos');
let docs = modal.querySelector('#documents');
if (data.documents?.length) {
let siteDocs = new SiteDocuments;
siteDocs.siteData = data;
docs.innerHTML = siteDocs.render();
} else {
docs.innerHTML = '<p class="has-text-centered">Nessun documento disponibile</p>'
}
let surveys = data.images.filter(i => i.type === 'Survey');
let photos = data.images.filter(i => i.type === 'Photo');
let videos = data.images.filter(i => i.type === 'Video');
if (surveys.length === 0 && photos.length === 0 && videos.length === 0) {
images.innerHTML = '<p class="has-text-centered">Nessuna risorsa visuale disponibile</p>';
}
if (images.innerHTML.length === 0) {
let siteSurveys = new SiteSurveys;
siteSurveys.siteData = surveys[0] ?? undefined;
images.innerHTML += surveys[0] ? siteSurveys.render() : '';
let siteMedia = new SiteMedia;
siteMedia.siteData = photos[0] ?? undefined;
images.innerHTML += photos[0] ? siteMedia.renderPhotos() : '';
siteMedia.siteData = videos[0] ?? undefined;
images.innerHTML += videos[0] ? siteMedia.renderVideos() : '';
}
modal.classList.add('is-active');
this.imageGallery('gallery-1', surveys);
this.imageGallery('gallery-2', photos);
this.imageGallery('gallery-video', videos, true);
}
/**
* @param {object} data The data retrieved from the DB to display as modal content
* @param {string} selector The modal selector
*/
UI.openNotConserModal = async function (data, selector) {
const modal = document.querySelector(selector);
let sheet = new NotConservedSheet();
sheet.siteData = data;
// For Stimulus biblio_controller
window.Biblio = sheet;
modal.querySelector('#not-conser-sheet').innerHTML = await sheet.render();
modal.classList.add('is-active');
}
/**
* @param {object} data The data retrieved from the DB to display as modal content
* @param {string} selector The modal selector
*/
UI.openFindingModal = async function (data, selector) {
const modal = document.querySelector(selector);
let dataTabs = modal.querySelectorAll('.data-tabs');
// Reset data tabs content
for (let tab of dataTabs) {
tab.innerHTML = '';
}
let finding = new Finding();
finding.data = data;
// For Stimulus biblio_controller
window.Biblio = finding;
finding.setImages();
modal.querySelector('#finding-sheet').innerHTML = await finding.render();
if (finding.images) {
modal.querySelector('#photos').innerHTML = finding.renderImages();
this.imageGallery('finding-gallery', finding.images);
}
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
* @param {string} galleryId The id of the trigger element
* @param {Array<Object>} images Array of image objects from DB
* @param {boolean} video Is this a video gallery?
*/
UI.imageGallery = function (galleryId, images, video = false) {
const element = document.querySelector(`#${galleryId}`);
if (element) {
let gallery = [];
for (let img of images) {
let mediaObj = {
description: `${img.caption} (${img.author})`
};
if (video) {
mediaObj.media = 'video';
mediaObj["src-mp4"] = `video/${img.filename}`;
mediaObj.poster = `video/${img.filename.replace('mp4', 'png')}`;
} else {
mediaObj.src = `img/${img.filename}`;
}
gallery.push(mediaObj);
}
document.querySelector(`#${galleryId}`).addEventListener('click', () => {
Spotlight.show(gallery);
});
}
}
export default UI;