fix: resolve post-milestone tech debt items

- Add DataGrid RowStyle with red highlighting for invalid CSV rows
  in BulkMembersView, BulkSitesView, and FolderStructureView
- Fix cancel test locale mismatch by setting EN culture before assertion
- Remove dead FeatureTabBase placeholder (replaced by full tab views)
- Clean up unused xmlns:controls from MainWindow.xaml

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Dev
2026-04-07 09:15:02 +02:00
parent c81d8959f7
commit b815c323d7
7 changed files with 56 additions and 59 deletions

View File

@@ -1,3 +1,4 @@
using System.Globalization;
using Microsoft.Extensions.Logging.Abstractions;
using SharepointToolbox.Core.Models;
using SharepointToolbox.ViewModels;
@@ -61,23 +62,33 @@ public class FeatureViewModelBaseTests
[Fact]
public async Task CancelCommand_DuringOperation_SetsStatusMessageToCancelled()
{
var vm = new TestViewModel();
var started = new TaskCompletionSource<bool>();
vm.OperationFunc = async (ct, p) =>
// Ensure EN culture so TranslationSource resolves "Operation cancelled"
var prev = CultureInfo.CurrentUICulture;
CultureInfo.CurrentUICulture = CultureInfo.GetCultureInfo("en");
try
{
started.SetResult(true);
await Task.Delay(5000, ct); // Will be cancelled
};
var vm = new TestViewModel();
var started = new TaskCompletionSource<bool>();
var runTask = vm.RunCommand.ExecuteAsync(null);
await started.Task;
vm.OperationFunc = async (ct, p) =>
{
started.SetResult(true);
await Task.Delay(5000, ct); // Will be cancelled
};
vm.CancelCommand.Execute(null);
await runTask;
var runTask = vm.RunCommand.ExecuteAsync(null);
await started.Task;
Assert.Contains("cancel", vm.StatusMessage, StringComparison.OrdinalIgnoreCase);
Assert.False(vm.IsRunning);
vm.CancelCommand.Execute(null);
await runTask;
Assert.Contains("cancel", vm.StatusMessage, StringComparison.OrdinalIgnoreCase);
Assert.False(vm.IsRunning);
}
finally
{
CultureInfo.CurrentUICulture = prev;
}
}
[Fact]

View File

@@ -4,7 +4,7 @@
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:loc="clr-namespace:SharepointToolbox.Localization"
xmlns:controls="clr-namespace:SharepointToolbox.Views.Controls"
xmlns:views="clr-namespace:SharepointToolbox.Views.Tabs"
mc:Ignorable="d"
Title="{Binding Source={x:Static loc:TranslationSource.Instance}, Path=[app.title]}"
@@ -39,7 +39,7 @@
Background="Black" Foreground="LimeGreen"
FontFamily="Consolas" FontSize="11" />
<!-- TabControl: 7 stub tabs use FeatureTabBase; Settings tab wired in plan 01-07 -->
<!-- TabControl -->
<TabControl>
<TabItem x:Name="PermissionsTabItem"
Header="{Binding Source={x:Static loc:TranslationSource.Instance}, Path=[tab.permissions]}">

View File

@@ -1,33 +0,0 @@
<UserControl x:Class="SharepointToolbox.Views.Controls.FeatureTabBase"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:loc="clr-namespace:SharepointToolbox.Localization">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<!-- Placeholder content — Phase 2+ replaces Row 0 -->
<TextBlock Grid.Row="0"
Text="{Binding Source={x:Static loc:TranslationSource.Instance}, Path=[tab.comingsoon]}"
HorizontalAlignment="Center" VerticalAlignment="Center" />
<!-- Per-tab progress/cancel strip (shown only when IsRunning) -->
<Grid Grid.Row="1" Margin="8,4"
Visibility="{Binding IsRunning, Converter={StaticResource BoolToVisibilityConverter}}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<ProgressBar Grid.Column="0" Height="16" Minimum="0" Maximum="100"
Value="{Binding ProgressValue}" />
<TextBlock Grid.Column="1" Margin="8,0" VerticalAlignment="Center"
Text="{Binding StatusMessage}" />
<Button Grid.Column="2"
Content="{Binding Source={x:Static loc:TranslationSource.Instance}, Path=[btn.cancel]}"
Command="{Binding CancelCommand}" Width="70" />
</Grid>
</Grid>
</UserControl>

View File

@@ -1,11 +0,0 @@
using System.Windows.Controls;
namespace SharepointToolbox.Views.Controls;
public partial class FeatureTabBase : UserControl
{
public FeatureTabBase()
{
InitializeComponent();
}
}

View File

@@ -33,6 +33,16 @@
<!-- Preview DataGrid (Right) -->
<DataGrid ItemsSource="{Binding PreviewRows}" AutoGenerateColumns="False"
IsReadOnly="True" CanUserSortColumns="True">
<DataGrid.RowStyle>
<Style TargetType="DataGridRow">
<Style.Triggers>
<DataTrigger Binding="{Binding IsValid}" Value="False">
<Setter Property="Background" Value="#FFFDE0E0" />
<Setter Property="Foreground" Value="#FFB00020" />
</DataTrigger>
</Style.Triggers>
</Style>
</DataGrid.RowStyle>
<DataGrid.Columns>
<DataGridTextColumn Header="Valid" Binding="{Binding IsValid}" Width="50" />
<DataGridTextColumn Header="{Binding Source={x:Static loc:TranslationSource.Instance}, Path=[bulkmembers.groupname]}"

View File

@@ -31,6 +31,16 @@
<DataGrid ItemsSource="{Binding PreviewRows}" AutoGenerateColumns="False"
IsReadOnly="True" CanUserSortColumns="True">
<DataGrid.RowStyle>
<Style TargetType="DataGridRow">
<Style.Triggers>
<DataTrigger Binding="{Binding IsValid}" Value="False">
<Setter Property="Background" Value="#FFFDE0E0" />
<Setter Property="Foreground" Value="#FFB00020" />
</DataTrigger>
</Style.Triggers>
</Style>
</DataGrid.RowStyle>
<DataGrid.Columns>
<DataGridTextColumn Header="Valid" Binding="{Binding IsValid}" Width="50" />
<DataGridTextColumn Header="{Binding Source={x:Static loc:TranslationSource.Instance}, Path=[bulksites.name]}"

View File

@@ -38,6 +38,16 @@
<DataGrid ItemsSource="{Binding PreviewRows}" AutoGenerateColumns="False"
IsReadOnly="True" CanUserSortColumns="True">
<DataGrid.RowStyle>
<Style TargetType="DataGridRow">
<Style.Triggers>
<DataTrigger Binding="{Binding IsValid}" Value="False">
<Setter Property="Background" Value="#FFFDE0E0" />
<Setter Property="Foreground" Value="#FFB00020" />
</DataTrigger>
</Style.Triggers>
</Style>
</DataGrid.RowStyle>
<DataGrid.Columns>
<DataGridTextColumn Header="Valid" Binding="{Binding IsValid}" Width="50" />
<DataGridTextColumn Header="Level 1" Binding="{Binding Record.Level1}" Width="*" />