feat(ui): complete Avalonia UI port with 7 main pages, tool settings & top MenuBar
This commit is contained in:
@@ -0,0 +1,51 @@
|
||||
<Window xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:vm="using:ClawdDotNet.Desktop.ViewModels"
|
||||
mc:Ignorable="d" d:DesignWidth="450" d:DesignHeight="380"
|
||||
Width="480" Height="400"
|
||||
Padding="16"
|
||||
WindowStartupLocation="CenterOwner"
|
||||
CanResize="False"
|
||||
Title="Neuen Agenten anlegen"
|
||||
x:Class="ClawdDotNet.Desktop.Views.AddAgentWindow"
|
||||
x:DataType="vm:AddAgentViewModel">
|
||||
|
||||
<DockPanel>
|
||||
|
||||
<!-- Bottom Buttons -->
|
||||
<StackPanel DockPanel.Dock="Bottom" Orientation="Horizontal" HorizontalAlignment="Right" Spacing="8" Margin="0,16,0,0">
|
||||
<Button Content="Abbrechen" Command="{Binding CancelCommand}" />
|
||||
<Button Content="Anlegen" Command="{Binding ConfirmCommand}" Classes="accent" />
|
||||
</StackPanel>
|
||||
|
||||
<TextBlock DockPanel.Dock="Bottom" Text="{Binding StatusMessage}" Foreground="Red" Margin="0,8,0,0" />
|
||||
|
||||
<StackPanel Spacing="12">
|
||||
|
||||
<StackPanel Spacing="4">
|
||||
<TextBlock Text="Agent-ID (eindeutiger Schlüssel):" FontWeight="Bold" />
|
||||
<TextBox Text="{Binding AgentId}" PlaceholderText="z.B. dev-assistant" />
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel Spacing="4">
|
||||
<TextBlock Text="Anzeigename:" FontWeight="Bold" />
|
||||
<TextBox Text="{Binding DisplayName}" PlaceholderText="z.B. Dev Assistant" />
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel Spacing="4">
|
||||
<TextBlock Text="Standard-Modell:" FontWeight="Bold" />
|
||||
<ComboBox ItemsSource="{Binding AvailableModels}" SelectedItem="{Binding SelectedModel}" HorizontalAlignment="Stretch" />
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel Spacing="4">
|
||||
<TextBlock Text="Beschreibung / Rolle:" FontWeight="Bold" />
|
||||
<TextBox Text="{Binding Description}" PlaceholderText="Kurze Beschreibung der Rolle..." AcceptsReturn="True" Height="60" />
|
||||
</StackPanel>
|
||||
|
||||
</StackPanel>
|
||||
|
||||
</DockPanel>
|
||||
|
||||
</Window>
|
||||
@@ -0,0 +1,21 @@
|
||||
using Avalonia.Controls;
|
||||
using ClawdDotNet.Desktop.ViewModels;
|
||||
|
||||
namespace ClawdDotNet.Desktop.Views;
|
||||
|
||||
public partial class AddAgentWindow : Window
|
||||
{
|
||||
public AddAgentWindow()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
protected override void OnDataContextChanged(EventArgs e)
|
||||
{
|
||||
base.OnDataContextChanged(e);
|
||||
if (DataContext is AddAgentViewModel vm)
|
||||
{
|
||||
vm.CloseRequested += () => Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
<Window xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:vm="using:ClawdDotNet.Desktop.ViewModels"
|
||||
mc:Ignorable="d" d:DesignWidth="500" d:DesignHeight="450"
|
||||
Width="520" Height="460"
|
||||
Padding="16"
|
||||
WindowStartupLocation="CenterOwner"
|
||||
CanResize="False"
|
||||
Title="Job hinzufügen / bearbeiten"
|
||||
x:Class="ClawdDotNet.Desktop.Views.AddJobWindow"
|
||||
x:DataType="vm:AddJobViewModel">
|
||||
|
||||
<DockPanel>
|
||||
|
||||
<!-- Bottom Buttons -->
|
||||
<StackPanel DockPanel.Dock="Bottom" Orientation="Horizontal" HorizontalAlignment="Right" Spacing="8" Margin="0,16,0,0">
|
||||
<Button Content="Abbrechen" Command="{Binding CancelCommand}" />
|
||||
<Button Content="Speichern" Command="{Binding ConfirmCommand}" Classes="accent" />
|
||||
</StackPanel>
|
||||
|
||||
<TextBlock DockPanel.Dock="Bottom" Text="{Binding StatusMessage}" Foreground="Red" Margin="0,8,0,0" />
|
||||
|
||||
<ScrollViewer>
|
||||
<StackPanel Spacing="12">
|
||||
|
||||
<!-- Agent Selection -->
|
||||
<StackPanel Spacing="4">
|
||||
<TextBlock Text="Agent:" FontWeight="Bold" />
|
||||
<ComboBox ItemsSource="{Binding AvailableAgents}" SelectedItem="{Binding SelectedAgent}" HorizontalAlignment="Stretch">
|
||||
<ComboBox.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<TextBlock Text="{Binding DisplayName}" />
|
||||
</DataTemplate>
|
||||
</ComboBox.ItemTemplate>
|
||||
</ComboBox>
|
||||
</StackPanel>
|
||||
|
||||
<!-- Job Type RadioButtons -->
|
||||
<StackPanel Spacing="4" Margin="0,4,0,0">
|
||||
<TextBlock Text="Job-Typ:" FontWeight="Bold" />
|
||||
<RadioButton Content="Agent Wakeup (Periodische Ausführung)" IsChecked="{Binding IsAgentWakeup}" />
|
||||
<RadioButton Content="Tool Job (Werkzeug-spezifischer Job)" IsChecked="{Binding IsToolJob}" />
|
||||
</StackPanel>
|
||||
|
||||
<!-- Tool Job Details -->
|
||||
<StackPanel Spacing="8" IsVisible="{Binding IsToolJob}" Margin="12,4,0,0">
|
||||
<StackPanel Spacing="4">
|
||||
<TextBlock Text="Tool:" FontWeight="Bold" />
|
||||
<ComboBox ItemsSource="{Binding AvailableTools}" SelectedItem="{Binding SelectedToolName}" HorizontalAlignment="Stretch" />
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel Spacing="4">
|
||||
<TextBlock Text="Job-Typ-ID / Name:" FontWeight="Bold" />
|
||||
<TextBox Text="{Binding JobTypeId}" PlaceholderText="z.B. PollMail" />
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
|
||||
<!-- Agent Wakeup Details -->
|
||||
<StackPanel Spacing="4" IsVisible="{Binding IsAgentWakeup}">
|
||||
<TextBlock Text="Aufgabenbeschreibung / Nachricht:" FontWeight="Bold" />
|
||||
<TextBox Text="{Binding TaskMessage}" PlaceholderText="Nachricht an den Agenten..." AcceptsReturn="True" Height="60" />
|
||||
</StackPanel>
|
||||
|
||||
<!-- Cron & Options -->
|
||||
<StackPanel Spacing="4">
|
||||
<TextBlock Text="Cron-Ausdruck:" FontWeight="Bold" />
|
||||
<TextBox Text="{Binding CronExpression}" PlaceholderText="0 * * * *" />
|
||||
<TextBlock Text="Syntax: Min Std Tag Mon Wochentag (z.B. '*/15 * * * *' alle 15 Minuten)" Classes="caption" />
|
||||
</StackPanel>
|
||||
|
||||
<CheckBox Content="Beim Anwendungsstart einmalig sofort ausführen" IsChecked="{Binding RunOnStart}" Margin="0,4,0,0" />
|
||||
|
||||
</StackPanel>
|
||||
</ScrollViewer>
|
||||
|
||||
</DockPanel>
|
||||
|
||||
</Window>
|
||||
@@ -0,0 +1,21 @@
|
||||
using Avalonia.Controls;
|
||||
using ClawdDotNet.Desktop.ViewModels;
|
||||
|
||||
namespace ClawdDotNet.Desktop.Views;
|
||||
|
||||
public partial class AddJobWindow : Window
|
||||
{
|
||||
public AddJobWindow()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
protected override void OnDataContextChanged(EventArgs e)
|
||||
{
|
||||
base.OnDataContextChanged(e);
|
||||
if (DataContext is AddJobViewModel vm)
|
||||
{
|
||||
vm.CloseRequested += () => Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
<Window xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:vm="using:ClawdDotNet.Desktop.ViewModels"
|
||||
mc:Ignorable="d" d:DesignWidth="450" d:DesignHeight="350"
|
||||
Width="480" Height="360"
|
||||
Padding="16"
|
||||
WindowStartupLocation="CenterOwner"
|
||||
CanResize="False"
|
||||
Title="Dienst (Service) hinzufügen"
|
||||
x:Class="ClawdDotNet.Desktop.Views.AddServiceWindow"
|
||||
x:DataType="vm:AddServiceViewModel">
|
||||
|
||||
<DockPanel>
|
||||
|
||||
<!-- Bottom Buttons -->
|
||||
<StackPanel DockPanel.Dock="Bottom" Orientation="Horizontal" HorizontalAlignment="Right" Spacing="8" Margin="0,16,0,0">
|
||||
<Button Content="Abbrechen" Command="{Binding CancelCommand}" />
|
||||
<Button Content="Hinzufügen" Command="{Binding ConfirmCommand}" Classes="accent" />
|
||||
</StackPanel>
|
||||
|
||||
<TextBlock DockPanel.Dock="Bottom" Text="{Binding StatusMessage}" Foreground="Red" Margin="0,8,0,0" />
|
||||
|
||||
<StackPanel Spacing="12">
|
||||
|
||||
<StackPanel Spacing="4">
|
||||
<TextBlock Text="Name des Dienstes:" FontWeight="Bold" />
|
||||
<TextBox Text="{Binding ServiceName}" PlaceholderText="z.B. WebHookService" />
|
||||
</StackPanel>
|
||||
|
||||
<Grid ColumnDefinitions="*,*" RowDefinitions="Auto,Auto">
|
||||
<StackPanel Grid.Column="0" Spacing="4" Margin="0,0,4,0">
|
||||
<TextBlock Text="Typ:" FontWeight="Bold" />
|
||||
<ComboBox ItemsSource="{Binding AvailableServiceTypes}" SelectedItem="{Binding ServiceType}" HorizontalAlignment="Stretch" />
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel Grid.Column="1" Spacing="4" Margin="4,0,0,0">
|
||||
<TextBlock Text="Port:" FontWeight="Bold" />
|
||||
<NumericUpDown Value="{Binding ServicePort}" Minimum="1" Maximum="65535" FormatString="0" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
|
||||
<StackPanel Spacing="4">
|
||||
<TextBlock Text="Beschreibung:" FontWeight="Bold" />
|
||||
<TextBox Text="{Binding ServiceDescription}" PlaceholderText="Optionale Beschreibung..." AcceptsReturn="True" Height="60" />
|
||||
</StackPanel>
|
||||
|
||||
</StackPanel>
|
||||
|
||||
</DockPanel>
|
||||
|
||||
</Window>
|
||||
@@ -0,0 +1,21 @@
|
||||
using Avalonia.Controls;
|
||||
using ClawdDotNet.Desktop.ViewModels;
|
||||
|
||||
namespace ClawdDotNet.Desktop.Views;
|
||||
|
||||
public partial class AddServiceWindow : Window
|
||||
{
|
||||
public AddServiceWindow()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
protected override void OnDataContextChanged(EventArgs e)
|
||||
{
|
||||
base.OnDataContextChanged(e);
|
||||
if (DataContext is AddServiceViewModel vm)
|
||||
{
|
||||
vm.CloseRequested += () => Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,155 @@
|
||||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:vm="using:ClawdDotNet.Desktop.ViewModels"
|
||||
mc:Ignorable="d" d:DesignWidth="900" d:DesignHeight="700"
|
||||
Padding="16"
|
||||
x:Class="ClawdDotNet.Desktop.Views.AgentsPageView"
|
||||
x:DataType="vm:AgentsPageViewModel">
|
||||
|
||||
<DockPanel>
|
||||
|
||||
<!-- Statusbar am unteren Rand -->
|
||||
<Border Classes="statusbar" DockPanel.Dock="Bottom">
|
||||
<TextBlock Text="{Binding StatusText}" VerticalAlignment="Center" />
|
||||
</Border>
|
||||
|
||||
<!-- Master-Detail Split -->
|
||||
<Grid ColumnDefinitions="260,*">
|
||||
|
||||
<!-- Linke Spalte: Agenten-Liste -->
|
||||
<DockPanel Grid.Column="0" Margin="0,0,12,0">
|
||||
|
||||
<!-- Toolbar -->
|
||||
<StackPanel Classes="toolbar" DockPanel.Dock="Top">
|
||||
<Button Content="Neu" Command="{Binding AddAgentCommand}" Classes="accent" />
|
||||
<Button Content="Entfernen" Command="{Binding RemoveAgentCommand}" IsEnabled="{Binding SelectedAgent, Converter={x:Static ObjectConverters.IsNotNull}}" />
|
||||
<Button Content="Speichern" Command="{Binding SaveAgentsCommand}" />
|
||||
</StackPanel>
|
||||
|
||||
<!-- Liste -->
|
||||
<ListBox ItemsSource="{Binding Agents}" SelectedItem="{Binding SelectedAgent}">
|
||||
<ListBox.ItemTemplate>
|
||||
<DataTemplate DataType="vm:AgentItemViewModel">
|
||||
<StackPanel Margin="4">
|
||||
<TextBlock Text="{Binding DisplayName}" FontWeight="Bold" />
|
||||
<TextBlock Text="{Binding Model}" Classes="caption" />
|
||||
</StackPanel>
|
||||
</DataTemplate>
|
||||
</ListBox.ItemTemplate>
|
||||
</ListBox>
|
||||
|
||||
</DockPanel>
|
||||
|
||||
<!-- Rechte Spalte: Agenten-Details -->
|
||||
<ContentControl Grid.Column="1" Content="{Binding SelectedAgent}">
|
||||
<ContentControl.ContentTemplate>
|
||||
<DataTemplate DataType="vm:AgentItemViewModel">
|
||||
<TabControl>
|
||||
|
||||
<!-- TAB 1: Allgemein & Modell -->
|
||||
<TabItem Header="Allgemein & Modell">
|
||||
<ScrollViewer Padding="8">
|
||||
<StackPanel Spacing="12">
|
||||
|
||||
<Grid ColumnDefinitions="140,*" RowDefinitions="Auto,Auto,Auto,Auto,Auto">
|
||||
<TextBlock Grid.Row="0" Grid.Column="0" Text="Agent ID:" FontWeight="Bold" VerticalAlignment="Center" />
|
||||
<TextBox Grid.Row="0" Grid.Column="1" Text="{Binding AgentId}" IsReadOnly="True" />
|
||||
|
||||
<TextBlock Grid.Row="1" Grid.Column="0" Text="Anzeigename:" FontWeight="Bold" VerticalAlignment="Center" Margin="0,8,0,0" />
|
||||
<TextBox Grid.Row="1" Grid.Column="1" Text="{Binding DisplayName}" Margin="0,8,0,0" />
|
||||
|
||||
<TextBlock Grid.Row="2" Grid.Column="0" Text="Modell:" FontWeight="Bold" VerticalAlignment="Center" Margin="0,8,0,0" />
|
||||
<ComboBox Grid.Row="2" Grid.Column="1" ItemsSource="{Binding $parent[UserControl].((vm:AgentsPageViewModel)DataContext).KnownModels}" SelectedItem="{Binding Model}" HorizontalAlignment="Stretch" Margin="0,8,0,0" />
|
||||
|
||||
<TextBlock Grid.Row="3" Grid.Column="0" Text="Rolle / Beschreibung:" FontWeight="Bold" VerticalAlignment="Center" Margin="0,8,0,0" />
|
||||
<TextBox Grid.Row="3" Grid.Column="1" Text="{Binding Description}" AcceptsReturn="True" Height="60" Margin="0,8,0,0" />
|
||||
|
||||
<TextBlock Grid.Row="4" Grid.Column="0" Text="Prompt Caching:" FontWeight="Bold" VerticalAlignment="Center" Margin="0,8,0,0" />
|
||||
<ComboBox Grid.Row="4" Grid.Column="1" ItemsSource="{Binding $parent[UserControl].((vm:AgentsPageViewModel)DataContext).CachingOptions}" SelectedItem="{Binding PromptCaching}" Width="150" HorizontalAlignment="Left" Margin="0,8,0,0" />
|
||||
</Grid>
|
||||
|
||||
<!-- Limits Card -->
|
||||
<Border Classes="card" Margin="0,8,0,0">
|
||||
<StackPanel Spacing="8">
|
||||
<TextBlock Text="Schutzgrenzen (LoopGuard & Budget)" Classes="heading" />
|
||||
<Grid ColumnDefinitions="*,*" RowDefinitions="Auto,Auto,Auto">
|
||||
<StackPanel Grid.Row="0" Grid.Column="0" Spacing="4">
|
||||
<TextBlock Text="Max. Schritte pro Run:" />
|
||||
<NumericUpDown Value="{Binding MaxSteps}" Minimum="1" Maximum="100" />
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel Grid.Row="0" Grid.Column="1" Spacing="4" Margin="8,0,0,0">
|
||||
<TextBlock Text="Timeout (Sekunden):" />
|
||||
<NumericUpDown Value="{Binding TimeoutSeconds}" Minimum="10" Maximum="3600" />
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel Grid.Row="1" Grid.Column="0" Spacing="4" Margin="0,8,0,0">
|
||||
<TextBlock Text="Max. Kontext-Tokens:" />
|
||||
<NumericUpDown Value="{Binding MaxContextTokens}" Minimum="1000" Maximum="2000000" />
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel Grid.Row="1" Grid.Column="1" Spacing="4" Margin="8,8,0,0">
|
||||
<TextBlock Text="Max. Tool-Ergebnis (Zeichen):" />
|
||||
<NumericUpDown Value="{Binding MaxToolResultChars}" Minimum="1000" Maximum="500000" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
|
||||
</StackPanel>
|
||||
</ScrollViewer>
|
||||
</TabItem>
|
||||
|
||||
<!-- TAB 2: System Prompt & Seele -->
|
||||
<TabItem Header="System-Prompt & Soul">
|
||||
<ScrollViewer Padding="8">
|
||||
<StackPanel Spacing="12">
|
||||
<StackPanel Spacing="4">
|
||||
<TextBlock Text="System-Prompt (Zusätzliche Anweisungen):" FontWeight="Bold" />
|
||||
<TextBox Text="{Binding SystemPrompt}" AcceptsReturn="True" Height="120" TextWrapping="Wrap" />
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel Spacing="4">
|
||||
<TextBlock Text="Identität (Identity):" FontWeight="Bold" />
|
||||
<TextBox Text="{Binding Identity}" AcceptsReturn="True" Height="100" TextWrapping="Wrap" />
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel Spacing="4">
|
||||
<TextBlock Text="Seele & Werte (Soul):" FontWeight="Bold" />
|
||||
<TextBox Text="{Binding Soul}" AcceptsReturn="True" Height="100" TextWrapping="Wrap" />
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</ScrollViewer>
|
||||
</TabItem>
|
||||
|
||||
<!-- TAB 3: Werkzeuge (Tools) -->
|
||||
<TabItem Header="Werkzeuge (Tools)">
|
||||
<ScrollViewer Padding="8">
|
||||
<StackPanel Spacing="8">
|
||||
<TextBlock Text="Zugelassene Werkzeuge für diesen Agenten:" Classes="heading" />
|
||||
<ItemsControl ItemsSource="{Binding AvailableTools}">
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate DataType="vm:ToolItemViewModel">
|
||||
<Grid ColumnDefinitions="200,Auto" Margin="0,4">
|
||||
<CheckBox Content="{Binding Name}" IsChecked="{Binding IsEnabled}" Grid.Column="0" VerticalAlignment="Center" />
|
||||
<Button Content="⚙ Konfigurieren" Command="{Binding $parent[UserControl].((vm:AgentsPageViewModel)DataContext).ConfigureToolCommand}" CommandParameter="{Binding}" IsEnabled="{Binding IsEnabled}" Grid.Column="1" />
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
</StackPanel>
|
||||
</ScrollViewer>
|
||||
</TabItem>
|
||||
|
||||
</TabControl>
|
||||
</DataTemplate>
|
||||
</ContentControl.ContentTemplate>
|
||||
</ContentControl>
|
||||
|
||||
</Grid>
|
||||
|
||||
</DockPanel>
|
||||
|
||||
</UserControl>
|
||||
@@ -0,0 +1,46 @@
|
||||
using Avalonia.Controls;
|
||||
using ClawdDotNet.Desktop.ViewModels;
|
||||
|
||||
namespace ClawdDotNet.Desktop.Views;
|
||||
|
||||
public partial class AgentsPageView : UserControl
|
||||
{
|
||||
public AgentsPageView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
protected override void OnDataContextChanged(EventArgs e)
|
||||
{
|
||||
base.OnDataContextChanged(e);
|
||||
if (DataContext is AgentsPageViewModel vm)
|
||||
{
|
||||
vm.RequestAddAgentDialog += OnRequestAddAgentDialog;
|
||||
vm.RequestToolSettingsDialog += OnRequestToolSettingsDialog;
|
||||
}
|
||||
}
|
||||
|
||||
private async Task<AddAgentResultData?> OnRequestAddAgentDialog(AddAgentViewModel vm)
|
||||
{
|
||||
var topLevel = TopLevel.GetTopLevel(this);
|
||||
if (topLevel is Window window)
|
||||
{
|
||||
var dialog = new AddAgentWindow { DataContext = vm };
|
||||
await dialog.ShowDialog(window);
|
||||
return vm.Result;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private async Task<Dictionary<string, object?>?> OnRequestToolSettingsDialog(ToolSettingsViewModel vm)
|
||||
{
|
||||
var topLevel = TopLevel.GetTopLevel(this);
|
||||
if (topLevel is Window window)
|
||||
{
|
||||
var dialog = new ToolSettingsWindow { DataContext = vm };
|
||||
await dialog.ShowDialog(window);
|
||||
return vm.Result;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:vm="using:ClawdDotNet.Desktop.ViewModels"
|
||||
mc:Ignorable="d" d:DesignWidth="900" d:DesignHeight="700"
|
||||
Padding="16"
|
||||
x:Class="ClawdDotNet.Desktop.Views.BackupPageView"
|
||||
x:DataType="vm:BackupPageViewModel">
|
||||
|
||||
<DockPanel>
|
||||
|
||||
<!-- Statusbar am unteren Rand -->
|
||||
<Border Classes="statusbar" DockPanel.Dock="Bottom">
|
||||
<TextBlock Text="{Binding StatusText}" VerticalAlignment="Center" />
|
||||
</Border>
|
||||
|
||||
<ScrollViewer>
|
||||
<StackPanel Spacing="16">
|
||||
|
||||
<TextBlock Text="Sicherung & Wiederherstellung" Classes="heading" FontSize="20" />
|
||||
|
||||
<!-- Card: Neue Sicherung erstellen -->
|
||||
<Border Classes="card">
|
||||
<StackPanel Spacing="12">
|
||||
<TextBlock Text="Manuelle Sicherung erstellen" Classes="heading" />
|
||||
|
||||
<Grid ColumnDefinitions="*,Auto" RowDefinitions="Auto">
|
||||
<TextBox Text="{Binding TargetFolder}" Grid.Column="0" PlaceholderText="Zielordner für Sicherungen..." />
|
||||
<Button Content="Ordner wählen" Click="OnBrowseTargetFolder" Grid.Column="1" Margin="8,0,0,0" />
|
||||
</Grid>
|
||||
|
||||
<!-- Zugangsdaten Optionen -->
|
||||
<TextBlock Text="Zugangsdaten (API-Schlüssel, Passwörter):" FontWeight="Bold" Margin="0,4,0,0" />
|
||||
<RadioButton Content="Zugangsdaten NICHT mit sichern (ohne Passphrase)" IsChecked="{Binding SecretsExclude}" />
|
||||
<RadioButton Content="Mit Passphrase verschlüsseln" IsChecked="{Binding SecretsPassphrase}" />
|
||||
|
||||
<StackPanel Spacing="8" IsVisible="{Binding SecretsPassphrase}" Margin="20,0,0,0">
|
||||
<TextBox Text="{Binding Passphrase}" PasswordChar="*" PlaceholderText="Passphrase eingeben" Width="300" HorizontalAlignment="Left" />
|
||||
<TextBox Text="{Binding PassphraseRepeat}" PasswordChar="*" PlaceholderText="Passphrase wiederholen" Width="300" HorizontalAlignment="Left" />
|
||||
</StackPanel>
|
||||
|
||||
<!-- Inhalt Optionen -->
|
||||
<CheckBox Content="Protokolle (Logs) mit einschließen" IsChecked="{Binding IncludeLogs}" />
|
||||
<CheckBox Content="Chatverläufe mit einschließen" IsChecked="{Binding IncludeChatHistory}" />
|
||||
|
||||
<Button Content="▶ Sicherung jetzt erstellen" Command="{Binding CreateBackupCommand}"
|
||||
IsEnabled="{Binding !IsBusy}" Classes="accent" HorizontalAlignment="Left" Margin="0,8,0,0" />
|
||||
</StackPanel>
|
||||
</Border>
|
||||
|
||||
<!-- Card: Automatische Sicherung -->
|
||||
<Border Classes="card">
|
||||
<StackPanel Spacing="12">
|
||||
<TextBlock Text="Automatische Sicherung" Classes="heading" />
|
||||
|
||||
<CheckBox Content="Automatische tägliche Sicherung aktivieren" IsChecked="{Binding AutoBackupEnabled}" />
|
||||
|
||||
<StackPanel Orientation="Horizontal" Spacing="16" IsEnabled="{Binding AutoBackupEnabled}">
|
||||
<StackPanel Orientation="Horizontal" Spacing="8">
|
||||
<TextBlock Text="Uhrzeit:" VerticalAlignment="Center" />
|
||||
<TextBox Text="{Binding AutoBackupTime}" Width="80" PlaceholderText="03:00" />
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel Orientation="Horizontal" Spacing="8">
|
||||
<TextBlock Text="Max. Anzahl behalten:" VerticalAlignment="Center" />
|
||||
<NumericUpDown Value="{Binding KeepCount}" Minimum="1" Maximum="999" Width="120" />
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
|
||||
<!-- Vorhandene Sicherungen List -->
|
||||
<Border Classes="card">
|
||||
<DockPanel Height="260">
|
||||
<StackPanel Classes="toolbar" DockPanel.Dock="Top">
|
||||
<TextBlock Text="Vorhandene Sicherungen" Classes="heading" VerticalAlignment="Center" />
|
||||
<Button Content="Aktualisieren" Command="{Binding RefreshBackupListCommand}" Margin="12,0,0,0" />
|
||||
<Button Content="Ordner öffnen" Command="{Binding ShowSelectedInFolderCommand}" IsEnabled="{Binding SelectedBackup, Converter={x:Static ObjectConverters.IsNotNull}}" />
|
||||
<Button Content="Löschen" Command="{Binding DeleteSelectedCommand}" IsEnabled="{Binding SelectedBackup, Converter={x:Static ObjectConverters.IsNotNull}}" />
|
||||
<Button Content="Wiederherstellen..." Command="{Binding RestoreSelectedCommand}" IsEnabled="{Binding SelectedBackup, Converter={x:Static ObjectConverters.IsNotNull}}" Classes="accent" />
|
||||
</StackPanel>
|
||||
|
||||
<DataGrid ItemsSource="{Binding Backups}" SelectedItem="{Binding SelectedBackup}" AutoGenerateColumns="False" IsReadOnly="True">
|
||||
<DataGrid.Columns>
|
||||
<DataGridTextColumn Header="Dateiname" Binding="{Binding FileName}" Width="220" />
|
||||
<DataGridTextColumn Header="Erstellt am" Binding="{Binding LastWriteTime, StringFormat='{}{0:g}'}" Width="150" />
|
||||
<DataGridTextColumn Header="Instanz" Binding="{Binding InstanceName}" Width="130" />
|
||||
<DataGridTextColumn Header="Größe" Binding="{Binding SizeFormatted}" Width="100" />
|
||||
<DataGridTextColumn Header="Zugangsdaten" Binding="{Binding SecretsInfo}" Width="*" />
|
||||
</DataGrid.Columns>
|
||||
</DataGrid>
|
||||
</DockPanel>
|
||||
</Border>
|
||||
|
||||
</StackPanel>
|
||||
</ScrollViewer>
|
||||
|
||||
</DockPanel>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,56 @@
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Interactivity;
|
||||
using Avalonia.Platform.Storage;
|
||||
using ClawdDotNet.Desktop.ViewModels;
|
||||
|
||||
namespace ClawdDotNet.Desktop.Views;
|
||||
|
||||
public partial class BackupPageView : UserControl
|
||||
{
|
||||
public BackupPageView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
protected override void OnDataContextChanged(EventArgs e)
|
||||
{
|
||||
base.OnDataContextChanged(e);
|
||||
if (DataContext is BackupPageViewModel vm)
|
||||
{
|
||||
vm.RequestRestoreDialog += OnRequestRestoreDialog;
|
||||
}
|
||||
}
|
||||
|
||||
private async Task<RestoreResultData?> OnRequestRestoreDialog(RestoreBackupViewModel vm)
|
||||
{
|
||||
var topLevel = TopLevel.GetTopLevel(this);
|
||||
if (topLevel is Window window)
|
||||
{
|
||||
var dialog = new RestoreBackupWindow { DataContext = vm };
|
||||
await dialog.ShowDialog(window);
|
||||
return vm.Result;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private async void OnBrowseTargetFolder(object? sender, RoutedEventArgs e)
|
||||
{
|
||||
if (DataContext is not BackupPageViewModel vm) return;
|
||||
|
||||
var topLevel = TopLevel.GetTopLevel(this);
|
||||
if (topLevel?.StorageProvider is null) return;
|
||||
|
||||
var folders = await topLevel.StorageProvider.OpenFolderPickerAsync(new FolderPickerOpenOptions
|
||||
{
|
||||
Title = "Zielordner für Sicherungen wählen",
|
||||
AllowMultiple = false
|
||||
});
|
||||
|
||||
if (folders.Count > 0 && folders[0].TryGetLocalPath() is { } path)
|
||||
{
|
||||
vm.TargetFolder = path;
|
||||
vm.SaveSettings();
|
||||
vm.RefreshBackupListCommand.Execute(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:vm="using:ClawdDotNet.Desktop.ViewModels"
|
||||
xmlns:conv="using:ClawdDotNet.Desktop.Converters"
|
||||
mc:Ignorable="d" d:DesignWidth="900" d:DesignHeight="700"
|
||||
Padding="16"
|
||||
x:Class="ClawdDotNet.Desktop.Views.ChatPageView"
|
||||
x:DataType="vm:ChatPageViewModel">
|
||||
|
||||
<DockPanel>
|
||||
|
||||
<!-- Statusleiste am unteren Rand -->
|
||||
<Border Classes="statusbar" DockPanel.Dock="Bottom">
|
||||
<TextBlock Text="{Binding StatusText}" VerticalAlignment="Center" />
|
||||
</Border>
|
||||
|
||||
<!-- Top Toolbar -->
|
||||
<StackPanel Classes="toolbar" DockPanel.Dock="Top">
|
||||
<TextBlock Text="Agent:" VerticalAlignment="Center" FontWeight="Bold" />
|
||||
<ComboBox ItemsSource="{Binding AvailableAgents}" SelectedItem="{Binding SelectedAgent}" MinWidth="200">
|
||||
<ComboBox.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<TextBlock Text="{Binding DisplayName}" />
|
||||
</DataTemplate>
|
||||
</ComboBox.ItemTemplate>
|
||||
</ComboBox>
|
||||
|
||||
<Button Content="Verlauf leeren" Command="{Binding ClearHistoryCommand}" Margin="12,0,0,0" />
|
||||
<Button Content="Abbrechen" Command="{Binding AbortCommand}" IsEnabled="{Binding IsSending}" />
|
||||
</StackPanel>
|
||||
|
||||
<!-- Eingabezeile unten -->
|
||||
<Grid DockPanel.Dock="Bottom" ColumnDefinitions="*,Auto" Margin="0,8,0,0">
|
||||
<TextBox Text="{Binding InputPrompt}" PlaceholderText="Nachricht eingeben... (Strg+Eingabe zum Senden)"
|
||||
AcceptsReturn="True" Height="60" TextWrapping="Wrap" Grid.Column="0" KeyDown="OnInputKeyDown" />
|
||||
<Button Content="Senden" Command="{Binding SendMessageCommand}" IsEnabled="{Binding !IsSending}"
|
||||
Classes="accent" VerticalAlignment="Stretch" Margin="8,0,0,0" Grid.Column="1" Width="90" />
|
||||
</Grid>
|
||||
|
||||
<!-- Nachrichtenverlauf (Mitte) -->
|
||||
<ScrollViewer x:Name="ChatScroller">
|
||||
<ItemsControl ItemsSource="{Binding ChatEntries}">
|
||||
<ItemsControl.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<StackPanel Spacing="10" />
|
||||
</ItemsPanelTemplate>
|
||||
</ItemsControl.ItemsPanel>
|
||||
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate DataType="vm:ChatEntryItemViewModel">
|
||||
<!-- Distinct styling: User right-aligned bubble vs Assistant left-aligned card -->
|
||||
<DockPanel HorizontalAlignment="{Binding IsUser, Converter={x:Static conv:ChatAlignmentConverter.Instance}}">
|
||||
<Border Classes="card" CornerRadius="8" MaxWidth="680"
|
||||
Background="{Binding IsUser, Converter={x:Static conv:ChatBubbleBrushConverter.Instance}, TargetNullValue={x:Null}}">
|
||||
<StackPanel Spacing="4">
|
||||
<DockPanel>
|
||||
<TextBlock Text="{Binding Sender}" FontWeight="Bold" FontSize="12" />
|
||||
<TextBlock Text="{Binding Timestamp, StringFormat='{}{0:HH:mm}'}" Classes="caption" HorizontalAlignment="Right" Margin="8,0,0,0" />
|
||||
</DockPanel>
|
||||
|
||||
<SelectableTextBlock Text="{Binding Text}" TextWrapping="Wrap" FontSize="13" />
|
||||
</StackPanel>
|
||||
</Border>
|
||||
</DockPanel>
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
</ScrollViewer>
|
||||
|
||||
</DockPanel>
|
||||
|
||||
</UserControl>
|
||||
@@ -0,0 +1,25 @@
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Input;
|
||||
using ClawdDotNet.Desktop.ViewModels;
|
||||
|
||||
namespace ClawdDotNet.Desktop.Views;
|
||||
|
||||
public partial class ChatPageView : UserControl
|
||||
{
|
||||
public ChatPageView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void OnInputKeyDown(object? sender, KeyEventArgs e)
|
||||
{
|
||||
if (e.Key == Key.Enter && e.KeyModifiers.HasFlag(KeyModifiers.Control))
|
||||
{
|
||||
if (DataContext is ChatPageViewModel vm && vm.SendMessageCommand.CanExecute(null))
|
||||
{
|
||||
vm.SendMessageCommand.Execute(null);
|
||||
e.Handled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:vm="using:ClawdDotNet.Desktop.ViewModels"
|
||||
mc:Ignorable="d" d:DesignWidth="900" d:DesignHeight="600"
|
||||
x:Class="ClawdDotNet.Desktop.Views.InfoPageView"
|
||||
x:DataType="vm:InfoPageViewModel">
|
||||
|
||||
<ScrollViewer Padding="16">
|
||||
<StackPanel Spacing="16">
|
||||
|
||||
<!-- Titel -->
|
||||
<TextBlock Text="Software- & Instanz-Informationen" Classes="heading" FontSize="20" />
|
||||
|
||||
<!-- Anwendungs-Details Card -->
|
||||
<Border Classes="card">
|
||||
<StackPanel Spacing="8">
|
||||
<TextBlock Text="Anwendung" Classes="heading" />
|
||||
<Grid RowDefinitions="Auto,Auto" ColumnDefinitions="140,*">
|
||||
<TextBlock Grid.Row="0" Grid.Column="0" Text="Version:" FontWeight="Bold" />
|
||||
<TextBlock Grid.Row="0" Grid.Column="1" Text="{Binding AppVersion}" />
|
||||
|
||||
<TextBlock Grid.Row="1" Grid.Column="0" Text="Build-Summary:" FontWeight="Bold" Margin="0,4,0,0" />
|
||||
<TextBlock Grid.Row="1" Grid.Column="1" Text="{Binding BuildSummary}" Margin="0,4,0,0" TextWrapping="Wrap" />
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
|
||||
<!-- Instanz-Details Card -->
|
||||
<Border Classes="card">
|
||||
<StackPanel Spacing="8">
|
||||
<TextBlock Text="Aktuelle Instanz" Classes="heading" />
|
||||
<Grid RowDefinitions="Auto,Auto,Auto,Auto,Auto" ColumnDefinitions="140,*">
|
||||
<TextBlock Grid.Row="0" Grid.Column="0" Text="Name:" FontWeight="Bold" />
|
||||
<TextBlock Grid.Row="0" Grid.Column="1" Text="{Binding InstanceName}" />
|
||||
|
||||
<TextBlock Grid.Row="1" Grid.Column="0" Text="ID:" FontWeight="Bold" Margin="0,4,0,0" />
|
||||
<TextBlock Grid.Row="1" Grid.Column="1" Text="{Binding InstanceId}" Margin="0,4,0,0" />
|
||||
|
||||
<TextBlock Grid.Row="2" Grid.Column="0" Text="Pfad:" FontWeight="Bold" Margin="0,4,0,0" />
|
||||
<TextBlock Grid.Row="2" Grid.Column="1" Text="{Binding InstancePath}" Margin="0,4,0,0" TextWrapping="Wrap" />
|
||||
|
||||
<TextBlock Grid.Row="3" Grid.Column="0" Text="Log-Ordner:" FontWeight="Bold" Margin="0,4,0,0" />
|
||||
<TextBlock Grid.Row="3" Grid.Column="1" Text="{Binding LogDirectory}" Margin="0,4,0,0" TextWrapping="Wrap" />
|
||||
|
||||
<TextBlock Grid.Row="4" Grid.Column="0" Text="OpenRouter Status:" FontWeight="Bold" Margin="0,4,0,0" />
|
||||
<TextBlock Grid.Row="4" Grid.Column="1" Text="{Binding OpenRouterStatus}" Margin="0,4,0,0" />
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
|
||||
<!-- Assembly Build Info Card -->
|
||||
<Border Classes="card">
|
||||
<StackPanel Spacing="8">
|
||||
<TextBlock Text="Module & Baugruppen" Classes="heading" />
|
||||
<DataGrid ItemsSource="{Binding Assemblies}" AutoGenerateColumns="False" IsReadOnly="True" GridLinesVisibility="Horizontal">
|
||||
<DataGrid.Columns>
|
||||
<DataGridTextColumn Header="Modul" Binding="{Binding ShortName}" Width="160" />
|
||||
<DataGridTextColumn Header="Build #" Binding="{Binding BuildNumber}" Width="80" />
|
||||
<DataGridTextColumn Header="Build-Datum" Binding="{Binding BuildDate}" Width="160" />
|
||||
<DataGridTextColumn Header="Änderungen" Binding="{Binding Changes}" Width="*" />
|
||||
</DataGrid.Columns>
|
||||
</DataGrid>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
|
||||
</StackPanel>
|
||||
</ScrollViewer>
|
||||
|
||||
</UserControl>
|
||||
@@ -0,0 +1,11 @@
|
||||
using Avalonia.Controls;
|
||||
|
||||
namespace ClawdDotNet.Desktop.Views;
|
||||
|
||||
public partial class InfoPageView : UserControl
|
||||
{
|
||||
public InfoPageView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
<Window xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:vm="using:ClawdDotNet.Desktop.ViewModels"
|
||||
xmlns:models="using:ClawdDotNet.App.Models"
|
||||
mc:Ignorable="d" d:DesignWidth="720" d:DesignHeight="460"
|
||||
x:Class="ClawdDotNet.Desktop.Views.InstancePickerWindow"
|
||||
x:DataType="vm:InstancePickerViewModel"
|
||||
Icon="/Assets/app.ico"
|
||||
Title="ClawdDotNet – Instanz wählen"
|
||||
Width="720" Height="460"
|
||||
WindowStartupLocation="CenterScreen">
|
||||
|
||||
<DockPanel Margin="16">
|
||||
|
||||
<TextBlock DockPanel.Dock="Top" Classes="heading" Text="Instanz wählen" />
|
||||
|
||||
<TextBlock DockPanel.Dock="Top" Classes="caption" Margin="0,0,0,12"
|
||||
TextWrapping="Wrap"
|
||||
Text="{Binding InstancesDirectory, StringFormat='Verzeichnis: {0}'}" />
|
||||
|
||||
<!-- Fehlerzeile: nimmt keinen Platz weg, solange nichts anliegt -->
|
||||
<TextBlock DockPanel.Dock="Bottom"
|
||||
Margin="0,8,0,0"
|
||||
Foreground="{DynamicResource SystemFillColorCriticalBrush}"
|
||||
TextWrapping="Wrap"
|
||||
Text="{Binding ErrorText}"
|
||||
IsVisible="{Binding ErrorText, Converter={x:Static StringConverters.IsNotNullOrEmpty}}" />
|
||||
|
||||
<!-- Aktionen -->
|
||||
<Grid DockPanel.Dock="Bottom" ColumnDefinitions="*,Auto,Auto" Margin="0,12,0,0">
|
||||
|
||||
<StackPanel Orientation="Horizontal" Spacing="6" Grid.Column="0">
|
||||
<TextBox Width="200"
|
||||
Watermark="Name der neuen Instanz"
|
||||
Text="{Binding NewInstanceName}" />
|
||||
<Button Content="Anlegen" Command="{Binding CreateCommand}" />
|
||||
</StackPanel>
|
||||
|
||||
<Button Grid.Column="1" Content="Abbrechen" Margin="0,0,6,0"
|
||||
Command="{Binding CancelCommand}" />
|
||||
|
||||
<Button Grid.Column="2" Content="Starten"
|
||||
Classes="accent"
|
||||
IsDefault="True"
|
||||
Command="{Binding StartCommand}" />
|
||||
</Grid>
|
||||
|
||||
<!-- Liste -->
|
||||
<DataGrid ItemsSource="{Binding Instances}"
|
||||
SelectedItem="{Binding Selected}"
|
||||
AutoGenerateColumns="False"
|
||||
IsReadOnly="True"
|
||||
SelectionMode="Single"
|
||||
GridLinesVisibility="Horizontal">
|
||||
|
||||
<DataGrid.Columns>
|
||||
<DataGridTextColumn Header="Instanzname" Width="2*"
|
||||
Binding="{Binding InstanceName, x:DataType=models:InstanceInfo}" />
|
||||
<DataGridTextColumn Header="Ordner" Width="2*"
|
||||
Binding="{Binding FolderName, x:DataType=models:InstanceInfo}" />
|
||||
<DataGridTextColumn Header="Agenten" Width="Auto"
|
||||
Binding="{Binding AgentCount, x:DataType=models:InstanceInfo}" />
|
||||
<DataGridTextColumn Header="API-Key" Width="Auto"
|
||||
Binding="{Binding ApiKeyStatus, x:DataType=models:InstanceInfo}" />
|
||||
</DataGrid.Columns>
|
||||
|
||||
</DataGrid>
|
||||
|
||||
</DockPanel>
|
||||
|
||||
</Window>
|
||||
@@ -0,0 +1,24 @@
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Input;
|
||||
using ClawdDotNet.Desktop.ViewModels;
|
||||
|
||||
namespace ClawdDotNet.Desktop.Views;
|
||||
|
||||
public partial class InstancePickerWindow : Window
|
||||
{
|
||||
public InstancePickerWindow()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
// Doppelklick auf eine Zeile startet — wie in der WinForms-Fassung. Das laesst
|
||||
// sich nicht sinnvoll als Befehl binden, weil DataGrid kein DoubleTapped je
|
||||
// Zeile anbietet; deshalb hier und nicht im Ansichtsmodell.
|
||||
AddHandler(DoubleTappedEvent, OnDoubleTapped, handledEventsToo: false);
|
||||
}
|
||||
|
||||
private void OnDoubleTapped(object? sender, TappedEventArgs e)
|
||||
{
|
||||
if (DataContext is InstancePickerViewModel vm && vm.StartCommand.CanExecute(null))
|
||||
vm.StartCommand.Execute(null);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
<Window xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:vm="using:ClawdDotNet.Desktop.ViewModels"
|
||||
mc:Ignorable="d" d:DesignWidth="520" d:DesignHeight="320"
|
||||
x:Class="ClawdDotNet.Desktop.Views.LicenseWindow"
|
||||
x:DataType="vm:LicenseViewModel"
|
||||
Icon="/Assets/app.ico"
|
||||
Title="ClawdDotNet – Lizenz"
|
||||
Width="520" SizeToContent="Height"
|
||||
CanResize="False"
|
||||
WindowStartupLocation="CenterScreen">
|
||||
|
||||
<StackPanel Margin="20" Spacing="12">
|
||||
|
||||
<TextBlock Classes="heading" Text="Lizenzschlüssel" />
|
||||
|
||||
<!-- Nur sichtbar, wenn es einen Grund gibt -->
|
||||
<Border Classes="card"
|
||||
IsVisible="{Binding Problem, Converter={x:Static StringConverters.IsNotNullOrEmpty}}">
|
||||
<TextBlock Text="{Binding Problem}" TextWrapping="Wrap"
|
||||
Foreground="{DynamicResource SystemFillColorCriticalBrush}" />
|
||||
</Border>
|
||||
|
||||
<TextBox Watermark="XXXXX-XXXXX-XXXXX-XXXXX-XXXXX"
|
||||
Text="{Binding Key}"
|
||||
FontFamily="{DynamicResource ContentControlThemeFontFamily}" />
|
||||
|
||||
<StackPanel Spacing="4">
|
||||
<TextBlock Classes="caption" Text="Hardware-ID (für den Support):" />
|
||||
<SelectableTextBlock Classes="caption"
|
||||
Text="{Binding HardwareId}"
|
||||
TextWrapping="Wrap" />
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel Orientation="Horizontal" Spacing="8" HorizontalAlignment="Right">
|
||||
<Button Content="Beenden" Command="{Binding CancelCommand}" />
|
||||
<Button Content="Prüfen" Classes="accent" IsDefault="True"
|
||||
Command="{Binding ConfirmCommand}" />
|
||||
</StackPanel>
|
||||
|
||||
</StackPanel>
|
||||
|
||||
</Window>
|
||||
@@ -0,0 +1,16 @@
|
||||
using Avalonia.Controls;
|
||||
using ClawdDotNet.Desktop.ViewModels;
|
||||
|
||||
namespace ClawdDotNet.Desktop.Views;
|
||||
|
||||
public partial class LicenseWindow : Window
|
||||
{
|
||||
public LicenseWindow()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
// Wer das Fenster ueber das Kreuz schliesst, hat abgebrochen. Ohne das bliebe
|
||||
// der wartende Task fuer immer offen und der Start haenge.
|
||||
Closed += (_, _) => (DataContext as LicenseViewModel)?.CancelIfPending();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:vm="using:ClawdDotNet.Desktop.ViewModels"
|
||||
xmlns:svc="using:ClawdDotNet.App.Services"
|
||||
xmlns:conv="using:ClawdDotNet.Desktop.Converters"
|
||||
mc:Ignorable="d" d:DesignWidth="900" d:DesignHeight="600"
|
||||
x:Class="ClawdDotNet.Desktop.Views.LogPageView"
|
||||
x:DataType="vm:LogPageViewModel">
|
||||
|
||||
<DockPanel>
|
||||
|
||||
<!-- Werkzeugleiste -->
|
||||
<StackPanel Classes="toolbar" DockPanel.Dock="Top">
|
||||
|
||||
<TextBlock Text="Modul:" VerticalAlignment="Center" />
|
||||
<ComboBox ItemsSource="{Binding Modules}"
|
||||
SelectedItem="{Binding SelectedModule}"
|
||||
MinWidth="180" />
|
||||
|
||||
<TextBlock Text="Stufe:" VerticalAlignment="Center" Margin="12,0,0,0" />
|
||||
<ComboBox ItemsSource="{Binding Levels}"
|
||||
SelectedItem="{Binding SelectedLevel}"
|
||||
MinWidth="100" />
|
||||
|
||||
<Button Content="Aktualisieren" Command="{Binding RefreshModulesCommand}" Margin="12,0,0,0" />
|
||||
<Button Content="Leeren" Command="{Binding ClearCommand}" />
|
||||
<Button Content="Ordner öffnen" Command="{Binding OpenFolderCommand}" />
|
||||
|
||||
<CheckBox Content="Mitlaufen" IsChecked="{Binding FollowTail}"
|
||||
VerticalAlignment="Center" Margin="12,0,0,0" />
|
||||
|
||||
</StackPanel>
|
||||
|
||||
<!--
|
||||
SelectableTextBlock je Zeile statt eines grossen TextBlocks: So laesst sich eine
|
||||
einzelne Zeile herauskopieren, und die Virtualisierung des ItemsControl haelt auch
|
||||
bei 2000 Zeilen die Darstellung fluessig.
|
||||
-->
|
||||
<ScrollViewer Name="Scroller" Padding="8">
|
||||
<ItemsControl ItemsSource="{Binding Lines}">
|
||||
|
||||
<ItemsControl.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<VirtualizingStackPanel />
|
||||
</ItemsPanelTemplate>
|
||||
</ItemsControl.ItemsPanel>
|
||||
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate DataType="svc:LogLine">
|
||||
<SelectableTextBlock Text="{Binding Text}"
|
||||
FontFamily="Consolas, Menlo, DejaVu Sans Mono, monospace"
|
||||
FontSize="12"
|
||||
TextWrapping="NoWrap"
|
||||
Foreground="{Binding Level,
|
||||
Converter={x:Static conv:LogLevelBrushConverter.Instance},
|
||||
TargetNullValue={x:Null}}" />
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
|
||||
</ItemsControl>
|
||||
</ScrollViewer>
|
||||
|
||||
</DockPanel>
|
||||
|
||||
</UserControl>
|
||||
@@ -0,0 +1,21 @@
|
||||
using Avalonia.Controls;
|
||||
using ClawdDotNet.Desktop.ViewModels;
|
||||
|
||||
namespace ClawdDotNet.Desktop.Views;
|
||||
|
||||
public partial class LogPageView : UserControl
|
||||
{
|
||||
public LogPageView()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
// Mitlaufen: Nach jeder neuen Zeile ans Ende springen — aber nur, solange der
|
||||
// Haken gesetzt ist. Das gehoert in die Ansicht, weil nur sie den ScrollViewer
|
||||
// kennt; das Ansichtsmodell haelt lediglich den Schalter.
|
||||
Scroller.ScrollChanged += (_, _) =>
|
||||
{
|
||||
if (DataContext is LogPageViewModel { FollowTail: true })
|
||||
Scroller.ScrollToEnd();
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
<Window xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:vm="using:ClawdDotNet.Desktop.ViewModels"
|
||||
mc:Ignorable="d" d:DesignWidth="1100" d:DesignHeight="700"
|
||||
x:Class="ClawdDotNet.Desktop.Views.MainWindow"
|
||||
x:DataType="vm:MainWindowViewModel"
|
||||
Icon="/Assets/app.ico"
|
||||
Title="ClawdDotNet"
|
||||
Width="1100" Height="700"
|
||||
MinWidth="800" MinHeight="500">
|
||||
|
||||
<Design.DataContext>
|
||||
<vm:MainWindowViewModel />
|
||||
</Design.DataContext>
|
||||
|
||||
<DockPanel>
|
||||
|
||||
<!-- Haupt-Menüleiste -->
|
||||
<Menu DockPanel.Dock="Top">
|
||||
<MenuItem Header="_Datei">
|
||||
<MenuItem Header="_Beenden" Command="{Binding ExitCommand}" InputGesture="Alt+F4" />
|
||||
</MenuItem>
|
||||
<MenuItem Header="_Bearbeiten">
|
||||
<MenuItem Header="_Instanz-Ordner öffnen" Command="{Binding OpenInstanceFolderCommand}" />
|
||||
<MenuItem Header="_Log-Ordner öffnen" Command="{Binding OpenLogFolderCommand}" />
|
||||
</MenuItem>
|
||||
<MenuItem Header="_Instanz">
|
||||
<MenuItem Header="_Instanz-Manager..." Command="{Binding OpenInstanceManagerCommand}" />
|
||||
</MenuItem>
|
||||
<MenuItem Header="_Ansicht">
|
||||
<MenuItem Header="_Chat" Command="{Binding SelectPageByTitleCommand}" CommandParameter="Chat" />
|
||||
<MenuItem Header="_Logs" Command="{Binding SelectPageByTitleCommand}" CommandParameter="Logs" />
|
||||
<MenuItem Header="_Agenten" Command="{Binding SelectPageByTitleCommand}" CommandParameter="Agenten" />
|
||||
<MenuItem Header="_Einstellungen" Command="{Binding SelectPageByTitleCommand}" CommandParameter="Einstellungen" />
|
||||
<MenuItem Header="_Aufgaben" Command="{Binding SelectPageByTitleCommand}" CommandParameter="Aufgaben" />
|
||||
<MenuItem Header="_Sicherung" Command="{Binding SelectPageByTitleCommand}" CommandParameter="Sicherung" />
|
||||
<MenuItem Header="_Info" Command="{Binding SelectPageByTitleCommand}" CommandParameter="Info" />
|
||||
</MenuItem>
|
||||
<MenuItem Header="_Hilfe">
|
||||
<MenuItem Header="_Info" Command="{Binding SelectPageByTitleCommand}" CommandParameter="Info" />
|
||||
</MenuItem>
|
||||
</Menu>
|
||||
|
||||
<!-- Statusleiste -->
|
||||
<Border Classes="statusbar" DockPanel.Dock="Bottom">
|
||||
<TextBlock Classes="caption" Text="{Binding StatusText}" />
|
||||
</Border>
|
||||
|
||||
<!-- Bereiche (Seitenleiste links) -->
|
||||
<TabControl ItemsSource="{Binding Pages}"
|
||||
SelectedItem="{Binding SelectedPage}"
|
||||
TabStripPlacement="Left">
|
||||
|
||||
<TabControl.ItemTemplate>
|
||||
<DataTemplate DataType="vm:PageViewModel">
|
||||
<TextBlock Text="{Binding Title}" Margin="4,8" />
|
||||
</DataTemplate>
|
||||
</TabControl.ItemTemplate>
|
||||
|
||||
<TabControl.ContentTemplate>
|
||||
<DataTemplate DataType="vm:PageViewModel">
|
||||
<ContentControl Content="{Binding}" />
|
||||
</DataTemplate>
|
||||
</TabControl.ContentTemplate>
|
||||
|
||||
</TabControl>
|
||||
|
||||
</DockPanel>
|
||||
|
||||
</Window>
|
||||
@@ -0,0 +1,28 @@
|
||||
using Avalonia.Controls;
|
||||
using ClawdDotNet.Desktop.ViewModels;
|
||||
|
||||
namespace ClawdDotNet.Desktop.Views;
|
||||
|
||||
public partial class MainWindow : Window
|
||||
{
|
||||
public MainWindow()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
protected override void OnDataContextChanged(EventArgs e)
|
||||
{
|
||||
base.OnDataContextChanged(e);
|
||||
if (DataContext is MainWindowViewModel vm)
|
||||
{
|
||||
vm.RequestExit += Close;
|
||||
vm.RequestInstanceManagerDialog += OnOpenInstanceManager;
|
||||
}
|
||||
}
|
||||
|
||||
private async void OnOpenInstanceManager()
|
||||
{
|
||||
var dialog = new InstancePickerWindow();
|
||||
await dialog.ShowDialog(this);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:vm="using:ClawdDotNet.Desktop.ViewModels"
|
||||
mc:Ignorable="d" d:DesignWidth="700" d:DesignHeight="400"
|
||||
x:Class="ClawdDotNet.Desktop.Views.PlaceholderPageView"
|
||||
x:DataType="vm:PlaceholderPageViewModel">
|
||||
|
||||
<Border Classes="card" Margin="16" VerticalAlignment="Top">
|
||||
<StackPanel Spacing="6">
|
||||
<TextBlock Classes="heading" Text="{Binding Title}" />
|
||||
<TextBlock Classes="caption" Text="{Binding Note}" TextWrapping="Wrap" />
|
||||
<TextBlock Classes="caption" Margin="0,8,0,0"
|
||||
Text="Dieser Bereich ist noch nicht portiert." />
|
||||
</StackPanel>
|
||||
</Border>
|
||||
|
||||
</UserControl>
|
||||
@@ -0,0 +1,8 @@
|
||||
using Avalonia.Controls;
|
||||
|
||||
namespace ClawdDotNet.Desktop.Views;
|
||||
|
||||
public partial class PlaceholderPageView : UserControl
|
||||
{
|
||||
public PlaceholderPageView() => InitializeComponent();
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
<Window xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:vm="using:ClawdDotNet.Desktop.ViewModels"
|
||||
mc:Ignorable="d" d:DesignWidth="600" d:DesignHeight="400"
|
||||
Width="640" Height="420"
|
||||
Padding="16"
|
||||
WindowStartupLocation="CenterOwner"
|
||||
CanResize="False"
|
||||
Title="Sicherung wiederherstellen"
|
||||
x:Class="ClawdDotNet.Desktop.Views.RestoreBackupWindow"
|
||||
x:DataType="vm:RestoreBackupViewModel">
|
||||
|
||||
<DockPanel>
|
||||
|
||||
<!-- Buttons unten -->
|
||||
<StackPanel DockPanel.Dock="Bottom" Orientation="Horizontal" HorizontalAlignment="Right" Spacing="8" Margin="0,16,0,0">
|
||||
<Button Content="Abbrechen" Command="{Binding CancelCommand}" />
|
||||
<Button Content="Wiederherstellen" Command="{Binding ConfirmCommand}" Classes="accent" />
|
||||
</StackPanel>
|
||||
|
||||
<!-- Statusmeldung unten -->
|
||||
<TextBlock DockPanel.Dock="Bottom" Text="{Binding StatusMessage}" Foreground="Red" Margin="0,8,0,0" TextWrapping="Wrap" />
|
||||
|
||||
<ScrollViewer>
|
||||
<StackPanel Spacing="12">
|
||||
|
||||
<!-- Information -->
|
||||
<Border Classes="card">
|
||||
<StackPanel Spacing="4">
|
||||
<TextBlock Text="Sicherungsinformationen" Classes="heading" />
|
||||
<TextBlock Text="{Binding InstanceName, StringFormat='Instanz: {0}'}" />
|
||||
<TextBlock Text="{Binding CreatedAt, StringFormat='Erstellt: {0:g}'}" />
|
||||
<TextBlock Text="{Binding FileCount, StringFormat='Dateien: {0}'}" />
|
||||
<TextBlock Text="{Binding SecretsDescription, StringFormat='Zugangsdaten: {0}'}" />
|
||||
</StackPanel>
|
||||
</Border>
|
||||
|
||||
<!-- Zielordner -->
|
||||
<StackPanel Spacing="4">
|
||||
<TextBlock Text="Zielordner:" FontWeight="Bold" />
|
||||
<Grid ColumnDefinitions="*,Auto">
|
||||
<TextBox Text="{Binding TargetDirectory}" Grid.Column="0" />
|
||||
<Button Content="Ordner wählen" Click="OnBrowseFolder" Grid.Column="1" Margin="8,0,0,0" />
|
||||
</Grid>
|
||||
<TextBlock Text="Hinweis: Es wird empfohlen, in einen neuen Ordner wiederherzustellen, um Konflikte mit laufenden Prozessen zu vermeiden."
|
||||
Classes="caption" TextWrapping="Wrap" />
|
||||
</StackPanel>
|
||||
|
||||
<!-- Passphrase -->
|
||||
<StackPanel Spacing="4" IsVisible="{Binding NeedsPassphrase}">
|
||||
<TextBlock Text="Passphrase:" FontWeight="Bold" />
|
||||
<TextBox Text="{Binding Passphrase}" PasswordChar="*" />
|
||||
<TextBlock Text="Diese Sicherung enthält geschützte Zugangsdaten." Classes="caption" />
|
||||
</StackPanel>
|
||||
|
||||
<!-- Überschreiben -->
|
||||
<CheckBox Content="Vorhandene Dateien im Zielordner überschreiben" IsChecked="{Binding Overwrite}" Margin="0,8,0,0" />
|
||||
|
||||
</StackPanel>
|
||||
</ScrollViewer>
|
||||
|
||||
</DockPanel>
|
||||
|
||||
</Window>
|
||||
@@ -0,0 +1,42 @@
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Interactivity;
|
||||
using Avalonia.Platform.Storage;
|
||||
using ClawdDotNet.Desktop.ViewModels;
|
||||
|
||||
namespace ClawdDotNet.Desktop.Views;
|
||||
|
||||
public partial class RestoreBackupWindow : Window
|
||||
{
|
||||
public RestoreBackupWindow()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
protected override void OnDataContextChanged(EventArgs e)
|
||||
{
|
||||
base.OnDataContextChanged(e);
|
||||
if (DataContext is RestoreBackupViewModel vm)
|
||||
{
|
||||
vm.CloseRequested += () => Close();
|
||||
}
|
||||
}
|
||||
|
||||
private async void OnBrowseFolder(object? sender, RoutedEventArgs e)
|
||||
{
|
||||
if (DataContext is not RestoreBackupViewModel vm) return;
|
||||
|
||||
var storage = StorageProvider;
|
||||
if (storage is null) return;
|
||||
|
||||
var folders = await storage.OpenFolderPickerAsync(new FolderPickerOpenOptions
|
||||
{
|
||||
Title = "Zielordner für Wiederherstellung wählen",
|
||||
AllowMultiple = false
|
||||
});
|
||||
|
||||
if (folders.Count > 0 && folders[0].TryGetLocalPath() is { } path)
|
||||
{
|
||||
vm.TargetDirectory = path;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:vm="using:ClawdDotNet.Desktop.ViewModels"
|
||||
mc:Ignorable="d" d:DesignWidth="900" d:DesignHeight="700"
|
||||
Padding="16"
|
||||
x:Class="ClawdDotNet.Desktop.Views.SettingsPageView"
|
||||
x:DataType="vm:SettingsPageViewModel">
|
||||
|
||||
<DockPanel>
|
||||
|
||||
<!-- Statusbar am unteren Rand -->
|
||||
<Border Classes="statusbar" DockPanel.Dock="Bottom">
|
||||
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right" Spacing="8">
|
||||
<Button Content="Verwerfen / Zurücksetzen" Command="{Binding LoadFromHostCommand}" />
|
||||
<Button Content="Speichern" Command="{Binding SaveSettingsCommand}" Classes="accent" />
|
||||
</StackPanel>
|
||||
</Border>
|
||||
|
||||
<ScrollViewer>
|
||||
<StackPanel Spacing="16">
|
||||
|
||||
<TextBlock Text="Anwendungs- & Instanz-Einstellungen" Classes="heading" FontSize="20" />
|
||||
|
||||
<!-- Card: Instanz-Einstellungen -->
|
||||
<Border Classes="card">
|
||||
<StackPanel Spacing="12">
|
||||
<TextBlock Text="Aktuelle Instanz" Classes="heading" />
|
||||
|
||||
<Grid ColumnDefinitions="180,*" RowDefinitions="Auto,Auto,Auto,Auto">
|
||||
<TextBlock Grid.Row="0" Grid.Column="0" Text="Instanz-Name:" FontWeight="Bold" VerticalAlignment="Center" />
|
||||
<TextBox Grid.Row="0" Grid.Column="1" Text="{Binding InstanceName}" />
|
||||
|
||||
<TextBlock Grid.Row="1" Grid.Column="0" Text="OpenRouter API-Key:" FontWeight="Bold" VerticalAlignment="Center" Margin="0,8,0,0" />
|
||||
<TextBox Grid.Row="1" Grid.Column="1" Text="{Binding OpenRouterApiKey}" PasswordChar="*" Margin="0,8,0,0" />
|
||||
|
||||
<TextBlock Grid.Row="2" Grid.Column="0" Text="Tagesbudget ($ USD):" FontWeight="Bold" VerticalAlignment="Center" Margin="0,8,0,0" />
|
||||
<NumericUpDown Grid.Row="2" Grid.Column="1" Value="{Binding InstanceDailyCostUsd}" Minimum="0" Maximum="10000" FormatString="F2" Width="140" HorizontalAlignment="Left" Margin="0,8,0,0" />
|
||||
|
||||
<TextBlock Grid.Row="3" Grid.Column="0" Text="Tagesbudget (Tokens):" FontWeight="Bold" VerticalAlignment="Center" Margin="0,8,0,0" />
|
||||
<NumericUpDown Grid.Row="3" Grid.Column="1" Value="{Binding InstanceDailyTokens}" Minimum="0" Maximum="100000000" FormatString="0" Width="180" HorizontalAlignment="Left" Margin="0,8,0,0" />
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
|
||||
<!-- Card: Allgemein & Pfade -->
|
||||
<Border Classes="card">
|
||||
<StackPanel Spacing="12">
|
||||
<TextBlock Text="Allgemein & Pfade" Classes="heading" />
|
||||
|
||||
<Grid ColumnDefinitions="180,*" RowDefinitions="Auto,Auto,Auto,Auto">
|
||||
<TextBlock Grid.Row="0" Grid.Column="0" Text="Log-Verzeichnis:" FontWeight="Bold" VerticalAlignment="Center" />
|
||||
<TextBox Grid.Row="0" Grid.Column="1" Text="{Binding LogDirectory}" />
|
||||
|
||||
<TextBlock Grid.Row="1" Grid.Column="0" Text="Instanzen-Verzeichnis:" FontWeight="Bold" VerticalAlignment="Center" Margin="0,8,0,0" />
|
||||
<TextBox Grid.Row="1" Grid.Column="1" Text="{Binding InstancesDirectory}" Margin="0,8,0,0" />
|
||||
|
||||
<TextBlock Grid.Row="2" Grid.Column="0" Text="Minimaler Log-Level:" FontWeight="Bold" VerticalAlignment="Center" Margin="0,8,0,0" />
|
||||
<ComboBox Grid.Row="2" Grid.Column="1" ItemsSource="{Binding LogLevels}" SelectedItem="{Binding MinimumLogLevel}" Width="140" HorizontalAlignment="Left" Margin="0,8,0,0" />
|
||||
|
||||
<TextBlock Grid.Row="3" Grid.Column="0" Text="OpenRouter Base-URL:" FontWeight="Bold" VerticalAlignment="Center" Margin="0,8,0,0" />
|
||||
<TextBox Grid.Row="3" Grid.Column="1" Text="{Binding OpenRouterBaseUrl}" Margin="0,8,0,0" />
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
|
||||
<!-- Card: Deploymentcenter & Lizenz -->
|
||||
<Border Classes="card">
|
||||
<StackPanel Spacing="12">
|
||||
<TextBlock Text="Deploymentcenter & Lizenz" Classes="heading" />
|
||||
|
||||
<Grid ColumnDefinitions="180,*" RowDefinitions="Auto,Auto,Auto,Auto,Auto">
|
||||
<TextBlock Grid.Row="0" Grid.Column="0" Text="Server-URL:" FontWeight="Bold" VerticalAlignment="Center" />
|
||||
<TextBox Grid.Row="0" Grid.Column="1" Text="{Binding DeploymentcenterUrl}" />
|
||||
|
||||
<TextBlock Grid.Row="1" Grid.Column="0" Text="Master-Token:" FontWeight="Bold" VerticalAlignment="Center" Margin="0,8,0,0" />
|
||||
<TextBox Grid.Row="1" Grid.Column="1" Text="{Binding DeploymentcenterToken}" PasswordChar="*" Margin="0,8,0,0" />
|
||||
|
||||
<TextBlock Grid.Row="2" Grid.Column="0" Text="Update-Kanal:" FontWeight="Bold" VerticalAlignment="Center" Margin="0,8,0,0" />
|
||||
<ComboBox Grid.Row="2" Grid.Column="1" ItemsSource="{Binding UpdateChannels}" SelectedItem="{Binding UpdateChannel}" Width="140" HorizontalAlignment="Left" Margin="0,8,0,0" />
|
||||
|
||||
<TextBlock Grid.Row="3" Grid.Column="0" Text="Umgebung:" FontWeight="Bold" VerticalAlignment="Center" Margin="0,8,0,0" />
|
||||
<ComboBox Grid.Row="3" Grid.Column="1" ItemsSource="{Binding Environments}" SelectedItem="{Binding DeploymentcenterEnvironment}" Width="160" HorizontalAlignment="Left" Margin="0,8,0,0" />
|
||||
|
||||
<TextBlock Grid.Row="4" Grid.Column="0" Text="Lizenzschlüssel:" FontWeight="Bold" VerticalAlignment="Center" Margin="0,8,0,0" />
|
||||
<TextBox Grid.Row="4" Grid.Column="1" Text="{Binding LicenseKey}" PasswordChar="*" Margin="0,8,0,0" />
|
||||
</Grid>
|
||||
|
||||
<CheckBox Content="Fehler automatisch an Deploymentcenter melden" IsChecked="{Binding ErrorReportingEnabled}" Margin="0,4,0,0" />
|
||||
<CheckBox Content="Beim Start automatisch auf Updates prüfen" IsChecked="{Binding UpdateCheckEnabled}" />
|
||||
</StackPanel>
|
||||
</Border>
|
||||
|
||||
</StackPanel>
|
||||
</ScrollViewer>
|
||||
|
||||
</DockPanel>
|
||||
|
||||
</UserControl>
|
||||
@@ -0,0 +1,11 @@
|
||||
using Avalonia.Controls;
|
||||
|
||||
namespace ClawdDotNet.Desktop.Views;
|
||||
|
||||
public partial class SettingsPageView : UserControl
|
||||
{
|
||||
public SettingsPageView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:vm="using:ClawdDotNet.Desktop.ViewModels"
|
||||
mc:Ignorable="d" d:DesignWidth="900" d:DesignHeight="700"
|
||||
Padding="16"
|
||||
x:Class="ClawdDotNet.Desktop.Views.TasksPageView"
|
||||
x:DataType="vm:TasksPageViewModel">
|
||||
|
||||
<DockPanel>
|
||||
|
||||
<!-- Statusbar unten -->
|
||||
<Border Classes="statusbar" DockPanel.Dock="Bottom">
|
||||
<TextBlock Text="{Binding StatusText}" VerticalAlignment="Center" />
|
||||
</Border>
|
||||
|
||||
<TabControl>
|
||||
|
||||
<!-- TAB 1: Jobs (Scheduled / Worker) -->
|
||||
<TabItem Header="Geplante Jobs">
|
||||
<DockPanel Margin="0,8,0,0">
|
||||
|
||||
<!-- Toolbar -->
|
||||
<StackPanel Classes="toolbar" DockPanel.Dock="Top">
|
||||
<Button Content="Job hinzufügen" Command="{Binding AddJobCommand}" Classes="accent" />
|
||||
<Button Content="Bearbeiten" Command="{Binding EditJobCommand}" IsEnabled="{Binding SelectedJob, Converter={x:Static ObjectConverters.IsNotNull}}" />
|
||||
<Button Content="Entfernen" Command="{Binding RemoveJobCommand}" IsEnabled="{Binding SelectedJob, Converter={x:Static ObjectConverters.IsNotNull}}" />
|
||||
<Button Content="▶ Jetzt ausführen" Command="{Binding RunJobNowCommand}" IsEnabled="{Binding SelectedJob, Converter={x:Static ObjectConverters.IsNotNull}}" Margin="12,0,0,0" />
|
||||
<Button Content="Aktualisieren" Command="{Binding RefreshJobListCommand}" />
|
||||
</StackPanel>
|
||||
|
||||
<!-- Jobs DataGrid -->
|
||||
<DataGrid ItemsSource="{Binding JobEntries}" SelectedItem="{Binding SelectedJob}" AutoGenerateColumns="False" IsReadOnly="True" GridLinesVisibility="Horizontal">
|
||||
<DataGrid.Columns>
|
||||
<DataGridTextColumn Header="Typ" Binding="{Binding JobType}" Width="120" />
|
||||
<DataGridTextColumn Header="Agent" Binding="{Binding AgentName}" Width="150" />
|
||||
<DataGridTextColumn Header="Tool / Nachricht" Binding="{Binding TaskMessage}" Width="*" />
|
||||
<DataGridTextColumn Header="Cron-Ausdruck" Binding="{Binding CronExpression}" Width="120" />
|
||||
<DataGridTextColumn Header="Nächster Lauf" Binding="{Binding NextRun}" Width="140" />
|
||||
<DataGridTextColumn Header="Letzter Lauf" Binding="{Binding LastRun}" Width="140" />
|
||||
<DataGridTextColumn Header="Status" Binding="{Binding Status}" Width="100" />
|
||||
</DataGrid.Columns>
|
||||
</DataGrid>
|
||||
|
||||
</DockPanel>
|
||||
</TabItem>
|
||||
|
||||
<!-- TAB 2: Dienste (Services) -->
|
||||
<TabItem Header="Dienste (Services)">
|
||||
<DockPanel Margin="0,8,0,0">
|
||||
|
||||
<!-- Toolbar -->
|
||||
<StackPanel Classes="toolbar" DockPanel.Dock="Top">
|
||||
<Button Content="Dienst hinzufügen" Command="{Binding AddServiceCommand}" Classes="accent" />
|
||||
<Button Content="Entfernen" Command="{Binding RemoveServiceCommand}" IsEnabled="{Binding SelectedService, Converter={x:Static ObjectConverters.IsNotNull}}" />
|
||||
<Button Content="Aktualisieren" Command="{Binding RefreshServiceListCommand}" />
|
||||
</StackPanel>
|
||||
|
||||
<!-- Services DataGrid -->
|
||||
<DataGrid ItemsSource="{Binding ServiceEntries}" SelectedItem="{Binding SelectedService}" AutoGenerateColumns="False" IsReadOnly="True" GridLinesVisibility="Horizontal">
|
||||
<DataGrid.Columns>
|
||||
<DataGridTextColumn Header="Dienstname" Binding="{Binding Name}" Width="180" />
|
||||
<DataGridTextColumn Header="Typ" Binding="{Binding Type}" Width="100" />
|
||||
<DataGridTextColumn Header="Port" Binding="{Binding Port}" Width="80" />
|
||||
<DataGridTextColumn Header="Status" Binding="{Binding Status}" Width="110" />
|
||||
<DataGridTextColumn Header="Beschreibung" Binding="{Binding Description}" Width="*" />
|
||||
</DataGrid.Columns>
|
||||
</DataGrid>
|
||||
|
||||
</DockPanel>
|
||||
</TabItem>
|
||||
|
||||
<!-- TAB 3: Verlauf (Job History) -->
|
||||
<TabItem Header="Verlauf (History)">
|
||||
<DockPanel Margin="0,8,0,0">
|
||||
|
||||
<!-- Toolbar -->
|
||||
<StackPanel Classes="toolbar" DockPanel.Dock="Top">
|
||||
<Button Content="Verlauf aktualisieren" Command="{Binding RefreshJobHistoryCommand}" />
|
||||
</StackPanel>
|
||||
|
||||
<!-- History DataGrid -->
|
||||
<DataGrid ItemsSource="{Binding JobHistoryEntries}" AutoGenerateColumns="False" IsReadOnly="True" GridLinesVisibility="Horizontal">
|
||||
<DataGrid.Columns>
|
||||
<DataGridTextColumn Header="Zeitpunkt" Binding="{Binding Time, StringFormat='{}{0:g}'}" Width="140" />
|
||||
<DataGridTextColumn Header="Job-Name" Binding="{Binding JobName}" Width="140" />
|
||||
<DataGridTextColumn Header="Agent" Binding="{Binding Agent}" Width="140" />
|
||||
<DataGridTextColumn Header="Beschreibung" Binding="{Binding JobDescription}" Width="220" />
|
||||
<DataGridTextColumn Header="Status" Binding="{Binding Status}" Width="100" />
|
||||
<DataGridTextColumn Header="Details / Info" Binding="{Binding Info}" Width="*" />
|
||||
</DataGrid.Columns>
|
||||
</DataGrid>
|
||||
|
||||
</DockPanel>
|
||||
</TabItem>
|
||||
|
||||
</TabControl>
|
||||
|
||||
</DockPanel>
|
||||
|
||||
</UserControl>
|
||||
@@ -0,0 +1,46 @@
|
||||
using Avalonia.Controls;
|
||||
using ClawdDotNet.Desktop.ViewModels;
|
||||
|
||||
namespace ClawdDotNet.Desktop.Views;
|
||||
|
||||
public partial class TasksPageView : UserControl
|
||||
{
|
||||
public TasksPageView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
protected override void OnDataContextChanged(EventArgs e)
|
||||
{
|
||||
base.OnDataContextChanged(e);
|
||||
if (DataContext is TasksPageViewModel vm)
|
||||
{
|
||||
vm.RequestAddJobDialog += OnRequestAddJobDialog;
|
||||
vm.RequestAddServiceDialog += OnRequestAddServiceDialog;
|
||||
}
|
||||
}
|
||||
|
||||
private async Task<AddJobResultData?> OnRequestAddJobDialog(AddJobViewModel vm)
|
||||
{
|
||||
var topLevel = TopLevel.GetTopLevel(this);
|
||||
if (topLevel is Window window)
|
||||
{
|
||||
var dialog = new AddJobWindow { DataContext = vm };
|
||||
await dialog.ShowDialog(window);
|
||||
return vm.Result;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private async Task<AddServiceResultData?> OnRequestAddServiceDialog(AddServiceViewModel vm)
|
||||
{
|
||||
var topLevel = TopLevel.GetTopLevel(this);
|
||||
if (topLevel is Window window)
|
||||
{
|
||||
var dialog = new AddServiceWindow { DataContext = vm };
|
||||
await dialog.ShowDialog(window);
|
||||
return vm.Result;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,180 @@
|
||||
<Window xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:vm="using:ClawdDotNet.Desktop.ViewModels"
|
||||
xmlns:models="using:ClawdDotNet.Models"
|
||||
xmlns:conv="using:ClawdDotNet.Desktop.Converters"
|
||||
mc:Ignorable="d" d:DesignWidth="560" d:DesignHeight="480"
|
||||
Width="580" Height="500"
|
||||
Padding="16"
|
||||
WindowStartupLocation="CenterOwner"
|
||||
CanResize="False"
|
||||
Title="Werkzeug-Einstellungen"
|
||||
x:Class="ClawdDotNet.Desktop.Views.ToolSettingsWindow"
|
||||
x:DataType="vm:ToolSettingsViewModel">
|
||||
|
||||
<DockPanel>
|
||||
|
||||
<!-- Bottom Buttons -->
|
||||
<StackPanel DockPanel.Dock="Bottom" Orientation="Horizontal" HorizontalAlignment="Right" Spacing="8" Margin="0,16,0,0">
|
||||
<Button Content="Abbrechen" Command="{Binding CancelCommand}" />
|
||||
<Button Content="Speichern" Command="{Binding ConfirmCommand}" Classes="accent" />
|
||||
</StackPanel>
|
||||
|
||||
<ScrollViewer>
|
||||
<StackPanel Spacing="12">
|
||||
|
||||
<TextBlock Text="{Binding ToolName, StringFormat='Einstellungen für {0}'}" Classes="heading" FontSize="18" />
|
||||
|
||||
<!-- Forms for each Tool -->
|
||||
<StackPanel Spacing="8">
|
||||
|
||||
<!-- 1. FTP -->
|
||||
<Grid ColumnDefinitions="140,*" RowDefinitions="Auto,Auto,Auto,Auto,Auto" IsVisible="{Binding ToolName, Converter={x:Static conv:ToolMatchConverter.Instance}, ConverterParameter=FTP}">
|
||||
<TextBlock Grid.Row="0" Grid.Column="0" Text="Host:" FontWeight="Bold" VerticalAlignment="Center" />
|
||||
<TextBox Grid.Row="0" Grid.Column="1" Text="{Binding FtpHost}" PlaceholderText="ftp.example.com" />
|
||||
|
||||
<TextBlock Grid.Row="1" Grid.Column="0" Text="Port:" FontWeight="Bold" VerticalAlignment="Center" Margin="0,8,0,0" />
|
||||
<NumericUpDown Grid.Row="1" Grid.Column="1" Value="{Binding FtpPort}" Minimum="1" Maximum="65535" Width="120" HorizontalAlignment="Left" Margin="0,8,0,0" />
|
||||
|
||||
<TextBlock Grid.Row="2" Grid.Column="0" Text="Benutzername:" FontWeight="Bold" VerticalAlignment="Center" Margin="0,8,0,0" />
|
||||
<TextBox Grid.Row="2" Grid.Column="1" Text="{Binding FtpUsername}" Margin="0,8,0,0" />
|
||||
|
||||
<TextBlock Grid.Row="3" Grid.Column="0" Text="Passwort:" FontWeight="Bold" VerticalAlignment="Center" Margin="0,8,0,0" />
|
||||
<TextBox Grid.Row="3" Grid.Column="1" Text="{Binding FtpPassword}" PasswordChar="*" Margin="0,8,0,0" />
|
||||
|
||||
<TextBlock Grid.Row="4" Grid.Column="0" Text="Root-Pfad:" FontWeight="Bold" VerticalAlignment="Center" Margin="0,8,0,0" />
|
||||
<TextBox Grid.Row="4" Grid.Column="1" Text="{Binding FtpRootPath}" Margin="0,8,0,0" />
|
||||
</Grid>
|
||||
|
||||
<!-- 2. Mail -->
|
||||
<Grid ColumnDefinitions="140,*" RowDefinitions="Auto,Auto,Auto,Auto,Auto,Auto,Auto" IsVisible="{Binding ToolName, Converter={x:Static conv:ToolMatchConverter.Instance}, ConverterParameter=Mail}">
|
||||
<TextBlock Grid.Row="0" Grid.Column="0" Text="Benutzername:" FontWeight="Bold" VerticalAlignment="Center" />
|
||||
<TextBox Grid.Row="0" Grid.Column="1" Text="{Binding MailUsername}" />
|
||||
|
||||
<TextBlock Grid.Row="1" Grid.Column="0" Text="Passwort:" FontWeight="Bold" VerticalAlignment="Center" Margin="0,8,0,0" />
|
||||
<TextBox Grid.Row="1" Grid.Column="1" Text="{Binding MailPassword}" PasswordChar="*" Margin="0,8,0,0" />
|
||||
|
||||
<TextBlock Grid.Row="2" Grid.Column="0" Text="IMAP-Host:" FontWeight="Bold" VerticalAlignment="Center" Margin="0,8,0,0" />
|
||||
<TextBox Grid.Row="2" Grid.Column="1" Text="{Binding MailImapHost}" Margin="0,8,0,0" />
|
||||
|
||||
<TextBlock Grid.Row="3" Grid.Column="0" Text="IMAP-Port:" FontWeight="Bold" VerticalAlignment="Center" Margin="0,8,0,0" />
|
||||
<NumericUpDown Grid.Row="3" Grid.Column="1" Value="{Binding MailImapPort}" Minimum="1" Maximum="65535" Width="120" HorizontalAlignment="Left" Margin="0,8,0,0" />
|
||||
|
||||
<TextBlock Grid.Row="4" Grid.Column="0" Text="SMTP-Host:" FontWeight="Bold" VerticalAlignment="Center" Margin="0,8,0,0" />
|
||||
<TextBox Grid.Row="4" Grid.Column="1" Text="{Binding MailSmtpHost}" Margin="0,8,0,0" />
|
||||
|
||||
<TextBlock Grid.Row="5" Grid.Column="0" Text="SMTP-Port:" FontWeight="Bold" VerticalAlignment="Center" Margin="0,8,0,0" />
|
||||
<NumericUpDown Grid.Row="5" Grid.Column="1" Value="{Binding MailSmtpPort}" Minimum="1" Maximum="65535" Width="120" HorizontalAlignment="Left" Margin="0,8,0,0" />
|
||||
|
||||
<TextBlock Grid.Row="6" Grid.Column="0" Text="Erlaubte Empfänger:" FontWeight="Bold" VerticalAlignment="Center" Margin="0,8,0,0" />
|
||||
<TextBox Grid.Row="6" Grid.Column="1" Text="{Binding MailAllowedRecipients}" PlaceholderText="email1@domain.de, email2@domain.de" Margin="0,8,0,0" />
|
||||
</Grid>
|
||||
|
||||
<!-- 3. Database -->
|
||||
<Grid ColumnDefinitions="140,*" RowDefinitions="Auto,Auto,Auto,Auto" IsVisible="{Binding ToolName, Converter={x:Static conv:ToolMatchConverter.Instance}, ConverterParameter=Database}">
|
||||
<TextBlock Grid.Row="0" Grid.Column="0" Text="Typ:" FontWeight="Bold" VerticalAlignment="Center" />
|
||||
<ComboBox Grid.Row="0" Grid.Column="1" ItemsSource="{Binding DbTypes}" SelectedItem="{Binding DbType}" HorizontalAlignment="Stretch" />
|
||||
|
||||
<TextBlock Grid.Row="1" Grid.Column="0" Text="Connection-String:" FontWeight="Bold" VerticalAlignment="Center" Margin="0,8,0,0" />
|
||||
<TextBox Grid.Row="1" Grid.Column="1" Text="{Binding DbConnectionString}" PasswordChar="*" Margin="0,8,0,0" />
|
||||
|
||||
<TextBlock Grid.Row="2" Grid.Column="0" Text="Zugriffsebene:" FontWeight="Bold" VerticalAlignment="Center" Margin="0,8,0,0" />
|
||||
<ComboBox Grid.Row="2" Grid.Column="1" ItemsSource="{Binding DbAccessLevels}" SelectedItem="{Binding DbAccessLevel}" HorizontalAlignment="Stretch" Margin="0,8,0,0" />
|
||||
|
||||
<TextBlock Grid.Row="3" Grid.Column="0" Text="Erlaubte Tabellen:" FontWeight="Bold" VerticalAlignment="Center" Margin="0,8,0,0" />
|
||||
<TextBox Grid.Row="3" Grid.Column="1" Text="{Binding DbAllowedTables}" PlaceholderText="tabelle1, tabelle2" Margin="0,8,0,0" />
|
||||
</Grid>
|
||||
|
||||
<!-- 4. Telegram -->
|
||||
<Grid ColumnDefinitions="140,*" RowDefinitions="Auto,Auto,Auto" IsVisible="{Binding ToolName, Converter={x:Static conv:ToolMatchConverter.Instance}, ConverterParameter=Telegram}">
|
||||
<TextBlock Grid.Row="0" Grid.Column="0" Text="Bot-Token:" FontWeight="Bold" VerticalAlignment="Center" />
|
||||
<TextBox Grid.Row="0" Grid.Column="1" Text="{Binding TelegramBotToken}" PasswordChar="*" />
|
||||
|
||||
<TextBlock Grid.Row="1" Grid.Column="0" Text="Standard Chat-ID:" FontWeight="Bold" VerticalAlignment="Center" Margin="0,8,0,0" />
|
||||
<TextBox Grid.Row="1" Grid.Column="1" Text="{Binding TelegramDefaultChatId}" Margin="0,8,0,0" />
|
||||
|
||||
<TextBlock Grid.Row="2" Grid.Column="0" Text="Erlaubte Chat-IDs:" FontWeight="Bold" VerticalAlignment="Center" Margin="0,8,0,0" />
|
||||
<TextBox Grid.Row="2" Grid.Column="1" Text="{Binding TelegramAllowedChatIds}" PlaceholderText="id1, id2" Margin="0,8,0,0" />
|
||||
</Grid>
|
||||
|
||||
<!-- 5. DirectAPI -->
|
||||
<Grid ColumnDefinitions="140,*" RowDefinitions="Auto,Auto,Auto,Auto" IsVisible="{Binding ToolName, Converter={x:Static conv:ToolMatchConverter.Instance}, ConverterParameter=DirectAPI}">
|
||||
<TextBlock Grid.Row="0" Grid.Column="0" Text="Standard-Provider:" FontWeight="Bold" VerticalAlignment="Center" />
|
||||
<TextBox Grid.Row="0" Grid.Column="1" Text="{Binding DirectApiDefaultProvider}" />
|
||||
|
||||
<TextBlock Grid.Row="1" Grid.Column="0" Text="Cache TTL (Sek.):" FontWeight="Bold" VerticalAlignment="Center" Margin="0,8,0,0" />
|
||||
<NumericUpDown Grid.Row="1" Grid.Column="1" Value="{Binding DirectApiCacheTtlSeconds}" Minimum="0" Maximum="86400" Width="120" HorizontalAlignment="Left" Margin="0,8,0,0" />
|
||||
|
||||
<TextBlock Grid.Row="2" Grid.Column="0" Text="Twelve Data Key:" FontWeight="Bold" VerticalAlignment="Center" Margin="0,8,0,0" />
|
||||
<TextBox Grid.Row="2" Grid.Column="1" Text="{Binding DirectApiTwelveDataKey}" PasswordChar="*" Margin="0,8,0,0" />
|
||||
|
||||
<TextBlock Grid.Row="3" Grid.Column="0" Text="Alpha Vantage Key:" FontWeight="Bold" VerticalAlignment="Center" Margin="0,8,0,0" />
|
||||
<TextBox Grid.Row="3" Grid.Column="1" Text="{Binding DirectApiAlphaVantageKey}" PasswordChar="*" Margin="0,8,0,0" />
|
||||
</Grid>
|
||||
|
||||
<!-- 6. WebFetch -->
|
||||
<Grid ColumnDefinitions="140,*" RowDefinitions="Auto,Auto,Auto" IsVisible="{Binding ToolName, Converter={x:Static conv:ToolMatchConverter.Instance}, ConverterParameter=WebFetch}">
|
||||
<TextBlock Grid.Row="0" Grid.Column="0" Text="Erlaubte Domains:" FontWeight="Bold" VerticalAlignment="Center" />
|
||||
<TextBox Grid.Row="0" Grid.Column="1" Text="{Binding WebFetchAllowedDomains}" PlaceholderText="reuters.com, bloomberg.com" />
|
||||
|
||||
<TextBlock Grid.Row="1" Grid.Column="0" Text="Max Response KB:" FontWeight="Bold" VerticalAlignment="Center" Margin="0,8,0,0" />
|
||||
<NumericUpDown Grid.Row="1" Grid.Column="1" Value="{Binding WebFetchMaxResponseKb}" Minimum="1" Maximum="10000" Width="120" HorizontalAlignment="Left" Margin="0,8,0,0" />
|
||||
|
||||
<TextBlock Grid.Row="2" Grid.Column="0" Text="User Agent:" FontWeight="Bold" VerticalAlignment="Center" Margin="0,8,0,0" />
|
||||
<TextBox Grid.Row="2" Grid.Column="1" Text="{Binding WebFetchUserAgent}" Margin="0,8,0,0" />
|
||||
</Grid>
|
||||
|
||||
<!-- 7. SocialMediaManager -->
|
||||
<Grid ColumnDefinitions="160,*" RowDefinitions="Auto,Auto,Auto,Auto,Auto,Auto,Auto" IsVisible="{Binding ToolName, Converter={x:Static conv:ToolMatchConverter.Instance}, ConverterParameter=SocialMediaManager}">
|
||||
<TextBlock Grid.Row="0" Grid.Column="0" Text="X (Twitter) API-Key:" FontWeight="Bold" VerticalAlignment="Center" />
|
||||
<TextBox Grid.Row="0" Grid.Column="1" Text="{Binding SmmXApiKey}" PasswordChar="*" />
|
||||
|
||||
<TextBlock Grid.Row="1" Grid.Column="0" Text="X Accounts:" FontWeight="Bold" VerticalAlignment="Center" Margin="0,8,0,0" />
|
||||
<TextBox Grid.Row="1" Grid.Column="1" Text="{Binding SmmXWatchAccounts}" PlaceholderText="elonmusk, unusual_whales" Margin="0,8,0,0" />
|
||||
|
||||
<TextBlock Grid.Row="2" Grid.Column="0" Text="Subreddits:" FontWeight="Bold" VerticalAlignment="Center" Margin="0,8,0,0" />
|
||||
<TextBox Grid.Row="2" Grid.Column="1" Text="{Binding SmmRedditWatchSubreddits}" PlaceholderText="wallstreetbets, stocks" Margin="0,8,0,0" />
|
||||
|
||||
<TextBlock Grid.Row="3" Grid.Column="0" Text="Reddit Post Limit:" FontWeight="Bold" VerticalAlignment="Center" Margin="0,8,0,0" />
|
||||
<NumericUpDown Grid.Row="3" Grid.Column="1" Value="{Binding SmmRedditPostLimit}" Minimum="1" Maximum="100" Width="120" HorizontalAlignment="Left" Margin="0,8,0,0" />
|
||||
|
||||
<TextBlock Grid.Row="4" Grid.Column="0" Text="OpenRouter Key:" FontWeight="Bold" VerticalAlignment="Center" Margin="0,8,0,0" />
|
||||
<TextBox Grid.Row="4" Grid.Column="1" Text="{Binding SmmOpenRouterApiKey}" PasswordChar="*" Margin="0,8,0,0" />
|
||||
|
||||
<TextBlock Grid.Row="5" Grid.Column="0" Text="STT Modell:" FontWeight="Bold" VerticalAlignment="Center" Margin="0,8,0,0" />
|
||||
<TextBox Grid.Row="5" Grid.Column="1" Text="{Binding SmmSttModel}" Margin="0,8,0,0" />
|
||||
|
||||
<TextBlock Grid.Row="6" Grid.Column="0" Text="YouTube Kanäle:" FontWeight="Bold" VerticalAlignment="Center" Margin="0,8,0,0" />
|
||||
<TextBox Grid.Row="6" Grid.Column="1" Text="{Binding SmmYoutubeChannels}" PlaceholderText="URL1, URL2" Margin="0,8,0,0" />
|
||||
</Grid>
|
||||
|
||||
<!-- 8. FileRW -->
|
||||
<Grid ColumnDefinitions="180,*" RowDefinitions="Auto,Auto,Auto,Auto" IsVisible="{Binding ToolName, Converter={x:Static conv:ToolMatchConverter.Instance}, ConverterParameter=FileRW}">
|
||||
<TextBlock Grid.Row="0" Grid.Column="0" Text="Personal Allowed Ext:" FontWeight="Bold" VerticalAlignment="Center" />
|
||||
<TextBox Grid.Row="0" Grid.Column="1" Text="{Binding FileRwPersonalAllowedExtensions}" />
|
||||
|
||||
<TextBlock Grid.Row="1" Grid.Column="0" Text="Shared Access Level:" FontWeight="Bold" VerticalAlignment="Center" Margin="0,8,0,0" />
|
||||
<ComboBox Grid.Row="1" Grid.Column="1" ItemsSource="{Binding FileRwAccessLevels}" SelectedItem="{Binding FileRwSharedAccessLevel}" HorizontalAlignment="Stretch" Margin="0,8,0,0" />
|
||||
|
||||
<TextBlock Grid.Row="2" Grid.Column="0" Text="Shared Allowed Ext:" FontWeight="Bold" VerticalAlignment="Center" Margin="0,8,0,0" />
|
||||
<TextBox Grid.Row="2" Grid.Column="1" Text="{Binding FileRwSharedAllowedExtensions}" Margin="0,8,0,0" />
|
||||
|
||||
<TextBlock Grid.Row="3" Grid.Column="0" Text="Geschützte Pfade:" FontWeight="Bold" VerticalAlignment="Center" Margin="0,8,0,0" />
|
||||
<TextBox Grid.Row="3" Grid.Column="1" Text="{Binding FileRwProtectedPaths}" Margin="0,8,0,0" />
|
||||
</Grid>
|
||||
|
||||
<!-- Fallback info for tools without extra config -->
|
||||
<TextBlock Text="Dieses Werkzeug benötigt keine weiteren Einstellungen."
|
||||
IsVisible="{Binding SettingsObject, Converter={x:Static ObjectConverters.IsNull}}"
|
||||
FontStyle="Italic" />
|
||||
|
||||
</StackPanel>
|
||||
|
||||
</StackPanel>
|
||||
</ScrollViewer>
|
||||
|
||||
</DockPanel>
|
||||
|
||||
</Window>
|
||||
@@ -0,0 +1,21 @@
|
||||
using Avalonia.Controls;
|
||||
using ClawdDotNet.Desktop.ViewModels;
|
||||
|
||||
namespace ClawdDotNet.Desktop.Views;
|
||||
|
||||
public partial class ToolSettingsWindow : Window
|
||||
{
|
||||
public ToolSettingsWindow()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
protected override void OnDataContextChanged(EventArgs e)
|
||||
{
|
||||
base.OnDataContextChanged(e);
|
||||
if (DataContext is ToolSettingsViewModel vm)
|
||||
{
|
||||
vm.CloseRequested += () => Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user