Compare commits
36 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| cb39695e6c | |||
| 487995366e | |||
| f9daaefbdd | |||
| 743bbc2f3b | |||
| 0de6158652 | |||
| 692ef13574 | |||
| f83f95a51a | |||
| c313194e15 | |||
| 1a3c95487f | |||
| b0915d0973 | |||
| ebea10059e | |||
| 249a31d11a | |||
| 4d95aa7fce | |||
| e7f1ed7a98 | |||
| 5cf42ff4be | |||
| 0f16af95e7 | |||
| 13550078cb | |||
| 262540e735 | |||
| c8de489ead | |||
| 952dc3f841 | |||
| 00cedfeb85 | |||
| 53c3f6c6b2 | |||
| 77d42a2c27 | |||
| 40cc2ef88b | |||
| e6578225ec | |||
| 986c4b0a75 | |||
| f849f885f9 | |||
| 9196653c0d | |||
| e3a3b30ade | |||
| 065e49ccb2 | |||
| 106c8f60bc | |||
| e3d98c2e5d | |||
| 377447f63a | |||
| cfcd1e8e80 | |||
| 378e14d56a | |||
| f68216c84c |
@@ -59,4 +59,4 @@ Photo Sphere Viewer, Three.js (da cui dipende Photo Sphere Viewer) e Stimulus.
|
|||||||
## TODO
|
## TODO
|
||||||
|
|
||||||
- [ ] Auto-discovery per Stimulus?
|
- [ ] Auto-discovery per Stimulus?
|
||||||
- [ ] Refactor con app state per evitare oggetti globali
|
- [x] Refactor con app state per evitare oggetti globali
|
||||||
@@ -186,4 +186,9 @@ a:visited {
|
|||||||
|
|
||||||
.marker-cluster-small span {
|
.marker-cluster-small span {
|
||||||
color: #fff;
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Apply Bulma's is-danger color based on state */
|
||||||
|
input:invalid {
|
||||||
|
border-color: #ff6685;
|
||||||
}
|
}
|
||||||
BIN
img/pub/AC_36-1.jpg
Executable file
BIN
img/pub/AC_36-1.jpg
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 43 KiB |
16
index.html
16
index.html
@@ -498,6 +498,22 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</article>
|
</article>
|
||||||
|
<article class="media mt-4 pb-6">
|
||||||
|
<figure class="media-left">
|
||||||
|
<p class="image is-128x128">
|
||||||
|
<img src="img/pub/AC_36-1.jpg" />
|
||||||
|
</p>
|
||||||
|
</figure>
|
||||||
|
<div class="media-content">
|
||||||
|
<div class="content">
|
||||||
|
<p>
|
||||||
|
Caratelli G., Giorgi C., Paraciani N. 2025,
|
||||||
|
<em>From archaeological survey to data accessibility: a WebGIS for the island of Capri</em>,
|
||||||
|
«Archeologia e Calcolatori», 36.1, 65-86 (<a href="https://doi.org/10.19282/ac.36.1.2025.04">https://doi.org/10.19282/ac.36.1.2025.04</a>)
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</article>
|
||||||
</section>
|
</section>
|
||||||
<footer class="modal-card-foot">
|
<footer class="modal-card-foot">
|
||||||
</footer>
|
</footer>
|
||||||
|
|||||||
144
webgis/geojson/villa_bismarck_area.geojson
Normal file
144
webgis/geojson/villa_bismarck_area.geojson
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
BIN
webgis/img/icons/reimpiego.png
Normal file
BIN
webgis/img/icons/reimpiego.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 34 KiB |
BIN
webgis/img/icons/reimpiego_menu.png
Normal file
BIN
webgis/img/icons/reimpiego_menu.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 20 KiB |
@@ -26,7 +26,7 @@
|
|||||||
<script src="js/index.js" type="module"></script>
|
<script src="js/index.js" type="module"></script>
|
||||||
<title>WebGIS Isola di Capri</title>
|
<title>WebGIS Isola di Capri</title>
|
||||||
</head>
|
</head>
|
||||||
<body data-controller="menu"
|
<body data-controller="menu modal"
|
||||||
data-action="menu-ready@document->menu#buildMenu menu-ready@document->menu#buildCartographyMenu">
|
data-action="menu-ready@document->menu#buildMenu menu-ready@document->menu#buildCartographyMenu">
|
||||||
<nav class="navbar mb-0" role="navigation">
|
<nav class="navbar mb-0" role="navigation">
|
||||||
<div class="navbar-brand">
|
<div class="navbar-brand">
|
||||||
@@ -61,11 +61,13 @@
|
|||||||
<span class="icon mr-2">
|
<span class="icon mr-2">
|
||||||
<i class="fa fa-map"></i>
|
<i class="fa fa-map"></i>
|
||||||
</span>
|
</span>
|
||||||
Cartografia
|
Catasto storico
|
||||||
</button>
|
</button>
|
||||||
<button class="button is-outlined is-rounded is-link mr-4 mt-1" id="howto" title="Istruzioni">
|
<button class="button is-white mr-2 mt-1" title="Cerca"
|
||||||
<span class="icon is-large has-text-link">
|
data-id="search"
|
||||||
<i class="fas fa-question fa-lg"></i>
|
data-action="menu#toggleMenu">
|
||||||
|
<span class="icon" data-id="search" data-action="menu#toggleMenu">
|
||||||
|
<i data-id="search" class="fa fa-search"></i>
|
||||||
</span>
|
</span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
@@ -77,7 +79,74 @@
|
|||||||
<div class="main columns">
|
<div class="main columns">
|
||||||
<div class="column mb-0 pb-0 is-full is-relative">
|
<div class="column mb-0 pb-0 is-full is-relative">
|
||||||
<div class="pb-0 is-relative" id="map" aria-describedby="map-progress" aria-busy="true">
|
<div class="pb-0 is-relative" id="map" aria-describedby="map-progress" aria-busy="true">
|
||||||
<progress id="map-progress" class="p-2 progress is-medium is-link" aria-label="Map loading..." />
|
<progress id="map-progress" class="p-2 progress is-medium is-link" aria-label="Caricamento mappa..." />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="menu-overlay column is-hidden is-4 is-4-desktop is-5-mobile is-pulled-right is-overlay has-background-white-ter"
|
||||||
|
data-menu-target="search" data-controller="layer search">
|
||||||
|
<button title="Chiudi ricerca" class="delete is-pulled-right" data-action="menu#closeSearch"></button>
|
||||||
|
<h1 class="is-size-5">Ricerca</h1>
|
||||||
|
<form id="search-form" method="POST" data-search-target="search" data-action="submit->search#submitSearch">
|
||||||
|
<div class="field">
|
||||||
|
<label class="label">Testo libero</label>
|
||||||
|
<div class="control is-full-width">
|
||||||
|
<input class="input" type="text" minlength="3" name="text" placeholder="Inserire parole chiave" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="field">
|
||||||
|
<label class="label">Categoria sito</label>
|
||||||
|
<div class="control">
|
||||||
|
<div class="select">
|
||||||
|
<select name="category">
|
||||||
|
<option default value="">-- Scegliere la categoria del sito --</option>
|
||||||
|
<option value="site">Sito conservato</option>
|
||||||
|
<!--<option value="not_conserved">Sito non conservato</option>-->
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="field">
|
||||||
|
<label class="label">Tecnica muraria</label>
|
||||||
|
<div class="control">
|
||||||
|
<div class="select">
|
||||||
|
<select name="technique">
|
||||||
|
<option default value="">-- 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 class="field is-grouped mt-5 mb-0 pb-0">
|
||||||
|
<div class="control">
|
||||||
|
<button class="button is-link" type="submit">
|
||||||
|
<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" type="reset" data-action="search#clearSearch">
|
||||||
|
<span>Cancella filtri</span>
|
||||||
|
<span class="icon is-small">
|
||||||
|
<i class="fa fa-times"></i>
|
||||||
|
</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
<div class="content pt-2 mt-3 is-hidden" data-search-target="container">
|
||||||
|
<table class="table is-fullwidth is-striped">
|
||||||
|
<thead>
|
||||||
|
<tr><td class="has-text-centered has-text-weight-bold is-size-5" colspan="2">Risultati</td></tr>
|
||||||
|
</thead>
|
||||||
|
<tbody data-search-target="results"></tbody>
|
||||||
|
</table>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="menu-overlay column is-hidden is-4 is-4-desktop is-5-mobile is-pulled-right is-overlay has-background-white-ter"
|
<div class="menu-overlay column is-hidden is-4 is-4-desktop is-5-mobile is-pulled-right is-overlay has-background-white-ter"
|
||||||
@@ -192,6 +261,30 @@
|
|||||||
</span>
|
</span>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</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">
|
<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">
|
<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>
|
<i class="fa fa-xs fa-eye-slash" data-layer-target="icon"></i>
|
||||||
@@ -284,23 +377,10 @@
|
|||||||
</template>
|
</template>
|
||||||
<aside class="menu ml-4 mt-3" data-id="cartography-aside">
|
<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>
|
<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>
|
</aside>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
<!-- Bibliography citations template -->
|
<!-- Bibliography citations template -->
|
||||||
<template id="biblio-item-template">
|
<template id="biblio-item-template">
|
||||||
<span class="is-clickable has-text-link"
|
<span class="is-clickable has-text-link"
|
||||||
@@ -452,12 +532,63 @@
|
|||||||
<button class="modal-close is-large" aria-label="close" data-action="modal#close tabs#reset"></button>
|
<button class="modal-close is-large" aria-label="close" data-action="modal#close tabs#reset"></button>
|
||||||
</div>
|
</div>
|
||||||
<!-- Underwater modal -->
|
<!-- Underwater modal -->
|
||||||
<div class="modal" id="underwater-data" data-controller="modal biblio marker" data-modal-target="modal">
|
<div class="modal" id="underwater-data" data-controller="modal tabs marker" data-modal-target="modal">
|
||||||
<div class="modal-background" data-action="click->modal#close"></div>
|
<div class="modal-background" data-action="click->modal#close click->tabs#reset"></div>
|
||||||
<div class="modal-content has-background-white">
|
<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>
|
||||||
|
<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>
|
</div>
|
||||||
<button class="modal-close is-large" aria-label="close" data-action="modal#close"></button>
|
<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>
|
</div>
|
||||||
<!-- Spherical photo modal -->
|
<!-- Spherical photo modal -->
|
||||||
<div class="modal" id="spherical-modal">
|
<div class="modal" id="spherical-modal">
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { GisState } from "../state.js";
|
import Utils from "./utils.js";
|
||||||
/**
|
/**
|
||||||
* @class Finding
|
* @class Finding
|
||||||
*/
|
*/
|
||||||
@@ -23,7 +23,7 @@ export class Finding {
|
|||||||
<strong>Misure:</strong> ${this._data.measurements}
|
<strong>Misure:</strong> ${this._data.measurements}
|
||||||
</p>
|
</p>
|
||||||
<p class="p-2">
|
<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>
|
||||||
<p class="p-2">
|
<p class="p-2">
|
||||||
<strong>Datazione:</strong> ${this._data.dating}
|
<strong>Datazione:</strong> ${this._data.dating}
|
||||||
@@ -36,7 +36,7 @@ export class Finding {
|
|||||||
</p>
|
</p>
|
||||||
<p class="mt-4 pl-2 pr-5">
|
<p class="mt-4 pl-2 pr-5">
|
||||||
<strong class="pb-3">Descrizione</strong></br>
|
<strong class="pb-3">Descrizione</strong></br>
|
||||||
${this._data.description}
|
${Utils.parseMarkers(this._data.description)}
|
||||||
</p>
|
</p>
|
||||||
<p class="mt-4 pl-2 pr-5">
|
<p class="mt-4 pl-2 pr-5">
|
||||||
<span class="icon has-text-link">
|
<span class="icon has-text-link">
|
||||||
@@ -50,64 +50,25 @@ export class Finding {
|
|||||||
</p>
|
</p>
|
||||||
</div>`;
|
</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 {HTMLElement} imageContainer
|
||||||
* @param {Function} gallery
|
* @param {Function} gallery
|
||||||
*/
|
*/
|
||||||
async setImages(imageContainer, gallery) {
|
async setImages(imageContainer, gallery) {
|
||||||
let record = await this.fetchData(`${GisState.apiUrl}/finding/${this._data.id}`)
|
if (this._data.images?.length) {
|
||||||
|
imageContainer.innerHTML = Utils.renderImages('finding-gallery', this._data.images);
|
||||||
if (record.images.length) {
|
gallery('finding-gallery', this._data.images);
|
||||||
this.images = record.images;
|
} else
|
||||||
imageContainer.innerHTML = this.renderImages();
|
imageContainer.innerHTML = '<p class="has-text-centered">Nessuna risorsa visuale disponibile</p>';
|
||||||
gallery('finding-gallery', this.images);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* @param {number} recordId
|
* @param {number} recordId
|
||||||
*/
|
*/
|
||||||
async biblio(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 = '';
|
return 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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getReference(id) {
|
getReference(id) {
|
||||||
@@ -116,8 +77,4 @@ export class Finding {
|
|||||||
return ref.match(regex);
|
return ref.match(regex);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async fetchData(url) {
|
|
||||||
return await fetch(url).then(res => res.json());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { GisState } from "../state.js";
|
import Utils from "./utils.js";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Component to render data for not conserved assets
|
* Component to render data for not conserved assets
|
||||||
@@ -32,11 +32,11 @@ export class NotConserved {
|
|||||||
<span class="icon has-text-link">
|
<span class="icon has-text-link">
|
||||||
<i class="fa fa-map"></i>
|
<i class="fa fa-map"></i>
|
||||||
</span>
|
</span>
|
||||||
<strong>Località generica:</strong> ${this._data.genericLocation}
|
<strong>Località generica:</strong> ${Utils.parseMarkers(this._data.genericLocation)}
|
||||||
</p>
|
</p>
|
||||||
<p class="mt-4 pl-2 pr-5">
|
<p class="mt-4 pl-2 pr-5">
|
||||||
<strong class="pb-3">Descrizione</strong></br>
|
<strong class="pb-3">Descrizione</strong></br>
|
||||||
${this._data.shortDescription}
|
${Utils.parseMarkers(this._data.shortDescription)}
|
||||||
</p>
|
</p>
|
||||||
<p class="mt-4 pl-2 pr-5">
|
<p class="mt-4 pl-2 pr-5">
|
||||||
<span class="icon has-text-link">
|
<span class="icon has-text-link">
|
||||||
@@ -51,116 +51,27 @@ export class NotConserved {
|
|||||||
</div>`;
|
</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 {HTMLElement} imageContainer
|
||||||
* @param {Function} gallery
|
* @param {Function} gallery
|
||||||
*/
|
*/
|
||||||
async setImages(imageContainer, gallery) {
|
setImages(imageContainer, gallery) {
|
||||||
if (this._data.images.length) {
|
if (this._data.images?.length) {
|
||||||
this.images = this._data.images;
|
imageContainer.innerHTML = Utils.renderImages('not-conserved-gallery', this._data.images);
|
||||||
imageContainer.innerHTML = this.renderImages();
|
gallery('not-conserved-gallery', this._data.images);
|
||||||
gallery('not-conserved-gallery', this.images);
|
|
||||||
} else
|
} else
|
||||||
imageContainer.innerHTML = '<p class="has-text-centered">Nessuna risorsa visuale disponibile</p>';
|
imageContainer.innerHTML = '<p class="has-text-centered">Nessuna risorsa visuale disponibile</p>';
|
||||||
}
|
}
|
||||||
|
|
||||||
async renderDocs() {
|
async renderDocs() {
|
||||||
let record = await this.fetchData(`${GisState.apiUrl}/not_conserved/${this._data.id}`);
|
return await Utils.generateDocsTable(this._data, 'not_conserved');
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async biblio(recordId) {
|
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 = '';
|
return 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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getReference(id) {
|
getReference(id) {
|
||||||
@@ -169,8 +80,4 @@ export class NotConserved {
|
|||||||
return ref.match(regex);
|
return ref.match(regex);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async fetchData(url) {
|
|
||||||
return await fetch(url).then(res => res.json());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { GisState } from "../state.js";
|
import Utils from "./utils.js";
|
||||||
/**
|
/**
|
||||||
* @class Prehistoric
|
* @class Prehistoric
|
||||||
*/
|
*/
|
||||||
@@ -32,11 +32,11 @@ export class Prehistoric {
|
|||||||
<span class="icon has-text-link">
|
<span class="icon has-text-link">
|
||||||
<i class="fa fa-map"></i>
|
<i class="fa fa-map"></i>
|
||||||
</span>
|
</span>
|
||||||
<strong>Località generica:</strong> ${this._data.genericPlace}
|
<strong>Località generica:</strong> ${Utils.parseMarkers(this._data.genericPlace)}
|
||||||
</p>
|
</p>
|
||||||
<p class="mt-4 pl-2 pr-5">
|
<p class="mt-4 pl-2 pr-5">
|
||||||
<strong class="pb-3">Descrizione breve</strong></br>
|
<strong class="pb-3">Descrizione breve</strong></br>
|
||||||
${this._data.description}
|
${Utils.parseMarkers(this._data.description)}
|
||||||
</p>
|
</p>
|
||||||
<p class="p-2">
|
<p class="p-2">
|
||||||
<strong>Conservazione:</strong> ${this._data.conservation}
|
<strong>Conservazione:</strong> ${this._data.conservation}
|
||||||
@@ -44,10 +44,16 @@ export class Prehistoric {
|
|||||||
<p class="p-2 mb-4">
|
<p class="p-2 mb-4">
|
||||||
<strong>Autore scheda:</strong> ${this._data.author}
|
<strong>Autore scheda:</strong> ${this._data.author}
|
||||||
</p>
|
</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>
|
||||||
</div>`;
|
</div>`;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
||||||
<p class="mt-4 pl-2 pr-5">
|
<p class="mt-4 pl-2 pr-5">
|
||||||
<span class="icon has-text-link">
|
<span class="icon has-text-link">
|
||||||
<i class="fa fa-book"></i>
|
<i class="fa fa-book"></i>
|
||||||
@@ -58,32 +64,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 {HTMLElement} imageContainer
|
||||||
* @param {Function} gallery
|
* @param {Function} gallery
|
||||||
*/
|
*/
|
||||||
async setImages(imageContainer, gallery) {
|
async setImages(imageContainer, gallery) {
|
||||||
if (this._data.images.length) {
|
if (this._data.images?.length) {
|
||||||
this.images = this._data.images;
|
imageContainer.innerHTML = Utils.renderImages('prehist-gallery', this._data.images);
|
||||||
imageContainer.innerHTML = this.renderImages();
|
gallery('prehist-gallery', this._data.images);
|
||||||
gallery('prehist-gallery', this.images);
|
|
||||||
} else
|
} else
|
||||||
imageContainer.innerHTML = '<p class="has-text-centered">Nessuna risorsa visuale disponibile</p>';
|
imageContainer.innerHTML = '<p class="has-text-centered">Nessuna risorsa visuale disponibile</p>';
|
||||||
}
|
}
|
||||||
@@ -91,29 +79,10 @@ export class Prehistoric {
|
|||||||
* @param {number} recordId
|
* @param {number} recordId
|
||||||
*/
|
*/
|
||||||
async biblio(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 = '';
|
return 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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getReference(id) {
|
getReference(id) {
|
||||||
@@ -122,8 +91,4 @@ export class Prehistoric {
|
|||||||
return ref.match(regex);
|
return ref.match(regex);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async fetchData(url) {
|
|
||||||
return await fetch(url).then(res => res.json());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
81
webgis/js/components/Reuse.js
Normal file
81
webgis/js/components/Reuse.js
Normal 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);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -43,4 +43,21 @@ export class SiteMedia {
|
|||||||
</div>
|
</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>
|
||||||
|
`;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,14 +1,10 @@
|
|||||||
|
import Utils from "./utils.js";
|
||||||
/**
|
/**
|
||||||
* Component to render data for site sheet
|
* Component to render data for site sheet
|
||||||
* @class SiteSheet
|
* @class SiteSheet
|
||||||
*/
|
*/
|
||||||
export class SiteSheet {
|
export class SiteSheet {
|
||||||
biblioElements = [];
|
biblioElements = [];
|
||||||
/*
|
|
||||||
constructor(data) {
|
|
||||||
this._siteData = data;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
/**
|
/**
|
||||||
* @param {object} data
|
* @param {object} data
|
||||||
*/
|
*/
|
||||||
@@ -16,9 +12,13 @@ export class SiteSheet {
|
|||||||
this._siteData = data;
|
this._siteData = data;
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
|
* @todo Refactor!
|
||||||
* @returns {string} HTML
|
* @returns {string} HTML
|
||||||
*/
|
*/
|
||||||
render() {
|
render() {
|
||||||
|
const description = Utils.parseMarkers(this._siteData.description);
|
||||||
|
const localization = Utils.parseMarkers(this._siteData.localization);
|
||||||
|
|
||||||
return `<div class="container has-bottom-border">
|
return `<div class="container has-bottom-border">
|
||||||
<table class="table is-fullwidth is-striped">
|
<table class="table is-fullwidth is-striped">
|
||||||
<tr class="is-link"><th class="is-size-5 has-text-centered" colspan=2>Identificazione</th></tr>
|
<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>Comune</th><td>${this._siteData.municipality}</td></tr>
|
||||||
<tr><th>Indirizzo</th><td>${this._siteData.address}</td></tr>
|
<tr><th>Indirizzo</th><td>${this._siteData.address}</td></tr>
|
||||||
<tr><th>Località</th><td>${this._siteData.place}</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 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>Periodo</th><td>${this._siteData.period}</td></tr>
|
||||||
<tr><th>Fase</th><td>${this._siteData.phase}</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>Stato di conservazione</th><td>${this._siteData.conservationState}</td></tr>
|
||||||
<tr><th>Tecniche edilizie impiegate:</th><td>${this._siteData.techniques}</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 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>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 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><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 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 class="is-link"><th class="is-size-5 has-text-centered" colspan=2>Bibliografia</th></tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan=2>
|
<td colspan=2>
|
||||||
@@ -60,6 +60,8 @@ export class SiteSheet {
|
|||||||
}
|
}
|
||||||
|
|
||||||
renderShort() {
|
renderShort() {
|
||||||
|
const shortDesc = Utils.parseMarkers(this._siteData.shortDescription);
|
||||||
|
|
||||||
return `
|
return `
|
||||||
<div class="container p-3">
|
<div class="container p-3">
|
||||||
<p class="p-2">
|
<p class="p-2">
|
||||||
@@ -81,7 +83,7 @@ export class SiteSheet {
|
|||||||
<strong>Località generica:</strong> ${this._siteData.genericPlace}
|
<strong>Località generica:</strong> ${this._siteData.genericPlace}
|
||||||
</p>
|
</p>
|
||||||
<p class="mt-4 pl-2 pr-5">
|
<p class="mt-4 pl-2 pr-5">
|
||||||
${this._siteData.shortDescription}
|
${shortDesc}
|
||||||
</p>
|
</p>
|
||||||
<p class="mt-4 pl-2 pr-5">
|
<p class="mt-4 pl-2 pr-5">
|
||||||
<span class="icon has-text-link">
|
<span class="icon has-text-link">
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import Utils from "./utils.js";
|
||||||
/**
|
/**
|
||||||
* @class Underwater
|
* @class Underwater
|
||||||
*/
|
*/
|
||||||
@@ -27,15 +28,26 @@ export class Underwater {
|
|||||||
</p>
|
</p>
|
||||||
<p class="mt-4 pl-2 pr-5">
|
<p class="mt-4 pl-2 pr-5">
|
||||||
<strong class="pb-3">Descrizione breve</strong></br>
|
<strong class="pb-3">Descrizione breve</strong></br>
|
||||||
${this._data.shortDescription}
|
${Utils.parseMarkers(this._data.shortDescription)}
|
||||||
</p>
|
</p>
|
||||||
<p class="p-2 mb-4">
|
<p class="p-2 mb-4">
|
||||||
<strong>Autore scheda:</strong> ${this._data.author}
|
<strong>Autore scheda:</strong> ${this._data.author}
|
||||||
</p>
|
</p>
|
||||||
</div>`;
|
</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) {
|
async renderDocs() {
|
||||||
return await fetch(url).then(res => res.json());
|
return await Utils.generateDocsTable(this._data, 'underwater');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
175
webgis/js/components/utils.js
Normal file
175
webgis/js/components/utils.js
Normal 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;
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
import { Controller } from "@hotwired/stimulus";
|
import { Controller } from "@hotwired/stimulus";
|
||||||
import { GisState, getMarkerByCoords } from "../state.js";
|
import { GisState, getMarkerByCoords } from "../state.js";
|
||||||
|
import UI from "../ui.js";
|
||||||
|
|
||||||
export default class extends Controller {
|
export default class extends Controller {
|
||||||
static values = {
|
static values = {
|
||||||
@@ -7,18 +8,17 @@ export default class extends Controller {
|
|||||||
'group': String,
|
'group': String,
|
||||||
'id': String,
|
'id': String,
|
||||||
};
|
};
|
||||||
|
|
||||||
END_ZOOM = 19;
|
uiModals = {
|
||||||
// Animation breaks automatic tooltip opening...
|
sites: '#site-data',
|
||||||
mapAnimate = {
|
notConserved: '#not-conser-data',
|
||||||
animate: true,
|
finding: '#finding-data',
|
||||||
duration: 1,
|
prehist: '#prehist-data',
|
||||||
easeLinearity: 0.25
|
reuse: '#reuse-data',
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
END_ZOOM = 19;
|
||||||
* @param {Event} event
|
|
||||||
*/
|
|
||||||
go() {
|
go() {
|
||||||
let map = GisState.map;
|
let map = GisState.map;
|
||||||
const coords = this.coordsValue.split(' ');
|
const coords = this.coordsValue.split(' ');
|
||||||
@@ -31,8 +31,40 @@ export default class extends Controller {
|
|||||||
|
|
||||||
let marker = this.getMarker(map, coords);
|
let marker = this.getMarker(map, coords);
|
||||||
// DEBUG for sites
|
// DEBUG for sites
|
||||||
if (this.groupValue) marker = getMarkerByCoords(coords, this.groupValue);
|
//if (this.groupValue) marker = getMarkerByCoords(coords, this.groupValue);
|
||||||
marker?.openTooltip();
|
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
|
* @param {L.Map} map
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ export default class extends Controller {
|
|||||||
'list',
|
'list',
|
||||||
'menu',
|
'menu',
|
||||||
'cartography',
|
'cartography',
|
||||||
|
'search',
|
||||||
'icon'
|
'icon'
|
||||||
];
|
];
|
||||||
|
|
||||||
@@ -86,12 +87,17 @@ export default class extends Controller {
|
|||||||
toggleMenu(event) {
|
toggleMenu(event) {
|
||||||
const menuId = event.target.dataset.id;
|
const menuId = event.target.dataset.id;
|
||||||
|
|
||||||
|
console.debug(menuId, event.target);
|
||||||
|
|
||||||
// Stupid...
|
// Stupid...
|
||||||
if (menuId === 'main') {
|
if (menuId === 'main') {
|
||||||
this.menuTarget.classList.toggle('is-hidden');
|
this.menuTarget.classList.toggle('is-hidden');
|
||||||
if (!this.cartographyTarget.classList.contains('is-hidden')) {
|
if (!this.cartographyTarget.classList.contains('is-hidden')) {
|
||||||
this.cartographyTarget.classList.add('is-hidden');
|
this.cartographyTarget.classList.add('is-hidden');
|
||||||
}
|
}
|
||||||
|
if (!this.searchTarget.classList.contains('is-hidden')) {
|
||||||
|
this.searchTarget.classList.add('is-hidden');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (menuId === 'cartography') {
|
if (menuId === 'cartography') {
|
||||||
@@ -99,6 +105,18 @@ export default class extends Controller {
|
|||||||
if (!this.menuTarget.classList.contains('is-hidden')) {
|
if (!this.menuTarget.classList.contains('is-hidden')) {
|
||||||
this.menuTarget.classList.add('is-hidden');
|
this.menuTarget.classList.add('is-hidden');
|
||||||
}
|
}
|
||||||
|
if (!this.searchTarget.classList.contains('is-hidden')) {
|
||||||
|
this.searchTarget.classList.add('is-hidden');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (menuId === 'search') {
|
||||||
|
this.searchTarget.classList.toggle('is-hidden');
|
||||||
|
if (!this.menuTarget.classList.contains('is-hidden')) {
|
||||||
|
this.menuTarget.classList.add('is-hidden');
|
||||||
|
}
|
||||||
|
if (!this.cartographyTarget.classList.contains('is-hidden')) {
|
||||||
|
this.cartographyTarget.classList.add('is-hidden');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -110,6 +128,10 @@ export default class extends Controller {
|
|||||||
this.cartographyTarget.classList.add('is-hidden');
|
this.cartographyTarget.classList.add('is-hidden');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
closeSearch() {
|
||||||
|
this.searchTarget.classList.add('is-hidden');
|
||||||
|
}
|
||||||
|
|
||||||
toggleList(id) {
|
toggleList(id) {
|
||||||
document.querySelector(`#${id}`).classList.toggle('is-hidden');
|
document.querySelector(`#${id}`).classList.toggle('is-hidden');
|
||||||
}
|
}
|
||||||
|
|||||||
139
webgis/js/controllers/search_controller.js
Normal file
139
webgis/js/controllers/search_controller.js
Normal file
@@ -0,0 +1,139 @@
|
|||||||
|
import { Controller } from "@hotwired/stimulus";
|
||||||
|
import { GisState } from "../state.js";
|
||||||
|
import UI from "../ui.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();
|
||||||
|
|
||||||
|
console.warn(body);
|
||||||
|
|
||||||
|
this.containerTarget.classList.remove('is-hidden');
|
||||||
|
this.#injectResults(results);
|
||||||
|
if (results.length) {
|
||||||
|
this.#filterMap(results);
|
||||||
|
// Should technique always be shown after a search?
|
||||||
|
for (const key of Object.keys(techsMarkers)) {
|
||||||
|
if (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');
|
||||||
|
}
|
||||||
|
|
||||||
|
#injectResults(results) {
|
||||||
|
/**
|
||||||
|
* @type {HTMLOutputElement} output
|
||||||
|
*/
|
||||||
|
const output = this.resultsTarget;
|
||||||
|
output.innerHTML = '';
|
||||||
|
|
||||||
|
if (results.length === 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>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
const sites = GisState.markers.sites;
|
||||||
|
|
||||||
|
for (const result of results) {
|
||||||
|
let coordinates = ''
|
||||||
|
for (let key of Object.keys(sites)) {
|
||||||
|
if (sites[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-coords-value="${coordinates}"
|
||||||
|
data-marker-group-value="sites">
|
||||||
|
Vai al sito
|
||||||
|
<span class="ml-1 icon">
|
||||||
|
<i class="fa fa-chevron-right"></i>
|
||||||
|
</span>
|
||||||
|
</button>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
`;
|
||||||
|
|
||||||
|
output.innerHTML += item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {Array<Object>} results
|
||||||
|
*/
|
||||||
|
#filterMap(results) {
|
||||||
|
const map = GisState.map;
|
||||||
|
const labels = [];
|
||||||
|
results.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]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
181
webgis/js/gis.js
181
webgis/js/gis.js
@@ -5,6 +5,7 @@ import API_CONFIG from "./config.js";
|
|||||||
import Icons from "./icons.js";
|
import Icons from "./icons.js";
|
||||||
import { SphericalPhoto } from "./components/SphericalPhoto.js";
|
import { SphericalPhoto } from "./components/SphericalPhoto.js";
|
||||||
import { GisState } from "./state.js";
|
import { GisState } from "./state.js";
|
||||||
|
import Options from "./layer_options.js";
|
||||||
|
|
||||||
const MAPBOX_TOKEN = 'pk.eyJ1Ijoibmljb3BhIiwiYSI6ImNseWNwZjJjbjFidzcya3BoYTU0bHg4NnkifQ.3036JnCXZTEMt6jVgMzVRw';
|
const MAPBOX_TOKEN = 'pk.eyJ1Ijoibmljb3BhIiwiYSI6ImNseWNwZjJjbjFidzcya3BoYTU0bHg4NnkifQ.3036JnCXZTEMt6jVgMzVRw';
|
||||||
const BASE_URL = location.href;
|
const BASE_URL = location.href;
|
||||||
@@ -28,47 +29,6 @@ GIS.INIT_ZOOM = 14;
|
|||||||
GIS.MIN_ZOOM = 11;
|
GIS.MIN_ZOOM = 11;
|
||||||
GIS.MAX_ZOOM = 24;
|
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
|
* Capitalize a text string
|
||||||
* @todo Move to utils
|
* @todo Move to utils
|
||||||
@@ -108,37 +68,38 @@ GIS.initMap = async function (mapId, zoomLevel = this.INIT_ZOOM) {
|
|||||||
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.loadGeoJSON('vincoli.geojson', optionsVincoli);
|
let layerVincoli = await this.loadGeoJSON('vincoli.geojson', Options.constraintsArch);
|
||||||
let layerPaesistici = await this.loadGeoJSON('paesistici.geojson', optionsPaesistici);
|
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.addLayerGroups(map);
|
||||||
await this.fetchCartographyLayers();
|
await this.fetchCartographyLayers();
|
||||||
|
const buildingTechs = await this.buildingTechs();
|
||||||
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 reprojectedWMSLayer = GIS.reprojectWMS();
|
||||||
const wmsLayer = new reprojectedWMSLayer(
|
const wmsLayer = new reprojectedWMSLayer(
|
||||||
'https://wms.cartografia.agenziaentrate.gov.it/inspire/wms/ows01.php?',
|
'https://wms.cartografia.agenziaentrate.gov.it/inspire/wms/ows01.php?',
|
||||||
{
|
{
|
||||||
layers: 'CP.CadastralParcel,fabbricati',
|
layers: 'CP.CadastralParcel,codice_plla,fabbricati',
|
||||||
transparent: true,
|
transparent: true,
|
||||||
format: 'image/png',
|
format: 'image/png',
|
||||||
version: '1.1.1',
|
version: '1.1.1',
|
||||||
minZoom: 15,
|
minZoom: this.INIT_ZOOM,
|
||||||
maxZoom: this.MAX_ZOOM,
|
maxZoom: this.MAX_ZOOM,
|
||||||
tileSize: 1024,
|
tileSize: 1024,
|
||||||
opacity: 0.6,
|
opacity: 0.6,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
const cartography = {
|
||||||
|
'Catasto Agenzia delle Entrate (zoom per visualizzare)' : wmsLayer,
|
||||||
|
'Fabbricati' : buildings,
|
||||||
|
'Vincoli archeologici' : layerVincoli,
|
||||||
|
'Vincoli archeologici indiretti' : layerPaesistici,
|
||||||
|
'Tecniche murarie' : buildingTechs,
|
||||||
|
};
|
||||||
|
L.control.layers(baseMap, cartography).addTo(map);
|
||||||
|
|
||||||
GisState.cartography.cadastral = wmsLayer;
|
GisState.map = map;
|
||||||
|
|
||||||
return map;
|
return map;
|
||||||
}
|
}
|
||||||
@@ -155,6 +116,35 @@ GIS.fetchCartographyLayers = async function () {
|
|||||||
GisState.cartography.historic.push({id, label});
|
GisState.cartography.historic.push({id, label});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* Create building techs layer
|
||||||
|
* @returns {L.Layer}
|
||||||
|
*/
|
||||||
|
GIS.buildingTechs = async function () {
|
||||||
|
let techsData = await fetch(`${API_URL}/building_techs`)
|
||||||
|
.then(data => data.json());
|
||||||
|
|
||||||
|
let techs = new L.LayerGroup();
|
||||||
|
|
||||||
|
for (let record of techsData) {
|
||||||
|
const marker = L.marker(
|
||||||
|
record.coordinates,
|
||||||
|
{icon: Icons.techs, label: record.technique}
|
||||||
|
)
|
||||||
|
.bindTooltip(record.technique)
|
||||||
|
.bindPopup(UI.createBuildingTechTable(record));
|
||||||
|
|
||||||
|
techs.addLayer(marker);
|
||||||
|
const markerLabel = `${record.coordinates[0]} ${record.coordinates[1]}`;
|
||||||
|
marker.options.data = record;
|
||||||
|
marker.options.site = record.site.label;
|
||||||
|
GisState.markers.buildingTechs[markerLabel] = marker;
|
||||||
|
}
|
||||||
|
|
||||||
|
GisState.layers.buildingTechs = techs;
|
||||||
|
|
||||||
|
return techs;
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* Load georeferenced image overlays layer group
|
* Load georeferenced image overlays layer group
|
||||||
* @param {Number} imageId - The API id of the georeferenced image
|
* @param {Number} imageId - The API id of the georeferenced image
|
||||||
@@ -199,6 +189,7 @@ GIS.addLayerGroups = async function (map) {
|
|||||||
this.findings(),
|
this.findings(),
|
||||||
this.prehistoric(),
|
this.prehistoric(),
|
||||||
this.underwater(),
|
this.underwater(),
|
||||||
|
this.reuse(),
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
groups.forEach(group => group.addTo(map));
|
groups.forEach(group => group.addTo(map));
|
||||||
@@ -211,15 +202,20 @@ GIS.sites = async function () {
|
|||||||
let sitesData = await fetch(`${API_URL}/sites`)
|
let sitesData = await fetch(`${API_URL}/sites`)
|
||||||
.then(data => data.json());
|
.then(data => data.json());
|
||||||
|
|
||||||
let sites = L.markerClusterGroup(clusterOptions);
|
let sites = L.markerClusterGroup(Options.cluster);
|
||||||
let geom = [];
|
let geom = [];
|
||||||
|
|
||||||
for (let record of sitesData) {
|
for (let record of sitesData) {
|
||||||
if (record.geojson) {
|
if (record.geojson) {
|
||||||
const options = record.gisId === 'grotta_azzurra' ?
|
const options = record.gisId === 'grotta_azzurra' ?
|
||||||
optionsGrotta : optionsSiti;
|
Options.grotta : Options.site;
|
||||||
geom.push(await this.loadSiteLayer(record, options));
|
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(
|
const marker = L.marker(
|
||||||
record.coordinates,
|
record.coordinates,
|
||||||
@@ -235,6 +231,7 @@ GIS.sites = async function () {
|
|||||||
// Populate app state for reuse and avoid window.Sites etc.
|
// Populate app state for reuse and avoid window.Sites etc.
|
||||||
// Municipality (Capri, Anacapri) added for reuse in dynamic menu
|
// Municipality (Capri, Anacapri) added for reuse in dynamic menu
|
||||||
marker.options.municipality = record.municipality;
|
marker.options.municipality = record.municipality;
|
||||||
|
marker.options.data = record;
|
||||||
const markerIndex = `${record.coordinates[0]} ${record.coordinates[1]}`;
|
const markerIndex = `${record.coordinates[0]} ${record.coordinates[1]}`;
|
||||||
GisState.markers.sites[markerIndex] = marker;
|
GisState.markers.sites[markerIndex] = marker;
|
||||||
}
|
}
|
||||||
@@ -251,7 +248,7 @@ GIS.notConserved = async function () {
|
|||||||
let notConserData = await fetch(`${API_URL}/not_conserved`)
|
let notConserData = await fetch(`${API_URL}/not_conserved`)
|
||||||
.then(data => data.json());
|
.then(data => data.json());
|
||||||
|
|
||||||
let notConserved = L.markerClusterGroup(clusterOptions);
|
let notConserved = L.markerClusterGroup(Options.cluster);
|
||||||
|
|
||||||
for (let record of notConserData.records) {
|
for (let record of notConserData.records) {
|
||||||
const marker = L.marker(
|
const marker = L.marker(
|
||||||
@@ -265,6 +262,7 @@ GIS.notConserved = async function () {
|
|||||||
// Populate app state for reuse and avoid window.Sites etc.
|
// Populate app state for reuse and avoid window.Sites etc.
|
||||||
const markerLabel = `${record.coordinates[0]} ${record.coordinates[1]}`;
|
const markerLabel = `${record.coordinates[0]} ${record.coordinates[1]}`;
|
||||||
marker.options.municipality = record.municipality;
|
marker.options.municipality = record.municipality;
|
||||||
|
marker.options.data = record;
|
||||||
GisState.markers.notConserved[markerLabel] = marker;
|
GisState.markers.notConserved[markerLabel] = marker;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -281,7 +279,7 @@ GIS.findings = async function () {
|
|||||||
.then(data => data.json());
|
.then(data => data.json());
|
||||||
|
|
||||||
let findings = L.markerClusterGroup(
|
let findings = L.markerClusterGroup(
|
||||||
clusterOptions
|
Options.cluster
|
||||||
);
|
);
|
||||||
|
|
||||||
for (let record of findingsData) {
|
for (let record of findingsData) {
|
||||||
@@ -297,6 +295,7 @@ GIS.findings = async function () {
|
|||||||
findings.addLayer(marker);
|
findings.addLayer(marker);
|
||||||
const markerLabel = `${record.coordinates[0]} ${record.coordinates[1]}`;
|
const markerLabel = `${record.coordinates[0]} ${record.coordinates[1]}`;
|
||||||
marker.options.municipality = record.municipality;
|
marker.options.municipality = record.municipality;
|
||||||
|
marker.options.data = record;
|
||||||
GisState.markers.findings[markerLabel] = marker;
|
GisState.markers.findings[markerLabel] = marker;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -313,7 +312,7 @@ GIS.prehistoric = async function () {
|
|||||||
.then(data => data.json());
|
.then(data => data.json());
|
||||||
|
|
||||||
let prehistoric = L.markerClusterGroup(
|
let prehistoric = L.markerClusterGroup(
|
||||||
clusterOptions
|
Options.cluster
|
||||||
);
|
);
|
||||||
|
|
||||||
for (let record of data.records) {
|
for (let record of data.records) {
|
||||||
@@ -328,6 +327,7 @@ GIS.prehistoric = async function () {
|
|||||||
|
|
||||||
const markerLabel = `${record.coordinates[0]} ${record.coordinates[1]}`;
|
const markerLabel = `${record.coordinates[0]} ${record.coordinates[1]}`;
|
||||||
marker.options.municipality = record.municipality;
|
marker.options.municipality = record.municipality;
|
||||||
|
marker.options.data = record;
|
||||||
GisState.markers.prehistoric[markerLabel] = marker;
|
GisState.markers.prehistoric[markerLabel] = marker;
|
||||||
|
|
||||||
prehistoric.addLayer(marker);
|
prehistoric.addLayer(marker);
|
||||||
@@ -345,7 +345,7 @@ GIS.underwater = async function () {
|
|||||||
let underwaterData = await fetch(`${API_URL}/underwater`)
|
let underwaterData = await fetch(`${API_URL}/underwater`)
|
||||||
.then(data => data.json());
|
.then(data => data.json());
|
||||||
|
|
||||||
let underwater = L.markerClusterGroup(clusterOptions);
|
let underwater = L.markerClusterGroup(Options.cluster);
|
||||||
|
|
||||||
for (let record of underwaterData.records) {
|
for (let record of underwaterData.records) {
|
||||||
const marker = L.marker(
|
const marker = L.marker(
|
||||||
@@ -358,7 +358,8 @@ GIS.underwater = async function () {
|
|||||||
);
|
);
|
||||||
|
|
||||||
const markerLabel = `${record.coordinates[0]} ${record.coordinates[1]}`;
|
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);
|
underwater.addLayer(marker);
|
||||||
}
|
}
|
||||||
@@ -367,10 +368,42 @@ GIS.underwater = async function () {
|
|||||||
|
|
||||||
return underwater;
|
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
|
* 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}}}
|
* @returns {{baseMap: {"OpenStreetMap": L.TileLayer}}}
|
||||||
*/
|
*/
|
||||||
@@ -389,16 +422,15 @@ GIS.initLayers = async function(map) {
|
|||||||
maxZoom: GIS.MAX_ZOOM,
|
maxZoom: GIS.MAX_ZOOM,
|
||||||
attribution: '© Mapbox'
|
attribution: '© Mapbox'
|
||||||
});
|
});
|
||||||
|
|
||||||
let boundaries = await this.loadGeoJSON('confini.geojson', {}, false);
|
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]);
|
const baseGroup = new L.LayerGroup([osmap]);
|
||||||
baseGroup.addTo(map);
|
baseGroup.addTo(map);
|
||||||
const baseMap = {
|
const baseMap = {
|
||||||
"OpenStreetMap" : osmap,
|
"OpenStreetMap" : osmap,
|
||||||
"Satellite" : mapbox,
|
"Satellite" : mapbox,
|
||||||
"Cartografia catastale" : baseCatasto,
|
'Limiti amministrativi' : boundaries,
|
||||||
};
|
};
|
||||||
|
|
||||||
return baseMap;
|
return baseMap;
|
||||||
@@ -479,9 +511,10 @@ GIS.loadGeoJSON = async function (geoJSON, options, popup = true) {
|
|||||||
* @param {boolean} popup Should the features have a popup?
|
* @param {boolean} popup Should the features have a popup?
|
||||||
* @returns {L.Layer}
|
* @returns {L.Layer}
|
||||||
*/
|
*/
|
||||||
GIS.loadSiteLayer = async function (site, options, popup = true) {
|
GIS.loadSiteLayer = async function (site, options, popup = true, area = false) {
|
||||||
const geoJSON = `${site.gisId}.geojson`;
|
let geoJSON = site.gisId;
|
||||||
const geo = await fetch(`${BASE_URL}/geojson/${geoJSON}`)
|
geoJSON += area ? '_area.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}`));
|
||||||
|
|
||||||
@@ -560,11 +593,13 @@ GIS.cacheDBData = async function (layerId, dbId) {
|
|||||||
GIS.featurePopup = function (layerName, feature) {
|
GIS.featurePopup = function (layerName, feature) {
|
||||||
const html = `
|
const html = `
|
||||||
<table class="table is-striped is-size-6 m-2">
|
<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>Anno</th><td>${feature.properties.ANNO}</td></tr>
|
||||||
<tr><th>Comune</th><td>${capitalize(feature.properties.COMUNE)}</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>Località</th><td>${capitalize(feature.properties.LOCALITA) ?? 'n.d.'}</td></tr>
|
||||||
<tr><th>Proprietà</th><td>${capitalize(feature.properties.PROPRIETA)}</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>
|
</table>
|
||||||
`;
|
`;
|
||||||
const content = {
|
const content = {
|
||||||
@@ -586,10 +621,8 @@ GIS.reprojectWMS = function (crs = 'EPSG:4258') {
|
|||||||
const reprojectedWMSLayer = L.TileLayer.WMS.extend({
|
const reprojectedWMSLayer = L.TileLayer.WMS.extend({
|
||||||
getTileUrl(tilePoint) {
|
getTileUrl(tilePoint) {
|
||||||
const map = GisState.map;
|
const map = GisState.map;
|
||||||
//const crs = map.options.crs;
|
|
||||||
const tileSize = this.getTileSize();
|
const tileSize = this.getTileSize();
|
||||||
|
|
||||||
//const geoPoint = L.point(tilePoint.x, tilePoint.y);
|
|
||||||
const nwPoint = L.point(
|
const nwPoint = L.point(
|
||||||
tilePoint.x * tileSize.x,
|
tilePoint.x * tileSize.x,
|
||||||
tilePoint.y * tileSize.y,
|
tilePoint.y * tileSize.y,
|
||||||
|
|||||||
@@ -48,6 +48,17 @@ 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'});
|
Icons.camera = L.divIcon({className: 'fa fa-camera'});
|
||||||
|
|
||||||
|
Icons.techs = L.divIcon({className: 'fa fa-circle has-text-primary-25'});
|
||||||
|
|
||||||
export default Icons;
|
export default Icons;
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
import GIS from './gis.js';
|
import GIS from './gis.js';
|
||||||
import UI from './ui.js';
|
import UI from './ui.js';
|
||||||
|
import { GisState } from './state.js';
|
||||||
import { Application } from '@hotwired/stimulus';
|
import { Application } from '@hotwired/stimulus';
|
||||||
import MenuController from './controllers/menu_controller.js';
|
import MenuController from './controllers/menu_controller.js';
|
||||||
import ModalController from './controllers/modal_controller.js';
|
import ModalController from './controllers/modal_controller.js';
|
||||||
@@ -7,6 +8,7 @@ import MarkerController from './controllers/marker_controller.js';
|
|||||||
import BiblioController from './controllers/biblio_controller.js';
|
import BiblioController from './controllers/biblio_controller.js';
|
||||||
import TabsController from './controllers/tabs_controller.js';
|
import TabsController from './controllers/tabs_controller.js';
|
||||||
import LayerController from './controllers/layer_controller.js';
|
import LayerController from './controllers/layer_controller.js';
|
||||||
|
import SearchController from './controllers/search_controller.js';
|
||||||
|
|
||||||
document.addEventListener('DOMContentLoaded', async () => {
|
document.addEventListener('DOMContentLoaded', async () => {
|
||||||
// Register Stimulus controllers
|
// Register Stimulus controllers
|
||||||
@@ -14,13 +16,13 @@ document.addEventListener('DOMContentLoaded', async () => {
|
|||||||
|
|
||||||
let progress = document.querySelector('progress');
|
let progress = document.querySelector('progress');
|
||||||
const map = await GIS.initMap('map');
|
const map = await GIS.initMap('map');
|
||||||
progress.classList.add('is-hidden');
|
|
||||||
|
|
||||||
map._container.setAttribute('aria-busy', false);
|
|
||||||
|
|
||||||
// Trigger Stimulus buildMenu method...
|
// Trigger Stimulus buildMenu method...
|
||||||
const menuEvent = new Event('menu-ready');
|
const menuEvent = new Event('menu-ready');
|
||||||
document.dispatchEvent(menuEvent);
|
document.dispatchEvent(menuEvent);
|
||||||
|
|
||||||
|
progress.classList.add('is-hidden');
|
||||||
|
map._container.setAttribute('aria-busy', false);
|
||||||
|
|
||||||
GIS.toggleSpherical(map);
|
GIS.toggleSpherical(map);
|
||||||
|
|
||||||
@@ -36,4 +38,5 @@ function initStimulus() {
|
|||||||
Stimulus.register("biblio", BiblioController);
|
Stimulus.register("biblio", BiblioController);
|
||||||
Stimulus.register("tabs", TabsController);
|
Stimulus.register("tabs", TabsController);
|
||||||
Stimulus.register("layer", LayerController);
|
Stimulus.register("layer", LayerController);
|
||||||
|
Stimulus.register("search", SearchController);
|
||||||
}
|
}
|
||||||
54
webgis/js/layer_options.js
Normal file
54
webgis/js/layer_options.js
Normal 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;
|
||||||
@@ -27,6 +27,8 @@ export const GisState = {
|
|||||||
findings: {},
|
findings: {},
|
||||||
prehistoric: {},
|
prehistoric: {},
|
||||||
underwater: {},
|
underwater: {},
|
||||||
|
reuse: {},
|
||||||
|
buildingTechs: {},
|
||||||
},
|
},
|
||||||
layers: {
|
layers: {
|
||||||
sites: {},
|
sites: {},
|
||||||
@@ -34,6 +36,8 @@ export const GisState = {
|
|||||||
findings: {},
|
findings: {},
|
||||||
prehistoric: {},
|
prehistoric: {},
|
||||||
underwater: {},
|
underwater: {},
|
||||||
|
reuse: {},
|
||||||
|
buildingTechs: {},
|
||||||
},
|
},
|
||||||
bibliography: null,
|
bibliography: null,
|
||||||
apiUrl : null,
|
apiUrl : null,
|
||||||
|
|||||||
@@ -10,6 +10,9 @@ import { Finding } from './components/Finding.js';
|
|||||||
import { Prehistoric } from './components/Prehistoric.js';
|
import { Prehistoric } from './components/Prehistoric.js';
|
||||||
import { Underwater } from './components/Underwater.js';
|
import { Underwater } from './components/Underwater.js';
|
||||||
import { GisState } from "./state.js";
|
import { GisState } from "./state.js";
|
||||||
|
import { Reuse } from './components/Reuse.js';
|
||||||
|
|
||||||
|
const html = String.raw;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @namespace UI
|
* @namespace UI
|
||||||
@@ -100,8 +103,14 @@ UI.openSiteModal = function (data, selector) {
|
|||||||
let surveys = data.images.filter(i => i.type === 'Survey');
|
let surveys = data.images.filter(i => i.type === 'Survey');
|
||||||
let photos = data.images.filter(i => i.type === 'Photo');
|
let photos = data.images.filter(i => i.type === 'Photo');
|
||||||
let videos = data.images.filter(i => i.type === 'Video');
|
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>';
|
images.innerHTML = '<p class="has-text-centered">Nessuna risorsa visuale disponibile</p>';
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -114,6 +123,9 @@ UI.openSiteModal = function (data, selector) {
|
|||||||
siteMedia.siteData = photos[0] ?? undefined;
|
siteMedia.siteData = photos[0] ?? undefined;
|
||||||
images.innerHTML += photos[0] ? siteMedia.renderPhotos() : '';
|
images.innerHTML += photos[0] ? siteMedia.renderPhotos() : '';
|
||||||
|
|
||||||
|
siteMedia.siteData = reconstructions[0] ?? undefined;
|
||||||
|
images.innerHTML += reconstructions[0] ? siteMedia.renderReconstructions() : '';
|
||||||
|
|
||||||
siteMedia.siteData = videos[0] ?? undefined;
|
siteMedia.siteData = videos[0] ?? undefined;
|
||||||
images.innerHTML += videos[0] ? siteMedia.renderVideos() : '';
|
images.innerHTML += videos[0] ? siteMedia.renderVideos() : '';
|
||||||
}
|
}
|
||||||
@@ -122,6 +134,7 @@ UI.openSiteModal = function (data, selector) {
|
|||||||
|
|
||||||
this.imageGallery('gallery-1', surveys);
|
this.imageGallery('gallery-1', surveys);
|
||||||
this.imageGallery('gallery-2', photos);
|
this.imageGallery('gallery-2', photos);
|
||||||
|
this.imageGallery('gallery-3d', reconstructions);
|
||||||
this.imageGallery('gallery-video', videos, true);
|
this.imageGallery('gallery-video', videos, true);
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
@@ -182,7 +195,7 @@ UI.openPrehistModal = function (data, selector) {
|
|||||||
prehistoric.data = data;
|
prehistoric.data = data;
|
||||||
|
|
||||||
// For Stimulus biblio_controller
|
// For Stimulus biblio_controller
|
||||||
//GisState.bibliography = prehistoric;
|
GisState.bibliography = prehistoric;
|
||||||
prehistoric.render().then(html => modal.querySelector('#prehist-sheet').innerHTML = html);
|
prehistoric.render().then(html => modal.querySelector('#prehist-sheet').innerHTML = html);
|
||||||
prehistoric.setImages(modal.querySelector('#photos'), this.imageGallery);
|
prehistoric.setImages(modal.querySelector('#photos'), this.imageGallery);
|
||||||
modal.classList.add('is-active');
|
modal.classList.add('is-active');
|
||||||
@@ -201,6 +214,27 @@ UI.openUnderwaterModal = function (data, selector) {
|
|||||||
// For Stimulus biblio_controller
|
// For Stimulus biblio_controller
|
||||||
//GisState.bibliography = underwater;
|
//GisState.bibliography = underwater;
|
||||||
underwater.render().then(html => modal.querySelector('#underwater-sheet').innerHTML = html);
|
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');
|
modal.classList.add('is-active');
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
@@ -216,8 +250,9 @@ UI.imageGallery = function (galleryId, items, video = false) {
|
|||||||
let gallery = [];
|
let gallery = [];
|
||||||
for (let media of items) {
|
for (let media of items) {
|
||||||
let author = media.author ? ` (${media.author})` : '';
|
let author = media.author ? ` (${media.author})` : '';
|
||||||
|
let caption = media.caption ?? '';
|
||||||
let mediaObj = {
|
let mediaObj = {
|
||||||
description: media.caption + author
|
description: caption + author
|
||||||
};
|
};
|
||||||
|
|
||||||
if (video) {
|
if (video) {
|
||||||
@@ -237,5 +272,23 @@ UI.imageGallery = function (galleryId, items, video = false) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* @param {Object} record
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
UI.createBuildingTechTable = function(record) {
|
||||||
|
return html`
|
||||||
|
<table class="table is-striped is-size-6 m-2">
|
||||||
|
<tbody>
|
||||||
|
<tr><th>Tecnica</th><td>${record.technique}</td></tr>
|
||||||
|
<tr><th>Descrizione</th><td>${record.description}</td></tr>
|
||||||
|
<tr><th>Funzione</th><td>${record.function}</td></tr>
|
||||||
|
<tr><th>Materiale</th><td>${record.material}</td></tr>
|
||||||
|
<tr><th>Sito</th><td>${record.site.label}</td></tr>
|
||||||
|
<tr><th>Comune</th><td>${record.municipality}</td></tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
;`
|
||||||
|
}
|
||||||
|
|
||||||
export default UI;
|
export default UI;
|
||||||
|
|||||||
Reference in New Issue
Block a user