chore: organize solution into module folders (Core/Server/Drivers/Client/Tooling)
Group all 69 projects into category subfolders under src/ and tests/ so the Rider Solution Explorer mirrors the module structure. Folders: Core, Server, Drivers (with a nested Driver CLIs subfolder), Client, Tooling. - Move every project folder on disk with git mv (history preserved as renames). - Recompute relative paths in 57 .csproj files: cross-category ProjectReferences, the lib/ HintPath+None refs in Driver.Historian.Wonderware, and the external mxaccessgw refs in Driver.Galaxy and its test project. - Rebuild ZB.MOM.WW.OtOpcUa.slnx with nested solution folders. - Re-prefix project paths in functional scripts (e2e, compliance, smoke SQL, integration, install). Build green (0 errors); unit tests pass. Docs left for a separate pass. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,162 @@
|
||||
<Window xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:vm="using:ZB.MOM.WW.OtOpcUa.Client.UI.ViewModels"
|
||||
xmlns:views="using:ZB.MOM.WW.OtOpcUa.Client.UI.Views"
|
||||
x:Class="ZB.MOM.WW.OtOpcUa.Client.UI.Views.MainWindow"
|
||||
x:DataType="vm:MainWindowViewModel"
|
||||
Title="OPC UA Client"
|
||||
Width="1200"
|
||||
Height="800">
|
||||
<DockPanel>
|
||||
<!-- Top Connection Bar -->
|
||||
<Border DockPanel.Dock="Top" Background="#F0F0F0" Padding="12">
|
||||
<StackPanel Spacing="4">
|
||||
<!-- Always visible: URL + Connect/Disconnect -->
|
||||
<StackPanel Orientation="Horizontal" Spacing="8">
|
||||
<StackPanel Spacing="2" VerticalAlignment="Bottom">
|
||||
<TextBlock Text="Endpoint URL" FontSize="11" Foreground="Gray" />
|
||||
<TextBox Text="{Binding EndpointUrl}"
|
||||
Width="400"
|
||||
Watermark="opc.tcp://host:port" />
|
||||
</StackPanel>
|
||||
<Button Content="Connect"
|
||||
Command="{Binding ConnectCommand}"
|
||||
VerticalAlignment="Bottom" Padding="16,6" />
|
||||
<Button Content="Disconnect"
|
||||
Command="{Binding DisconnectCommand}"
|
||||
VerticalAlignment="Bottom" Padding="16,6" />
|
||||
</StackPanel>
|
||||
|
||||
<!-- Expandable settings -->
|
||||
<Expander Header="Connection Settings" Padding="0,4">
|
||||
<StackPanel Spacing="10" Margin="4,8,4,4">
|
||||
<!-- Row 1: Authentication -->
|
||||
<StackPanel Orientation="Horizontal" Spacing="12">
|
||||
<StackPanel Spacing="2">
|
||||
<TextBlock Text="Username" FontSize="11" Foreground="Gray" />
|
||||
<TextBox Text="{Binding Username}"
|
||||
Width="160"
|
||||
Watermark="(anonymous)" />
|
||||
</StackPanel>
|
||||
<StackPanel Spacing="2">
|
||||
<TextBlock Text="Password" FontSize="11" Foreground="Gray" />
|
||||
<TextBox Text="{Binding Password}"
|
||||
Width="160"
|
||||
Watermark="(none)"
|
||||
PasswordChar="*" />
|
||||
</StackPanel>
|
||||
<StackPanel Spacing="2">
|
||||
<TextBlock Text="Security Mode" FontSize="11" Foreground="Gray" />
|
||||
<ComboBox ItemsSource="{Binding SecurityModes}"
|
||||
SelectedItem="{Binding SelectedSecurityMode}"
|
||||
Width="160" />
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
|
||||
<!-- Row 2: Failover + Session -->
|
||||
<StackPanel Orientation="Horizontal" Spacing="12">
|
||||
<StackPanel Spacing="2">
|
||||
<TextBlock Text="Failover URLs (comma-separated)" FontSize="11" Foreground="Gray" />
|
||||
<TextBox Text="{Binding FailoverUrls}"
|
||||
Width="400"
|
||||
Watermark="opc.tcp://backup1:4840, opc.tcp://backup2:4840" />
|
||||
</StackPanel>
|
||||
<StackPanel Spacing="2">
|
||||
<TextBlock Text="Session Timeout (s)" FontSize="11" Foreground="Gray" />
|
||||
<NumericUpDown Value="{Binding SessionTimeoutSeconds}"
|
||||
Minimum="1" Maximum="3600"
|
||||
Width="120"
|
||||
FormatString="0" />
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
|
||||
<!-- Row 3: Certificates -->
|
||||
<StackPanel Orientation="Horizontal" Spacing="12">
|
||||
<StackPanel Spacing="2">
|
||||
<TextBlock Text="Certificate Store Path" FontSize="11" Foreground="Gray" />
|
||||
<StackPanel Orientation="Horizontal" Spacing="4">
|
||||
<TextBox Text="{Binding CertificateStorePath}"
|
||||
Width="370"
|
||||
IsReadOnly="True"
|
||||
Watermark="(default: AppData/LmxOpcUaClient/pki)" />
|
||||
<Button Name="BrowseCertPathButton"
|
||||
Content="..."
|
||||
Width="30"
|
||||
ToolTip.Tip="Browse for folder" />
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
<CheckBox IsChecked="{Binding AutoAcceptCertificates}"
|
||||
Content="Auto-accept untrusted server certificates"
|
||||
VerticalAlignment="Bottom"
|
||||
Margin="0,0,0,4" />
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</Expander>
|
||||
|
||||
<!-- Redundancy Info -->
|
||||
<StackPanel Orientation="Horizontal"
|
||||
Spacing="16"
|
||||
IsVisible="{Binding RedundancyInfo, Converter={x:Static ObjectConverters.IsNotNull}}"
|
||||
Margin="0,2,0,0">
|
||||
<TextBlock Text="{Binding RedundancyInfo.Mode, StringFormat='Redundancy: {0}'}"
|
||||
FontSize="11" Foreground="Gray" />
|
||||
<TextBlock Text="{Binding RedundancyInfo.ServiceLevel, StringFormat='Service Level: {0}'}"
|
||||
FontSize="11" Foreground="Gray" />
|
||||
<TextBlock Text="{Binding RedundancyInfo.ApplicationUri, StringFormat='URI: {0}'}"
|
||||
FontSize="11" Foreground="Gray" />
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
|
||||
<!-- Bottom Status Bar -->
|
||||
<Border DockPanel.Dock="Bottom" Background="#F0F0F0" Padding="8,4">
|
||||
<StackPanel Orientation="Horizontal" Spacing="20">
|
||||
<TextBlock Text="{Binding StatusMessage}" />
|
||||
<TextBlock Text="{Binding SessionLabel}" Foreground="Gray" />
|
||||
<TextBlock Text="{Binding SubscriptionCount, StringFormat='Subscriptions: {0}'}" />
|
||||
</StackPanel>
|
||||
</Border>
|
||||
|
||||
<!-- Main Content -->
|
||||
<Grid ColumnDefinitions="300,8,*">
|
||||
<!-- Left: Browse Tree -->
|
||||
<Border Grid.Column="0" BorderBrush="#CCCCCC" BorderThickness="0,0,1,0">
|
||||
<DockPanel>
|
||||
<TextBlock DockPanel.Dock="Top" Text="Browse Tree" FontWeight="Bold" Margin="8,8,8,4" />
|
||||
<views:BrowseTreeView DataContext="{Binding BrowseTree}"
|
||||
Name="BrowseTreePanel">
|
||||
<views:BrowseTreeView.ContextMenu>
|
||||
<ContextMenu Name="TreeContextMenu">
|
||||
<MenuItem Header="Subscribe" Name="SubscribeMenuItem" />
|
||||
<MenuItem Header="View History" Name="ViewHistoryMenuItem" />
|
||||
<Separator />
|
||||
<MenuItem Header="Monitor Alarms" Name="MonitorAlarmsMenuItem" />
|
||||
</ContextMenu>
|
||||
</views:BrowseTreeView.ContextMenu>
|
||||
</views:BrowseTreeView>
|
||||
</DockPanel>
|
||||
</Border>
|
||||
|
||||
<!-- Splitter -->
|
||||
<GridSplitter Grid.Column="1" Width="8" Background="Transparent" />
|
||||
|
||||
<!-- Right: Tab panels -->
|
||||
<TabControl Grid.Column="2"
|
||||
IsEnabled="{Binding IsConnected}"
|
||||
SelectedIndex="{Binding SelectedTabIndex}">
|
||||
<TabItem Header="Read/Write">
|
||||
<views:ReadWriteView DataContext="{Binding ReadWrite}" />
|
||||
</TabItem>
|
||||
<TabItem Header="{Binding SubscriptionsTabHeader}">
|
||||
<views:SubscriptionsView DataContext="{Binding Subscriptions}" />
|
||||
</TabItem>
|
||||
<TabItem Header="{Binding AlarmsTabHeader}">
|
||||
<views:AlarmsView DataContext="{Binding Alarms}" />
|
||||
</TabItem>
|
||||
<TabItem Header="History">
|
||||
<views:HistoryView DataContext="{Binding History}" />
|
||||
</TabItem>
|
||||
</TabControl>
|
||||
</Grid>
|
||||
</DockPanel>
|
||||
</Window>
|
||||
Reference in New Issue
Block a user