Add: SearchWindow with Id and string search
This commit is contained in:
		
							
								
								
									
										
											BIN
										
									
								
								PrototypWPFHAG/Images/pdf-icon.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								PrototypWPFHAG/Images/pdf-icon.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 10 KiB  | 
@@ -42,7 +42,7 @@ public partial class MainWindow : MetroWindow
 | 
			
		||||
            con.Open();
 | 
			
		||||
 | 
			
		||||
            // Check for correct UserName
 | 
			
		||||
            string userQuery = "SELECT COUNT(*) FROM \"User\" WHERE \"UserName\" = @username";
 | 
			
		||||
            string userQuery = "SELECT COUNT(*) FROM \"users\" WHERE \"username\" = @username";
 | 
			
		||||
            using (NpgsqlCommand userCmd = new NpgsqlCommand(userQuery, con))
 | 
			
		||||
            {
 | 
			
		||||
                userCmd.Parameters.AddWithValue("@username", username);
 | 
			
		||||
@@ -55,7 +55,7 @@ public partial class MainWindow : MetroWindow
 | 
			
		||||
            }
 | 
			
		||||
            
 | 
			
		||||
            // Check for correct Password
 | 
			
		||||
            string pwQuery = "SELECT COUNT(*) FROM \"User\" WHERE \"UserName\" = @username AND \"Password\" = @password";
 | 
			
		||||
            string pwQuery = "SELECT COUNT(*) FROM \"users\" WHERE \"username\" = @username AND \"password\" = @password";
 | 
			
		||||
            using (NpgsqlCommand pwCmd = new NpgsqlCommand(pwQuery, con))
 | 
			
		||||
            {
 | 
			
		||||
                pwCmd.Parameters.AddWithValue("@username", username);
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										52
									
								
								PrototypWPFHAG/PdfServiceClient.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								PrototypWPFHAG/PdfServiceClient.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,52 @@
 | 
			
		||||
using System.Net.Http;
 | 
			
		||||
using System.Text.Json;
 | 
			
		||||
using System.Text.Json.Serialization;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
 | 
			
		||||
public class DocumentResponse
 | 
			
		||||
{
 | 
			
		||||
    [JsonPropertyName("documents")]  // Konsistent mit Such-Endpoint
 | 
			
		||||
    public List<SearchResult> Documents { get; set; }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
public class PdfServiceClient
 | 
			
		||||
{
 | 
			
		||||
    private readonly HttpClient _httpClient;
 | 
			
		||||
    private const string BaseUrl = "http://localhost:8000"; // Microservice-URL
 | 
			
		||||
 | 
			
		||||
    public PdfServiceClient()
 | 
			
		||||
    {
 | 
			
		||||
        _httpClient = new HttpClient
 | 
			
		||||
        {
 | 
			
		||||
            BaseAddress = new Uri(BaseUrl), Timeout = TimeSpan.FromSeconds(30)
 | 
			
		||||
        };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public async Task<string> GetDocumentContentAsync(int documentId)
 | 
			
		||||
    {
 | 
			
		||||
        var response = await _httpClient.GetAsync($"{BaseUrl}/documents/{documentId}/markdown");
 | 
			
		||||
        response.EnsureSuccessStatusCode();
 | 
			
		||||
        var json = await response.Content.ReadAsStringAsync();
 | 
			
		||||
        var result = JsonSerializer.Deserialize<JsonElement>(json);
 | 
			
		||||
        return result.GetProperty("content").GetString();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public async Task<List<SearchResult>> SearchDocumentsAsync(string query)
 | 
			
		||||
    {
 | 
			
		||||
        var response = await _httpClient.GetAsync($"{BaseUrl}/documents/search?query={query}");
 | 
			
		||||
        response.EnsureSuccessStatusCode();
 | 
			
		||||
        var json = await response.Content.ReadAsStringAsync();
 | 
			
		||||
        return JsonSerializer.Deserialize<List<SearchResult>>(json);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
public class SearchResult
 | 
			
		||||
{
 | 
			
		||||
    [JsonPropertyName("id")]
 | 
			
		||||
    public int Id { get; set; }
 | 
			
		||||
 | 
			
		||||
    [JsonPropertyName("filename")]
 | 
			
		||||
    public string Filename { get; set; }
 | 
			
		||||
    [JsonPropertyName("content")]
 | 
			
		||||
    public string Content { get; set; }
 | 
			
		||||
}
 | 
			
		||||
@@ -14,6 +14,7 @@
 | 
			
		||||
 | 
			
		||||
  <ItemGroup>
 | 
			
		||||
    <None Remove="Images\databaseicon.png" />
 | 
			
		||||
    <None Remove="Images\pdf-icon.png" />
 | 
			
		||||
  </ItemGroup>
 | 
			
		||||
 | 
			
		||||
  <ItemGroup>
 | 
			
		||||
@@ -31,4 +32,8 @@
 | 
			
		||||
    <PackageReference Include="SixLabors.ImageSharp" Version="3.1.7" />
 | 
			
		||||
  </ItemGroup>
 | 
			
		||||
 | 
			
		||||
  <ItemGroup>
 | 
			
		||||
    <Resource Include="Images\pdf-icon.png" />
 | 
			
		||||
  </ItemGroup>
 | 
			
		||||
 | 
			
		||||
</Project>
 | 
			
		||||
 
 | 
			
		||||
@@ -1,69 +1,204 @@
 | 
			
		||||
<Window x:Class="PrototypWPFHAG.SearchWindow"
 | 
			
		||||
<mah:MetroWindow xmlns:mah="http://metro.mahapps.com/winfx/xaml/controls"
 | 
			
		||||
        x:Class="PrototypWPFHAG.SearchWindow"
 | 
			
		||||
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 | 
			
		||||
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
 | 
			
		||||
        xmlns:local="clr-namespace:PrototypWPFHAG"
 | 
			
		||||
        Title="Such Fenster" Height="600" Width="800">
 | 
			
		||||
        Title="PDF-Verwaltung (Admin)" Height="600" Width="1000"
 | 
			
		||||
        WindowTitleBrush="FireBrick"
 | 
			
		||||
        Icon="pack://application:,,,/Images/databaseicon.png">
 | 
			
		||||
    <Grid>
 | 
			
		||||
        <!-- 左侧垂直布局 -->
 | 
			
		||||
        <Grid.ColumnDefinitions>
 | 
			
		||||
            <ColumnDefinition Width="200"/>
 | 
			
		||||
            <ColumnDefinition Width="56.527"/>
 | 
			
		||||
            <ColumnDefinition Width="143.473"/>
 | 
			
		||||
            <!-- 左侧固定宽度 -->
 | 
			
		||||
            <ColumnDefinition Width="*"/>
 | 
			
		||||
            <!-- 右侧占满剩余空间 -->
 | 
			
		||||
        </Grid.ColumnDefinitions>
 | 
			
		||||
 | 
			
		||||
        <!-- 左侧区域 -->
 | 
			
		||||
        <StackPanel Orientation="Vertical" Margin="10">
 | 
			
		||||
            <Grid Margin="0,0,0,10">
 | 
			
		||||
        <Border 
 | 
			
		||||
            BorderBrush="FireBrick" 
 | 
			
		||||
            BorderThickness="3" Padding="20" 
 | 
			
		||||
            Grid.ColumnSpan="3"
 | 
			
		||||
        />
 | 
			
		||||
        
 | 
			
		||||
        <StackPanel 
 | 
			
		||||
            Orientation="Vertical" 
 | 
			
		||||
            Margin="10,10,772,10" 
 | 
			
		||||
            Grid.ColumnSpan="3">
 | 
			
		||||
            <Grid 
 | 
			
		||||
                    Margin="0,0,0,10" 
 | 
			
		||||
                    Height="85">
 | 
			
		||||
                <Grid.ColumnDefinitions>
 | 
			
		||||
                    <ColumnDefinition Width="*"/>
 | 
			
		||||
                    <ColumnDefinition Width="Auto"/>
 | 
			
		||||
                    <ColumnDefinition 
 | 
			
		||||
                            Width="*"
 | 
			
		||||
                        />
 | 
			
		||||
                    <ColumnDefinition 
 | 
			
		||||
                            Width="Auto"
 | 
			
		||||
                        />
 | 
			
		||||
                </Grid.ColumnDefinitions>
 | 
			
		||||
                <Grid.RowDefinitions>
 | 
			
		||||
                    <RowDefinition Height="Auto"/>
 | 
			
		||||
                    <RowDefinition Height="Auto"/>
 | 
			
		||||
                    <RowDefinition 
 | 
			
		||||
                           Height="Auto"
 | 
			
		||||
                    />
 | 
			
		||||
                    <RowDefinition 
 | 
			
		||||
                        Height="Auto"
 | 
			
		||||
                    />
 | 
			
		||||
                </Grid.RowDefinitions>
 | 
			
		||||
                <TextBox x:Name="TextField" Grid.Row="0" Height="50" VerticalContentAlignment="Center" Margin="0,0,5,0"/>
 | 
			
		||||
                <Border Grid.Row="0" Grid.Column="1" Background="LightGray" Height="50" Margin="5,0,0,0">
 | 
			
		||||
                    <TextBlock Text="Bild hochladen" VerticalAlignment="Center" HorizontalAlignment="Center"/>
 | 
			
		||||
 | 
			
		||||
                <Border 
 | 
			
		||||
                    BorderBrush="Gray" 
 | 
			
		||||
                    BorderThickness="1" 
 | 
			
		||||
                    Margin="5,10,0,-85" Grid.Row="1">
 | 
			
		||||
                    <Canvas   
 | 
			
		||||
                        x:Name="PdfDropCanvas"
 | 
			
		||||
                        Margin="5,0,0,-24" 
 | 
			
		||||
                        Grid.RowSpan="2"
 | 
			
		||||
                        AllowDrop="True"
 | 
			
		||||
                        Background="Transparent"
 | 
			
		||||
                        DragEnter="PdfDropCanvas_DragEnter"
 | 
			
		||||
                        Drop="PdfDropCanvas_Drop">
 | 
			
		||||
 | 
			
		||||
                        <TextBlock
 | 
			
		||||
                            x:Name="DropHintText"
 | 
			
		||||
                            Text="PDF hier rein ziehen"
 | 
			
		||||
                            HorizontalAlignment="Center"
 | 
			
		||||
                            VerticalAlignment="Center"
 | 
			
		||||
                            Foreground="Gray"
 | 
			
		||||
                        />
 | 
			
		||||
 | 
			
		||||
                        <!-- Vorschau-Elemente (unsichtbar, bis eine Datei abgelegt wird) -->
 | 
			
		||||
                        <Image 
 | 
			
		||||
                            x:Name="PdfIcon" 
 | 
			
		||||
                            Source="pack://application:,,,/Images/pdf-icon.png" 
 | 
			
		||||
                            Width="25" Height="25" 
 | 
			
		||||
                            Margin="0,5,0,0"
 | 
			
		||||
                            Visibility="Collapsed"
 | 
			
		||||
                        />
 | 
			
		||||
                        <TextBlock 
 | 
			
		||||
                            x:Name="PdfFileNameText" 
 | 
			
		||||
                            Margin="40,10,0,0" 
 | 
			
		||||
                            Visibility="Collapsed"
 | 
			
		||||
                        />
 | 
			
		||||
                    </Canvas>
 | 
			
		||||
                </Border>
 | 
			
		||||
                <Line Grid.Row="0" Grid.Column="1" X1="0" Y1="25" X2="1" Y2="25" Stroke="Black" StrokeThickness="1" Margin="5,0,0,0"/>
 | 
			
		||||
                <Button Content="Suchen" Width="180" Height="30" Grid.Row="1" Grid.ColumnSpan="2" HorizontalAlignment="Right" Margin="0,5,0,0"/>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
            </Grid>
 | 
			
		||||
 | 
			
		||||
            <!-- PDFField -->
 | 
			
		||||
            <Grid Margin="0,0,0,10">
 | 
			
		||||
                <Grid.ColumnDefinitions>
 | 
			
		||||
                    <ColumnDefinition Width="*"/>
 | 
			
		||||
                    <ColumnDefinition Width="Auto"/>
 | 
			
		||||
                    <ColumnDefinition 
 | 
			
		||||
                        Width="*"
 | 
			
		||||
                    />
 | 
			
		||||
                    <ColumnDefinition 
 | 
			
		||||
                        Width="Auto"
 | 
			
		||||
                    />
 | 
			
		||||
                </Grid.ColumnDefinitions>
 | 
			
		||||
                <Border Background="LightGray" Height="30" Margin="0,0,0,0" Grid.Column="0">
 | 
			
		||||
                    <TextBlock Text="PDF hochladen" VerticalAlignment="Center" HorizontalAlignment="Center" RenderTransformOrigin="0.514,5.613"/>
 | 
			
		||||
                </Border>
 | 
			
		||||
                <Button Content="ADD" Width="60" Height="30" Grid.Column="1" Margin="5,0,0,0"/>
 | 
			
		||||
                <Button 
 | 
			
		||||
                    Content="PDF hochladen" 
 | 
			
		||||
                    Width="auto" Height="30" 
 | 
			
		||||
                    Margin="5,0,0,0" 
 | 
			
		||||
                    Background="LightGreen"
 | 
			
		||||
                    Click="UploadButton_Click"
 | 
			
		||||
                />
 | 
			
		||||
 | 
			
		||||
            </Grid>
 | 
			
		||||
            <Button Content="Zurück " Margin="5,380" Click="BackToLogIn_Click"/>
 | 
			
		||||
 | 
			
		||||
            <StackPanel Orientation="Horizontal" Margin="5,10">
 | 
			
		||||
                <RadioButton x:Name="SearchByIdRadio" Content="ID" IsChecked="True"/>
 | 
			
		||||
                <RadioButton x:Name="SearchByTextRadio" Content="Text" Margin="10,0"/>
 | 
			
		||||
            </StackPanel>
 | 
			
		||||
 | 
			
		||||
            <TextBox 
 | 
			
		||||
                x:Name="SearchTextBox"
 | 
			
		||||
                Margin="5,0,0,0"
 | 
			
		||||
            />
 | 
			
		||||
 | 
			
		||||
            <Button 
 | 
			
		||||
                Content="Suchen" 
 | 
			
		||||
                x:Name="SearchButton" 
 | 
			
		||||
                Click="SearchButton_Click" 
 | 
			
		||||
                Margin="5,10,0,10"
 | 
			
		||||
            />
 | 
			
		||||
 | 
			
		||||
            <!-- ListField -->
 | 
			
		||||
            <ListBox 
 | 
			
		||||
                x:Name="SearchResultsListBox" 
 | 
			
		||||
                DisplayMemberPath="Filename"
 | 
			
		||||
                Margin="5,0,0,0" 
 | 
			
		||||
                ItemsSource="{Binding}"
 | 
			
		||||
                SelectionMode="Extended"
 | 
			
		||||
                SelectionChanged="SearchResultsListBox_SelectionChanged"
 | 
			
		||||
            />
 | 
			
		||||
 | 
			
		||||
            <TextBlock 
 | 
			
		||||
                x:Name="UploadStatusText" 
 | 
			
		||||
                TextAlignment="Center" Margin="0,35,0,35" Height="27"
 | 
			
		||||
            />
 | 
			
		||||
 | 
			
		||||
            <ProgressBar 
 | 
			
		||||
                x:Name="UploadProgressBar" 
 | 
			
		||||
                Height="10" 
 | 
			
		||||
                Minimum="0" Maximum="100"
 | 
			
		||||
                Visibility="Collapsed"
 | 
			
		||||
                Margin="0,20,0,0"
 | 
			
		||||
            />
 | 
			
		||||
            
 | 
			
		||||
            <Button 
 | 
			
		||||
                Content="Zurück zur Anmeldung" 
 | 
			
		||||
                Click="BackToLogIn_Click"
 | 
			
		||||
                Margin="5,10,0,0"
 | 
			
		||||
                Height="30"
 | 
			
		||||
                Background="#ffd64f"
 | 
			
		||||
            />
 | 
			
		||||
 | 
			
		||||
        </StackPanel>
 | 
			
		||||
 | 
			
		||||
        <!-- 右侧区域 -->
 | 
			
		||||
        <Grid Grid.Column="1" Margin="10">
 | 
			
		||||
            <Label Content="Zeugnisse:" HorizontalAlignment="Left" Margin="0,2,0,8"/>
 | 
			
		||||
            <!-- ListField -->
 | 
			
		||||
            <ListBox x:Name="ListField" Margin="0,29,0,35" BorderThickness="1" BorderBrush="Black">
 | 
			
		||||
                <ListBox.ItemTemplate>
 | 
			
		||||
                    <DataTemplate>
 | 
			
		||||
                        <StackPanel Orientation="Vertical">
 | 
			
		||||
                            <!-- 内容 -->
 | 
			
		||||
                            <TextBlock Text="{Binding}" VerticalAlignment="Center" HorizontalAlignment="Stretch" Padding="5"/>
 | 
			
		||||
                            <!-- 分隔线 -->
 | 
			
		||||
                            <Border Height="1" Background="Black" Margin="0,2,0,2"/>
 | 
			
		||||
                        </StackPanel>
 | 
			
		||||
                    </DataTemplate>
 | 
			
		||||
                </ListBox.ItemTemplate>
 | 
			
		||||
            </ListBox>
 | 
			
		||||
        <Grid 
 | 
			
		||||
            Grid.Column="2" 
 | 
			
		||||
            Margin="60,10,10,10">
 | 
			
		||||
 | 
			
		||||
            <Label 
 | 
			
		||||
                Content="PDF-Inhalt:" 
 | 
			
		||||
                HorizontalAlignment="Left" 
 | 
			
		||||
                Margin="0,2,0,8"
 | 
			
		||||
            />
 | 
			
		||||
 | 
			
		||||
            <ScrollViewer 
 | 
			
		||||
                x:Name="ContentScrollViewer" 
 | 
			
		||||
                Margin="0,0,0,35"
 | 
			
		||||
                VerticalScrollBarVisibility="Auto"
 | 
			
		||||
                HorizontalScrollBarVisibility="Auto">
 | 
			
		||||
 | 
			
		||||
                <TextBox 
 | 
			
		||||
                    x:Name="ContentTextBox" 
 | 
			
		||||
                    Text="{Binding SelectedDocument.Content}"
 | 
			
		||||
                    IsReadOnly="True"
 | 
			
		||||
                    TextWrapping="Wrap"
 | 
			
		||||
                    AcceptsReturn="True"
 | 
			
		||||
                    VerticalScrollBarVisibility="Auto"
 | 
			
		||||
                    HorizontalScrollBarVisibility="Auto"
 | 
			
		||||
                    Margin="5,25, 0, 35"
 | 
			
		||||
                    Height="Auto"
 | 
			
		||||
                    MinHeight="494"
 | 
			
		||||
                />
 | 
			
		||||
 | 
			
		||||
            </ScrollViewer>
 | 
			
		||||
 | 
			
		||||
            <!-- 删除按钮 -->
 | 
			
		||||
            <Button Content="Löschen" Width="100" Height="30" HorizontalAlignment="Right" VerticalAlignment="Bottom"/>
 | 
			
		||||
            <Button 
 | 
			
		||||
                Content="Löschen" 
 | 
			
		||||
                Width="100" 
 | 
			
		||||
                Height="30" 
 | 
			
		||||
                HorizontalAlignment="Right" 
 | 
			
		||||
                VerticalAlignment="Bottom" 
 | 
			
		||||
                Background="Firebrick"
 | 
			
		||||
                Click="DeleteButton_Click"
 | 
			
		||||
            />
 | 
			
		||||
        </Grid>
 | 
			
		||||
    </Grid>
 | 
			
		||||
</Window>
 | 
			
		||||
</mah:MetroWindow>
 | 
			
		||||
@@ -1,27 +1,42 @@
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using MahApps.Metro.Controls;
 | 
			
		||||
using System.Diagnostics;
 | 
			
		||||
using System.IO;
 | 
			
		||||
using System.Net;
 | 
			
		||||
using System.Net.Http;
 | 
			
		||||
using System.Text;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
using System.Text.Json;
 | 
			
		||||
using System.Text.Json.Serialization;
 | 
			
		||||
using System.Web;
 | 
			
		||||
using System.Windows;
 | 
			
		||||
using System.Windows.Controls;
 | 
			
		||||
using System.Windows.Data;
 | 
			
		||||
using System.Windows.Documents;
 | 
			
		||||
using System.Windows.Input;
 | 
			
		||||
using System.Windows.Media;
 | 
			
		||||
using System.Windows.Media.Imaging;
 | 
			
		||||
using System.Windows.Shapes;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
namespace PrototypWPFHAG
 | 
			
		||||
{
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// Interaktionslogik für SearchWindow.xaml
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public partial class SearchWindow : Window
 | 
			
		||||
    
 | 
			
		||||
    public class DocumentResponse
 | 
			
		||||
    {
 | 
			
		||||
        [JsonPropertyName("documents")]
 | 
			
		||||
        public List<SearchResult> Documents {  get; set; }
 | 
			
		||||
    }
 | 
			
		||||
    public partial class SearchWindow : MetroWindow
 | 
			
		||||
    {
 | 
			
		||||
        public readonly HttpClient _httpClient;
 | 
			
		||||
        private bool _isSearchInProgress;
 | 
			
		||||
        private readonly PdfServiceClient _pdfServiceClient = new();
 | 
			
		||||
        private const string BaseUrl = "http://localhost:8000"; // Microservice-URL
 | 
			
		||||
        private string _selectedPdfPath;
 | 
			
		||||
        public SearchWindow()
 | 
			
		||||
        {
 | 
			
		||||
            InitializeComponent();
 | 
			
		||||
            _httpClient = new HttpClient
 | 
			
		||||
            {
 | 
			
		||||
                BaseAddress = new Uri(BaseUrl),
 | 
			
		||||
                Timeout = TimeSpan.FromSeconds(30)
 | 
			
		||||
            };
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void BackToLogIn_Click(object sender, RoutedEventArgs e)
 | 
			
		||||
@@ -30,5 +45,353 @@ namespace PrototypWPFHAG
 | 
			
		||||
                loginWindow.Show(); // Open new window
 | 
			
		||||
                this.Close(); // Close this window
 | 
			
		||||
        }
 | 
			
		||||
        private async void SearchButton_Click(object sender, RoutedEventArgs e)
 | 
			
		||||
        {
 | 
			
		||||
            if (_isSearchInProgress) return;
 | 
			
		||||
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                _isSearchInProgress = true;
 | 
			
		||||
                SearchButton.IsEnabled = false;
 | 
			
		||||
 | 
			
		||||
                if (SearchByIdRadio.IsChecked == true)
 | 
			
		||||
                {
 | 
			
		||||
                    await SearchByIdAsync();
 | 
			
		||||
                }
 | 
			
		||||
                else
 | 
			
		||||
                {
 | 
			
		||||
                    await SearchByTextAsync();
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            catch (Exception ex)
 | 
			
		||||
            {
 | 
			
		||||
                MessageBox.Show($"Fehler bei der Suche: {ex.Message}",
 | 
			
		||||
                              "Fehler",
 | 
			
		||||
                              MessageBoxButton.OK,
 | 
			
		||||
                              MessageBoxImage.Error);
 | 
			
		||||
            }
 | 
			
		||||
            finally
 | 
			
		||||
            {
 | 
			
		||||
                _isSearchInProgress = false;
 | 
			
		||||
                SearchButton.IsEnabled = true;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        private async Task SearchByIdAsync()
 | 
			
		||||
        {
 | 
			
		||||
            if (!int.TryParse(SearchTextBox.Text, out int documentId))
 | 
			
		||||
            {
 | 
			
		||||
                MessageBox.Show("Bitte eine gültige ID eingeben");
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                var response = await _httpClient.GetAsync($"/documents/by-id/{documentId}");
 | 
			
		||||
                var json = await response.Content.ReadAsStringAsync();
 | 
			
		||||
                var result = JsonSerializer.Deserialize<JsonElement>(json);
 | 
			
		||||
 | 
			
		||||
                // Extrahiere das Array "documents"
 | 
			
		||||
                var documents = result.GetProperty("documents");
 | 
			
		||||
                if (documents.GetArrayLength() == 0)
 | 
			
		||||
                {
 | 
			
		||||
                    MessageBox.Show("Dokument nicht gefunden");
 | 
			
		||||
                    return;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                // Nimm das erste Element des Arrays
 | 
			
		||||
                var document = documents[0];
 | 
			
		||||
 | 
			
		||||
                // UI aktualisieren
 | 
			
		||||
                await Dispatcher.InvokeAsync(() =>
 | 
			
		||||
                {
 | 
			
		||||
                    SearchResultsListBox.ItemsSource = new List<SearchResult>
 | 
			
		||||
            {
 | 
			
		||||
                new SearchResult
 | 
			
		||||
                {
 | 
			
		||||
                    Id = document.GetProperty("id").GetInt32(),
 | 
			
		||||
                    Filename = document.GetProperty("filename").GetString(),
 | 
			
		||||
                    Content = document.GetProperty("content").GetString()
 | 
			
		||||
                }
 | 
			
		||||
            };
 | 
			
		||||
                    ContentTextBox.Text = document.GetProperty("content").GetString();
 | 
			
		||||
                });
 | 
			
		||||
            }
 | 
			
		||||
            catch (Exception ex)
 | 
			
		||||
            {
 | 
			
		||||
                MessageBox.Show($"Fehler: {ex.Message}");
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        private async Task SearchByTextAsync()
 | 
			
		||||
        {
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                var encodedQuery = Uri.EscapeDataString(SearchTextBox.Text);
 | 
			
		||||
                var response = await _httpClient.GetAsync($"/documents/search?query={encodedQuery}");
 | 
			
		||||
 | 
			
		||||
                var json = await response.Content.ReadAsStringAsync();
 | 
			
		||||
                var result = JsonSerializer.Deserialize<JsonElement>(json);
 | 
			
		||||
 | 
			
		||||
                var documents = JsonSerializer.Deserialize<List<SearchResult>>(
 | 
			
		||||
                    result.GetProperty("documents").GetRawText());
 | 
			
		||||
 | 
			
		||||
                MessageBox.Show($"Gefundene Dokumente: {documents?.Count}", "Debug");
 | 
			
		||||
 | 
			
		||||
                SearchResultsListBox.ItemsSource = documents;
 | 
			
		||||
                SearchResultsListBox.DisplayMemberPath = "Filename";
 | 
			
		||||
            }
 | 
			
		||||
            catch (Exception ex)
 | 
			
		||||
            {
 | 
			
		||||
                MessageBox.Show($"Fehler: {ex.Message}");
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        private void PdfDropCanvas_DragEnter(object sender, DragEventArgs e)
 | 
			
		||||
        {
 | 
			
		||||
            // Nur PDF-Dateien erlauben
 | 
			
		||||
            if (e.Data.GetDataPresent(DataFormats.FileDrop))
 | 
			
		||||
            {
 | 
			
		||||
                var files = (string[])e.Data.GetData(DataFormats.FileDrop);
 | 
			
		||||
                if (files.Any(f => System.IO.Path.GetExtension(f).Equals(".pdf", StringComparison.OrdinalIgnoreCase)))
 | 
			
		||||
                {
 | 
			
		||||
                    e.Effects = DragDropEffects.Copy;
 | 
			
		||||
                    DropHintText.Visibility = Visibility.Collapsed; // Platzhalter ausblenden
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                e.Effects = DragDropEffects.None;
 | 
			
		||||
            }
 | 
			
		||||
            e.Handled = true;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void PdfDropCanvas_Drop(object sender, DragEventArgs e)
 | 
			
		||||
        {
 | 
			
		||||
            if (e.Data.GetDataPresent(DataFormats.FileDrop))
 | 
			
		||||
            {
 | 
			
		||||
                string[] files = (string[])e.Data.GetData(DataFormats.FileDrop);
 | 
			
		||||
                _selectedPdfPath = files.FirstOrDefault(f => System.IO.Path.GetExtension(f).Equals(".pdf", StringComparison.OrdinalIgnoreCase));
 | 
			
		||||
 | 
			
		||||
                if (_selectedPdfPath != null)
 | 
			
		||||
                {
 | 
			
		||||
                    // Vorschau anzeigen
 | 
			
		||||
                    PdfIcon.Visibility = Visibility.Visible;
 | 
			
		||||
                    PdfFileNameText.Text = System.IO.Path.GetFileName(_selectedPdfPath);
 | 
			
		||||
                    PdfFileNameText.Visibility = Visibility.Visible;
 | 
			
		||||
                    DropHintText.Visibility = Visibility.Collapsed;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Response-Klassen
 | 
			
		||||
        public class ApiResponse
 | 
			
		||||
        {
 | 
			
		||||
            [JsonPropertyName("success")]
 | 
			
		||||
            public bool Success { get; set; }
 | 
			
		||||
 | 
			
		||||
            [JsonPropertyName("document")]
 | 
			
		||||
            public DocumentDetail Document { get; set; }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public class DocumentDetail
 | 
			
		||||
        {
 | 
			
		||||
            [JsonPropertyName("id")]
 | 
			
		||||
            public int Id { get; set; }
 | 
			
		||||
 | 
			
		||||
            [JsonPropertyName("filename")]
 | 
			
		||||
            public string Filename { get; set; }
 | 
			
		||||
 | 
			
		||||
            [JsonPropertyName("content")]
 | 
			
		||||
            public string Content { get; set; }
 | 
			
		||||
        }
 | 
			
		||||
        public class ApiError
 | 
			
		||||
        {
 | 
			
		||||
            public string Detail { get; set; }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private async void UploadButton_Click(object sender, RoutedEventArgs e)
 | 
			
		||||
        {
 | 
			
		||||
            if (string.IsNullOrEmpty(_selectedPdfPath))
 | 
			
		||||
            {
 | 
			
		||||
                MessageBox.Show("Keine PDF ausgewählt!");
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // UI zurücksetzen
 | 
			
		||||
            UploadProgressBar.Visibility = Visibility.Visible;
 | 
			
		||||
            UploadProgressBar.Value = 0;
 | 
			
		||||
            UploadStatusText.Text = "Upload läuft...";
 | 
			
		||||
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                using (var httpClient = new HttpClient())
 | 
			
		||||
                using (var fileStream = File.OpenRead(_selectedPdfPath))
 | 
			
		||||
                {
 | 
			
		||||
                    var progress = new Progress<float>(percent =>
 | 
			
		||||
                    {
 | 
			
		||||
                        Dispatcher.Invoke(() =>
 | 
			
		||||
                        {
 | 
			
		||||
                            UploadProgressBar.Value = percent * 100;
 | 
			
		||||
                            UploadStatusText.Text = $"Upload: {(int)(percent * 100)}%";
 | 
			
		||||
                        });
 | 
			
		||||
                    });
 | 
			
		||||
 | 
			
		||||
                    var content = new StreamContent(fileStream);
 | 
			
		||||
                    var formData = new MultipartFormDataContent();
 | 
			
		||||
                    formData.Add(content, "file", Path.GetFileName(_selectedPdfPath));
 | 
			
		||||
 | 
			
		||||
                    // Simulierter Fortschritt
 | 
			
		||||
                    for (int i = 0; i <= 100; i += 10)
 | 
			
		||||
                    {
 | 
			
		||||
                        await Task.Delay(100);
 | 
			
		||||
                        ((IProgress<float>)progress).Report(i / 100f);
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    var response = await httpClient.PostAsync($"{BaseUrl}/upload-pdf", formData);
 | 
			
		||||
 | 
			
		||||
                    if (response.IsSuccessStatusCode)
 | 
			
		||||
                    {
 | 
			
		||||
                        // Erfolgsmeldung anzeigen
 | 
			
		||||
                        UploadStatusText.Text = "Erfolgreich hochgeladen!";
 | 
			
		||||
 | 
			
		||||
                        // Canvas zurücksetzen
 | 
			
		||||
                        Dispatcher.Invoke(() =>
 | 
			
		||||
                        {
 | 
			
		||||
                            PdfIcon.Visibility = Visibility.Collapsed;
 | 
			
		||||
                            PdfFileNameText.Visibility = Visibility.Collapsed;
 | 
			
		||||
                            DropHintText.Visibility = Visibility.Visible;
 | 
			
		||||
                            _selectedPdfPath = null;
 | 
			
		||||
                        });
 | 
			
		||||
 | 
			
		||||
                        // Erfolgsmeldung nach 3 Sekunden ausblenden
 | 
			
		||||
                        await Task.Delay(3000);
 | 
			
		||||
                        UploadStatusText.Text = string.Empty;
 | 
			
		||||
                    }
 | 
			
		||||
                    else
 | 
			
		||||
                    {
 | 
			
		||||
                        UploadStatusText.Text = "Fehler beim Upload";
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            catch (Exception ex)
 | 
			
		||||
            {
 | 
			
		||||
                UploadStatusText.Text = $"Fehler: {ex.Message}";
 | 
			
		||||
            }
 | 
			
		||||
            finally
 | 
			
		||||
            {
 | 
			
		||||
                UploadProgressBar.Visibility = Visibility.Collapsed;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        private async void DeleteButton_Click(object sender, RoutedEventArgs e)
 | 
			
		||||
        {
 | 
			
		||||
            if (SearchResultsListBox.SelectedItems.Count == 0)
 | 
			
		||||
            {
 | 
			
		||||
                MessageBox.Show("Bitte Dokumente auswählen.");
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            var result = MessageBox.Show(
 | 
			
		||||
                $"{SearchResultsListBox.SelectedItems.Count} Dokument(e) löschen?",
 | 
			
		||||
                "Bestätigung",
 | 
			
		||||
                MessageBoxButton.YesNo,
 | 
			
		||||
                MessageBoxImage.Warning
 | 
			
		||||
            );
 | 
			
		||||
 | 
			
		||||
            if (result != MessageBoxResult.Yes) return;
 | 
			
		||||
 | 
			
		||||
            var deletedIds = new List<int>();
 | 
			
		||||
            var errorIds = new List<int>();
 | 
			
		||||
 | 
			
		||||
            foreach (var item in SearchResultsListBox.SelectedItems.Cast<SearchResult>().ToList())
 | 
			
		||||
            {
 | 
			
		||||
                try
 | 
			
		||||
                {
 | 
			
		||||
                    var response = await _httpClient.DeleteAsync($"/documents/by-id/{item.Id}/delete");
 | 
			
		||||
                    if (response.IsSuccessStatusCode)
 | 
			
		||||
                    {
 | 
			
		||||
                        deletedIds.Add(item.Id);
 | 
			
		||||
                        Debug.WriteLine($"Gelöscht: {item.Id}");
 | 
			
		||||
                    }
 | 
			
		||||
                    else
 | 
			
		||||
                    {
 | 
			
		||||
                        errorIds.Add(item.Id);
 | 
			
		||||
                        var errorContent = await response.Content.ReadAsStringAsync();
 | 
			
		||||
                        Debug.WriteLine($"Fehler bei {item.Id}: {errorContent}");
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                catch (Exception ex)
 | 
			
		||||
                {
 | 
			
		||||
                    errorIds.Add(item.Id);
 | 
			
		||||
                    Debug.WriteLine($"Ausnahme: {ex.Message}");
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // Aktualisiere die Liste unabhängig vom Suchmodus
 | 
			
		||||
            if (SearchByIdRadio.IsChecked == true)
 | 
			
		||||
            {
 | 
			
		||||
                await SearchByIdAsync();  // Neu laden der ID-Suche
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                await SearchByTextAsync(); // Neu laden der Textsuche
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // Feedback an Benutzer
 | 
			
		||||
            var message = new StringBuilder();
 | 
			
		||||
            if (deletedIds.Count > 0)
 | 
			
		||||
            {
 | 
			
		||||
                message.AppendLine($"{deletedIds.Count} Dokument(e) gelöscht.");
 | 
			
		||||
            }
 | 
			
		||||
            if (errorIds.Count > 0)
 | 
			
		||||
            {
 | 
			
		||||
                message.AppendLine($"{errorIds.Count} Dokument(e) konnten nicht gelöscht werden.");
 | 
			
		||||
            }
 | 
			
		||||
            MessageBox.Show(message.ToString());
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private async void SearchResultsListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
 | 
			
		||||
        {
 | 
			
		||||
            if (SearchResultsListBox.SelectedItem is SearchResult selectedDocument)
 | 
			
		||||
            {
 | 
			
		||||
                try
 | 
			
		||||
                {
 | 
			
		||||
                    var response = await _httpClient.GetAsync($"/documents/by-id/{selectedDocument.Id}");
 | 
			
		||||
                    var json = await response.Content.ReadAsStringAsync();
 | 
			
		||||
                    var result = JsonSerializer.Deserialize<JsonElement>(json);
 | 
			
		||||
 | 
			
		||||
                    // Sicherstellen, dass das "documents" Array existiert
 | 
			
		||||
                    if (!result.TryGetProperty("documents", out var documents))
 | 
			
		||||
                    {
 | 
			
		||||
                        ContentTextBox.Text = "Ungültiges Antwortformat";
 | 
			
		||||
                        return;
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    // Sicherstellen, dass das Array mindestens ein Element hat
 | 
			
		||||
                    if (documents.GetArrayLength() == 0)
 | 
			
		||||
                    {
 | 
			
		||||
                        ContentTextBox.Text = "Dokument nicht gefunden";
 | 
			
		||||
                        return;
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    var document = documents[0];
 | 
			
		||||
 | 
			
		||||
                    // Sicherstellen, dass alle benötigten Felder existieren
 | 
			
		||||
                    if (!document.TryGetProperty("content", out var contentProp))
 | 
			
		||||
                    {
 | 
			
		||||
                        ContentTextBox.Text = "Dokumentinhalt fehlt";
 | 
			
		||||
                        return;
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    ContentTextBox.Text = contentProp.GetString();
 | 
			
		||||
 | 
			
		||||
                    Debug.WriteLine($"API-Antwort: {json}");
 | 
			
		||||
                }
 | 
			
		||||
                catch (Exception ex)
 | 
			
		||||
                {
 | 
			
		||||
                    ContentTextBox.Text = $"Fehler: {ex.Message}";
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user