postit: add mapsui location picker to rdv form
This commit is contained in:
parent
7dd3821175
commit
91e78a1270
6 changed files with 114 additions and 1 deletions
|
|
@ -16,6 +16,8 @@
|
||||||
<PackageVersion Include="Avalonia.Headless" Version="$(AvaloniaVersionBase)" />
|
<PackageVersion Include="Avalonia.Headless" Version="$(AvaloniaVersionBase)" />
|
||||||
<PackageVersion Include="Avalonia.Headless.Xunit" Version="$(AvaloniaVersionBase)" />
|
<PackageVersion Include="Avalonia.Headless.Xunit" Version="$(AvaloniaVersionBase)" />
|
||||||
<PackageVersion Include="Avalonia.Fonts.Inter" Version="$(AvaloniaVersionBase)" />
|
<PackageVersion Include="Avalonia.Fonts.Inter" Version="$(AvaloniaVersionBase)" />
|
||||||
|
<PackageVersion Include="Mapsui" Version="5.1.0" />
|
||||||
|
<PackageVersion Include="Mapsui.Avalonia12" Version="5.1.0" />
|
||||||
|
|
||||||
<PackageVersion Include="Material.Avalonia" Version="3.19.0" />
|
<PackageVersion Include="Material.Avalonia" Version="3.19.0" />
|
||||||
<PackageVersion Include="AvaloniaUI.DiagnosticsSupport" Version="2.2.3" />
|
<PackageVersion Include="AvaloniaUI.DiagnosticsSupport" Version="2.2.3" />
|
||||||
|
|
|
||||||
|
|
@ -115,6 +115,26 @@ public class BillingCommandPageViewModelTests
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ApplyLocationFromMap_sets_coordinates_and_updates_status()
|
||||||
|
{
|
||||||
|
var api = new RecordingApi();
|
||||||
|
var client = new BillingApiClient(api, "https://business.example/api/v1/");
|
||||||
|
var vm =
|
||||||
|
new CommandFormSummary { Id = 12, ActionName = "Rdv", Title = "Rendez-vous" }
|
||||||
|
.CreateCommandPageViewModel(
|
||||||
|
new ActivityInfo { Code = "dev", Name = "Développement" },
|
||||||
|
new ActivityUserDisplayItem { PerformerId = "perf-1", UserName = "Alice" },
|
||||||
|
client) as RdvViewModel;
|
||||||
|
|
||||||
|
vm!.Address = string.Empty;
|
||||||
|
vm.ApplyLocationFromMap(48.85661234, 2.35224567);
|
||||||
|
|
||||||
|
Assert.Equal(48.856612, vm.Latitude);
|
||||||
|
Assert.Equal(2.352246, vm.Longitude);
|
||||||
|
Assert.Contains("Position sélectionnée", vm.StatusMessage, StringComparison.OrdinalIgnoreCase);
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task InitializeAsync_loads_prestations_for_brush_and_submit_posts_selected_prestation()
|
public async Task InitializeAsync_loads_prestations_for_brush_and_submit_posts_selected_prestation()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,8 @@
|
||||||
<IncludeAssets Condition="'$(Configuration)' != 'Debug'">None</IncludeAssets>
|
<IncludeAssets Condition="'$(Configuration)' != 'Debug'">None</IncludeAssets>
|
||||||
<PrivateAssets Condition="'$(Configuration)' != 'Debug'">All</PrivateAssets>
|
<PrivateAssets Condition="'$(Configuration)' != 'Debug'">All</PrivateAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
|
<PackageReference Include="Mapsui" />
|
||||||
|
<PackageReference Include="Mapsui.Avalonia12" />
|
||||||
<PackageReference Include="CommunityToolkit.Mvvm" />
|
<PackageReference Include="CommunityToolkit.Mvvm" />
|
||||||
<PackageReference Include="IdentityModel.OidcClient" />
|
<PackageReference Include="IdentityModel.OidcClient" />
|
||||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" />
|
<PackageReference Include="Microsoft.Extensions.DependencyInjection" />
|
||||||
|
|
|
||||||
|
|
@ -113,6 +113,20 @@ public partial class RdvViewModel : BillingCommandPageViewModel
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void ApplyLocationFromMap(double latitude, double longitude)
|
||||||
|
{
|
||||||
|
Latitude = Math.Round(latitude, 6);
|
||||||
|
Longitude = Math.Round(longitude, 6);
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(Address))
|
||||||
|
{
|
||||||
|
this.SetInfoStatus("Position sélectionnée sur la carte. Complétez l'adresse puis envoyez la commande.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.SetInfoStatus("Position sélectionnée sur la carte.");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
protected override async Task SubmitAsync()
|
protected override async Task SubmitAsync()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,13 @@
|
||||||
<ContentPage xmlns="https://github.com/avaloniaui"
|
<ContentPage xmlns="https://github.com/avaloniaui"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:cvm="using:PostIt.ViewModels.Commands"
|
xmlns:cvm="using:PostIt.ViewModels.Commands"
|
||||||
|
xmlns:mapsui="using:Mapsui.UI.Avalonia"
|
||||||
xmlns:postitControls="using:PostIt.Controls"
|
xmlns:postitControls="using:PostIt.Controls"
|
||||||
x:Class="PostIt.Views.Commands.RdvPage"
|
x:Class="PostIt.Views.Commands.RdvPage"
|
||||||
x:DataType="cvm:RdvViewModel"
|
x:DataType="cvm:RdvViewModel"
|
||||||
Header="Commande billing">
|
Header="Commande billing">
|
||||||
<ScrollViewer>
|
<ScrollViewer>
|
||||||
<Grid RowDefinitions="Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto" ColumnDefinitions="Auto,*" Margin="12">
|
<Grid RowDefinitions="Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto" ColumnDefinitions="Auto,*" Margin="12">
|
||||||
<TextBlock Grid.Row="0" Grid.ColumnSpan="2"
|
<TextBlock Grid.Row="0" Grid.ColumnSpan="2"
|
||||||
Text="{Binding Title}"
|
Text="{Binding Title}"
|
||||||
FontSize="18"
|
FontSize="18"
|
||||||
|
|
@ -52,6 +53,15 @@
|
||||||
<TextBlock Grid.Row="9" Text="Longitude" VerticalAlignment="Center" Margin="0,0,12,8" />
|
<TextBlock Grid.Row="9" Text="Longitude" VerticalAlignment="Center" Margin="0,0,12,8" />
|
||||||
<TextBox Grid.Row="9" Grid.Column="1" Text="{Binding Longitude, Mode=TwoWay}" PlaceholderText="Optionnel" Margin="0,0,0,8" />
|
<TextBox Grid.Row="9" Grid.Column="1" Text="{Binding Longitude, Mode=TwoWay}" PlaceholderText="Optionnel" Margin="0,0,0,8" />
|
||||||
|
|
||||||
|
<TextBlock Grid.Row="10" Grid.ColumnSpan="2"
|
||||||
|
Text="Carte: cliquez pour positionner le rendez-vous"
|
||||||
|
Margin="0,0,0,8"
|
||||||
|
Opacity="0.85" />
|
||||||
|
<mapsui:MapControl Grid.Row="11"
|
||||||
|
Grid.ColumnSpan="2"
|
||||||
|
x:Name="LocationMap"
|
||||||
|
Height="260"
|
||||||
|
Margin="0,0,0,8" />
|
||||||
|
|
||||||
<TextBlock Grid.Row="12"
|
<TextBlock Grid.Row="12"
|
||||||
Text="Informations"
|
Text="Informations"
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,82 @@
|
||||||
using Avalonia.Controls;
|
using Avalonia.Controls;
|
||||||
using Avalonia.Markup.Xaml;
|
using Avalonia.Markup.Xaml;
|
||||||
|
using Mapsui;
|
||||||
|
using Mapsui.Projections;
|
||||||
|
using Mapsui.Tiling;
|
||||||
|
using Mapsui.UI.Avalonia;
|
||||||
|
using PostIt.ViewModels.Commands;
|
||||||
|
|
||||||
namespace PostIt.Views.Commands;
|
namespace PostIt.Views.Commands;
|
||||||
|
|
||||||
public partial class RdvPage : ContentPage
|
public partial class RdvPage : ContentPage
|
||||||
{
|
{
|
||||||
|
private MapControl? _locationMap;
|
||||||
|
|
||||||
public RdvPage()
|
public RdvPage()
|
||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
|
InitializeMap();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void InitializeComponent()
|
private void InitializeComponent()
|
||||||
{
|
{
|
||||||
AvaloniaXamlLoader.Load(this);
|
AvaloniaXamlLoader.Load(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void InitializeMap()
|
||||||
|
{
|
||||||
|
_locationMap = this.FindControl<MapControl>("LocationMap");
|
||||||
|
if (_locationMap is null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var map = new Map();
|
||||||
|
map.Layers.Add(OpenStreetMap.CreateTileLayer());
|
||||||
|
_locationMap.Map = map;
|
||||||
|
_locationMap.MapTapped += OnMapTapped;
|
||||||
|
|
||||||
|
DataContextChanged += OnDataContextChanged;
|
||||||
|
CenterFromViewModel();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnDataContextChanged(object? sender, System.EventArgs e)
|
||||||
|
{
|
||||||
|
CenterFromViewModel();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnMapTapped(object? sender, MapEventArgs e)
|
||||||
|
{
|
||||||
|
if (DataContext is not RdvViewModel vm)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var (longitude, latitude) = SphericalMercator.ToLonLat(e.WorldPosition.X, e.WorldPosition.Y);
|
||||||
|
vm.ApplyLocationFromMap(latitude, longitude);
|
||||||
|
CenterMap(latitude, longitude, zoomLevel: 13);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CenterFromViewModel()
|
||||||
|
{
|
||||||
|
if (DataContext is not RdvViewModel vm)
|
||||||
|
{
|
||||||
|
CenterMap(48.8566, 2.3522, zoomLevel: 4);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vm.Latitude.HasValue && vm.Longitude.HasValue)
|
||||||
|
{
|
||||||
|
CenterMap(vm.Latitude.Value, vm.Longitude.Value, zoomLevel: 13);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
CenterMap(48.8566, 2.3522, zoomLevel: 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CenterMap(double latitude, double longitude, int zoomLevel)
|
||||||
|
{
|
||||||
|
if (_locationMap?.Map is null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var (x, y) = SphericalMercator.FromLonLat(longitude, latitude);
|
||||||
|
_locationMap.Map.Navigator.CenterOn(x, y);
|
||||||
|
_locationMap.Map.Navigator.ZoomToLevel(zoomLevel);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue