90 lines
4.1 KiB
C#
90 lines
4.1 KiB
C#
using System.Collections.ObjectModel;
|
|
using Avalonia.Controls;
|
|
using Avalonia.Interactivity;
|
|
using Avalonia.Platform.Storage;
|
|
using CommunityToolkit.Mvvm.ComponentModel;
|
|
using LehrerApp.Templating;
|
|
using System.Runtime.Versioning;
|
|
|
|
namespace LehrerApp.TemplateDesigner;
|
|
|
|
public partial class PdfImportDialogViewModel : ObservableObject
|
|
{
|
|
[ObservableProperty] private string _examplePath = "";
|
|
[ObservableProperty] private string _templatePath = "";
|
|
[ObservableProperty] private bool _useAi = true;
|
|
[ObservableProperty] private string _username = "";
|
|
[ObservableProperty] private string _password = "";
|
|
[ObservableProperty] private string _status = "Bitte mindestens ein ausgefülltes Beispiel-PDF auswählen.";
|
|
[ObservableProperty] private bool _isBusy;
|
|
[ObservableProperty] private bool _hasResult;
|
|
public ObservableCollection<PdfImportCandidate> Candidates { get; } = [];
|
|
public IReadOnlyList<PlaceholderType> PlaceholderTypes { get; } =
|
|
[PlaceholderType.Text, PlaceholderType.Multiline, PlaceholderType.Date, PlaceholderType.Number];
|
|
public bool CanAnalyze => !IsBusy && File.Exists(ExamplePath) && (!UseAi
|
|
|| (!string.IsNullOrWhiteSpace(Username) && !string.IsNullOrWhiteSpace(Password)));
|
|
partial void OnExamplePathChanged(string value) => OnPropertyChanged(nameof(CanAnalyze));
|
|
partial void OnUseAiChanged(bool value) => OnPropertyChanged(nameof(CanAnalyze));
|
|
partial void OnUsernameChanged(string value) => OnPropertyChanged(nameof(CanAnalyze));
|
|
partial void OnPasswordChanged(string value) => OnPropertyChanged(nameof(CanAnalyze));
|
|
partial void OnIsBusyChanged(bool value) => OnPropertyChanged(nameof(CanAnalyze));
|
|
}
|
|
|
|
[SupportedOSPlatform("windows")]
|
|
[SupportedOSPlatform("linux")]
|
|
[SupportedOSPlatform("macos")]
|
|
public partial class PdfImportDialog : Window
|
|
{
|
|
private readonly PdfImportDialogViewModel _viewModel = new();
|
|
private PdfImportResult? _result;
|
|
public PdfImportResult? Result { get; private set; }
|
|
|
|
public PdfImportDialog() { InitializeComponent(); DataContext = _viewModel; }
|
|
|
|
private async void OnChooseExample(object? sender, RoutedEventArgs e)
|
|
{
|
|
var file = await ChoosePdf("Ausgefülltes Beispiel-PDF auswählen");
|
|
if (file is not null) _viewModel.ExamplePath = file;
|
|
}
|
|
|
|
private async void OnChooseTemplate(object? sender, RoutedEventArgs e)
|
|
{
|
|
var file = await ChoosePdf("Leeres Template-PDF auswählen");
|
|
if (file is not null) _viewModel.TemplatePath = file;
|
|
}
|
|
|
|
private async Task<string?> ChoosePdf(string title)
|
|
{
|
|
var files = await StorageProvider.OpenFilePickerAsync(new()
|
|
{ Title = title, AllowMultiple = false, FileTypeFilter = [new("PDF-Dateien") { Patterns = ["*.pdf"] }] });
|
|
return files.Count == 0 ? null : files[0].Path.LocalPath;
|
|
}
|
|
|
|
private async void OnAnalyze(object? sender, RoutedEventArgs e)
|
|
{
|
|
_viewModel.IsBusy = true; _viewModel.HasResult = false; _viewModel.Status = "PDF wird lokal analysiert …";
|
|
try
|
|
{
|
|
_result = await new PdfImportPipeline().BuildAsync(_viewModel.ExamplePath,
|
|
string.IsNullOrWhiteSpace(_viewModel.TemplatePath) ? null : _viewModel.TemplatePath,
|
|
_viewModel.UseAi ? _viewModel.Username : null, _viewModel.UseAi ? _viewModel.Password : null);
|
|
_viewModel.Candidates.Clear();
|
|
foreach (var candidate in _result.Candidates) _viewModel.Candidates.Add(candidate);
|
|
_viewModel.HasResult = true;
|
|
_viewModel.Status = $"{_viewModel.Candidates.Count} variable Textbereiche erkannt. Bitte Zuordnung prüfen und bestätigen.";
|
|
}
|
|
catch (Exception ex) { _viewModel.Status = $"Import fehlgeschlagen: {ex.Message}"; }
|
|
finally { _viewModel.IsBusy = false; }
|
|
}
|
|
|
|
private void OnAccept(object? sender, RoutedEventArgs e)
|
|
{
|
|
if (_result is null) return;
|
|
var document = new PdfImportPipeline().Extract(_viewModel.ExamplePath);
|
|
Result = new PdfImportPipeline().BuildResult(_viewModel.ExamplePath, document, _viewModel.Candidates);
|
|
Close(true);
|
|
}
|
|
|
|
private void OnCancel(object? sender, RoutedEventArgs e) => Close(false);
|
|
}
|