Compare commits
9 Commits
ebea635c53
...
main
Author | SHA1 | Date | |
---|---|---|---|
a6654ef708 | |||
9445cec743 | |||
52b64e4430 | |||
3e9d887a12 | |||
0041872afd | |||
ba44f03264 | |||
e94dfb54e1 | |||
c6b6a2359c | |||
8bf09d9088 |
@@ -2,7 +2,7 @@
|
|||||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:local="clr-namespace:PrototypWPFHAG"
|
xmlns:local="clr-namespace:PrototypWPFHAG"
|
||||||
StartupUri="MainWindow.xaml">
|
StartupUri="SearchWindow.xaml">
|
||||||
<Application.Resources>
|
<Application.Resources>
|
||||||
<ResourceDictionary>
|
<ResourceDictionary>
|
||||||
<ResourceDictionary.MergedDictionaries>
|
<ResourceDictionary.MergedDictionaries>
|
||||||
|
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 |
@@ -28,10 +28,6 @@
|
|||||||
<PasswordBox Width="170" Height="30" Margin="0,5,34,0" x:Name="PasswordTextBox"
|
<PasswordBox Width="170" Height="30" Margin="0,5,34,0" x:Name="PasswordTextBox"
|
||||||
PasswordChanged="PasswordTextBox_PasswordChanged"/>
|
PasswordChanged="PasswordTextBox_PasswordChanged"/>
|
||||||
|
|
||||||
<<<<<<< HEAD
|
|
||||||
<!-- 登录按钮 -->
|
|
||||||
<Button Height="30" Width="100" Content="Log in" Margin="0,20,0,0" Click="LoginButton_Click" />
|
|
||||||
=======
|
|
||||||
<!-- Textbox for visible password (hidden at default) -->
|
<!-- Textbox for visible password (hidden at default) -->
|
||||||
<TextBox Width="170" Height="30" Margin="0,5,34,0" x:Name="PasswordVisibleTextBox"
|
<TextBox Width="170" Height="30" Margin="0,5,34,0" x:Name="PasswordVisibleTextBox"
|
||||||
Visibility="Collapsed" IsReadOnly="True"/>
|
Visibility="Collapsed" IsReadOnly="True"/>
|
||||||
@@ -45,7 +41,6 @@
|
|||||||
<!-- Login Button -->
|
<!-- Login Button -->
|
||||||
<Button Height="30" Width="100" Content="Zur Suche" Margin="0,20,0,0"
|
<Button Height="30" Width="100" Content="Zur Suche" Margin="0,20,0,0"
|
||||||
Click="loginButton_Click" IsDefault="True" />
|
Click="loginButton_Click" IsDefault="True" />
|
||||||
>>>>>>> 1195250b98172d34b8c49b85a81c21d1f26cdbac
|
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</Border>
|
</Border>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
@@ -1,6 +1,4 @@
|
|||||||
using System.Data;
|
using System.Data;
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
using System.Security.Principal;
|
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
using System.Windows.Controls;
|
using System.Windows.Controls;
|
||||||
@@ -25,14 +23,6 @@ public partial class MainWindow : MetroWindow
|
|||||||
public MainWindow()
|
public MainWindow()
|
||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
<<<<<<< HEAD
|
|
||||||
//TestConnection();
|
|
||||||
//Console.ReadKey();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void TestConnection()
|
|
||||||
=======
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Window_Loaded(object sender, RoutedEventArgs e)
|
private void Window_Loaded(object sender, RoutedEventArgs e)
|
||||||
@@ -46,14 +36,13 @@ public partial class MainWindow : MetroWindow
|
|||||||
}
|
}
|
||||||
|
|
||||||
private string ValidateUser(string username, string password)
|
private string ValidateUser(string username, string password)
|
||||||
>>>>>>> 1195250b98172d34b8c49b85a81c21d1f26cdbac
|
|
||||||
{
|
{
|
||||||
using (NpgsqlConnection con = GetConnection())
|
using (NpgsqlConnection con = GetConnection())
|
||||||
{
|
{
|
||||||
con.Open();
|
con.Open();
|
||||||
|
|
||||||
// Check for correct UserName
|
// 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))
|
using (NpgsqlCommand userCmd = new NpgsqlCommand(userQuery, con))
|
||||||
{
|
{
|
||||||
userCmd.Parameters.AddWithValue("@username", username);
|
userCmd.Parameters.AddWithValue("@username", username);
|
||||||
@@ -66,7 +55,7 @@ public partial class MainWindow : MetroWindow
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check for correct Password
|
// 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))
|
using (NpgsqlCommand pwCmd = new NpgsqlCommand(pwQuery, con))
|
||||||
{
|
{
|
||||||
pwCmd.Parameters.AddWithValue("@username", username);
|
pwCmd.Parameters.AddWithValue("@username", username);
|
||||||
@@ -79,15 +68,8 @@ public partial class MainWindow : MetroWindow
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
<<<<<<< HEAD
|
|
||||||
}
|
|
||||||
private static NpgsqlConnection GetConnection()
|
|
||||||
{
|
|
||||||
return new NpgsqlConnection(@"Server=localhost;Port=7854;User Id=postgres;Database=postgres;");
|
|
||||||
=======
|
|
||||||
|
|
||||||
return "Erfolgreich";
|
return "Erfolgreich";
|
||||||
>>>>>>> 1195250b98172d34b8c49b85a81c21d1f26cdbac
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ShowPasswordButton_PreviewMouseDown(object sender, RoutedEventArgs e)
|
private void ShowPasswordButton_PreviewMouseDown(object sender, RoutedEventArgs e)
|
||||||
|
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>
|
<ItemGroup>
|
||||||
<None Remove="Images\databaseicon.png" />
|
<None Remove="Images\databaseicon.png" />
|
||||||
|
<None Remove="Images\pdf-icon.png" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
@@ -33,4 +34,8 @@
|
|||||||
<PackageReference Include="SixLabors.ImageSharp" Version="3.1.7" />
|
<PackageReference Include="SixLabors.ImageSharp" Version="3.1.7" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Resource Include="Images\pdf-icon.png" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
@@ -1,69 +1,153 @@
|
|||||||
<Window x:Class="PrototypWPFHAG.SearchWindow"
|
<mah:MetroWindow xmlns:mah="http://metro.mahapps.com/winfx/xaml/controls"
|
||||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
x:Class="PrototypWPFHAG.SearchWindow"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
xmlns:local="clr-namespace:PrototypWPFHAG"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
Title="Such Fenster" Height="600" Width="800">
|
xmlns:local="clr-namespace:PrototypWPFHAG"
|
||||||
<Grid>
|
Title="PDF-Verwaltung (Admin)"
|
||||||
<!-- 左侧垂直布局 -->
|
Height="600" Width="1000"
|
||||||
<Grid.ColumnDefinitions>
|
MinWidth="800" MinHeight="500"
|
||||||
<ColumnDefinition Width="200"/>
|
WindowTitleBrush="FireBrick"
|
||||||
<!-- 左侧固定宽度 -->
|
Icon="pack://application:,,,/Images/databaseicon.png"
|
||||||
<ColumnDefinition Width="*"/>
|
ResizeMode="CanResizeWithGrip"
|
||||||
<!-- 右侧占满剩余空间 -->
|
WindowStartupLocation="CenterScreen">
|
||||||
</Grid.ColumnDefinitions>
|
|
||||||
|
|
||||||
<!-- 左侧区域 -->
|
<Border BorderBrush="FireBrick" BorderThickness="3">
|
||||||
<StackPanel Orientation="Vertical" Margin="10">
|
<Grid>
|
||||||
<Grid Margin="0,0,0,10">
|
<Grid.ColumnDefinitions>
|
||||||
<Grid.ColumnDefinitions>
|
<ColumnDefinition Width="500" MinWidth="400"/>
|
||||||
<ColumnDefinition Width="*"/>
|
<ColumnDefinition Width="*"/>
|
||||||
<ColumnDefinition Width="Auto"/>
|
</Grid.ColumnDefinitions>
|
||||||
</Grid.ColumnDefinitions>
|
|
||||||
<Grid.RowDefinitions>
|
|
||||||
<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>
|
|
||||||
<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"/>
|
|
||||||
</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"/>
|
|
||||||
</Grid>
|
|
||||||
<Button Content="Zurück " Margin="5,380" Click="BackToLogIn_Click"/>
|
|
||||||
</StackPanel>
|
|
||||||
|
|
||||||
<!-- 右侧区域 -->
|
<!-- Linke Seite -->
|
||||||
<Grid Grid.Column="1" Margin="10">
|
<Border Grid.Column="0" Margin="10" Padding="10">
|
||||||
<Label Content="Zeugnisse:" HorizontalAlignment="Left" Margin="0,2,0,8"/>
|
<Grid>
|
||||||
<!-- ListField -->
|
<Grid.RowDefinitions>
|
||||||
<ListBox x:Name="ListField" Margin="0,29,0,35" BorderThickness="1" BorderBrush="Black">
|
<RowDefinition Height="Auto"/>
|
||||||
<ListBox.ItemTemplate>
|
<!-- Drag & Drop -->
|
||||||
<DataTemplate>
|
<RowDefinition Height="Auto"/>
|
||||||
<StackPanel Orientation="Vertical">
|
<!-- Upload/Auswahl-Buttons -->
|
||||||
<!-- 内容 -->
|
<RowDefinition Height="Auto"/>
|
||||||
<TextBlock Text="{Binding}" VerticalAlignment="Center" HorizontalAlignment="Stretch" Padding="5"/>
|
<!-- Suchmodus -->
|
||||||
<!-- 分隔线 -->
|
<RowDefinition Height="Auto"/>
|
||||||
<Border Height="1" Background="Black" Margin="0,2,0,2"/>
|
<!-- Suchfeld -->
|
||||||
</StackPanel>
|
<RowDefinition Height="*"/>
|
||||||
</DataTemplate>
|
<!-- Suchergebnisse -->
|
||||||
</ListBox.ItemTemplate>
|
<RowDefinition Height="Auto"/>
|
||||||
</ListBox>
|
<!-- Status -->
|
||||||
|
<RowDefinition Height="Auto"/>
|
||||||
|
<!-- Zurück-Button -->
|
||||||
|
</Grid.RowDefinitions>
|
||||||
|
|
||||||
|
<!-- Drag & Drop Bereich -->
|
||||||
|
<Border Grid.Row="0" Height="75" Margin="0,5"
|
||||||
|
BorderBrush="Gray" BorderThickness="1">
|
||||||
|
<Grid Background="Transparent" AllowDrop="True"
|
||||||
|
DragEnter="PdfDropCanvas_DragEnter"
|
||||||
|
Drop="PdfDropCanvas_Drop">
|
||||||
|
<TextBlock x:Name="DropHintText" Text="PDF hier rein ziehen"
|
||||||
|
VerticalAlignment="Center" HorizontalAlignment="Center"/>
|
||||||
|
<StackPanel Orientation="Horizontal" VerticalAlignment="Center">
|
||||||
|
<Image x:Name="PdfIcon" Source="pack://application:,,,/Images/pdf-icon.png"
|
||||||
|
Width="25" Height="25" Visibility="Collapsed"/>
|
||||||
|
<TextBlock x:Name="PdfFileNameText" Margin="10"
|
||||||
|
TextWrapping="Wrap" Visibility="Collapsed"/>
|
||||||
|
</StackPanel>
|
||||||
|
</Grid>
|
||||||
|
</Border>
|
||||||
|
|
||||||
<!-- 删除按钮 -->
|
<!-- Upload/Auswahl-Buttons -->
|
||||||
<Button Content="Löschen" Width="100" Height="30" HorizontalAlignment="Right" VerticalAlignment="Bottom"/>
|
<StackPanel Grid.Row="1" Orientation="Horizontal" Margin="0,10">
|
||||||
|
<Button Content="PDF hochladen"
|
||||||
|
Width="210" Height="30"
|
||||||
|
Background="LightGreen"
|
||||||
|
Click="UploadButton_Click"/>
|
||||||
|
|
||||||
|
<Button Content="PDF auswählen"
|
||||||
|
Width="210" Height="30" Margin="40,0,0,0"
|
||||||
|
Background="Firebrick"
|
||||||
|
Click="ChoosePdfButton_Click"/>
|
||||||
|
</StackPanel>
|
||||||
|
|
||||||
|
<!-- Suchmodus-Auswahl -->
|
||||||
|
<StackPanel Grid.Row="2" Orientation="Horizontal" Margin="0,10">
|
||||||
|
<RadioButton x:Name="SearchByIdRadio"
|
||||||
|
Content="ID"
|
||||||
|
Margin="5"
|
||||||
|
IsChecked="True"/>
|
||||||
|
<RadioButton x:Name="SearchByTextRadio"
|
||||||
|
Content="Text"
|
||||||
|
Margin="5"/>
|
||||||
|
</StackPanel>
|
||||||
|
|
||||||
|
<!-- Suchfeld -->
|
||||||
|
<StackPanel Grid.Row="3" Margin="0,10">
|
||||||
|
<TextBox x:Name="SearchTextBox"
|
||||||
|
Margin="0,0,0,5"
|
||||||
|
HorizontalAlignment="Stretch"/>
|
||||||
|
<Button Content="Suchen"
|
||||||
|
x:Name="SearchButton"
|
||||||
|
Height="30"
|
||||||
|
HorizontalAlignment="Stretch"
|
||||||
|
Click="SearchButton_Click"/>
|
||||||
|
</StackPanel>
|
||||||
|
|
||||||
|
<!-- Suchergebnisse -->
|
||||||
|
<ListBox Grid.Row="4"
|
||||||
|
x:Name="SearchResultsListBox"
|
||||||
|
Margin="0,10"
|
||||||
|
DisplayMemberPath="DocumentName"
|
||||||
|
ScrollViewer.VerticalScrollBarVisibility="Auto"
|
||||||
|
SelectionMode="Extended"
|
||||||
|
SelectionChanged="SearchResultsListBox_SelectionChanged"/>
|
||||||
|
|
||||||
|
<!-- Status & Fortschritt -->
|
||||||
|
<StackPanel Grid.Row="5" Orientation="Vertical" Margin="0,10">
|
||||||
|
<TextBlock x:Name="UploadStatusText" TextAlignment="Center"/>
|
||||||
|
<ProgressBar x:Name="UploadProgressBar"
|
||||||
|
Height="10"
|
||||||
|
Minimum="0"
|
||||||
|
Maximum="100"
|
||||||
|
Visibility="Collapsed"/>
|
||||||
|
</StackPanel>
|
||||||
|
|
||||||
|
<!-- Zurück-Button -->
|
||||||
|
<Button Grid.Row="6"
|
||||||
|
Content="Zurück zur Anmeldung"
|
||||||
|
Height="30" Margin="0,10"
|
||||||
|
HorizontalAlignment="Stretch"
|
||||||
|
Background="#ffd64f"
|
||||||
|
Click="BackToLogIn_Click"/>
|
||||||
|
</Grid>
|
||||||
|
</Border>
|
||||||
|
|
||||||
|
<!-- Rechte Seite -->
|
||||||
|
<Border Grid.Column="1" Margin="10">
|
||||||
|
<Grid>
|
||||||
|
<Grid.RowDefinitions>
|
||||||
|
<RowDefinition Height="Auto"/>
|
||||||
|
<RowDefinition Height="*"/>
|
||||||
|
<RowDefinition Height="Auto"/>
|
||||||
|
</Grid.RowDefinitions>
|
||||||
|
|
||||||
|
<Label Content="PDF-Inhalt:" Margin="0,0,0,5"/>
|
||||||
|
|
||||||
|
<TextBox Grid.Row="1"
|
||||||
|
x:Name="ContentTextBox"
|
||||||
|
TextWrapping="Wrap"
|
||||||
|
AcceptsReturn="True"
|
||||||
|
VerticalScrollBarVisibility="Auto"
|
||||||
|
HorizontalScrollBarVisibility="Auto"
|
||||||
|
IsReadOnly="True"/>
|
||||||
|
|
||||||
|
<Button Grid.Row="2"
|
||||||
|
Content="Löschen"
|
||||||
|
Width="100" Height="30"
|
||||||
|
Margin="0,10"
|
||||||
|
HorizontalAlignment="Center"
|
||||||
|
Background="Firebrick"
|
||||||
|
Click="DeleteButton_Click"/>
|
||||||
|
</Grid>
|
||||||
|
</Border>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Grid>
|
</Border>
|
||||||
</Window>
|
</mah:MetroWindow>
|
@@ -1,27 +1,46 @@
|
|||||||
using System;
|
using MahApps.Metro.Controls;
|
||||||
using System.Collections.Generic;
|
using System.ComponentModel;
|
||||||
using System.Linq;
|
using System.Diagnostics;
|
||||||
|
using System.IO;
|
||||||
|
using System.Net;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
using System.Text;
|
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;
|
||||||
using System.Windows.Controls;
|
using System.Windows.Controls;
|
||||||
using System.Windows.Data;
|
|
||||||
using System.Windows.Documents;
|
using System.Windows.Documents;
|
||||||
using System.Windows.Input;
|
|
||||||
using System.Windows.Media;
|
|
||||||
using System.Windows.Media.Imaging;
|
|
||||||
using System.Windows.Shapes;
|
|
||||||
|
|
||||||
namespace PrototypWPFHAG
|
namespace PrototypWPFHAG
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Interaktionslogik für SearchWindow.xaml
|
/// Interaktionslogik für SearchWindow.xaml
|
||||||
/// </summary>
|
/// </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;
|
||||||
|
private List<string> _selectedPdfPaths = new List<string>();
|
||||||
public SearchWindow()
|
public SearchWindow()
|
||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
|
_httpClient = new HttpClient
|
||||||
|
{
|
||||||
|
BaseAddress = new Uri(BaseUrl),
|
||||||
|
Timeout = TimeSpan.FromSeconds(30)
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private void BackToLogIn_Click(object sender, RoutedEventArgs e)
|
private void BackToLogIn_Click(object sender, RoutedEventArgs e)
|
||||||
@@ -30,5 +49,327 @@ namespace PrototypWPFHAG
|
|||||||
loginWindow.Show(); // Open new window
|
loginWindow.Show(); // Open new window
|
||||||
this.Close(); // Close this 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 SearchBySimilarityAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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/{documentId}");
|
||||||
|
response.EnsureSuccessStatusCode();
|
||||||
|
|
||||||
|
var json = await response.Content.ReadAsStringAsync();
|
||||||
|
var result = JsonSerializer.Deserialize<DocumentDetail>(json);
|
||||||
|
|
||||||
|
await Dispatcher.InvokeAsync(() =>
|
||||||
|
{
|
||||||
|
SearchResultsListBox.ItemsSource = new List<DocumentDetail> { result };
|
||||||
|
ContentTextBox.Text = result.Content;
|
||||||
|
SearchResultsListBox.DisplayMemberPath = "DocumentName";
|
||||||
|
});
|
||||||
|
}
|
||||||
|
catch (HttpRequestException ex) when (ex.StatusCode == HttpStatusCode.NotFound)
|
||||||
|
{
|
||||||
|
MessageBox.Show("Dokument nicht gefunden");
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
MessageBox.Show($"Fehler: {ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task SearchBySimilarityAsync()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var encodedQuery = HttpUtility.UrlEncode(SearchTextBox.Text);
|
||||||
|
var response = await _httpClient.GetAsync($"/documents/search/similarity?query={encodedQuery}");
|
||||||
|
|
||||||
|
var json = await response.Content.ReadAsStringAsync();
|
||||||
|
var result = JsonSerializer.Deserialize<ApiResponse>(json);
|
||||||
|
|
||||||
|
await Dispatcher.InvokeAsync(() =>
|
||||||
|
{
|
||||||
|
SearchResultsListBox.ItemsSource = result?.Documents;
|
||||||
|
SearchResultsListBox.DisplayMemberPath = "DocumentName";
|
||||||
|
});
|
||||||
|
}
|
||||||
|
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 ChoosePdfButton_Click(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
var openFileDialog = new Microsoft.Win32.OpenFileDialog
|
||||||
|
{
|
||||||
|
Filter = "PDF Files (*.pdf)|*.pdf",
|
||||||
|
Multiselect = true
|
||||||
|
};
|
||||||
|
|
||||||
|
if (openFileDialog.ShowDialog() == true)
|
||||||
|
{
|
||||||
|
_selectedPdfPaths.AddRange(openFileDialog.FileNames);
|
||||||
|
|
||||||
|
|
||||||
|
PdfIcon.Visibility = Visibility.Visible;
|
||||||
|
PdfFileNameText.Text = string.Join(", ", _selectedPdfPaths.Select(System.IO.Path.GetFileName));
|
||||||
|
PdfFileNameText.Visibility = Visibility.Visible;
|
||||||
|
DropHintText.Visibility = Visibility.Collapsed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private void PdfDropCanvas_Drop(object sender, DragEventArgs e)
|
||||||
|
{
|
||||||
|
if (e.Data.GetDataPresent(DataFormats.FileDrop))
|
||||||
|
{
|
||||||
|
string[] files = (string[])e.Data.GetData(DataFormats.FileDrop);
|
||||||
|
var pdfFiles = files.Where(f => System.IO.Path.GetExtension(f).Equals(".pdf", StringComparison.OrdinalIgnoreCase)).ToList();
|
||||||
|
|
||||||
|
if (pdfFiles.Any())
|
||||||
|
{
|
||||||
|
_selectedPdfPaths.AddRange(pdfFiles);
|
||||||
|
|
||||||
|
// 更新UI以显示所有文件
|
||||||
|
PdfIcon.Visibility = Visibility.Visible;
|
||||||
|
PdfFileNameText.Text = string.Join(", ", _selectedPdfPaths.Select(System.IO.Path.GetFileName));
|
||||||
|
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; }
|
||||||
|
|
||||||
|
[JsonPropertyName("documents")]
|
||||||
|
public List<DocumentDetail> Documents { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class DocumentDetail : INotifyPropertyChanged
|
||||||
|
{
|
||||||
|
[JsonPropertyName("id")]
|
||||||
|
public int Id { get; set; }
|
||||||
|
|
||||||
|
[JsonPropertyName("document_name")]
|
||||||
|
public string DocumentName { get; set; }
|
||||||
|
|
||||||
|
[JsonPropertyName("content")]
|
||||||
|
public string Content { get; set; }
|
||||||
|
|
||||||
|
[JsonPropertyName("distance")]
|
||||||
|
public double Distance { get; set; }
|
||||||
|
|
||||||
|
private bool _isSelected;
|
||||||
|
public bool IsSelected
|
||||||
|
{
|
||||||
|
get => _isSelected;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (_isSelected != value)
|
||||||
|
{
|
||||||
|
_isSelected = value;
|
||||||
|
OnPropertyChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public event PropertyChangedEventHandler PropertyChanged;
|
||||||
|
|
||||||
|
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
|
||||||
|
{
|
||||||
|
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ApiError
|
||||||
|
{
|
||||||
|
public string Detail { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private async void UploadButton_Click(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
if (!_selectedPdfPaths.Any())
|
||||||
|
{
|
||||||
|
MessageBox.Show("Keine PDF ausgewählt!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
UploadProgressBar.Visibility = Visibility.Visible;
|
||||||
|
UploadProgressBar.Value = 0;
|
||||||
|
UploadStatusText.Text = "Upload läuft...";
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using var formData = new MultipartFormDataContent();
|
||||||
|
|
||||||
|
foreach (var pdfPath in _selectedPdfPaths)
|
||||||
|
{
|
||||||
|
var fileContent = new StreamContent(File.OpenRead(pdfPath));
|
||||||
|
formData.Add(fileContent, "files", Path.GetFileName(pdfPath));
|
||||||
|
}
|
||||||
|
|
||||||
|
var response = await _httpClient.PostAsync("/upload-pdfs/", formData);
|
||||||
|
response.EnsureSuccessStatusCode();
|
||||||
|
|
||||||
|
var json = await response.Content.ReadAsStringAsync();
|
||||||
|
var result = JsonSerializer.Deserialize<ApiResponse>(json);
|
||||||
|
|
||||||
|
if (result?.Success == true)
|
||||||
|
{
|
||||||
|
UploadStatusText.Text = "Upload erfolgreich!";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
UploadStatusText.Text = $"Fehler: {ex.Message}";
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
UploadProgressBar.Visibility = Visibility.Collapsed;
|
||||||
|
_selectedPdfPaths.Clear();
|
||||||
|
PdfIcon.Visibility = Visibility.Collapsed;
|
||||||
|
PdfFileNameText.Visibility = Visibility.Collapsed;
|
||||||
|
DropHintText.Visibility = Visibility.Visible;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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<DocumentDetail>().ToList())
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var response = await _httpClient.DeleteAsync($"/documents/{item.Id}");
|
||||||
|
if (response.IsSuccessStatusCode)
|
||||||
|
{
|
||||||
|
deletedIds.Add(item.Id);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
errorIds.Add(item.Id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
errorIds.Add(item.Id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Aktualisiere die Liste
|
||||||
|
if (SearchByIdRadio.IsChecked == true)
|
||||||
|
{
|
||||||
|
await SearchByIdAsync();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
await SearchBySimilarityAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Feedback
|
||||||
|
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 DocumentDetail selected)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var response = await _httpClient.GetAsync($"/documents/{selected.Id}/markdown");
|
||||||
|
var content = await response.Content.ReadAsStringAsync();
|
||||||
|
var result = JsonSerializer.Deserialize<JsonElement>(content);
|
||||||
|
|
||||||
|
ContentTextBox.Text = result.GetProperty("document")
|
||||||
|
.GetProperty("content")
|
||||||
|
.GetString();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
ContentTextBox.Text = $"Fehler: {ex.Message}";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user