Skip to content
Draft
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
d7fac7e
ManageServers: bind DataGrid to ServerVersionInfo, add version probin…
mas-mark-y May 19, 2026
a0626af
ManageServers: bind DataGrid to ServerVersionInfo, add version probin…
mas-mark-y May 19, 2026
5321ff4
Resolve Process-Level Blockers 1-4
mas-mark-y May 20, 2026
20c51a1
ManageServers: bind DataGrid to ServerVersionInfo, add version probin…
mas-mark-y May 19, 2026
53eeca5
Fix Dashboard.Tests errorManageServers: bind DataGrid to ServerVersio…
mas-mark-y May 19, 2026
ebb8cf5
Resolve Merge conflicts
mas-mark-y May 21, 2026
e67e682
Remove unnecessary comments
mas-mark-y May 21, 2026
ff6698f
Resolve Dashboard Tests CI issues - add a lock file, add a build step…
mas-mark-y May 21, 2026
5480ce7
Reverted the VisualStudioVersion edit
mas-mark-y May 21, 2026
2b6d8db
Fixed items #4, #5, and #6 from the original PR review
mas-mark-y Jun 2, 2026
33e7973
Fix #7 - progress bar oscillations under parallel upgrades
mas-mark-y Jun 22, 2026
81a6428
Fix #8 - Button Bar overflow due to insufficient width
mas-mark-y Jun 22, 2026
65c3de5
Fix #11 - Add exception handling to ManageServersWindow_Closing()
mas-mark-y Jun 22, 2026
0a5f418
ManageServers: bind DataGrid to ServerVersionInfo, add version probin…
mas-mark-y May 19, 2026
3d62459
Resolve Process-Level Blockers 1-4
mas-mark-y May 20, 2026
977603b
ManageServers: bind DataGrid to ServerVersionInfo, add version probin…
mas-mark-y May 19, 2026
0a94b9e
Fix Dashboard.Tests errorManageServers: bind DataGrid to ServerVersio…
mas-mark-y May 19, 2026
f150e49
Resolve Dashboard Tests CI issues - add a lock file, add a build step…
mas-mark-y May 21, 2026
61b0a42
Reverted the VisualStudioVersion edit
mas-mark-y May 21, 2026
77095cd
Fixed items #4, #5, and #6 from the original PR review
mas-mark-y Jun 2, 2026
3f47200
Fix #7 - progress bar oscillations under parallel upgrades
mas-mark-y Jun 22, 2026
880c459
Fix #8 - Button Bar overflow due to insufficient width
mas-mark-y Jun 22, 2026
ba667b7
Fix #11 - Add exception handling to ManageServersWindow_Closing()
mas-mark-y Jun 22, 2026
bc572a8
ManageServers: bind DataGrid to ServerVersionInfo, add version probin…
mas-mark-y May 19, 2026
ecad770
Resolve Process-Level Blockers 1-4
mas-mark-y May 20, 2026
24f4d36
ManageServers: bind DataGrid to ServerVersionInfo, add version probin…
mas-mark-y May 19, 2026
902d219
ManageServers: bind DataGrid to ServerVersionInfo, add version probin…
mas-mark-y May 19, 2026
b4ffd5b
Remove unnecessary comments
mas-mark-y May 21, 2026
631d902
Reverted the VisualStudioVersion edit
mas-mark-y May 21, 2026
47d0676
Fixed items #4, #5, and #6 from the original PR review
mas-mark-y Jun 2, 2026
c940b59
Merge branch 'feature/815-bulk-server-upgrades' of https://github.com…
mas-mark-y Jun 24, 2026
1286c96
Merge upstream/dev branch commits to feature/815-bulk-server-upgrades
mas-mark-y Jun 25, 2026
ddb28a7
Add a missing Using statement
mas-mark-y Jun 25, 2026
b987a6f
Address remaining issues
mas-mark-y Jun 25, 2026
03309b3
Normalize line endings
mas-mark-y Jun 26, 2026
731c5df
Resolve merge conflicts
mas-mark-y Jul 1, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions Dashboard.Tests/Dashboard.Tests.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net8.0-windows</TargetFramework>
<IsTestProject>true</IsTestProject>
<Nullable>enable</Nullable>
<UseWPF>false</UseWPF>
<IsPackable>false</IsPackable>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.4.0" />
<PackageReference Include="xunit" Version="2.6.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="3.1.5" />
</ItemGroup>

<ItemGroup>
<!-- Ensure this path matches your dashboard project file -->
<ProjectReference Include="..\Dashboard\Dashboard.csproj" />
</ItemGroup>

</Project>
54 changes: 54 additions & 0 deletions Dashboard.Tests/UpgradeAggregationTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
using PerformanceMonitorDashboard;
using Xunit;

namespace Dashboard.Tests
{
public class UpgradeAggregationTests
{
[Fact]
public void AggregatesServerAndStepCounts_Correctly()
{
// Arrange: three servers, two successes, one failure
var inputs = new[]
{
// success: 2 upgrade steps succeeded, 1 step succeeded
new AggregationInput(true, 2, 0, 1, 0),
// failure: 0 succeeded, 1 upgrade failed
new AggregationInput(false, 0, 1, 0, 0),
// success: 1 upgrade succeeded
new AggregationInput(true, 1, 0, 0, 0)
};

// Act
var result = UpgradeAggregator.Aggregate(inputs);

// Assert
Assert.Equal(2, result.ServerSuccessCount);
Assert.Equal(1, result.ServerFailCount);

// Steps succeeded: (2+1) + (0) + (1) = 4
Assert.Equal(4, result.StepsSucceeded);
// Steps failed: 1
Assert.Equal(1, result.StepsFailed);

// Summary contains expected fragments
Assert.Contains("2 servers upgraded", result.Summary);
Assert.Contains("4 steps succeeded", result.Summary);
Assert.Contains("1 step failed", result.Summary);
}

[Fact]
public void Aggregator_FormatsSingularPlural_Correctly()
{
var singleSuccess = new[] { new AggregationInput(true, 1, 0, 0, 0) };
var r1 = UpgradeAggregator.Aggregate(singleSuccess);
Assert.Equal(1, r1.ServerSuccessCount);
Assert.Contains("1 server upgraded", r1.Summary);

var singleFail = new[] { new AggregationInput(false, 0, 0, 0, 1) };
var r2 = UpgradeAggregator.Aggregate(singleFail);
Assert.Equal(1, r2.ServerFailCount);
Assert.Contains("1 step failed", r2.Summary);
}
}
}
42 changes: 34 additions & 8 deletions Dashboard/ManageServersWindow.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Manage Servers"
Height="450" Width="960"
Height="450" Width="1024"
WindowStartupLocation="CenterOwner"
ResizeMode="CanResizeWithGrip"
Background="{DynamicResource BackgroundBrush}">
Expand Down Expand Up @@ -37,6 +37,7 @@
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>

<!-- Header -->
Expand All @@ -60,7 +61,8 @@
AlternatingRowBackground="{DynamicResource BackgroundLightBrush}"
BorderThickness="0"
MouseDoubleClick="ServersDataGrid_MouseDoubleClick"
ContextMenu="{StaticResource DataGridContextMenu}">
ContextMenu="{StaticResource DataGridContextMenu}"
ScrollViewer.HorizontalScrollBarVisibility="Auto">
<DataGrid.Columns>
<DataGridTemplateColumn Header="" Width="30" CanUserSort="False">
<DataGridTemplateColumn.CellTemplate>
Expand All @@ -71,11 +73,13 @@
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTextColumn Header="Display Name" Binding="{Binding DisplayName}" Width="150"/>
<DataGridTextColumn Header="Server" Binding="{Binding ServerName}" Width="180"/>
<DataGridTextColumn Header="Authentication" Binding="{Binding AuthenticationDisplay}" Width="120"/>
<DataGridTextColumn Header="Installed Version" Binding="{Binding InstalledVersion}" Width="130"/>
<DataGridTextColumn Header="Monthly Cost ($)" Binding="{Binding MonthlyCostUsd, StringFormat='{}{0:N0}'}" Width="120">

<!-- Use star-sizing so columns shrink/grow responsively -->
<DataGridTextColumn Header="Display Name" Binding="{Binding DisplayName}" Width="1.2*"/>
<DataGridTextColumn Header="Server" Binding="{Binding ServerName}" Width="1.2*"/>
<DataGridTextColumn Header="Authentication" Binding="{Binding AuthenticationDisplay}" Width="1*"/>
<DataGridTextColumn Header="Installed Version" Binding="{Binding InstalledVersion}" Width="110"/>
<DataGridTextColumn Header="Monthly Cost ($)" Binding="{Binding MonthlyCostUsd, StringFormat='{}{0:N0}'}" Width="110">
<DataGridTextColumn.ElementStyle>
<Style TargetType="TextBlock">
<Setter Property="HorizontalAlignment" Value="Right"/>
Expand All @@ -87,8 +91,27 @@
</DataGrid>
</Border>

<!-- Progress Panel -->
<Border x:Name="UpgradeProgressPanel" Grid.Row="2" Visibility="Collapsed"
Background="{DynamicResource BackgroundLightBrush}"
CornerRadius="4" Padding="12" Margin="0,8,0,0">
<StackPanel>
<TextBlock x:Name="UpgradeProgressText" TextWrapping="Wrap"
Foreground="{DynamicResource ForegroundBrush}" Margin="0,0,0,6"/>
<ProgressBar x:Name="UpgradeProgressBar" Height="6" Margin="0,0,0,6"
Foreground="{DynamicResource AccentBrush}"
Background="{DynamicResource BackgroundLighterBrush}"/>
<TextBox x:Name="UpgradeLogTextBox" FontFamily="Consolas" FontSize="11"
MaxHeight="150" IsReadOnly="True" TextWrapping="Wrap"
VerticalScrollBarVisibility="Auto"
Background="{DynamicResource BackgroundDarkBrush}"
Foreground="{DynamicResource ForegroundBrush}"
Margin="0,0,0,6"/>
</StackPanel>
</Border>

<!-- Buttons -->
<Grid Grid.Row="2" Margin="0,16,0,0">
<Grid Grid.Row="3" Margin="0,16,0,0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
Expand All @@ -100,6 +123,9 @@
<Button Content="Edit..." Width="80" Height="30" Margin="0,0,8,0" Click="EditServer_Click"/>
<Button x:Name="ToggleFavoriteButton" Content="Toggle Favorite" Width="110" Height="30" Margin="0,0,8,0" Click="ToggleFavorite_Click"/>
<Button x:Name="CheckUpdatesButton" Content="Check Server Version" Width="140" Height="30" Margin="0,0,8,0" Click="CheckForUpdates_Click"/>
<Button x:Name="CheckAllVersionsButton" Content="Check All Versions" Width="130" Height="30" Margin="0,0,8,0" Click="CheckAllVersions_Click"/>
<Button x:Name="UpgradeAllButton" Content="Upgrade All Outdated" Width="140" Height="30" Margin="0,0,8,0" Click="UpgradeAll_Click" Visibility="Collapsed"/>
<Button x:Name="CancelUpgradeButton" Content="Cancel Upgrade" Width="130" Height="30" Margin="0,0,8,0" Click="CancelUpgrade_Click" Visibility="Collapsed" IsEnabled="false"/>
<Button Content="Excluded Databases" Width="140" Height="30" Margin="0,0,8,0" Click="ExcludedDatabases_Click"/>
<Button Content="Purge Now" Width="100" Height="30" Margin="0,0,8,0" Click="PurgeNow_Click"/>
<Button Content="Remove" Width="80" Height="30" Margin="0,0,8,0" Click="RemoveServer_Click"
Expand Down
Loading
Loading