Compare commits

..

28 Commits

Author SHA1 Message Date
1a3c95487f Temp search form 2025-11-21 17:54:50 +01:00
b0915d0973 Simplify marker regex + link CSS 2025-11-12 17:16:53 +01:00
ebea10059e Prevent null in captions... 2025-11-10 10:15:11 +01:00
249a31d11a More marker changes... 2025-11-07 11:41:35 +01:00
4d95aa7fce More markers in site sheet... 2025-11-03 10:11:09 +01:00
e7f1ed7a98 Markers in localization 2025-10-30 15:27:25 +01:00
5cf42ff4be Update marker parsing regex 2025-10-30 09:36:53 +01:00
0f16af95e7 Update for internal links 2025-10-30 08:52:16 +01:00
13550078cb Open modal for internal links (WIP) 2025-10-29 18:23:41 +01:00
262540e735 Bloody whitespace... 2025-10-24 15:31:47 +02:00
c8de489ead Parse markers for other record types 2025-10-24 15:24:39 +02:00
952dc3f841 Parse marker shortcodes (WIP) 2025-10-24 10:27:28 +02:00
00cedfeb85 Fix undefined bug... 2025-09-03 15:54:34 +02:00
53c3f6c6b2 More refactoring components (minus Site) 2025-09-02 09:59:02 +02:00
77d42a2c27 Refactor components (WIP) 2025-09-01 17:20:47 +02:00
40cc2ef88b Update main menu 2025-08-25 11:15:22 +02:00
e6578225ec Populate biblio state for reuse data 2025-08-08 16:28:22 +02:00
986c4b0a75 Images for Reuse 2025-08-08 14:17:01 +02:00
f849f885f9 Add Reuse asset type 2025-08-08 12:06:38 +02:00
9196653c0d Another feature popup fix... 2025-07-15 16:11:44 +02:00
e3a3b30ade Merge branch 'master' of https://git.electricmandarine.cloud/nicolo/caprigis 2025-07-15 16:08:38 +02:00
065e49ccb2 Update GeoJSON layer and feature popup 2025-07-15 16:07:27 +02:00
106c8f60bc Update GeoJSON layers 2025-07-14 10:17:13 +02:00
e3d98c2e5d Move boundaries to base map control 2025-07-08 14:44:01 +02:00
377447f63a Fix stupid bug... 2025-07-08 12:21:10 +02:00
cfcd1e8e80 Render 3D reconstructions for sites 2025-07-08 12:07:08 +02:00
378e14d56a Add Villa Bismarck geojson; refactor layer options 2025-07-07 13:19:06 +02:00
f68216c84c WMS in layers control 2025-06-30 11:18:13 +02:00
19 changed files with 951 additions and 399 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

View File

@@ -26,7 +26,7 @@
<script src="js/index.js" type="module"></script>
<title>WebGIS Isola di Capri</title>
</head>
<body data-controller="menu"
<body data-controller="menu modal"
data-action="menu-ready@document->menu#buildMenu menu-ready@document->menu#buildCartographyMenu">
<nav class="navbar mb-0" role="navigation">
<div class="navbar-brand">
@@ -61,11 +61,18 @@
<span class="icon mr-2">
<i class="fa fa-map"></i>
</span>
Cartografia
Catasto storico
</button>
<button class="button is-outlined is-rounded is-link mr-4 mt-1" id="howto" title="Istruzioni">
<span class="icon is-large has-text-link">
<i class="fas fa-question fa-lg"></i>
<button class="button is-white mr-2 mt-1" title="Cerca"
data-id="search"
data-action="modal#open">
<span class="icon">
<i class="fa fa-search"></i>
</span>
</button>
<button class="button is-outlined is-rounded mr-4 mt-1" id="howto" title="Istruzioni">
<span class="icon has-text-black">
<i class="fas fa-question"></i>
</span>
</button>
</div>
@@ -192,6 +199,30 @@
</span>
</li>
</ul>
<p class="menu-label is-size-5 is-clickable" data-id="reuse">
<span class="icon pl-1 mr-2 is-small" data-layer-target="reuse" data-action="click->layer#toggle">
<i class="fa fa-xs fa-eye-slash" data-layer-target="icon"></i>
</span>
<span class="icon pr-1">
<img class="image" src="img/icons/reimpiego_menu.png"/>
</span>
<span role="button" data-action="click->menu#toggle" data-id="reuse">
Reimpiego
<span class="icon pl-2">
<i class="fa fa-chevron-right" data-menu-target="icon" data-id="reuse"></i>
</span>
</span>
</p>
<ul class="menu-list is-hidden" id="reuse-list" data-menu-target="list" data-controller="marker">
<li data-list-id="reuse-capri-sub">
<span role="button" class="is-clickable" data-action="click->menu#openSubList" data-list-id="reuse-capri-sub">
Capri
<span class="icon ml-2">
<i class="fa fa-chevron-right" data-menu-target="icon"></i>
</span>
</span>
</li>
</ul>
<p class="menu-label is-size-5 is-clickable" data-id="prehistoric">
<span class="icon pl-1 mr-2 is-small" title="Nascondi" data-layer-target="prehistoric" data-action="click->layer#toggle">
<i class="fa fa-xs fa-eye-slash" data-layer-target="icon"></i>
@@ -284,22 +315,86 @@
</template>
<aside class="menu ml-4 mt-3" data-id="cartography-aside">
<button title="Chiudi menu" class="delete is-pulled-right" data-action="menu#closeCartography"></button>
<ul class="menu-list">
<li>
<input type="checkbox" data-controller="layer" data-action="layer#toggleCadastral" />
Catasto Agenzia delle Entrate (particelle e fabbricati)
</li>
</ul>
<p class="menu-label is-size-5 mt-4 is-clickable" data-id="historic">
<span role="button" data-action="click->menu#toggle" data-id="historic">
Catasto storico
<span class="icon pl-2">
<i class="fa fa-chevron-right" data-menu-target="icon" data-id="historic"></i>
</span>
</span>
</p>
</aside>
</div>
<!-- Search modal -->
<div class="modal" id="search" data-modal-target="modal">
<div class="modal-background" data-action="click->modal#close click->tabs#reset"></div>
<div class="modal-content has-background-white pt-4 mr-4 ml-4 pl-4 pr-4" style="min-height: 400px;">
<h1 class="is-size-4 has-text-centered">Ricerca</h1>
<div class="field">
<label class="label">Testo libero</label>
<div class="control is-full-width">
<input class="input" type="text" placeholder="Inserire parole chiave">
</div>
</div>
<div class="columns mt-5 pt-3">
<div class="field column">
<label class="label">Categoria sito</label>
<div class="control">
<div class="select">
<select>
<option default>-- Scegliere la categoria del sito --</option>
<option>Sito conservato</option>
<option>Sito non conservato</option>
</select>
</div>
</div>
</div>
<div class="field column">
<label class="label">Categoria reperto</label>
<div class="control">
<div class="select">
<select>
<option default>-- Scegliere la categoria del reperto --</option>
<option>Scultura</option>
<option>Epigrafe</option>
<option>Elemento architettonico</option>
<option>Decorazione parietale</option>
<option>Pavimentazione</option>
<option>Arredo</option>
<option>Abbigliamento e ornamenti personali</option>
</select>
</div>
</div>
</div>
<div class="field column">
<label class="label">Tecnica muraria</label>
<div class="control">
<div class="select">
<select>
<option default>-- Scegliere tecnica --</option>
<option>Opera poligonale</option>
<option>Opera incerta</option>
<option>Opera reticolata</option>
<option>Opera laterizia</option>
<option>Opera mista</option>
<option>Opera cementizia</option>
</select>
</div>
</div>
</div>
</div>
<div class="field is-grouped mt-5 has-text-right">
<div class="control">
<button class="button is-link">
<span>Cerca</span>
<span class="icon is-small">
<i class="fa fa-search"></i>
</span>
</button>
</div>
<div class="control">
<button class="button is-link is-light">
<span>Cancella filtri</span>
<span class="icon is-small">
<i class="fa fa-times"></i>
</span>
</button>
</div>
</div>
</div>
</div>
</div>
<!-- Bibliography citations template -->
<template id="biblio-item-template">
@@ -452,12 +547,63 @@
<button class="modal-close is-large" aria-label="close" data-action="modal#close tabs#reset"></button>
</div>
<!-- Underwater modal -->
<div class="modal" id="underwater-data" data-controller="modal biblio marker" data-modal-target="modal">
<div class="modal-background" data-action="click->modal#close"></div>
<div class="modal" id="underwater-data" data-controller="modal tabs marker" data-modal-target="modal">
<div class="modal-background" data-action="click->modal#close click->tabs#reset"></div>
<div class="modal-content has-background-white">
<div id="underwater-sheet"></div>
<div class="tabs is-centered">
<ul>
<li class="is-active" id="for-underwater-sheet" data-tabs-target="tab active" data-action="click->tabs#activate">
<a>
<span class="icon is-small"><i class="fas fa-info-circle" aria-hidden="true"></i></span>
<span>Scheda</span>
</a>
</li>
<li id="for-photos" data-tabs-target="tab" data-action="click->tabs#activate">
<a>
<span class="icon is-small"><i class="fas fa-image" aria-hidden="true"></i></span>
<span>Immagini</span>
</a>
</li>
<li id="for-documents" data-tabs-target="tab" data-action="click->tabs#activate">
<a>
<span class="icon is-small"><i class="fas fa-book" aria-hidden="true"></i></span>
<span>Documenti</span>
</a>
</li>
</ul>
</div>
<button class="modal-close is-large" aria-label="close" data-action="modal#close"></button>
<div class="data-tabs" id="underwater-sheet" data-tabs-target="content"></div>
<div class="data-tabs is-hidden" id="photos" data-tabs-target="content"></div>
<div class="data-tabs is-hidden" id="documents" data-tabs-target="content"></div>
</div>
<button class="modal-close is-large" aria-label="close" data-action="modal#close tabs#reset"></button>
</div>
<!-- Reuse modal -->
<div class="modal" id="reuse-data" data-controller="modal biblio tabs marker" data-modal-target="modal">
<div class="modal-background" data-action="click->modal#close click->tabs#reset"></div>
<div class="modal-content has-background-white">
<div class="tabs is-centered">
<ul>
<li class="is-active" id="for-reuse-sheet" data-tabs-target="tab active" data-action="click->tabs#activate">
<a>
<span class="icon is-small"><i class="fas fa-info-circle" aria-hidden="true"></i></span>
<span>Scheda</span>
</a>
</li>
<li id="for-photos" data-tabs-target="tab" data-action="click->tabs#activate">
<a>
<span class="icon is-small"
><i class="fas fa-image" aria-hidden="true"></i
></span>
<span>Immagini</span>
</a>
</li>
</ul>
</div>
<div class="data-tabs" id="reuse-sheet" data-tabs-target="content"></div>
<div class="data-tabs is-hidden" id="photos" data-tabs-target="content"></div>
</div>
<button class="modal-close is-large" aria-label="close" data-action="modal#close tabs#reset"></button>
</div>
<!-- Spherical photo modal -->
<div class="modal" id="spherical-modal">

View File

@@ -1,4 +1,4 @@
import { GisState } from "../state.js";
import Utils from "./utils.js";
/**
* @class Finding
*/
@@ -23,7 +23,7 @@ export class Finding {
<strong>Misure:</strong> ${this._data.measurements}
</p>
<p class="p-2">
<strong>Luogo e anno rinvenimento:</strong> ${this._data.place}. ${this._data.year}
<strong>Luogo e anno rinvenimento:</strong> ${Utils.parseMarkers(this._data.place)}. ${this._data.year}
</p>
<p class="p-2">
<strong>Datazione:</strong> ${this._data.dating}
@@ -36,7 +36,7 @@ export class Finding {
</p>
<p class="mt-4 pl-2 pr-5">
<strong class="pb-3">Descrizione</strong></br>
${this._data.description}
${Utils.parseMarkers(this._data.description)}
</p>
<p class="mt-4 pl-2 pr-5">
<span class="icon has-text-link">
@@ -50,64 +50,25 @@ export class Finding {
</p>
</div>`;
}
renderImages() {
let content = `<div class="content has-text-centered">
<p class="is-size-5 mt-3">Immagini</p>`;
content += `
<div style="max-width: 70%; margin: 0 auto">
<p class="is-size-6 has-text-centered">Cliccare sull'immagine per aprire la gallery</p>
<figure class="is-relative is-clickable has-text-centered" id="finding-gallery">
<img src="img/${this.images[0].filename}" width="300"/>
<div class="icon overlay is-flex is-justify-content-center is-align-items-center">
<i class="is-flex fa fa-2x fa-play-circle"></i>
</div>
</figure>
</div>
</div>`;
return content;
}
/**
* @param {HTMLElement} imageContainer
* @param {Function} gallery
*/
async setImages(imageContainer, gallery) {
let record = await this.fetchData(`${GisState.apiUrl}/finding/${this._data.id}`)
if (record.images.length) {
this.images = record.images;
imageContainer.innerHTML = this.renderImages();
gallery('finding-gallery', this.images);
}
if (this._data.images?.length) {
imageContainer.innerHTML = Utils.renderImages('finding-gallery', this._data.images);
gallery('finding-gallery', this._data.images);
} else
imageContainer.innerHTML = '<p class="has-text-centered">Nessuna risorsa visuale disponibile</p>';
}
/**
* @param {number} recordId
*/
async biblio(recordId) {
let finding = await this.fetchData(`${GisState.apiUrl}/finding/${recordId}`);
let {citations, biblioElements} = await Utils.buildBibliography('finding', recordId);
this.biblioElements = biblioElements;
let citations = '';
if (finding.bibliography.length) {
finding.bibliography.forEach(record => {
citations += `
<span class="is-clickable has-text-link"
data-action="click->biblio#open"
id="cit-${record.id}">
${record.citation}</span>`;
citations += record.pages?.length ? `, ${record.pages};` : ';';
this.biblioElements.push(`
<div class="p-2 mt-2" id="ref-${record.id}">
<p class="p-3">${record.reference}</p>
</div>
`);
});
}
return citations.trim().slice(0, -1);
return citations;
}
getReference(id) {
@@ -116,8 +77,4 @@ export class Finding {
return ref.match(regex);
});
}
async fetchData(url) {
return await fetch(url).then(res => res.json());
}
}

View File

@@ -1,4 +1,4 @@
import { GisState } from "../state.js";
import Utils from "./utils.js";
/**
* Component to render data for not conserved assets
@@ -32,11 +32,11 @@ export class NotConserved {
<span class="icon has-text-link">
<i class="fa fa-map"></i>
</span>
<strong>Località generica:</strong> ${this._data.genericLocation}
<strong>Località generica:</strong> ${Utils.parseMarkers(this._data.genericLocation)}
</p>
<p class="mt-4 pl-2 pr-5">
<strong class="pb-3">Descrizione</strong></br>
${this._data.shortDescription}
${Utils.parseMarkers(this._data.shortDescription)}
</p>
<p class="mt-4 pl-2 pr-5">
<span class="icon has-text-link">
@@ -51,116 +51,27 @@ export class NotConserved {
</div>`;
}
renderImages() {
let content = `<div class="content has-text-centered">
<p class="is-size-5 mt-3">Immagini</p>`;
content += `
<div style="max-width: 70%; margin: 0 auto">
<p class="is-size-6 has-text-centered">Cliccare sull'immagine per aprire la gallery</p>
<figure class="is-relative is-clickable has-text-centered" id="not-conserved-gallery">
<img src="img/${this.images[0].filename}" width="300"/>
<div class="icon overlay is-flex is-justify-content-center is-align-items-center">
<i class="is-flex fa fa-2x fa-play-circle"></i>
</div>
</figure>
</div>
</div>`;
return content;
}
/**
* @param {HTMLElement} imageContainer
* @param {Function} gallery
*/
async setImages(imageContainer, gallery) {
if (this._data.images.length) {
this.images = this._data.images;
imageContainer.innerHTML = this.renderImages();
gallery('not-conserved-gallery', this.images);
setImages(imageContainer, gallery) {
if (this._data.images?.length) {
imageContainer.innerHTML = Utils.renderImages('not-conserved-gallery', this._data.images);
gallery('not-conserved-gallery', this._data.images);
} else
imageContainer.innerHTML = '<p class="has-text-centered">Nessuna risorsa visuale disponibile</p>';
}
async renderDocs() {
let record = await this.fetchData(`${GisState.apiUrl}/not_conserved/${this._data.id}`);
this.documentation = record.documents.filter(d => d.type === 'documentazione')
this.publications = record.documents.filter(d => d.type === 'pubblicazione');
let content = `
<div class="has-bottom-border">
<div class="p-2">
<table class="p-4 table is-fullwidth is-striped">
<thead>
<tr><th colspan=3 class="p-2 has-text-centered is-size-5">Documentazione di archivio</th>
<tr><th>Titolo</th><th>Luogo di conservazione</th><th>Download</th></tr>
</thead>
<tbody>
`;
for (const doc of this.documentation) {
content += `
<tr><td>${doc.title}</td><td>${doc.conservationPlace}</td><td><a class="button is-link has-text-white" href="docs/${doc.filename}">
<i class="fa fa-download mr-2"></i> PDF
</a></td></tr>
`;
}
if (this.publications.length) {
content += `
</tbody>
<thead>
<tr><th colspan=3 class="p-2 has-text-centered is-size-5">Pubblicazioni del progetto Carta Archeologica</th>
<tr><th>Titolo</th><th>Autori</th><th>Download</th></tr>
</thead>
<tbody>
`;
for (const doc of this.publications) {
content += `
<tr><td>${doc.title}</td><td>${doc.authors}</td><td><a class="button is-link has-text-white" href="docs/${doc.filename}">
<i class="fa fa-download mr-2"></i> PDF
</a></td></tr>
`;
}
}
content += `
</tbody>
</table>
</div>
</div>
`;
if (!this.publications.length && !this.documentation.length) {
content = '<p class="has-text-centered">Nessun documento disponibile.</p>';
}
return content;
return await Utils.generateDocsTable(this._data, 'not_conserved');
}
async biblio(recordId) {
let record = await this.fetchData(`${GisState.apiUrl}/not_conserved/${recordId}`);
let {citations, biblioElements} = await Utils.buildBibliography('not_conserved', recordId);
this.biblioElements = biblioElements;
let citations = '';
if (record.bibliography.length) {
record.bibliography.forEach(record => {
citations += `
<span class="is-clickable has-text-link"
data-action="click->biblio#open"
id="cit-${record.id}">
${record.citation.trim()}</span>`;
citations += record.pages?.length ? `, ${record.pages};` : ';';
this.biblioElements.push(`
<div class="p-2 mt-2" id="ref-${record.id}">
<p class="p-3">${record.reference}</p>
</div>
`
);
});
}
return citations.trim().slice(0, -1);
return citations;
}
getReference(id) {
@@ -169,8 +80,4 @@ export class NotConserved {
return ref.match(regex);
});
}
async fetchData(url) {
return await fetch(url).then(res => res.json());
}
}

View File

@@ -1,4 +1,4 @@
import { GisState } from "../state.js";
import Utils from "./utils.js";
/**
* @class Prehistoric
*/
@@ -32,11 +32,11 @@ export class Prehistoric {
<span class="icon has-text-link">
<i class="fa fa-map"></i>
</span>
<strong>Località generica:</strong> ${this._data.genericPlace}
<strong>Località generica:</strong> ${Utils.parseMarkers(this._data.genericPlace)}
</p>
<p class="mt-4 pl-2 pr-5">
<strong class="pb-3">Descrizione breve</strong></br>
${this._data.description}
${Utils.parseMarkers(this._data.description)}
</p>
<p class="p-2">
<strong>Conservazione:</strong> ${this._data.conservation}
@@ -47,7 +47,6 @@ export class Prehistoric {
</div>`;
/*
<p class="mt-4 pl-2 pr-5">
<span class="icon has-text-link">
<i class="fa fa-book"></i>
@@ -58,32 +57,14 @@ export class Prehistoric {
*/
}
renderImages() {
let content = `<div class="content has-text-centered">
<p class="is-size-5 mt-3">Immagini</p>`;
content += `
<div style="max-width: 70%; margin: 0 auto">
<p class="is-size-6 has-text-centered">Cliccare sull'immagine per aprire la gallery</p>
<figure class="is-relative is-clickable has-text-centered" id="prehist-gallery">
<img src="img/${this.images[0].filename}" width="300"/>
<div class="icon overlay is-flex is-justify-content-center is-align-items-center">
<i class="is-flex fa fa-2x fa-play-circle"></i>
</div>
</figure>
</div>
</div>`;
return content;
}
/**
* @param {HTMLElement} imageContainer
* @param {Function} gallery
*/
async setImages(imageContainer, gallery) {
if (this._data.images.length) {
this.images = this._data.images;
imageContainer.innerHTML = this.renderImages();
gallery('prehist-gallery', this.images);
if (this._data.images?.length) {
imageContainer.innerHTML = Utils.renderImages('prehist-gallery', this._data.images);
gallery('prehist-gallery', this._data.images);
} else
imageContainer.innerHTML = '<p class="has-text-centered">Nessuna risorsa visuale disponibile</p>';
}
@@ -91,29 +72,10 @@ export class Prehistoric {
* @param {number} recordId
*/
async biblio(recordId) {
let finding = await this.fetchData(`${GisState.apiUrl}/prehistoric/${recordId}`);
let {citations, biblioElements} = await Utils.buildBibliography('prehistoric', recordId);
this.biblioElements = biblioElements;
let citations = '';
if (finding.bibliography.length) {
finding.bibliography.forEach(record => {
citations += `
<span class="is-clickable has-text-link"
data-action="click->biblio#open"
id="cit-${record.id}">
${record.citation}</span>`;
citations += record.pages?.length ? `, ${record.pages};` : ';';
this.biblioElements.push(`
<div class="p-2 mt-2" id="ref-${record.id}">
<p class="p-3">${record.reference}</p>
</div>
`);
});
}
return citations.trim().slice(0, -1);
return citations;
}
getReference(id) {
@@ -122,8 +84,4 @@ export class Prehistoric {
return ref.match(regex);
});
}
async fetchData(url) {
return await fetch(url).then(res => res.json());
}
}

View File

@@ -0,0 +1,81 @@
import Utils from "./utils.js";
/**
* @class Reuse
*/
export class Reuse {
biblioElements = [];
images = null;
set data(data) {
this._data = data;
}
async render() {
return `
<div class="container px-4 pt-4">
<p class="p-2">
<strong>Denominazione:</strong> ${this._data.denomination}
</p>
<p class="p-2">
<strong>Materia:</strong> ${this._data.material}
</p>
<p class="p-2">
<strong>Misure:</strong> ${this._data.measurements}
</p>
<p class="p-2">
<strong>Luogo di conservazione:</strong> ${this._data.conservationPlace}
</p>
<p class="p-2">
<strong>Stato di conservazione:</strong> ${this._data.conservationState}
</p>
<p class="p-2">
<strong>Luogo e anno rinvenimento:</strong> ${Utils.parseMarkers(this._data.finding)}
</p>
<p class="p-2">
<strong>Datazione:</strong> ${this._data.dating}
</p>
<p class="mt-4 pl-2 pr-5">
<strong class="pb-3">Descrizione</strong></br>
${Utils.parseMarkers(this._data.description)}
</p>
<p class="mt-4 pl-2 pr-5">
<span class="icon has-text-link">
<i class="fa fa-book"></i>
</span>
<strong>Bibliografia:</strong> ${await this.biblio(this._data.id)}
</p>
<div class="notification is-light mx-3 mt-4 mb-0 p-2 is-hidden" data-biblio-target="biblio"></div>
<p class="p-2 mb-4">
<strong>Autore scheda:</strong> ${this._data.author}
</p>
</div>`;
}
/**
* @param {HTMLElement} imageContainer
* @param {Function} gallery
*/
async setImages(imageContainer, gallery) {
if (this._data.images?.length) {
imageContainer.innerHTML = Utils.renderImages('reuse-gallery', this._data.images);
gallery('reuse-gallery', this._data.images);
} else
imageContainer.innerHTML = '<p class="has-text-centered">Nessuna risorsa visuale disponibile</p>';
}
/**
* @param {Number} recordId
*/
async biblio(recordId) {
let {citations, biblioElements} = await Utils.buildBibliography('reuse', recordId);
this.biblioElements = biblioElements;
return citations;
}
getReference(id) {
return this.biblioElements.find(ref => {
let regex = new RegExp('ref-'+id+'"');
return ref.match(regex);
});
}
}

View File

@@ -43,4 +43,21 @@ export class SiteMedia {
</div>
`;
}
renderReconstructions() {
return `
<div class="content has-text-centered mb-5 pb-5">
<p class="is-size-5 mt-3">Ricostruzioni 3D</p>
<div style="max-width: 70%; margin: 0 auto">
<p class="is-size-6 has-text-centered">Gallery ricostruzioni 3D</p>
<figure class="is-relative is-clickable has-text-centered" id="gallery-3d">
<img src="img/${this._siteData.filename}" width="300"/>
<div class="icon overlay is-flex is-justify-content-center is-align-items-center">
<i class="is-flex fa fa-2x fa-play-circle"></i>
</div>
</figure>
</div>
</div>
`;
}
}

View File

@@ -1,14 +1,10 @@
import Utils from "./utils.js";
/**
* Component to render data for site sheet
* @class SiteSheet
*/
export class SiteSheet {
biblioElements = [];
/*
constructor(data) {
this._siteData = data;
}
*/
/**
* @param {object} data
*/
@@ -16,9 +12,13 @@ export class SiteSheet {
this._siteData = data;
}
/**
* @todo Refactor!
* @returns {string} HTML
*/
render() {
const description = Utils.parseMarkers(this._siteData.description);
const localization = Utils.parseMarkers(this._siteData.localization);
return `<div class="container has-bottom-border">
<table class="table is-fullwidth is-striped">
<tr class="is-link"><th class="is-size-5 has-text-centered" colspan=2>Identificazione</th></tr>
@@ -28,7 +28,7 @@ export class SiteSheet {
<tr><th>Comune</th><td>${this._siteData.municipality}</td></tr>
<tr><th>Indirizzo</th><td>${this._siteData.address}</td></tr>
<tr><th>Località</th><td>${this._siteData.place}</td></tr>
<tr><th>Localizzazione</th><td>${this._siteData.localization}</td></tr>
<tr><th>Localizzazione</th><td>${localization}</td></tr>
<tr class="is-link"><th class="is-size-5 has-text-centered" colspan=2>Cronologia</th></tr>
<tr><th>Periodo</th><td>${this._siteData.period}</td></tr>
<tr><th>Fase</th><td>${this._siteData.phase}</td></tr>
@@ -38,13 +38,13 @@ export class SiteSheet {
<tr><th>Stato di conservazione</th><td>${this._siteData.conservationState}</td></tr>
<tr><th>Tecniche edilizie impiegate:</th><td>${this._siteData.techniques}</td></tr>
<tr class="is-link"><th class="is-size-5 has-text-centered" colspan=2>Ritrovamento e materiali</th></tr>
<tr><th>Anno di ritrovamento</th><td>${this._siteData.finding}</td></tr>
<tr><th>Modalità e anno di ritrovamento</th><td>${Utils.parseMarkers(this._siteData.finding)}</td></tr>
<tr><th>Materiali rinvenuti</th><td>${this._siteData.materials}</td></tr>
<tr><th>Luogo custodia materiali</th><td>${this._siteData.conservationPlace}</td></tr>
<tr><th>Luogo custodia materiali</th><td>${Utils.parseMarkers(this._siteData.conservationPlace)}</td></tr>
<tr class="is-link"><th class="is-size-5 has-text-centered" colspan=2>Rilievi</th></tr>
<tr><td colspan=2>${this._siteData.surveys ?? 'Nessun rilievo'}</td></tr>
<tr class="is-link"><th class="is-size-5 has-text-centered" colspan=2>Descrizione</th></tr>
<tr><td class="pr-6 pl-6 pt-3" colspan="2">${this._siteData.description}</td></tr>
<tr><td class="pr-6 pl-6 pt-3" colspan="2">${description}</td></tr>
<tr class="is-link"><th class="is-size-5 has-text-centered" colspan=2>Bibliografia</th></tr>
<tr>
<td colspan=2>
@@ -60,6 +60,8 @@ export class SiteSheet {
}
renderShort() {
const shortDesc = Utils.parseMarkers(this._siteData.shortDescription);
return `
<div class="container p-3">
<p class="p-2">
@@ -81,7 +83,7 @@ export class SiteSheet {
<strong>Località generica:</strong> ${this._siteData.genericPlace}
</p>
<p class="mt-4 pl-2 pr-5">
${this._siteData.shortDescription}
${shortDesc}
</p>
<p class="mt-4 pl-2 pr-5">
<span class="icon has-text-link">

View File

@@ -1,3 +1,4 @@
import Utils from "./utils.js";
/**
* @class Underwater
*/
@@ -27,15 +28,26 @@ export class Underwater {
</p>
<p class="mt-4 pl-2 pr-5">
<strong class="pb-3">Descrizione breve</strong></br>
${this._data.shortDescription}
${Utils.parseMarkers(this._data.shortDescription)}
</p>
<p class="p-2 mb-4">
<strong>Autore scheda:</strong> ${this._data.author}
</p>
</div>`;
}
/**
* @param {HTMLElement} imageContainer
* @param {Function} gallery
*/
setImages(imageContainer, gallery) {
if (this._data.images?.length) {
imageContainer.innerHTML = Utils.renderImages('underwater-gallery', this._data.images);
gallery('underwater-gallery', this._data.images);
} else
imageContainer.innerHTML = '<p class="has-text-centered">Nessuna risorsa visuale disponibile</p>';
}
async fetchData(url) {
return await fetch(url).then(res => res.json());
async renderDocs() {
return await Utils.generateDocsTable(this._data, 'underwater');
}
}

View File

@@ -0,0 +1,175 @@
import { GisState } from "../state.js";
/**
* @namespace Utils
*/
const Utils = {};
/**
*
* @param {string} galleryId The image gallery's id
* @param {Object} imagesData
* @returns {string}
*/
Utils.renderImages = function (galleryId, imagesData) {
let content = `<div class="content has-text-centered">
<p class="is-size-5 mt-3">Immagini</p>`;
content += `
<div style="max-width: 70%; margin: 0 auto">
<p class="is-size-6 has-text-centered">Cliccare sull'immagine per aprire la gallery</p>
<figure class="is-relative is-clickable has-text-centered" id="${galleryId}">
<img src="img/${imagesData[0].filename}" width="300"/>
<div class="icon overlay is-flex is-justify-content-center is-align-items-center">
<i class="is-flex fa fa-2x fa-play-circle"></i>
</div>
</figure>
</div>
</div>`;
return content;
}
/**
* @param {Object} imagesData
* @param {HTMLElement} imageContainer
* @param {Function} galleryGenerator The function that creates the image gallery
* @param {string} galleryId The image gallery's id
*/
Utils.setImages = function(imagesData, imageContainer, galleryGenerator, galleryId) {
imageContainer.innerHTML = Utils.renderImages(galleryId);
galleryGenerator(galleryId, imagesData);
}
/**
*
* @param {Object} data The component's data
* @param {String} resourceUri The resource URI to be used for API calls
* @returns {String} The table HTML
*/
Utils.generateDocsTable = async function(data, resourceUri) {
let record = await Utils.fetchData(`${GisState.apiUrl}/${resourceUri}/${data.id}`);
// TODO Horrible??
if (record instanceof Error) return '<p class="has-text-centered">Nessun documento disponibile.</p>';
const documentation = record.documents.filter(d => d.type === 'documentazione')
const publications = record.documents.filter(d => d.type === 'pubblicazione');
let content = `
<div class="has-bottom-border">
<div class="p-2">
<table class="p-4 table is-fullwidth is-striped">
<thead>
<tr><th colspan=3 class="p-2 has-text-centered is-size-5">Documentazione di archivio</th>
<tr><th>Titolo</th><th>Luogo di conservazione</th><th>Download</th></tr>
</thead>
<tbody>
`;
for (const doc of documentation) {
content += `
<tr><td>${doc.title}</td><td>${doc.conservationPlace}</td><td><a class="button is-link has-text-white" href="docs/${doc.filename}">
<i class="fa fa-download mr-2"></i> PDF
</a></td></tr>
`;
}
if (publications.length) {
content += `
</tbody>
<thead>
<tr><th colspan=3 class="p-2 has-text-centered is-size-5">Pubblicazioni del progetto Carta Archeologica</th>
<tr><th>Titolo</th><th>Autori</th><th>Download</th></tr>
</thead>
<tbody>
`;
for (const doc of publications) {
content += `
<tr><td>${doc.title}</td><td>${doc.authors}</td><td><a class="button is-link has-text-white" href="docs/${doc.filename}">
<i class="fa fa-download mr-2"></i> PDF
</a></td></tr>
`;
}
}
content += `
</tbody>
</table>
</div>
</div>
`;
if (publications.length === 0 && documentation.length === 0) {
content = '<p class="has-text-centered">Nessun documento disponibile.</p>';
}
return content;
}
/**
*
* @param {String} recordUri The record URI used for API calls
* @param {Number} recordId This record's ID
* @returns {{citations:String,biblioElements:String[]}}
*/
Utils.buildBibliography = async function(recordUri, recordId) {
let record = await Utils.fetchData(`${GisState.apiUrl}/${recordUri}/${recordId}`);
let biblioElements = [];
let citations = '';
if (record.bibliography.length) {
record.bibliography.forEach(record => {
citations += `
<span class="is-clickable has-text-link"
data-action="click->biblio#open"
id="cit-${record.id}">
${record.citation.trim()}
</span>
`;
citations += record.pages?.length ? `, ${record.pages};` : ';';
biblioElements.push(`
<div class="p-2 mt-2" id="ref-${record.id}">
<p class="p-3">${record.reference}</p>
</div>
`
);
});
}
const bibliography = {
citations: citations.trim().slice(0, -1),
biblioElements
}
return bibliography;
}
/**
* Parse marker strings (pseudo-shortcodes) and convert them
* to Stimulus links
* @param {String} text - The content text from database
*/
Utils.parseMarkers = function(text) {
const regex = /(?<marker>\[marker coords=\"(?<coords>[\d\s\.]+)\"\ ?(group=\"(?<group>\w+)\")?](?<content>[\s\S]+?)\[\/marker\])/mig;
if (!text) return text;
let matches = [...text.matchAll(regex)];
if (matches.length) {
matches.forEach(match => {
const replacement = `<a class="has-text-link" data-action="marker#go modal#close tabs#reset marker#goAndOpen" data-controller="marker"
data-marker-coords-value="${match.groups.coords}"
data-marker-group-value="${match.groups.group}">${match.groups.content.trim()}</a>`;
text = text.replace(match.groups.marker, replacement.trim());
});
}
return text;
}
Utils.fetchData = async function(url) {
return await fetch(url).then(res => res.ok ? res.json() : new Error())
.catch(err => console.log(err));
}
export default Utils;

View File

@@ -1,5 +1,6 @@
import { Controller } from "@hotwired/stimulus";
import { GisState, getMarkerByCoords } from "../state.js";
import UI from "../ui.js";
export default class extends Controller {
static values = {
@@ -8,17 +9,16 @@ export default class extends Controller {
'id': String,
};
END_ZOOM = 19;
// Animation breaks automatic tooltip opening...
mapAnimate = {
animate: true,
duration: 1,
easeLinearity: 0.25
uiModals = {
sites: '#site-data',
notConserved: '#not-conser-data',
finding: '#finding-data',
prehist: '#prehist-data',
reuse: '#reuse-data',
};
/**
* @param {Event} event
*/
END_ZOOM = 19;
go() {
let map = GisState.map;
const coords = this.coordsValue.split(' ');
@@ -31,8 +31,40 @@ export default class extends Controller {
let marker = this.getMarker(map, coords);
// DEBUG for sites
if (this.groupValue) marker = getMarkerByCoords(coords, this.groupValue);
//if (this.groupValue) marker = getMarkerByCoords(coords, this.groupValue);
marker?.openTooltip();
return marker;
}
/**
* Go to a marker location on the map
* and open its modal
*/
goAndOpen() {
const marker = this.go();
const selector = this.uiModals[this.groupValue];
const data = marker.options.data;
switch(this.groupValue) {
case 'sites':
UI.openSiteModal(data, selector);
break;
case 'notConserved':
UI.openNotConserModal(data, selector);
break;
case 'finding':
UI.openFindingModal(data, selector);
break;
case 'prehist':
UI.openPrehistModal(data, selector);
break;
case 'reuse':
UI.openReuseModal(data, selector);
break;
default:
console.log('Cannot open modal...');
break;
}
}
/**
* @param {L.Map} map

View File

@@ -5,6 +5,7 @@ import API_CONFIG from "./config.js";
import Icons from "./icons.js";
import { SphericalPhoto } from "./components/SphericalPhoto.js";
import { GisState } from "./state.js";
import Options from "./layer_options.js";
const MAPBOX_TOKEN = 'pk.eyJ1Ijoibmljb3BhIiwiYSI6ImNseWNwZjJjbjFidzcya3BoYTU0bHg4NnkifQ.3036JnCXZTEMt6jVgMzVRw';
const BASE_URL = location.href;
@@ -28,47 +29,6 @@ GIS.INIT_ZOOM = 14;
GIS.MIN_ZOOM = 11;
GIS.MAX_ZOOM = 24;
const optionsVincoli = {
color: '#222',
opacity: 0.8,
weight: 1,
fillColor: '#fa7861',
fillOpacity: 0.8
};
const optionsSiti = {
color: '#800040',
opacity: 1,
weight: 1.5,
fillColor: '#800040',
fillOpacity: 0.8
};
const optionsGrotta = {
color: '#205dac',
opacity: 1,
weight: 1.5,
fillColor: '#205dac',
fillOpacity: 0.8
}
const optionsPaesistici = {
color: '#222',
opacity: 1,
weight: 1.5,
fillColor: '#88d28d',
fillOpacity: 0.8
};
const optionsFabbricati = {
color: '#222',
opacity: 1,
weight: 1.5,
fillColor: '#5b5d5f',
fillOpacity: 0.8
};
const clusterOptions = {
spiderfyOnMaxZoom: false,
showCoverageOnHover: false,
disableClusteringAtZoom: 19,
};
/**
* Capitalize a text string
* @todo Move to utils
@@ -108,37 +68,36 @@ GIS.initMap = async function (mapId, zoomLevel = this.INIT_ZOOM) {
L.control.scale({imperial: false}).addTo(map);
L.control.graphicScale({fill: 'hollow', position: 'bottomright'}).addTo(map);
let layerVincoli = await this.loadGeoJSON('vincoli.geojson', optionsVincoli);
let layerPaesistici = await this.loadGeoJSON('paesistici.geojson', optionsPaesistici);
let layerVincoli = await this.loadGeoJSON('vincoli.geojson', Options.constraintsArch);
let layerPaesistici = await this.loadGeoJSON('paesistici.geojson', Options.constraintsLand);
let buildings = await this.loadGeoJSON('fabbricati.geojson', Options.buildings, false);
await this.addLayerGroups(map);
await this.fetchCartographyLayers();
const archeo = {
'Vincoli archeologici' : layerVincoli,
'Vincoli paesistici' : layerPaesistici,
//'Catasto storico' : historicCadastre,
};
L.control.layers(baseMap, archeo).addTo(map);
GisState.map = map;
const reprojectedWMSLayer = GIS.reprojectWMS();
const wmsLayer = new reprojectedWMSLayer(
'https://wms.cartografia.agenziaentrate.gov.it/inspire/wms/ows01.php?',
{
layers: 'CP.CadastralParcel,fabbricati',
layers: 'CP.CadastralParcel,codice_plla,fabbricati',
transparent: true,
format: 'image/png',
version: '1.1.1',
minZoom: 15,
minZoom: this.INIT_ZOOM,
maxZoom: this.MAX_ZOOM,
tileSize: 1024,
opacity: 0.6,
}
);
const cartography = {
'Catasto Agenzia delle Entrate (zoom per visualizzare)' : wmsLayer,
'Fabbricati' : buildings,
'Vincoli archeologici' : layerVincoli,
'Vincoli archeologici indiretti' : layerPaesistici,
};
L.control.layers(baseMap, cartography).addTo(map);
GisState.cartography.cadastral = wmsLayer;
GisState.map = map;
return map;
}
@@ -199,6 +158,7 @@ GIS.addLayerGroups = async function (map) {
this.findings(),
this.prehistoric(),
this.underwater(),
this.reuse(),
]
);
groups.forEach(group => group.addTo(map));
@@ -211,15 +171,20 @@ GIS.sites = async function () {
let sitesData = await fetch(`${API_URL}/sites`)
.then(data => data.json());
let sites = L.markerClusterGroup(clusterOptions);
let sites = L.markerClusterGroup(Options.cluster);
let geom = [];
for (let record of sitesData) {
if (record.geojson) {
const options = record.gisId === 'grotta_azzurra' ?
optionsGrotta : optionsSiti;
Options.grotta : Options.site;
geom.push(await this.loadSiteLayer(record, options));
}
if (record.area) {
const options = record.gisId === 'villa_bismarck' ?
Options.bismarck : Options.site;
geom.push(await this.loadSiteLayer(record, options, false, true));
}
const marker = L.marker(
record.coordinates,
@@ -235,6 +200,7 @@ GIS.sites = async function () {
// Populate app state for reuse and avoid window.Sites etc.
// Municipality (Capri, Anacapri) added for reuse in dynamic menu
marker.options.municipality = record.municipality;
marker.options.data = record;
const markerIndex = `${record.coordinates[0]} ${record.coordinates[1]}`;
GisState.markers.sites[markerIndex] = marker;
}
@@ -251,7 +217,7 @@ GIS.notConserved = async function () {
let notConserData = await fetch(`${API_URL}/not_conserved`)
.then(data => data.json());
let notConserved = L.markerClusterGroup(clusterOptions);
let notConserved = L.markerClusterGroup(Options.cluster);
for (let record of notConserData.records) {
const marker = L.marker(
@@ -265,6 +231,7 @@ GIS.notConserved = async function () {
// Populate app state for reuse and avoid window.Sites etc.
const markerLabel = `${record.coordinates[0]} ${record.coordinates[1]}`;
marker.options.municipality = record.municipality;
marker.options.data = record;
GisState.markers.notConserved[markerLabel] = marker;
}
@@ -281,7 +248,7 @@ GIS.findings = async function () {
.then(data => data.json());
let findings = L.markerClusterGroup(
clusterOptions
Options.cluster
);
for (let record of findingsData) {
@@ -297,6 +264,7 @@ GIS.findings = async function () {
findings.addLayer(marker);
const markerLabel = `${record.coordinates[0]} ${record.coordinates[1]}`;
marker.options.municipality = record.municipality;
marker.options.data = record;
GisState.markers.findings[markerLabel] = marker;
}
@@ -313,7 +281,7 @@ GIS.prehistoric = async function () {
.then(data => data.json());
let prehistoric = L.markerClusterGroup(
clusterOptions
Options.cluster
);
for (let record of data.records) {
@@ -328,6 +296,7 @@ GIS.prehistoric = async function () {
const markerLabel = `${record.coordinates[0]} ${record.coordinates[1]}`;
marker.options.municipality = record.municipality;
marker.options.data = record;
GisState.markers.prehistoric[markerLabel] = marker;
prehistoric.addLayer(marker);
@@ -345,7 +314,7 @@ GIS.underwater = async function () {
let underwaterData = await fetch(`${API_URL}/underwater`)
.then(data => data.json());
let underwater = L.markerClusterGroup(clusterOptions);
let underwater = L.markerClusterGroup(Options.cluster);
for (let record of underwaterData.records) {
const marker = L.marker(
@@ -358,7 +327,8 @@ GIS.underwater = async function () {
);
const markerLabel = `${record.coordinates[0]} ${record.coordinates[1]}`;
GisState.markers.prehistoric[markerLabel] = marker;
marker.options.data = record;
GisState.markers.underwater[markerLabel] = marker;
underwater.addLayer(marker);
}
@@ -367,10 +337,42 @@ GIS.underwater = async function () {
return underwater;
}
/**
* Create reused sites group ('reimpiego')
* @returns {L.MarkerClusterGroup}
*/
GIS.reuse = async function () {
let reuseData = await fetch(`${API_URL}/reuse`)
.then(data => data.json());
let reuse = L.markerClusterGroup(Options.cluster);
for (let record of reuseData.records) {
const marker = L.marker(
record.coordinates,
{icon: Icons.reuse}
).bindTooltip(record.label)
.on(
'click',
() => UI.openReuseModal(record, '#reuse-data')
);
const markerLabel = `${record.coordinates[0]} ${record.coordinates[1]}`;
marker.options.municipality = record.municipality;
marker.options.label = record.label;
marker.options.data = record;
GisState.markers.reuse[markerLabel] = marker;
reuse.addLayer(marker);
}
GisState.layers.reuse = reuse;
return reuse;
}
/**
* Adds layers to map and returns an object
* with {baseMap, archeoLayers, sitesLayerGroup}
* @todo Load areas for sites that have them!!
* @param {L.Map} map
* @returns {{baseMap: {"OpenStreetMap": L.TileLayer}}}
*/
@@ -389,16 +391,15 @@ GIS.initLayers = async function(map) {
maxZoom: GIS.MAX_ZOOM,
attribution: '&copy; Mapbox'
});
let boundaries = await this.loadGeoJSON('confini.geojson', {}, false);
let buildings = await this.loadGeoJSON('fabbricati.geojson', optionsFabbricati, false);
let baseCatasto = new L.LayerGroup([buildings, boundaries]);
const baseGroup = new L.LayerGroup([osmap]);
baseGroup.addTo(map);
const baseMap = {
"OpenStreetMap" : osmap,
"Satellite" : mapbox,
"Cartografia catastale" : baseCatasto,
'Limiti amministrativi' : boundaries,
};
return baseMap;
@@ -479,9 +480,10 @@ GIS.loadGeoJSON = async function (geoJSON, options, popup = true) {
* @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}`)
GIS.loadSiteLayer = async function (site, options, popup = true, area = false) {
let geoJSON = site.gisId;
geoJSON += area ? '_area.geojson' : '.geojson';
const geo = await fetch(`${BASE_URL}geojson/${geoJSON}`)
.then(res => res.json())
.catch(error => console.error(`Can't load layer ${geoJSON}. Reason: ${error}`));
@@ -560,11 +562,13 @@ GIS.cacheDBData = async function (layerId, dbId) {
GIS.featurePopup = function (layerName, feature) {
const html = `
<table class="table is-striped is-size-6 m-2">
<tr><th>Oggetto</th><td>${feature.properties.OGGETTO}</td></tr>
<tr><th>Oggetto</th><td>${feature.properties.OGGETTO ?? 'n.d.'}</td></tr>
<tr><th>Anno</th><td>${feature.properties.ANNO}</td></tr>
<tr><th>Comune</th><td>${capitalize(feature.properties.COMUNE)}</td></tr>
<tr><th>Località</th><td>${capitalize(feature.properties.LOCALITA)}</td></tr>
<tr><th>Proprietà</th><td>${capitalize(feature.properties.PROPRIETA)}</td></tr>
<tr><th>Località</th><td>${capitalize(feature.properties.LOCALITA) ?? 'n.d.'}</td></tr>
<tr><th>Proprietà</th><td>${capitalize(feature.properties.PROPRIETA) ?? 'n.d.'}</td></tr>
<tr><th>Foglio</th><td>${feature.properties.FOGLIO}</td></tr>
<tr><th>Particella</th><td>${feature.properties.PART_BIS ?? 'n.d.'}</td></tr>
</table>
`;
const content = {
@@ -586,10 +590,8 @@ GIS.reprojectWMS = function (crs = 'EPSG:4258') {
const reprojectedWMSLayer = L.TileLayer.WMS.extend({
getTileUrl(tilePoint) {
const map = GisState.map;
//const crs = map.options.crs;
const tileSize = this.getTileSize();
//const geoPoint = L.point(tilePoint.x, tilePoint.y);
const nwPoint = L.point(
tilePoint.x * tileSize.x,
tilePoint.y * tileSize.y,

View File

@@ -48,6 +48,15 @@ Icons.underwater = L.icon(
}
);
Icons.reuse = L.icon(
{
iconUrl: 'img/icons/reimpiego.png',
iconSize: [18, 27],
iconAnchor: [10, 24],
tooltipAnchor: [0, -22],
}
);
Icons.camera = L.divIcon({className: 'fa fa-camera'});
export default Icons;

View File

@@ -0,0 +1,54 @@
/**
* @namespace Options
*/
let Options = {};
Options.constraintsArch = {
color: '#222',
opacity: 0.8,
weight: 1,
fillColor: '#fa7861',
fillOpacity: 0.8
};
Options.site = {
color: '#800040',
opacity: 1,
weight: 1.5,
fillColor: '#800040',
fillOpacity: 0.8
};
Options.grotta = {
color: '#205dac',
opacity: 1,
weight: 1.5,
fillColor: '#205dac',
fillOpacity: 0.8
}
Options.bismarck = {
color: '#a4a79a',
opacity: 1,
weight: 1.5,
fillColor: '#a4a79a',
fillOpacity: 0.8
}
Options.constraintsLand = {
color: '#222',
opacity: 1,
weight: 1.5,
fillColor: '#88d28d',
fillOpacity: 0.8
};
Options.buildings = {
color: '#222',
opacity: 1,
weight: 1.5,
fillColor: '#5b5d5f',
fillOpacity: 0.8
};
Options.cluster = {
spiderfyOnMaxZoom: false,
showCoverageOnHover: false,
disableClusteringAtZoom: 19,
};
export default Options;

View File

@@ -27,6 +27,7 @@ export const GisState = {
findings: {},
prehistoric: {},
underwater: {},
reuse: {},
},
layers: {
sites: {},
@@ -34,6 +35,7 @@ export const GisState = {
findings: {},
prehistoric: {},
underwater: {},
reuse: {},
},
bibliography: null,
apiUrl : null,

View File

@@ -10,6 +10,7 @@ import { Finding } from './components/Finding.js';
import { Prehistoric } from './components/Prehistoric.js';
import { Underwater } from './components/Underwater.js';
import { GisState } from "./state.js";
import { Reuse } from './components/Reuse.js';
/**
* @namespace UI
@@ -100,8 +101,14 @@ UI.openSiteModal = function (data, selector) {
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');
let reconstructions = data.images.filter(i => i.type === 'Reconstruction');
if (surveys.length === 0 && photos.length === 0 && videos.length === 0) {
const noMedia = surveys.length === 0
&& photos.length === 0
&& reconstructions.length === 0
&& videos.length === 0;
if (noMedia) {
images.innerHTML = '<p class="has-text-centered">Nessuna risorsa visuale disponibile</p>';
}
@@ -114,6 +121,9 @@ UI.openSiteModal = function (data, selector) {
siteMedia.siteData = photos[0] ?? undefined;
images.innerHTML += photos[0] ? siteMedia.renderPhotos() : '';
siteMedia.siteData = reconstructions[0] ?? undefined;
images.innerHTML += reconstructions[0] ? siteMedia.renderReconstructions() : '';
siteMedia.siteData = videos[0] ?? undefined;
images.innerHTML += videos[0] ? siteMedia.renderVideos() : '';
}
@@ -122,6 +132,7 @@ UI.openSiteModal = function (data, selector) {
this.imageGallery('gallery-1', surveys);
this.imageGallery('gallery-2', photos);
this.imageGallery('gallery-3d', reconstructions);
this.imageGallery('gallery-video', videos, true);
}
/**
@@ -201,6 +212,27 @@ UI.openUnderwaterModal = function (data, selector) {
// For Stimulus biblio_controller
//GisState.bibliography = underwater;
underwater.render().then(html => modal.querySelector('#underwater-sheet').innerHTML = html);
underwater.renderDocs().then(html => modal.querySelector('#documents').innerHTML = html);
underwater.setImages(modal.querySelector('#photos'), this.imageGallery);
modal.classList.add('is-active');
}
/**
* @todo Biblio?
* @param {object} data The data retrieved from the DB to display as modal content
* @param {string} selector The modal selector
*/
UI.openReuseModal = function (data, selector) {
const modal = document.querySelector(selector);
let reuse = new Reuse();
reuse.data = data;
GisState.bibliography = reuse;
// For Stimulus biblio_controller
//GisState.bibliography = underwater;
reuse.render().then(html => modal.querySelector('#reuse-sheet').innerHTML = html);
reuse.setImages(modal.querySelector('#photos'), this.imageGallery);
modal.classList.add('is-active');
}
/**
@@ -216,8 +248,9 @@ UI.imageGallery = function (galleryId, items, video = false) {
let gallery = [];
for (let media of items) {
let author = media.author ? ` (${media.author})` : '';
let caption = media.caption ?? '';
let mediaObj = {
description: media.caption + author
description: caption + author
};
if (video) {