feat: page-based navigation shell + Tests page wizard

Replace the monolithic MainWindow with a SelectedPage-driven shell
(Dashboard / Pump / Bench / Tests / Results / Settings). The Tests
page gets the Plan -> Preconditions -> Running -> Done wizard from
ui-structure.md \u00a74, backed by a 7-item precondition gate and
shared sub-views (PhaseCardView / TestSectionView / GraphicIndicatorView)
extracted from the now-deleted monolithic TestPanelView.

New VMs / views:
- Tests wizard: TestPreconditions, PhaseCard, GraphicIndicator,
  TestSection, TestPlan, TestRunning, TestDone
- Dashboard panels: DashboardConnection, DashboardReadings,
  DashboardAlarms, InterlockBanner, ResultHistory
- Pump / bench panels: PumpIdentificationPanel, PumpLiveData,
  UnlockPanel, BenchDriveControl, BenchReadings, RelayBank,
  TemperatureControl, DtcList, AuthGate
- Dialogs: generic ConfirmDialog, UserManageDialog, UserPromptDialog

Supporting changes:
- IsOilPumpOn exposed on MainViewModel for precondition evaluation
- RequiresAuth added to TestDefinition (XML round-trip)
- BipStatusDefinition + CompletedTestRun models
- ~35 new Test.* localization keys (en + es)
- Settings moved from modal dialog to full page
- Pause / Retry / Skip stubs in TestRunningView; full spec in
  docs/gap-test-running-controls.md for follow-up implementation
- docs/ui-structure.md captures the wizard design

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-18 13:11:34 +02:00
parent 37d099cdbd
commit 0280a2fad1
110 changed files with 8008 additions and 1115 deletions

View File

@@ -0,0 +1,109 @@
<UserControl x:Class="HC_APTBS.Views.UserControls.BenchDriveControlView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
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"
mc:Ignorable="d"
d:DesignHeight="420" d:DesignWidth="180">
<!--
Manual drive control panel: direction, RPM start/stop with quick-select,
oil pump, and turn counter.
DataContext = BenchPageViewModel; operates on BenchControl.X.
-->
<StackPanel Width="170">
<!-- Direction toggle -->
<TextBlock Text="{DynamicResource Bench.Direction}" FontSize="10" Foreground="DimGray" Margin="0,4,0,2"/>
<ToggleButton IsChecked="{Binding BenchControl.IsDirectionRight}"
Height="32" FontSize="12" FontWeight="SemiBold">
<ToggleButton.Style>
<Style TargetType="ToggleButton">
<Setter Property="Content" Value="{DynamicResource Bench.Left}"/>
<Style.Triggers>
<Trigger Property="IsChecked" Value="True">
<Setter Property="Content" Value="{DynamicResource Bench.Right}"/>
</Trigger>
</Style.Triggers>
</Style>
</ToggleButton.Style>
</ToggleButton>
<!-- Start / Stop bench -->
<TextBlock Text="{DynamicResource Bench.Motor}" FontSize="10" Foreground="DimGray" Margin="0,8,0,2"/>
<Button Content="{DynamicResource Bench.Start}" FontSize="13" FontWeight="Bold" Height="36"
Foreground="DarkGreen" Margin="0,0,0,4"
Command="{Binding BenchControl.OpenRpmPopupCommand}"/>
<Popup StaysOpen="False" Placement="Left"
IsOpen="{Binding BenchControl.IsRpmPopupOpen, Mode=TwoWay}">
<Border Background="White" BorderBrush="Black" BorderThickness="1" Padding="8">
<StackPanel Width="200">
<TextBlock Text="{DynamicResource Bench.SetRpm}" FontSize="12" Margin="0,0,0,4"/>
<TextBox Text="{Binding BenchControl.RpmInputText, UpdateSourceTrigger=PropertyChanged}"
FontSize="16" FontFamily="Consolas" Height="28" Margin="0,0,0,6"/>
<Button Content="{DynamicResource Bench.Go}" FontSize="13" FontWeight="Bold" Height="30"
Foreground="DarkGreen" Margin="0,0,0,6"
Command="{Binding BenchControl.StartBenchCommand}"/>
<UniformGrid Columns="5">
<Button Content="100" Style="{StaticResource RelayButton}" Command="{Binding BenchControl.SetQuickRpmCommand}" CommandParameter="100"/>
<Button Content="200" Style="{StaticResource RelayButton}" Command="{Binding BenchControl.SetQuickRpmCommand}" CommandParameter="200"/>
<Button Content="300" Style="{StaticResource RelayButton}" Command="{Binding BenchControl.SetQuickRpmCommand}" CommandParameter="300"/>
<Button Content="400" Style="{StaticResource RelayButton}" Command="{Binding BenchControl.SetQuickRpmCommand}" CommandParameter="400"/>
<Button Content="500" Style="{StaticResource RelayButton}" Command="{Binding BenchControl.SetQuickRpmCommand}" CommandParameter="500"/>
<Button Content="600" Style="{StaticResource RelayButton}" Command="{Binding BenchControl.SetQuickRpmCommand}" CommandParameter="600"/>
<Button Content="700" Style="{StaticResource RelayButton}" Command="{Binding BenchControl.SetQuickRpmCommand}" CommandParameter="700"/>
<Button Content="800" Style="{StaticResource RelayButton}" Command="{Binding BenchControl.SetQuickRpmCommand}" CommandParameter="800"/>
<Button Content="900" Style="{StaticResource RelayButton}" Command="{Binding BenchControl.SetQuickRpmCommand}" CommandParameter="900"/>
<Button Content="1000" Style="{StaticResource RelayButton}" Command="{Binding BenchControl.SetQuickRpmCommand}" CommandParameter="1000"/>
<Button Content="1200" Style="{StaticResource RelayButton}" Command="{Binding BenchControl.SetQuickRpmCommand}" CommandParameter="1200"/>
<Button Content="1400" Style="{StaticResource RelayButton}" Command="{Binding BenchControl.SetQuickRpmCommand}" CommandParameter="1400"/>
<Button Content="1600" Style="{StaticResource RelayButton}" Command="{Binding BenchControl.SetQuickRpmCommand}" CommandParameter="1600"/>
<Button Content="1800" Style="{StaticResource RelayButton}" Command="{Binding BenchControl.SetQuickRpmCommand}" CommandParameter="1800"/>
<Button Content="2000" Style="{StaticResource RelayButton}" Command="{Binding BenchControl.SetQuickRpmCommand}" CommandParameter="2000"/>
</UniformGrid>
</StackPanel>
</Border>
</Popup>
<Button Content="{DynamicResource Bench.Stop}" FontSize="13" FontWeight="Bold" Height="36"
Foreground="DarkRed"
Command="{Binding BenchControl.StopBenchCommand}"/>
<!-- Oil pump toggle -->
<TextBlock Text="{DynamicResource Bench.OilPump}" FontSize="10" Foreground="DimGray" Margin="0,8,0,2"/>
<ToggleButton IsChecked="{Binding BenchControl.IsOilPumpOn}"
Height="32" FontSize="12" FontWeight="SemiBold">
<ToggleButton.Style>
<Style TargetType="ToggleButton">
<Setter Property="Content" Value="{DynamicResource Bench.OilOff}"/>
<Setter Property="Background" Value="LightGray"/>
<Style.Triggers>
<Trigger Property="IsChecked" Value="True">
<Setter Property="Content" Value="{DynamicResource Bench.OilOn}"/>
<Setter Property="Background" Value="#80FF80"/>
</Trigger>
</Style.Triggers>
</Style>
</ToggleButton.Style>
</ToggleButton>
<!-- Turn counter -->
<TextBlock Text="{DynamicResource Bench.Counter}" FontSize="10" Foreground="DimGray" Margin="0,8,0,2"/>
<ToggleButton Content="{DynamicResource Bench.Counter}"
IsChecked="{Binding BenchControl.IsCounterPopupOpen}"
Height="28" FontSize="11"/>
<Popup StaysOpen="False" Placement="Left"
IsOpen="{Binding BenchControl.IsCounterPopupOpen, Mode=TwoWay}">
<Border Background="White" BorderBrush="Black" BorderThickness="1" Padding="8">
<StackPanel Width="160">
<TextBlock Text="{DynamicResource Bench.Turns}" FontSize="12" Margin="0,0,0,4"/>
<TextBox Text="{Binding BenchControl.CounterInputText, UpdateSourceTrigger=PropertyChanged}"
FontSize="16" FontFamily="Consolas" Height="28" Margin="0,0,0,4"/>
<Button Content="{DynamicResource Bench.Send}" FontSize="12" Height="28"
Command="{Binding BenchControl.SendCounterCommand}"/>
</StackPanel>
</Border>
</Popup>
<TextBlock FontSize="14" FontFamily="Consolas" Margin="0,2"
Text="{Binding BenchControl.BenchCounterValue, StringFormat=00000000}"/>
</StackPanel>
</UserControl>