Vollständige Implementierung des EngineeringSync-Middleware-Tools: - Windows Service (Kestrel :5050) mit FileSystemWatcher + SignalR - WPF Tray-App mit PendingChanges- und Projektverwaltungs-Fenster - Setup-Wizard (8-Schritte-Installer) - SQLite/EF Core Datenschicht (WAL-Modus) - SHA-256-basiertes Debouncing (2s Fenster) - Backup-System mit konfigurierbarer Aufbewahrung Bugfixes & Verbesserungen: - BUG-1: AppDbContext OnConfiguring invertierte Bedingung behoben - BUG-2: Event-Handler-Leak in TrayApp (Fenster-Singleton-Pattern) - BUG-3: ProjectConfigChanged SignalR-Signal in allen CRUD-Endpoints - BUG-5: Rename-Sync löscht alte Datei im Simulations-Ordner - BUG-6: Doppeltes Dispose von SignalR verhindert - BUG-7: Registry-Deinstallation nur EngineeringSync-Eintrag entfernt - S1: Path-Traversal-Schutz via SafeCombine() im SyncManager - E1: FSW Buffer 64KB + automatischer Re-Scan bei Overflow - E2: Retry-Logik (3x) für gesperrte Dateien mit exponentiellem Backoff - E4: Channel.Writer.TryComplete() beim Shutdown - C2: HubMethodNames-Konstanten statt Magic Strings - E3: Pagination in Changes-API (page/pageSize Query-Parameter) - A1: Fire-and-Forget mit try/catch + Logging Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
362 lines
20 KiB
XML
362 lines
20 KiB
XML
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
|
|
|
|
<!-- ═══════════════════════════════════════════
|
|
FARBEN & BRUSHES
|
|
═══════════════════════════════════════════ -->
|
|
|
|
<Color x:Key="AccentColor">#0078D4</Color>
|
|
<Color x:Key="AccentHoverColor">#106EBE</Color>
|
|
<Color x:Key="AccentPressColor">#005A9E</Color>
|
|
<Color x:Key="SidebarTopColor">#1B1B2F</Color>
|
|
<Color x:Key="SidebarBottomColor">#16213E</Color>
|
|
<Color x:Key="SuccessColor">#107C10</Color>
|
|
<Color x:Key="ErrorColor">#C42B1C</Color>
|
|
<Color x:Key="WarningColor">#CA5010</Color>
|
|
<Color x:Key="SurfaceColor">#FAFAFA</Color>
|
|
<Color x:Key="BorderColor">#E0E0E0</Color>
|
|
<Color x:Key="TextPrimaryColor">#1A1A1A</Color>
|
|
<Color x:Key="TextSecondaryColor">#5F5F5F</Color>
|
|
|
|
<SolidColorBrush x:Key="AccentBrush" Color="{StaticResource AccentColor}"/>
|
|
<SolidColorBrush x:Key="AccentHoverBrush" Color="{StaticResource AccentHoverColor}"/>
|
|
<SolidColorBrush x:Key="AccentPressBrush" Color="{StaticResource AccentPressColor}"/>
|
|
<SolidColorBrush x:Key="SuccessBrush" Color="{StaticResource SuccessColor}"/>
|
|
<SolidColorBrush x:Key="ErrorBrush" Color="{StaticResource ErrorColor}"/>
|
|
<SolidColorBrush x:Key="WarningBrush" Color="{StaticResource WarningColor}"/>
|
|
<SolidColorBrush x:Key="SurfaceBrush" Color="{StaticResource SurfaceColor}"/>
|
|
<SolidColorBrush x:Key="BorderBrush" Color="{StaticResource BorderColor}"/>
|
|
<SolidColorBrush x:Key="TextPrimaryBrush" Color="{StaticResource TextPrimaryColor}"/>
|
|
<SolidColorBrush x:Key="TextSecondaryBrush" Color="{StaticResource TextSecondaryColor}"/>
|
|
|
|
<LinearGradientBrush x:Key="SidebarGradient" StartPoint="0,0" EndPoint="0,1">
|
|
<GradientStop Color="{StaticResource SidebarTopColor}" Offset="0"/>
|
|
<GradientStop Color="{StaticResource SidebarBottomColor}" Offset="1"/>
|
|
</LinearGradientBrush>
|
|
|
|
<!-- ═══════════════════════════════════════════
|
|
TYPOGRAPHY
|
|
═══════════════════════════════════════════ -->
|
|
<FontFamily x:Key="UiFont">Segoe UI</FontFamily>
|
|
|
|
<!-- ═══════════════════════════════════════════
|
|
BUTTON STYLES
|
|
═══════════════════════════════════════════ -->
|
|
|
|
<!-- Primärer Akzent-Button -->
|
|
<Style x:Key="PrimaryButtonStyle" TargetType="Button">
|
|
<Setter Property="Background" Value="{StaticResource AccentBrush}"/>
|
|
<Setter Property="Foreground" Value="White"/>
|
|
<Setter Property="BorderThickness" Value="0"/>
|
|
<Setter Property="Padding" Value="24,10"/>
|
|
<Setter Property="FontFamily" Value="{StaticResource UiFont}"/>
|
|
<Setter Property="FontSize" Value="13"/>
|
|
<Setter Property="FontWeight" Value="SemiBold"/>
|
|
<Setter Property="Cursor" Value="Hand"/>
|
|
<Setter Property="Template">
|
|
<Setter.Value>
|
|
<ControlTemplate TargetType="Button">
|
|
<Border x:Name="border"
|
|
Background="{TemplateBinding Background}"
|
|
CornerRadius="6"
|
|
Padding="{TemplateBinding Padding}">
|
|
<ContentPresenter HorizontalAlignment="Center"
|
|
VerticalAlignment="Center"/>
|
|
</Border>
|
|
<ControlTemplate.Triggers>
|
|
<Trigger Property="IsMouseOver" Value="True">
|
|
<Setter TargetName="border" Property="Background"
|
|
Value="{StaticResource AccentHoverBrush}"/>
|
|
</Trigger>
|
|
<Trigger Property="IsPressed" Value="True">
|
|
<Setter TargetName="border" Property="Background"
|
|
Value="{StaticResource AccentPressBrush}"/>
|
|
</Trigger>
|
|
<Trigger Property="IsEnabled" Value="False">
|
|
<Setter TargetName="border" Property="Background" Value="#BDBDBD"/>
|
|
<Setter Property="Foreground" Value="#888888"/>
|
|
</Trigger>
|
|
</ControlTemplate.Triggers>
|
|
</ControlTemplate>
|
|
</Setter.Value>
|
|
</Setter>
|
|
</Style>
|
|
|
|
<!-- Sekundärer Button (Ghost) -->
|
|
<Style x:Key="SecondaryButtonStyle" TargetType="Button">
|
|
<Setter Property="Background" Value="Transparent"/>
|
|
<Setter Property="Foreground" Value="{StaticResource TextPrimaryBrush}"/>
|
|
<Setter Property="BorderBrush" Value="{StaticResource BorderBrush}"/>
|
|
<Setter Property="BorderThickness" Value="1"/>
|
|
<Setter Property="Padding" Value="20,10"/>
|
|
<Setter Property="FontFamily" Value="{StaticResource UiFont}"/>
|
|
<Setter Property="FontSize" Value="13"/>
|
|
<Setter Property="Cursor" Value="Hand"/>
|
|
<Setter Property="Template">
|
|
<Setter.Value>
|
|
<ControlTemplate TargetType="Button">
|
|
<Border x:Name="border"
|
|
Background="{TemplateBinding Background}"
|
|
BorderBrush="{TemplateBinding BorderBrush}"
|
|
BorderThickness="{TemplateBinding BorderThickness}"
|
|
CornerRadius="6"
|
|
Padding="{TemplateBinding Padding}">
|
|
<ContentPresenter HorizontalAlignment="Center"
|
|
VerticalAlignment="Center"/>
|
|
</Border>
|
|
<ControlTemplate.Triggers>
|
|
<Trigger Property="IsMouseOver" Value="True">
|
|
<Setter TargetName="border" Property="Background" Value="#F5F5F5"/>
|
|
</Trigger>
|
|
<Trigger Property="IsPressed" Value="True">
|
|
<Setter TargetName="border" Property="Background" Value="#EBEBEB"/>
|
|
</Trigger>
|
|
<Trigger Property="IsEnabled" Value="False">
|
|
<Setter Property="Foreground" Value="#BDBDBD"/>
|
|
<Setter TargetName="border" Property="BorderBrush" Value="#E0E0E0"/>
|
|
</Trigger>
|
|
</ControlTemplate.Triggers>
|
|
</ControlTemplate>
|
|
</Setter.Value>
|
|
</Setter>
|
|
</Style>
|
|
|
|
<!-- Icon-Button für Folder-Browse -->
|
|
<Style x:Key="IconButtonStyle" TargetType="Button">
|
|
<Setter Property="Background" Value="Transparent"/>
|
|
<Setter Property="BorderThickness" Value="1"/>
|
|
<Setter Property="BorderBrush" Value="{StaticResource BorderBrush}"/>
|
|
<Setter Property="Width" Value="36"/>
|
|
<Setter Property="Height" Value="36"/>
|
|
<Setter Property="Cursor" Value="Hand"/>
|
|
<Setter Property="Template">
|
|
<Setter.Value>
|
|
<ControlTemplate TargetType="Button">
|
|
<Border x:Name="bd"
|
|
Background="{TemplateBinding Background}"
|
|
BorderBrush="{TemplateBinding BorderBrush}"
|
|
BorderThickness="{TemplateBinding BorderThickness}"
|
|
CornerRadius="6">
|
|
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
|
|
</Border>
|
|
<ControlTemplate.Triggers>
|
|
<Trigger Property="IsMouseOver" Value="True">
|
|
<Setter TargetName="bd" Property="Background" Value="#F0F7FF"/>
|
|
<Setter TargetName="bd" Property="BorderBrush" Value="{StaticResource AccentBrush}"/>
|
|
</Trigger>
|
|
</ControlTemplate.Triggers>
|
|
</ControlTemplate>
|
|
</Setter.Value>
|
|
</Setter>
|
|
</Style>
|
|
|
|
<!-- ═══════════════════════════════════════════
|
|
TEXTBOX STYLE
|
|
═══════════════════════════════════════════ -->
|
|
<Style x:Key="ModernTextBoxStyle" TargetType="TextBox">
|
|
<Setter Property="FontFamily" Value="{StaticResource UiFont}"/>
|
|
<Setter Property="FontSize" Value="13"/>
|
|
<Setter Property="Padding" Value="10,8"/>
|
|
<Setter Property="BorderThickness" Value="1"/>
|
|
<Setter Property="BorderBrush" Value="{StaticResource BorderBrush}"/>
|
|
<Setter Property="Background" Value="White"/>
|
|
<Setter Property="Foreground" Value="{StaticResource TextPrimaryBrush}"/>
|
|
<Setter Property="Template">
|
|
<Setter.Value>
|
|
<ControlTemplate TargetType="TextBox">
|
|
<Border x:Name="border"
|
|
Background="{TemplateBinding Background}"
|
|
BorderBrush="{TemplateBinding BorderBrush}"
|
|
BorderThickness="{TemplateBinding BorderThickness}"
|
|
CornerRadius="6">
|
|
<ScrollViewer x:Name="PART_ContentHost" Margin="2,0"/>
|
|
</Border>
|
|
<ControlTemplate.Triggers>
|
|
<Trigger Property="IsFocused" Value="True">
|
|
<Setter TargetName="border" Property="BorderBrush"
|
|
Value="{StaticResource AccentBrush}"/>
|
|
<Setter TargetName="border" Property="BorderThickness" Value="2"/>
|
|
</Trigger>
|
|
<Trigger Property="IsEnabled" Value="False">
|
|
<Setter TargetName="border" Property="Background" Value="#F5F5F5"/>
|
|
<Setter Property="Foreground" Value="#BDBDBD"/>
|
|
</Trigger>
|
|
</ControlTemplate.Triggers>
|
|
</ControlTemplate>
|
|
</Setter.Value>
|
|
</Setter>
|
|
</Style>
|
|
|
|
<!-- ═══════════════════════════════════════════
|
|
CHECKBOX STYLE
|
|
═══════════════════════════════════════════ -->
|
|
<Style x:Key="ModernCheckBoxStyle" TargetType="CheckBox">
|
|
<Setter Property="FontFamily" Value="{StaticResource UiFont}"/>
|
|
<Setter Property="FontSize" Value="13"/>
|
|
<Setter Property="Foreground" Value="{StaticResource TextPrimaryBrush}"/>
|
|
<Setter Property="Cursor" Value="Hand"/>
|
|
<Setter Property="Template">
|
|
<Setter.Value>
|
|
<ControlTemplate TargetType="CheckBox">
|
|
<StackPanel Orientation="Horizontal" VerticalAlignment="Center">
|
|
<Border x:Name="box"
|
|
Width="18" Height="18"
|
|
CornerRadius="4"
|
|
BorderThickness="2"
|
|
BorderBrush="{StaticResource BorderBrush}"
|
|
Background="White"
|
|
Margin="0,0,8,0">
|
|
<TextBlock x:Name="check"
|
|
Text=""
|
|
FontFamily="Segoe MDL2 Assets"
|
|
FontSize="11"
|
|
Foreground="White"
|
|
HorizontalAlignment="Center"
|
|
VerticalAlignment="Center"
|
|
Visibility="Collapsed"/>
|
|
</Border>
|
|
<ContentPresenter VerticalAlignment="Center"/>
|
|
</StackPanel>
|
|
<ControlTemplate.Triggers>
|
|
<Trigger Property="IsChecked" Value="True">
|
|
<Setter TargetName="box" Property="Background" Value="{StaticResource AccentBrush}"/>
|
|
<Setter TargetName="box" Property="BorderBrush" Value="{StaticResource AccentBrush}"/>
|
|
<Setter TargetName="check" Property="Visibility" Value="Visible"/>
|
|
</Trigger>
|
|
<Trigger Property="IsMouseOver" Value="True">
|
|
<Setter TargetName="box" Property="BorderBrush" Value="{StaticResource AccentBrush}"/>
|
|
</Trigger>
|
|
</ControlTemplate.Triggers>
|
|
</ControlTemplate>
|
|
</Setter.Value>
|
|
</Setter>
|
|
</Style>
|
|
|
|
<!-- ═══════════════════════════════════════════
|
|
LABELS & TYPOGRAPHY
|
|
═══════════════════════════════════════════ -->
|
|
|
|
<Style x:Key="PageTitleStyle" TargetType="TextBlock">
|
|
<Setter Property="FontFamily" Value="{StaticResource UiFont}"/>
|
|
<Setter Property="FontSize" Value="24"/>
|
|
<Setter Property="FontWeight" Value="Light"/>
|
|
<Setter Property="Foreground" Value="{StaticResource TextPrimaryBrush}"/>
|
|
<Setter Property="Margin" Value="0,0,0,8"/>
|
|
</Style>
|
|
|
|
<Style x:Key="PageSubtitleStyle" TargetType="TextBlock">
|
|
<Setter Property="FontFamily" Value="{StaticResource UiFont}"/>
|
|
<Setter Property="FontSize" Value="13"/>
|
|
<Setter Property="Foreground" Value="{StaticResource TextSecondaryBrush}"/>
|
|
<Setter Property="TextWrapping" Value="Wrap"/>
|
|
<Setter Property="Margin" Value="0,0,0,24"/>
|
|
<Setter Property="LineHeight" Value="20"/>
|
|
</Style>
|
|
|
|
<Style x:Key="FieldLabelStyle" TargetType="TextBlock">
|
|
<Setter Property="FontFamily" Value="{StaticResource UiFont}"/>
|
|
<Setter Property="FontSize" Value="12"/>
|
|
<Setter Property="FontWeight" Value="SemiBold"/>
|
|
<Setter Property="Foreground" Value="{StaticResource TextSecondaryBrush}"/>
|
|
<Setter Property="Margin" Value="0,0,0,4"/>
|
|
</Style>
|
|
|
|
<!-- ═══════════════════════════════════════════
|
|
SIDEBAR STEP ITEM
|
|
═══════════════════════════════════════════ -->
|
|
<Style x:Key="StepItemStyle" TargetType="ContentControl">
|
|
<Setter Property="Template">
|
|
<Setter.Value>
|
|
<ControlTemplate TargetType="ContentControl">
|
|
<Grid Margin="0,4">
|
|
<Grid.ColumnDefinitions>
|
|
<ColumnDefinition Width="36"/>
|
|
<ColumnDefinition Width="*"/>
|
|
</Grid.ColumnDefinitions>
|
|
|
|
<!-- Kreis-Indikator -->
|
|
<Border x:Name="circle"
|
|
Width="28" Height="28"
|
|
CornerRadius="14"
|
|
Background="#2A3050"
|
|
HorizontalAlignment="Center">
|
|
<TextBlock x:Name="iconText"
|
|
Text="{Binding Icon}"
|
|
FontFamily="Segoe MDL2 Assets"
|
|
FontSize="12"
|
|
Foreground="#8899BB"
|
|
HorizontalAlignment="Center"
|
|
VerticalAlignment="Center"/>
|
|
</Border>
|
|
|
|
<!-- Titel -->
|
|
<TextBlock x:Name="titleText"
|
|
Grid.Column="1"
|
|
Text="{Binding Title}"
|
|
FontFamily="{StaticResource UiFont}"
|
|
FontSize="12"
|
|
Foreground="#8899BB"
|
|
VerticalAlignment="Center"
|
|
Margin="8,0,0,0"/>
|
|
</Grid>
|
|
<ControlTemplate.Triggers>
|
|
<!-- Aktiver Schritt -->
|
|
<DataTrigger Binding="{Binding IsActive}" Value="True">
|
|
<Setter TargetName="circle" Property="Background" Value="{StaticResource AccentBrush}"/>
|
|
<Setter TargetName="iconText" Property="Foreground" Value="White"/>
|
|
<Setter TargetName="titleText" Property="Foreground" Value="White"/>
|
|
<Setter TargetName="titleText" Property="FontWeight" Value="SemiBold"/>
|
|
</DataTrigger>
|
|
<!-- Abgeschlossener Schritt -->
|
|
<DataTrigger Binding="{Binding IsCompleted}" Value="True">
|
|
<Setter TargetName="circle" Property="Background" Value="#107C10"/>
|
|
<Setter TargetName="iconText" Property="Text" Value=""/>
|
|
<Setter TargetName="iconText" Property="Foreground" Value="White"/>
|
|
<Setter TargetName="titleText" Property="Foreground" Value="#88CCAA"/>
|
|
</DataTrigger>
|
|
</ControlTemplate.Triggers>
|
|
</ControlTemplate>
|
|
</Setter.Value>
|
|
</Setter>
|
|
</Style>
|
|
|
|
<!-- ═══════════════════════════════════════════
|
|
INFO CARD (für Zusammenfassung etc.)
|
|
═══════════════════════════════════════════ -->
|
|
<Style x:Key="InfoCardStyle" TargetType="Border">
|
|
<Setter Property="Background" Value="White"/>
|
|
<Setter Property="BorderBrush" Value="{StaticResource BorderBrush}"/>
|
|
<Setter Property="BorderThickness" Value="1"/>
|
|
<Setter Property="CornerRadius" Value="8"/>
|
|
<Setter Property="Padding" Value="16"/>
|
|
<Setter Property="Margin" Value="0,0,0,12"/>
|
|
</Style>
|
|
|
|
<!-- ═══════════════════════════════════════════
|
|
PROGRESS BAR
|
|
═══════════════════════════════════════════ -->
|
|
<Style x:Key="ModernProgressBarStyle" TargetType="ProgressBar">
|
|
<Setter Property="Height" Value="6"/>
|
|
<Setter Property="Background" Value="#E0E0E0"/>
|
|
<Setter Property="Foreground" Value="{StaticResource AccentBrush}"/>
|
|
<Setter Property="BorderThickness" Value="0"/>
|
|
<Setter Property="Template">
|
|
<Setter.Value>
|
|
<ControlTemplate TargetType="ProgressBar">
|
|
<Grid>
|
|
<Border Background="{TemplateBinding Background}"
|
|
CornerRadius="3"/>
|
|
<Border x:Name="PART_Track" CornerRadius="3" ClipToBounds="True">
|
|
<Border x:Name="PART_Indicator"
|
|
Background="{TemplateBinding Foreground}"
|
|
CornerRadius="3"
|
|
HorizontalAlignment="Left"/>
|
|
</Border>
|
|
</Grid>
|
|
</ControlTemplate>
|
|
</Setter.Value>
|
|
</Setter>
|
|
</Style>
|
|
|
|
</ResourceDictionary>
|