Rilascia strumenti avanzati e archivio 0.3.0
This commit is contained in:
1 parent
b19afbce91
commit
620a4bec26
8 files changed
+1351
-33
No files matched your search
+208
-4
@@ -211,6 +211,10 @@
|
||||
|
||||
<section class="panel-section">
|
||||
<h2>Disegni e misure</h2>
|
||||
<div class="button-row">
|
||||
<button class="secondary-command" @onclick="UndoMapChange">Annulla</button>
|
||||
<button class="secondary-command" @onclick="RedoMapChange">Ripristina</button>
|
||||
</div>
|
||||
<label class="toggle-line project-save-option">
|
||||
<input type="checkbox" @bind="ShowDrawingMeasurements" @bind:after="ApplyDrawingMeasurementsVisibility" />
|
||||
<span>Mostra superficie, perimetro e lati</span>
|
||||
@@ -219,6 +223,7 @@
|
||||
@(DrawToolsVisible ? "Nascondi strumenti sulla mappa" : "Mostra strumenti sulla mappa")
|
||||
</button>
|
||||
<button class="danger-command" @onclick="ClearDrawings">Elimina disegni e POI</button>
|
||||
<button class="secondary-command" @onclick="RestoreAutosave">Recupera ultimo autosalvataggio</button>
|
||||
</section>
|
||||
|
||||
<section class="panel-section">
|
||||
@@ -246,9 +251,15 @@
|
||||
<option value="geojson">GeoJSON</option>
|
||||
<option value="kml">KML</option>
|
||||
<option value="kmz">KMZ compresso</option>
|
||||
<option value="gpx">GPX per GPS</option>
|
||||
<option value="pdf">Rapporto PDF</option>
|
||||
</select>
|
||||
</label>
|
||||
<div class="export-options" role="group" aria-label="Oggetti da esportare">
|
||||
<label class="toggle-line project-save-option">
|
||||
<input type="checkbox" @bind="ExportSelectedOnly" @bind:after="SaveFlagPreferences" />
|
||||
<span>Solo oggetti selezionati nel pannello Layer</span>
|
||||
</label>
|
||||
<label class="toggle-line project-save-option">
|
||||
<input type="checkbox" @bind="ExportImported" @bind:after="SaveFlagPreferences" />
|
||||
<span>Particelle e dati GIS importati</span>
|
||||
@@ -306,7 +317,7 @@
|
||||
<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>
|
||||
<option value="@project.Id">@(project.IsArchived ? "[ARCHIVIATO] " : "")@(string.IsNullOrWhiteSpace(project.Folder) ? "" : $"{project.Folder} / ")@project.Name - @project.UpdatedAt.ToLocalTime().ToString("dd/MM/yyyy HH:mm")</option>
|
||||
}
|
||||
</select>
|
||||
</label>
|
||||
@@ -314,9 +325,44 @@
|
||||
<button @onclick="LoadProject" disabled="@(ProjectBusy || string.IsNullOrWhiteSpace(SelectedProjectId))">Apri</button>
|
||||
<button class="danger-command" @onclick="DeleteProject" disabled="@(ProjectBusy || string.IsNullOrWhiteSpace(SelectedProjectId))">Elimina</button>
|
||||
</div>
|
||||
<label>
|
||||
Cartella
|
||||
<input @bind="ProjectFolder" placeholder="Es. Cantieri 2026" maxlength="60" />
|
||||
</label>
|
||||
<div class="button-row">
|
||||
<button class="secondary-command" @onclick="UpdateProjectFolder" disabled="@(ProjectBusy || string.IsNullOrWhiteSpace(SelectedProjectId))">Sposta</button>
|
||||
<button class="secondary-command" @onclick="DuplicateProject" disabled="@(ProjectBusy || string.IsNullOrWhiteSpace(SelectedProjectId))">Duplica</button>
|
||||
</div>
|
||||
<div class="button-row">
|
||||
<button class="secondary-command" @onclick="ToggleProjectArchive" disabled="@(ProjectBusy || string.IsNullOrWhiteSpace(SelectedProjectId))">@(SelectedProject?.IsArchived == true ? "Ripristina" : "Archivia")</button>
|
||||
<button class="secondary-command" @onclick="ShareProject" disabled="@(ProjectBusy || string.IsNullOrWhiteSpace(SelectedProjectId))">Condividi</button>
|
||||
</div>
|
||||
<label>
|
||||
Revisione precedente
|
||||
<select @bind="SelectedVersionId" disabled="@(ProjectVersions.Count == 0)">
|
||||
<option value="">Seleziona revisione</option>
|
||||
@foreach (var version in ProjectVersions)
|
||||
{
|
||||
<option value="@version.Id">@version.UpdatedAt.ToLocalTime().ToString("dd/MM/yyyy HH:mm:ss")</option>
|
||||
}
|
||||
</select>
|
||||
</label>
|
||||
<div class="button-row">
|
||||
<button class="secondary-command" @onclick="LoadProjectVersion" disabled="@(string.IsNullOrWhiteSpace(SelectedVersionId))">Apri revisione</button>
|
||||
<button class="secondary-command" @onclick="CompareProjectVersion" disabled="@(string.IsNullOrWhiteSpace(SelectedVersionId))">Confronta</button>
|
||||
</div>
|
||||
<div class="project-archive-state">@ProjectArchiveMessage</div>
|
||||
</section>
|
||||
|
||||
<section class="panel-section">
|
||||
<h2>Backup e trasferimento</h2>
|
||||
<div class="button-row">
|
||||
<button class="secondary-command" @onclick="ShareFullBackup">Crea backup</button>
|
||||
<button class="secondary-command" @onclick="RestoreBackup">Ripristina backup</button>
|
||||
</div>
|
||||
<button class="secondary-command" @onclick="ImportProject">Importa progetto condiviso</button>
|
||||
</section>
|
||||
|
||||
<section class="panel-section">
|
||||
<h2>Visualizzazione progetto</h2>
|
||||
<label class="toggle-line project-save-option">
|
||||
@@ -353,6 +399,7 @@
|
||||
<option value="topographic">Topografica - Esri World Topographic</option>
|
||||
<option value="terrain">Terreno - OpenTopoMap</option>
|
||||
<option value="carto">Strade chiare - CARTO Voyager</option>
|
||||
<option value="offline">Offline - solo dati vettoriali</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>
|
||||
@@ -383,6 +430,22 @@
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="panel-section">
|
||||
<h2>Modifica e sicurezza dati</h2>
|
||||
<label class="toggle-line project-save-option">
|
||||
<input type="checkbox" @bind="AutoSaveEnabled" @bind:after="ApplyAdvancedOptions" />
|
||||
<span>Autosalvataggio locale dopo ogni modifica</span>
|
||||
</label>
|
||||
<label class="toggle-line project-save-option">
|
||||
<input type="checkbox" @bind="SnapEnabled" @bind:after="ApplyAdvancedOptions" />
|
||||
<span>Aggancia i vertici agli oggetti vicini</span>
|
||||
</label>
|
||||
<label>
|
||||
Distanza aggancio in pixel
|
||||
<input type="range" min="4" max="40" step="1" @bind="SnapDistancePixels" @bind:after="ApplyAdvancedOptions" />
|
||||
</label>
|
||||
</section>
|
||||
|
||||
<section class="panel-section">
|
||||
<h2>GPS e percorso</h2>
|
||||
<label class="toggle-line project-save-option">
|
||||
@@ -393,6 +456,15 @@
|
||||
<input type="checkbox" @bind="TrailEnabled" @bind:after="ApplyTrailOption" />
|
||||
<span>Registra la traccia mentre cammini</span>
|
||||
</label>
|
||||
<label class="toggle-line project-save-option">
|
||||
<input type="checkbox" @bind="GpsProximityEnabled" @bind:after="ApplyAdvancedOptions" />
|
||||
<span>Distanza e direzione dal bordo selezionato</span>
|
||||
</label>
|
||||
<label class="toggle-line project-save-option">
|
||||
<input type="checkbox" @bind="GpsBoundaryAlertEnabled" @bind:after="ApplyAdvancedOptions" />
|
||||
<span>Avvisa quando entro o esco dall'area selezionata</span>
|
||||
</label>
|
||||
<button class="secondary-command" @onclick="SaveGpsMeasurementPoint">Salva punto GPS con precisione e ora</button>
|
||||
</section>
|
||||
|
||||
<section class="panel-section">
|
||||
@@ -453,6 +525,8 @@
|
||||
private string PoiName { get; set; } = string.Empty;
|
||||
private string SelectedProjectId { get; set; } = string.Empty;
|
||||
private string ProjectArchiveMessage { get; set; } = "Nessun progetto salvato.";
|
||||
private string ProjectFolder { get; set; } = string.Empty;
|
||||
private string SelectedVersionId { get; set; } = string.Empty;
|
||||
private string Status { get; set; } = "online";
|
||||
private string SelectedBaseLayer { get; set; } = "satellite";
|
||||
private string GoogleMapsApiKey { get; set; } = string.Empty;
|
||||
@@ -486,6 +560,12 @@
|
||||
private bool ExportDrawings { get; set; } = true;
|
||||
private bool ExportPoi { get; set; } = true;
|
||||
private bool ExportTrail { get; set; } = true;
|
||||
private bool ExportSelectedOnly { get; set; }
|
||||
private bool AutoSaveEnabled { get; set; } = true;
|
||||
private bool SnapEnabled { get; set; } = true;
|
||||
private int SnapDistancePixels { get; set; } = 14;
|
||||
private bool GpsProximityEnabled { get; set; } = true;
|
||||
private bool GpsBoundaryAlertEnabled { get; set; }
|
||||
private CancellationTokenSource? CatalogCancellation { get; set; }
|
||||
private CancellationTokenSource? GpsLookupCancellation { get; set; }
|
||||
private long LastGpsLookupAt;
|
||||
@@ -496,6 +576,8 @@
|
||||
private IReadOnlyList<string> Sheets { get; set; } = [];
|
||||
private IReadOnlyList<ParcelOption> Parcels { get; set; } = [];
|
||||
private IReadOnlyList<MapProjectSummary> Projects { get; set; } = [];
|
||||
private IReadOnlyList<MapProjectVersion> ProjectVersions { get; set; } = [];
|
||||
private MapProjectSummary? SelectedProject => Projects.FirstOrDefault(item => item.Id == SelectedProjectId);
|
||||
|
||||
private MunicipalityOption? SelectedMunicipality =>
|
||||
Municipalities.FirstOrDefault(item => item.Code == SelectedMunicipalityCode);
|
||||
@@ -574,6 +656,7 @@
|
||||
MapCallbackReference = DotNetObjectReference.Create(this);
|
||||
await JS.InvokeVoidAsync("lmeMap.init", MapCallbackReference);
|
||||
await ApplyFlagPreferencesToMapAsync();
|
||||
await ApplyAdvancedOptions();
|
||||
await CenterOnInitialLocationAsync();
|
||||
await MigrateLegacyProjectAsync();
|
||||
}
|
||||
@@ -1097,10 +1180,105 @@
|
||||
}
|
||||
}
|
||||
|
||||
private Task SelectProject(ChangeEventArgs args)
|
||||
private async Task SelectProject(ChangeEventArgs args)
|
||||
{
|
||||
SelectedProjectId = args.Value?.ToString() ?? string.Empty;
|
||||
return Task.CompletedTask;
|
||||
ProjectFolder = SelectedProject?.Folder ?? string.Empty;
|
||||
SelectedVersionId = string.Empty;
|
||||
ProjectVersions = string.IsNullOrWhiteSpace(SelectedProjectId)
|
||||
? []
|
||||
: await ProjectStorageService.GetVersionsAsync(SelectedProjectId);
|
||||
}
|
||||
|
||||
private Task UndoMapChange() => JS.InvokeVoidAsync("lmeMap.undoMapChange").AsTask();
|
||||
private Task RedoMapChange() => JS.InvokeVoidAsync("lmeMap.redoMapChange").AsTask();
|
||||
private Task RestoreAutosave() => JS.InvokeVoidAsync("lmeMap.restoreAutosave").AsTask();
|
||||
private Task SaveGpsMeasurementPoint() => JS.InvokeVoidAsync("lmeMap.saveGpsMeasurementPoint").AsTask();
|
||||
|
||||
private async Task DuplicateProject()
|
||||
{
|
||||
if (SelectedProject is null) return;
|
||||
var copy = await ProjectStorageService.DuplicateAsync(SelectedProject.Id);
|
||||
await RefreshProjectsAsync();
|
||||
SelectedProjectId = copy.Id;
|
||||
ProjectFolder = copy.Folder;
|
||||
await JS.InvokeVoidAsync("lmeMap.showInfo", $"Progetto duplicato: {copy.Name}.");
|
||||
}
|
||||
|
||||
private async Task UpdateProjectFolder()
|
||||
{
|
||||
if (SelectedProject is null) return;
|
||||
await ProjectStorageService.UpdateOrganizationAsync(SelectedProject.Id, ProjectFolder);
|
||||
await RefreshProjectsAsync();
|
||||
await JS.InvokeVoidAsync("lmeMap.showInfo", "Cartella del progetto aggiornata.");
|
||||
}
|
||||
|
||||
private async Task ToggleProjectArchive()
|
||||
{
|
||||
if (SelectedProject is not { } project) return;
|
||||
await ProjectStorageService.UpdateOrganizationAsync(project.Id, isArchived: !project.IsArchived);
|
||||
await RefreshProjectsAsync();
|
||||
await JS.InvokeVoidAsync("lmeMap.showInfo", project.IsArchived ? "Progetto ripristinato." : "Progetto archiviato.");
|
||||
}
|
||||
|
||||
private async Task ShareProject()
|
||||
{
|
||||
if (SelectedProject is null) return;
|
||||
var path = await ProjectStorageService.CreateProjectPackageAsync(SelectedProject.Id);
|
||||
await Share.Default.RequestAsync(new ShareFileRequest { Title = "Condividi progetto LME", File = new ShareFile(path, "application/json") });
|
||||
}
|
||||
|
||||
private async Task ShareFullBackup()
|
||||
{
|
||||
var path = await ProjectStorageService.CreateBackupAsync();
|
||||
await Share.Default.RequestAsync(new ShareFileRequest { Title = "Backup completo LME Mappe Catastali", File = new ShareFile(path, "application/zip") });
|
||||
}
|
||||
|
||||
private async Task RestoreBackup()
|
||||
{
|
||||
var file = await FilePicker.Default.PickAsync(new PickOptions { PickerTitle = "Scegli backup LME" });
|
||||
if (file is null) return;
|
||||
var path = await CopyPickedFileToCacheAsync(file);
|
||||
var count = await ProjectStorageService.RestoreBackupAsync(path);
|
||||
await RefreshProjectsAsync();
|
||||
await JS.InvokeVoidAsync("lmeMap.showInfo", $"Backup ripristinato: {count} progetti disponibili.");
|
||||
}
|
||||
|
||||
private async Task ImportProject()
|
||||
{
|
||||
var file = await FilePicker.Default.PickAsync(new PickOptions { PickerTitle = "Scegli progetto LME" });
|
||||
if (file is null) return;
|
||||
var path = await CopyPickedFileToCacheAsync(file);
|
||||
var imported = await ProjectStorageService.ImportProjectAsync(path);
|
||||
await RefreshProjectsAsync();
|
||||
SelectedProjectId = imported.Id;
|
||||
await JS.InvokeVoidAsync("lmeMap.showInfo", $"Progetto importato: {imported.Name}.");
|
||||
}
|
||||
|
||||
private static async Task<string> CopyPickedFileToCacheAsync(FileResult file)
|
||||
{
|
||||
var path = Path.Combine(FileSystem.CacheDirectory, $"{Guid.NewGuid():N}-{file.FileName}");
|
||||
await using var input = await file.OpenReadAsync();
|
||||
await using var output = File.Create(path);
|
||||
await input.CopyToAsync(output);
|
||||
return path;
|
||||
}
|
||||
|
||||
private async Task LoadProjectVersion()
|
||||
{
|
||||
if (SelectedProject is null || string.IsNullOrWhiteSpace(SelectedVersionId)) return;
|
||||
var snapshot = await ProjectStorageService.LoadVersionAsync(SelectedProject.Id, SelectedVersionId);
|
||||
var options = await JS.InvokeAsync<ProjectDisplayOptions>("lmeMap.loadProjectSnapshot", snapshot, $"{SelectedProject.Name} - revisione");
|
||||
ApplyProjectDisplayOptions(options);
|
||||
ActiveTab = "map";
|
||||
}
|
||||
|
||||
private async Task CompareProjectVersion()
|
||||
{
|
||||
if (SelectedProject is null || string.IsNullOrWhiteSpace(SelectedVersionId)) return;
|
||||
var current = await ProjectStorageService.LoadAsync(SelectedProject.Id);
|
||||
var previous = await ProjectStorageService.LoadVersionAsync(SelectedProject.Id, SelectedVersionId);
|
||||
ProjectArchiveMessage = await JS.InvokeAsync<string>("lmeMap.compareProjectSnapshots", current, previous);
|
||||
}
|
||||
|
||||
private async Task ExportMapFile()
|
||||
@@ -1122,7 +1300,8 @@
|
||||
includeCadastral = ExportCadastral,
|
||||
includeDrawings = ExportDrawings,
|
||||
includePoi = ExportPoi,
|
||||
includeTrail = ExportTrail
|
||||
includeTrail = ExportTrail,
|
||||
selectedOnly = ExportSelectedOnly
|
||||
});
|
||||
var exported = await MapExportService.CreateAsync(ExportFileName, ExportFormat, geoJson);
|
||||
await Share.Default.RequestAsync(new ShareFileRequest
|
||||
@@ -1403,6 +1582,12 @@
|
||||
ExportDrawings = GetFlagPreference("export_drawings", true);
|
||||
ExportPoi = GetFlagPreference("export_poi", true);
|
||||
ExportTrail = GetFlagPreference("export_trail", true);
|
||||
ExportSelectedOnly = GetFlagPreference("export_selected_only", false);
|
||||
AutoSaveEnabled = GetFlagPreference("auto_save", true);
|
||||
SnapEnabled = GetFlagPreference("snap_enabled", true);
|
||||
SnapDistancePixels = Preferences.Default.Get($"{FlagPreferencePrefix}snap_distance", 14);
|
||||
GpsProximityEnabled = GetFlagPreference("gps_proximity", true);
|
||||
GpsBoundaryAlertEnabled = GetFlagPreference("gps_boundary_alert", false);
|
||||
|
||||
foreach (var layer in CadastralLayers)
|
||||
{
|
||||
@@ -1428,6 +1613,12 @@
|
||||
SetFlagPreference("export_drawings", ExportDrawings);
|
||||
SetFlagPreference("export_poi", ExportPoi);
|
||||
SetFlagPreference("export_trail", ExportTrail);
|
||||
SetFlagPreference("export_selected_only", ExportSelectedOnly);
|
||||
SetFlagPreference("auto_save", AutoSaveEnabled);
|
||||
SetFlagPreference("snap_enabled", SnapEnabled);
|
||||
Preferences.Default.Set($"{FlagPreferencePrefix}snap_distance", SnapDistancePixels);
|
||||
SetFlagPreference("gps_proximity", GpsProximityEnabled);
|
||||
SetFlagPreference("gps_boundary_alert", GpsBoundaryAlertEnabled);
|
||||
|
||||
foreach (var layer in CadastralLayers)
|
||||
{
|
||||
@@ -1453,6 +1644,19 @@
|
||||
}
|
||||
}
|
||||
|
||||
private async Task ApplyAdvancedOptions()
|
||||
{
|
||||
SaveFlagPreferences();
|
||||
await JS.InvokeVoidAsync("lmeMap.setAdvancedOptions", new
|
||||
{
|
||||
autoSaveEnabled = AutoSaveEnabled,
|
||||
snapEnabled = SnapEnabled,
|
||||
snapDistancePixels = SnapDistancePixels,
|
||||
gpsProximityEnabled = GpsProximityEnabled,
|
||||
gpsBoundaryAlertEnabled = GpsBoundaryAlertEnabled
|
||||
});
|
||||
}
|
||||
|
||||
private static bool GetFlagPreference(string name, bool defaultValue) =>
|
||||
Preferences.Default.Get($"{FlagPreferencePrefix}{name}", defaultValue);
|
||||
|
||||
|
||||
Reference in new issue
Block a user