Reorganize map tools and improve KML sheet filtering

This commit is contained in:
livio committed 2026-09-21 11:01:12 +02:00
1 parent c8b8f21d8d
commit 7933b2e86a
6 files changed
+331 -173

No files matched your search

+157 -119
View File
@@ -72,6 +72,16 @@
<button class="gps-center" @onclick="CenterOnGps" aria-label="Centra posizione">Centra</button>
</div>
@if ((ActiveTab is "map" or "search") && !LayerPanelOpen)
{
<div class="map-measure-tools @(ActiveTab == "search" ? "search-open" : null)" aria-label="Strumenti rapidi di misura">
<span>Misura</span>
<button title="Disegna e misura un'area" @onclick='() => StartMeasurementDrawing("area")'>Area</button>
<button title="Disegna e misura una distanza" @onclick='() => StartMeasurementDrawing("distance")'>Distanza</button>
<button title="Disegna e misura un cerchio" @onclick='() => StartMeasurementDrawing("circle")'>Cerchio</button>
</div>
}
@if (ActiveTab is not "map" and not "search")
{
<aside class="tool-sheet">
@@ -149,130 +159,155 @@
</div>
</section>
}
else if (ActiveTab == "data")
{
<section class="panel-content">
<section class="panel-section">
<h2>File GIS</h2>
<label class="file-picker">
<span>Carica KML, KMZ o GeoJSON</span>
<input id="gisFileInput" type="file" accept=".kml,.kmz,.geojson,.json,application/vnd.google-earth.kml+xml,application/vnd.google-earth.kmz,application/geo+json" />
</label>
<label class="toggle-line project-save-option">
<input type="checkbox" checked="@IncludeKmlSheetLayer" @onchange="ToggleKmlSheetLayer" />
<span>KML/KMZ: includi anche il layer del foglio</span>
</label>
<small class="field-help">
@(IncludeKmlSheetLayer
? "Attivato: importa foglio, particelle e altri elementi KML/KMZ."
: "Disattivato: importa solo i poligoni delle particelle riconosciute.")
</small>
<label class="toggle-line project-save-option">
<input type="checkbox" checked="@ShowImportedMeasurements" @onchange="ToggleImportedMeasurements" />
<span>Mostra misure dei file caricati</span>
</label>
<div class="button-row">
<button @onclick="FitImportedLayers">Inquadra dati</button>
<button class="secondary-command" @onclick="ClearImportedLayers">Rimuovi dati</button>
</div>
</section>
<section class="panel-section">
<h2>Disegni e misure</h2>
<label class="toggle-line project-save-option">
<input type="checkbox" checked="@ShowDrawingMeasurements" @onchange="ToggleDrawingMeasurements" />
<span>Mostra superficie, perimetro e lati</span>
</label>
<button class="secondary-command" aria-pressed="@DrawToolsVisible" @onclick="ToggleDrawTools">
@(DrawToolsVisible ? "Nascondi barra completa" : "Mostra barra completa")
</button>
<button class="danger-command" @onclick="ClearDrawings">Elimina disegni e POI</button>
</section>
<section class="panel-section">
<h2>Punti di interesse</h2>
<label>
Nome POI
<input @bind="PoiName" @bind:event="oninput" placeholder="Nome del punto" />
</label>
<button class="primary-command" @onclick="AddProjectMarker">Aggiungi POI al centro mappa</button>
</section>
</section>
}
else if (ActiveTab == "projects")
{
<section class="panel-content">
<h2>File GIS</h2>
<label class="file-picker">
<span>Carica KML, KMZ o GeoJSON</span>
<input id="gisFileInput" type="file" accept=".kml,.kmz,.geojson,.json,application/vnd.google-earth.kml+xml,application/vnd.google-earth.kmz,application/geo+json" />
</label>
<label class="toggle-line project-save-option">
<input type="checkbox" checked="@ImportParcelsOnly" @onchange="ToggleImportParcelsOnly" />
<span>KML/KMZ: importa solo le particelle</span>
</label>
<label class="toggle-line project-save-option">
<input type="checkbox" checked="@ShowImportedMeasurements" @onchange="ToggleImportedMeasurements" />
<span>Mostra misure dei file caricati</span>
</label>
<div class="button-row">
<button @onclick="FitImportedLayers">Inquadra</button>
<button class="secondary-command" @onclick="ClearImportedLayers">Pulisci</button>
</div>
<section class="panel-section">
<h2>Salva progetto</h2>
<label>
Nome progetto
<input @bind="NewProjectName" @bind:event="oninput" placeholder="Es. Rilievo San Nicola" maxlength="80" />
</label>
<label class="toggle-line project-save-option">
<input type="checkbox" @bind="IncludeCadastralParcels" />
<span>Includi le particelle catastali rosse</span>
</label>
<button class="primary-command" @onclick="SaveProject" disabled="@(ProjectBusy || string.IsNullOrWhiteSpace(NewProjectName))">Salva progetto</button>
</section>
<h2>Archivio progetti</h2>
<label>
Nome progetto
<input @bind="NewProjectName" @bind:event="oninput" placeholder="Es. Rilievo San Nicola" maxlength="80" />
</label>
<label class="toggle-line project-save-option">
<input type="checkbox" @bind="IncludeCadastralParcels" />
<span>Includi le particelle catastali rosse</span>
</label>
<button class="primary-command" @onclick="SaveProject" disabled="@(ProjectBusy || string.IsNullOrWhiteSpace(NewProjectName))">Salva progetto</button>
<label>
Progetto salvato
<select value="@SelectedProjectId" @onchange="SelectProject" disabled="@(Projects.Count == 0 || ProjectBusy)">
<option value="">Seleziona un progetto</option>
@foreach (var project in Projects)
{
<option value="@project.Id">@project.Name - @project.UpdatedAt.ToLocalTime().ToString("dd/MM/yyyy HH:mm")</option>
}
</select>
</label>
<div class="button-row">
<button @onclick="LoadProject" disabled="@(ProjectBusy || string.IsNullOrWhiteSpace(SelectedProjectId))">Carica</button>
<button class="danger-command" @onclick="DeleteProject" disabled="@(ProjectBusy || string.IsNullOrWhiteSpace(SelectedProjectId))">Elimina</button>
</div>
<div class="project-archive-state">@ProjectArchiveMessage</div>
<h2>Misura e disegna</h2>
<div class="measurement-mode-grid" aria-label="Strumenti di misura">
<button @onclick='() => StartMeasurementDrawing("area")'>Area</button>
<button @onclick='() => StartMeasurementDrawing("distance")'>Distanza</button>
<button @onclick='() => StartMeasurementDrawing("circle")'>Cerchio</button>
</div>
<label class="toggle-line project-save-option">
<input type="checkbox" checked="@ShowDrawingMeasurements" @onchange="ToggleDrawingMeasurements" />
<span>Mostra superficie, perimetro e lati</span>
</label>
<button class="secondary-command" aria-pressed="@DrawToolsVisible" @onclick="ToggleDrawTools">
@(DrawToolsVisible ? "Nascondi strumenti completi" : "Mostra strumenti completi")
</button>
<h2>POI</h2>
<label>
Nome POI
<input @bind="PoiName" @bind:event="oninput" placeholder="Nome del punto" />
</label>
<button class="primary-command" @onclick="AddProjectMarker">Aggiungi POI al centro mappa</button>
<button class="danger-command" @onclick="ClearDrawings">Elimina disegni e POI</button>
<section class="panel-section">
<h2>Apri progetto</h2>
<label>
Progetto salvato
<select value="@SelectedProjectId" @onchange="SelectProject" disabled="@(Projects.Count == 0 || ProjectBusy)">
<option value="">Seleziona un progetto</option>
@foreach (var project in Projects)
{
<option value="@project.Id">@project.Name - @project.UpdatedAt.ToLocalTime().ToString("dd/MM/yyyy HH:mm")</option>
}
</select>
</label>
<div class="button-row">
<button @onclick="LoadProject" disabled="@(ProjectBusy || string.IsNullOrWhiteSpace(SelectedProjectId))">Apri</button>
<button class="danger-command" @onclick="DeleteProject" disabled="@(ProjectBusy || string.IsNullOrWhiteSpace(SelectedProjectId))">Elimina</button>
</div>
<div class="project-archive-state">@ProjectArchiveMessage</div>
</section>
</section>
}
else if (ActiveTab == "settings")
{
<section class="panel-content">
<h2>Visualizzazione</h2>
<label>
Sfondo
<select value="@SelectedBaseLayer" @onchange="ChangeBaseLayer">
<option value="satellite">Satellite - Esri World Imagery</option>
<option value="osm">Strade - OpenStreetMap</option>
<option value="streets-esri">Strade dettagliate - Esri World Street Map</option>
<option value="topographic">Topografica - Esri World Topographic</option>
<option value="terrain">Terreno - OpenTopoMap</option>
<option value="carto">Strade chiare - CARTO Voyager</option>
<option value="azure-road">Strade - Azure Maps</option>
<option value="azure-satellite">Satellite - Azure Maps</option>
<option value="google-satellite">Satellite - Google Maps</option>
<option value="google-roadmap">Strade - Google Maps</option>
</select>
</label>
<label>
Chiave Google Maps Platform
<input type="password" @bind="GoogleMapsApiKey" placeholder="API key" autocomplete="off" />
</label>
<button class="secondary-command" @onclick="SaveGoogleMapsApiKey">Salva chiave Google</button>
<label>
Chiave sottoscrizione Azure Maps Gen2
<input type="password" @bind="AzureMapsSubscriptionKey" placeholder="Subscription key" autocomplete="off" />
</label>
<button class="secondary-command" @onclick="SaveAzureMapsKey">Salva chiave Azure Maps</button>
<div class="service-note">
<strong>Quota gratuita Azure Maps Gen2</strong>
<p>Include ogni mese 5.000 transazioni per le mappe stradali e 1.000 per le immagini satellitari. Ogni transazione comprende fino a 15 tessere.</p>
</div>
<label>
Trasparenza catasto
<input type="range" min="0" max="1" step="0.05" value="0.75" @onchange="ChangeCadastreOpacity" />
</label>
<h2>GPS e percorso</h2>
<label class="toggle-line">
<input type="checkbox" checked="@TrailEnabled" @onchange="ToggleTrail" />
Registra la traccia mentre cammini
</label>
<section class="panel-section">
<h2>Mappa e sfondo</h2>
<label>
Sfondo
<select value="@SelectedBaseLayer" @onchange="ChangeBaseLayer">
<option value="satellite">Satellite - Esri World Imagery</option>
<option value="osm">Strade - OpenStreetMap</option>
<option value="streets-esri">Strade dettagliate - Esri World Street Map</option>
<option value="topographic">Topografica - Esri World Topographic</option>
<option value="terrain">Terreno - OpenTopoMap</option>
<option value="carto">Strade chiare - CARTO Voyager</option>
<option value="azure-road">Strade - Azure Maps</option>
<option value="azure-satellite">Satellite - Azure Maps</option>
<option value="google-satellite">Satellite - Google Maps</option>
<option value="google-roadmap">Strade - Google Maps</option>
</select>
</label>
<label>
Trasparenza catasto
<input type="range" min="0" max="1" step="0.05" value="0.75" @onchange="ChangeCadastreOpacity" />
</label>
</section>
<h2>Servizi Agenzia delle Entrate</h2>
<div class="service-note protected-service">
<strong>Download documenti e fogli ufficiali</strong>
<p>Il CAPTCHA o l'accesso SPID/CIE vengono gestiti direttamente dal sito dell'Agenzia. Per sicurezza l'app non tenta di aggirarli.</p>
<button class="primary-command" @onclick="OpenOfficialGeoportal">Apri Geoportale catastale</button>
<button class="secondary-command" @onclick="OpenOfficialReservedArea">Apri Area riservata per download</button>
</div>
<section class="panel-section">
<h2>Servizi mappa con chiave</h2>
<label>
Chiave Google Maps Platform
<input type="password" @bind="GoogleMapsApiKey" placeholder="API key" autocomplete="off" />
</label>
<button class="secondary-command" @onclick="SaveGoogleMapsApiKey">Salva chiave Google</button>
<label>
Chiave sottoscrizione Azure Maps Gen2
<input type="password" @bind="AzureMapsSubscriptionKey" placeholder="Subscription key" autocomplete="off" />
</label>
<button class="secondary-command" @onclick="SaveAzureMapsKey">Salva chiave Azure Maps</button>
<div class="service-note">
<strong>Quota gratuita Azure Maps Gen2</strong>
<p>Include ogni mese 5.000 transazioni per le mappe stradali e 1.000 per le immagini satellitari. Ogni transazione comprende fino a 15 tessere.</p>
</div>
</section>
<button class="secondary-command" @onclick="ExportCadastralImage">Mostra vista WMS corrente</button>
<footer>Dati catastali: Agenzia delle Entrate, licenza CC BY 4.0. App indipendente.</footer>
<section class="panel-section">
<h2>GPS e percorso</h2>
<label class="toggle-line project-save-option">
<input type="checkbox" checked="@TrailEnabled" @onchange="ToggleTrail" />
<span>Registra la traccia mentre cammini</span>
</label>
</section>
<section class="panel-section">
<h2>Servizi Agenzia delle Entrate</h2>
<div class="service-note protected-service">
<strong>Download documenti e fogli ufficiali</strong>
<p>Il CAPTCHA o l'accesso SPID/CIE vengono gestiti direttamente dal sito dell'Agenzia. Per sicurezza l'app non tenta di aggirarli.</p>
<button class="primary-command" @onclick="OpenOfficialGeoportal">Apri Geoportale catastale</button>
<button class="secondary-command" @onclick="OpenOfficialReservedArea">Apri Area riservata per download</button>
</div>
<button class="secondary-command" @onclick="ExportCadastralImage">Mostra vista WMS corrente</button>
<footer>Dati catastali: Agenzia delle Entrate, licenza CC BY 4.0. App indipendente.</footer>
</section>
</section>
}
</aside>
@@ -302,6 +337,7 @@
<nav class="bottom-tabs" aria-label="Sezioni principali">
<button class="@(ActiveTab == "map" || ActiveTab == "search" ? "active" : null)" @onclick='() => SelectTab("map")'>Mappa</button>
<button class="@(ActiveTab == "cadastre" ? "active" : null)" @onclick='() => SelectTab("cadastre")'>Catasto</button>
<button class="@(ActiveTab == "data" ? "active" : null)" @onclick='() => SelectTab("data")'>Dati</button>
<button class="@(ActiveTab == "projects" ? "active" : null)" @onclick='() => SelectTab("projects")'>Progetti</button>
<button class="@(ActiveTab == "settings" ? "active" : null)" @onclick='() => SelectTab("settings")'>Impostazioni</button>
</nav>
@@ -331,7 +367,7 @@
private bool TrailEnabled { get; set; }
private bool LayerPanelOpen { get; set; }
private bool IncludeCadastralParcels { get; set; } = true;
private bool ImportParcelsOnly { get; set; } = true;
private bool IncludeKmlSheetLayer { get; set; }
private bool ShowImportedMeasurements { get; set; }
private bool ShowDrawingMeasurements { get; set; } = true;
private bool ProjectBusy { get; set; }
@@ -355,7 +391,8 @@
private string PanelTitle => ActiveTab switch
{
"cadastre" => "Ricerca catastale",
"projects" => "Progetti e dati",
"data" => "Dati e disegni",
"projects" => "Archivio progetti",
"settings" => "Impostazioni",
_ => string.Empty
};
@@ -363,7 +400,8 @@
private string PanelEyebrow => ActiveTab switch
{
"cadastre" => "Regione, Comune, Foglio, Particella",
"projects" => "KML, KMZ, GeoJSON e POI",
"data" => "File GIS, misure e POI",
"projects" => "Salva e apri i tuoi lavori",
"settings" => "Mappa, GPS e servizi ufficiali",
_ => string.Empty
};
@@ -751,10 +789,10 @@
private Task ClearImportedLayers() => JS.InvokeVoidAsync("lmeMap.clearImported").AsTask();
private Task AddProjectMarker() => JS.InvokeVoidAsync("lmeMap.addProjectMarker", PoiName).AsTask();
private async Task ToggleImportParcelsOnly(ChangeEventArgs args)
private async Task ToggleKmlSheetLayer(ChangeEventArgs args)
{
ImportParcelsOnly = (bool?)args.Value == true;
await JS.InvokeVoidAsync("lmeMap.setImportParcelOnly", ImportParcelsOnly);
IncludeKmlSheetLayer = (bool?)args.Value == true;
await JS.InvokeVoidAsync("lmeMap.setIncludeKmlSheetLayer", IncludeKmlSheetLayer);
}
private async Task ToggleImportedMeasurements(ChangeEventArgs args)