WIP checkpoint - working on UI.

This commit is contained in:
Gino Canessa 2024-07-16 17:01:48 -05:00
Родитель 59d5e27ed4
Коммит 516fb0fd84
11 изменённых файлов: 248 добавлений и 33 удалений

Просмотреть файл

@ -1,25 +1,55 @@
<Application xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="fhir_codegen.App"
xmlns:themes="clr-namespace:Material.Styles.Themes;assembly=Material.Styles"
xmlns:materialIcons="clr-namespace:Material.Icons.Avalonia;assembly=Material.Icons.Avalonia"
xmlns:local="using:fhir_codegen"
RequestedThemeVariant="Dark">
<!-- "Default" ThemeVariant follows system theme variant. "Dark" or "Light" are other available options. -->
<Application.Styles>
<FluentTheme />
<!--<FluentTheme />-->
<themes:MaterialTheme BaseTheme="Dark" PrimaryColor="Indigo" SecondaryColor="Green" />
<StyleInclude Source="avares://Avalonia.Controls.DataGrid/Themes/Fluent.xaml"/>
<StyleInclude Source="avares://fhir-codegen/Icons.axaml" />
<Style Selector="Label">
<Setter Property="Margin" Value="8"/>
</Style>
<Style Selector="TextBox">
<materialIcons:MaterialIconStyles />
<Style Selector="AutoCompleteBox">
<Setter Property="Margin" Value="8"/>
<Setter Property="Width" Value="400"/>
</Style>
<Style Selector="Button">
<Setter Property="Margin" Value="8"/>
</Style>
<Style Selector="Button.cgIconButton">
<Setter Property="Margin" Value="8"/>
<Setter Property="Width" Value="32"/>
<Setter Property="Height" Value="32"/>
<Setter Property="Foreground" Value="White"/>
<Setter Property="Background" Value="Indigo"/>
</Style>
<Style Selector="ComboBox">
<Setter Property="Margin" Value="8"/>
<Setter Property="Width" Value="400"/>
</Style>
<Style Selector="DataGrid">
<Setter Property="Margin" Value="8"/>
</Style>
<Style Selector="Label">
<Setter Property="Margin" Value="8"/>
</Style>
<!--<Style Selector="Grid">
<Style Selector="^:Grid.RowDefinition">
<Setter Property="Height" Value="48"/>
</Style>
</Style>-->
<Style Selector="TextBox">
<Setter Property="Margin" Value="8"/>
<Setter Property="Width" Value="200"/>
</Style>
</Application.Styles>
<Application.DataTemplates>
<local:ViewLocator />
</Application.DataTemplates>
</Application>

Просмотреть файл

@ -1,9 +1,11 @@
using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Controls.Templates;
using Avalonia.Markup.Xaml;
using fhir_codegen.ViewModels;
using fhir_codegen.Views;
using Splat;
namespace fhir_codegen;

Просмотреть файл

@ -27,7 +27,12 @@ internal class Gui
try
{
RunningConfiguration = config;
BuildAvaloniaApp().StartWithClassicDesktopLifetime([]);
BuildAvaloniaApp().StartWithClassicDesktopLifetime([], Avalonia.Controls.ShutdownMode.OnMainWindowClose);
}
catch (System.Collections.Generic.KeyNotFoundException)
{
// This is a known issue with Avalonia and Material
return 0;
}
catch (Exception ex)
{

Просмотреть файл

@ -5,26 +5,131 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Media;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using Hl7.Fhir.Utility;
using Material.Icons;
using Microsoft.Health.Fhir.CodeGen._ForPackages;
using Microsoft.Health.Fhir.CodeGen.Configuration;
namespace fhir_codegen.ViewModels;
public partial class CoreComparisonViewModel : ViewModelBase, INavigableViewModel
{
public static string Label => "Compare FHIR Releases";
public static StreamGeometry? IconGeometry => (Application.Current?.TryGetResource("book_question_mark_regular", out object? icon) ?? false) && icon is StreamGeometry sg
? sg
: null;
public static MaterialIconKind IconKind => MaterialIconKind.Compare;
//public static StreamGeometry? IconGeometry => (Application.Current?.TryGetResource("book_question_mark_regular", out object? icon) ?? false) && icon is StreamGeometry sg
// ? sg
// : null;
[ObservableProperty]
private string _sourcePackageDirective = "";
private string _header = "Compare FHIR Core Releases";
[ObservableProperty]
private string _targetPackageDirective = "";
private string? _errorMessage = null;
[ObservableProperty]
private bool _processing = false;
[ObservableProperty]
private bool _onlyReleaseVersions = true;
partial void OnOnlyReleaseVersionsChanged(bool value)
{
CorePackages = value ? _releasedCorePackages : _allCorePackages;
}
[ObservableProperty]
private string _crossVersionDirectory = "git/fhir-cross-version";
[ObservableProperty]
private int _sourceIndex = 0;
[ObservableProperty]
private int _targetIndex = 0;
[ObservableProperty]
private List<string> _corePackages = [];
private List<string> _releasedCorePackages = [];
private List<string> _allCorePackages = [];
private static readonly Regex _corePackageRegex = new Regex("^hl7\\.fhir\\.r\\d+[A-Za-z]?\\.(core)$", RegexOptions.Compiled);
private static readonly HashSet<string> _releaseVersions = [ "1.0.2", "3.0.2", "4.0.1", "4.3.0", "5.0.0", ];
public CoreComparisonViewModel()
{
// get the current configuration
ConfigGui? config = Gui.RunningConfiguration;
if (config == null)
{
throw new InvalidOperationException("No configuration found");
}
DiskPackageCache cache = new(config.FhirCacheDirectory);
// first, we need to get the installed package references
IEnumerable<Firely.Fhir.Packages.PackageReference> internalReferences = cache.GetPackageReferences().Result;
// iterate over the internal references and convert them to the public references
foreach (Firely.Fhir.Packages.PackageReference pr in internalReferences)
{
if (string.IsNullOrEmpty(pr.Name) || string.IsNullOrEmpty(pr.Version))
{
continue;
}
if (!_corePackageRegex.IsMatch(pr.Name))
{
continue;
}
if (_releaseVersions.Contains(pr.Version))
{
_releasedCorePackages.Add(pr.Moniker);
}
_allCorePackages.Add(pr.Moniker);
}
CorePackages = _onlyReleaseVersions ? _releasedCorePackages : _allCorePackages;
}
[RelayCommand]
private void RunComparison()
{
if (Processing == true)
{
return;
}
Processing = true;
ErrorMessage = null;
if (SourceIndex == TargetIndex)
{
ErrorMessage = "Source and target cannot be the same";
Processing = false;
return;
}
ConfigCompare compareOptions = new()
{
Packages = [ CorePackages[SourceIndex] ],
ComparePackages = [ CorePackages[TargetIndex] ],
CrossVersionMapSourcePath = CrossVersionDirectory,
MapSaveStyle = ConfigCompare.ComparisonMapSaveStyle.None,
NoOutput = true,
};
}
}

Просмотреть файл

@ -10,6 +10,8 @@ using System.Text;
using System.Threading.Tasks;
using Avalonia.Controls;
using Avalonia.Media;
using Material.Icons;
using Material.Icons.Avalonia;
namespace fhir_codegen.ViewModels;
@ -17,5 +19,5 @@ internal interface INavigableViewModel
{
public static string Label { get; } = " - ";
public static StreamGeometry? IconGeometry { get; }
public static MaterialIconKind IconKind { get; }
}

Просмотреть файл

@ -13,6 +13,7 @@ using Avalonia.Media;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using fhir_codegen.Views;
using Material.Icons;
namespace fhir_codegen.ViewModels;
@ -23,7 +24,7 @@ public partial class MainWindowViewModel : ViewModelBase
private bool _isPaneOpen;
[ObservableProperty]
private UserControl _currentPage = new WelcomePageView();
private ViewModelBase _currentPage = new WelcomePageViewModel();
[ObservableProperty]
private NavigationItemTemplate? _selectedNavigationItem;
@ -35,7 +36,7 @@ public partial class MainWindowViewModel : ViewModelBase
return;
}
UserControl? target = (UserControl?)Activator.CreateInstance(value.Target);
ViewModelBase? target = (ViewModelBase?)Activator.CreateInstance(value.Target);
if (target == null)
{
@ -50,15 +51,15 @@ public partial class MainWindowViewModel : ViewModelBase
{
new NavigationItemTemplate
{
Target = typeof(WelcomePageView),
Target = typeof(WelcomePageViewModel),
Label = WelcomePageViewModel.Label,
IconGeometry = WelcomePageViewModel.IconGeometry,
IconKind = WelcomePageViewModel.IconKind,
},
new NavigationItemTemplate
{
Target = typeof(CoreComparisonView),
Target = typeof(CoreComparisonViewModel),
Label = CoreComparisonViewModel.Label,
IconGeometry = CoreComparisonViewModel.IconGeometry,
IconKind = CoreComparisonViewModel.IconKind,
},
};
@ -75,5 +76,5 @@ public class NavigationItemTemplate
public required string Label { get; init; }
public required StreamGeometry? IconGeometry { get; init; }
public required MaterialIconKind IconKind { get; init; }
}

Просмотреть файл

@ -14,6 +14,7 @@ using Avalonia;
using Avalonia.Controls;
using Avalonia.Media;
using CommunityToolkit.Mvvm.ComponentModel;
using Material.Icons;
using Microsoft.Health.Fhir.CodeGen._ForPackages;
using Microsoft.Health.Fhir.CodeGen.Configuration;
using static Microsoft.Health.Fhir.CodeGen._ForPackages.DiskPackageCache;
@ -39,9 +40,10 @@ public partial class WelcomePageViewModel : ViewModelBase, INavigableViewModel
}
public static string Label => "Home";
public static StreamGeometry? IconGeometry => (Application.Current?.TryGetResource("home_regular", out object? icon) ?? false) && icon is StreamGeometry sg
? sg
: null;
public static MaterialIconKind IconKind => MaterialIconKind.Home;
//public static StreamGeometry? IconGeometry => (Application.Current?.TryGetResource("home_regular", out object? icon) ?? false) && icon is StreamGeometry sg
// ? sg
// : null;
[ObservableProperty]
private string _header = "FHIR Codegen - FHIR Cache Contents";
@ -103,11 +105,11 @@ public partial class WelcomePageViewModel : ViewModelBase, INavigableViewModel
DiskPackageCache cache = new(config.FhirCacheDirectory);
List<InstalledPackageInfoRecord> installedPackages = new();
// first, we need to get the installed package references
IEnumerable<Firely.Fhir.Packages.PackageReference> internalReferences = cache.GetPackageReferences().Result;
List<InstalledPackageInfoRecord> installedPackages = new();
// iterate over the internal references and convert them to the public references
foreach (Firely.Fhir.Packages.PackageReference pr in internalReferences)
{

Просмотреть файл

@ -6,5 +6,71 @@
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="fhir_codegen.Views.CoreComparisonView"
x:DataType="vm:CoreComparisonViewModel">
Welcome to Avalonia!
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="40"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<StackPanel Orientation="Vertical" Grid.Row="0">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Label Grid.Column="0" Content="{Binding Header}" VerticalAlignment="Center"/>
<!--<StackPanel Grid.Column="2" Orientation="Horizontal" HorizontalAlignment="Right">
<Label Content="Moniker Filter:" VerticalAlignment="Center"/>
<TextBox Text="{Binding TableFilter, Mode=TwoWay}" VerticalAlignment="Center" Width="200" />
</StackPanel>-->
</Grid>
</StackPanel>
<TabControl Grid.Row="1">
<TabItem Header="Configuration">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="200"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="64" /> <!-- ReleasesOnly -->
<RowDefinition Height="64" /> <!-- SourcePackage -->
<RowDefinition Height="64" /> <!-- RowTargetPacakge -->
<RowDefinition Height="64" /> <!-- RowRunComparison -->
<RowDefinition Height="64" /> <!-- RowErrorMessage -->
<RowDefinition Height="64" /> <!-- RowSourceMaps -->
</Grid.RowDefinitions>
<CheckBox Grid.Row="0" Grid.Column="1" IsChecked="{Binding OnlyReleaseVersions}">Only Show Official Releases</CheckBox>
<Label Grid.Row="1" Grid.Column="0" Content="Source (left) Package:" VerticalAlignment="Center"/>
<ComboBox Grid.Row="1" Grid.Column="1" SelectedIndex="{Binding SourceIndex}" ItemsSource="{Binding CorePackages}"/>
<Label Grid.Row="2" Grid.Column="0" Content="Target (right) Package:" VerticalAlignment="Center"/>
<ComboBox Grid.Row="2" Grid.Column="1" SelectedIndex="{Binding TargetIndex}" ItemsSource="{Binding CorePackages}"/>
<StackPanel Grid.Row="3" Grid.Column="1" Orientation="Horizontal">
<Button Content="Run Comparison" Command="{Binding RunComparisonCommand}" />
<!--<ProgressBar Classes="Circle"/>-->
</StackPanel>
<Label Grid.Row="4" Grid.Column="1" Content="{Binding ErrorMessage}" Foreground="Red" />
<Label Grid.Row="5" Grid.Column="0" Content="Map source path"/>
<TextBox Grid.Row="5" Grid.Column="1" Text="{Binding CrossVersionDirectory}" />
</Grid>
</TabItem>
<TabItem Header="Results">
</TabItem>
</TabControl>
</Grid>
</UserControl>

Просмотреть файл

@ -3,6 +3,7 @@
xmlns:vm="using:fhir_codegen.ViewModels"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:materialIcons="clr-namespace:Material.Icons.Avalonia;assembly=Material.Icons.Avalonia"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="fhir_codegen.Views.MainWindow"
x:DataType="vm:MainWindowViewModel"
@ -27,12 +28,9 @@
HorizontalAlignment="Stretch"
VerticalAlignment="Top">
<Button HorizontalAlignment="Left"
Width="32"
Height="32"
Margin="8 8"
Background="Transparent"
Command="{Binding TriggerPaneCommand}">
<PathIcon Data="{StaticResource line_horizontal_3_regular}" />
Command="{Binding TriggerPaneCommand}"
Content="{materialIcons:MaterialIconExt Kind=Menu}"
Classes="cgIconButton">
</Button>
<ListBox ItemsSource="{Binding NavigationItems}"
@ -40,7 +38,7 @@
<ListBox.ItemTemplate>
<DataTemplate DataType="{x:Type vm:NavigationItemTemplate}">
<StackPanel Spacing="12" Margin="4 4" Orientation="Horizontal">
<PathIcon Data="{Binding IconGeometry}" />
<materialIcons:MaterialIcon Kind="{Binding IconKind}" Classes="cgInlineIcon" />
<TextBlock Text="{Binding Label}" />
</StackPanel>
</DataTemplate>

Просмотреть файл

@ -19,7 +19,7 @@
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="40"/>
<RowDefinition Height="64" />
<RowDefinition Height="*"/>
</Grid.RowDefinitions>

Просмотреть файл

@ -29,6 +29,10 @@
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.2.2" />
<PackageReference Include="Firely.Fhir.Packages" Version="4.6.0" />
<PackageReference Include="Hl7.Fhir.R5" Version="5.8.2" />
<PackageReference Include="Material.Avalonia" Version="3.6.0" />
<PackageReference Include="Material.Avalonia.DataGrid" Version="3.6.0" />
<PackageReference Include="Material.Avalonia.Dialogs" Version="3.6.0" />
<PackageReference Include="Material.Icons.Avalonia" Version="2.1.10" />
<PackageReference Include="Microsoft.Extensions.Configuration" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="8.0.0" />