Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
15 changes: 12 additions & 3 deletions src/PlanViewer.App/Controls/QueryStoreGridControl.axaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ public partial class QueryStoreGridControl : UserControl
private bool _initialOrderByLoaded;
private bool _suppressRangeChanged;
private string? _waitHighlightCategory;
private const int AutoSelectTopN = 1; // number of rows auto-selected after each fetch
private bool _waitStatsSupported; // false until version + capture mode confirmed
private bool _waitStatsEnabled = true;
private bool _waitPercentMode;
Expand All @@ -64,7 +65,6 @@ public QueryStoreGridControl(ServerConnection serverConnection, ICredentialServi
SetupColumnHeaders();
PopulateDatabaseBox(databases, initialDatabase);
TimeRangeSlicer.RangeChanged += OnTimeRangeChanged;
TimeRangeSlicer.IsExpanded = true;

WaitStatsProfile.CategoryClicked += OnWaitCategoryClicked;
WaitStatsProfile.CategoryDoubleClicked += OnWaitCategoryDoubleClicked;
Expand Down Expand Up @@ -211,7 +211,7 @@ private async System.Threading.Tasks.Task FetchPlansForRangeAsync()

ApplyFilters();
LoadButton.IsEnabled = true;
SelectToggleButton.Content = "Select None";
SelectToggleButton.Content = "Select All";

// Fetch per-plan wait stats after grid is populated (needs plan IDs)
if (_waitStatsSupported && _waitStatsEnabled && _slicerStartUtc.HasValue && _slicerEndUtc.HasValue)
Expand Down Expand Up @@ -496,6 +496,7 @@ private void OnWaitCategoryDoubleClicked(object? sender, string category)
// Clear column sort indicators since we're using custom sort
_sortedColumnTag = null;
UpdateSortIndicators(null);
ReapplyTopNSelection();
UpdateBarRatios();
}

Expand Down Expand Up @@ -937,6 +938,13 @@ private static string GetColumnLabel(StackPanel header)
return tb.Text?.TrimEnd(' ', '▲', '▼') ?? string.Empty;
}

private void ReapplyTopNSelection()
{
if (_filteredRows.Count == 0) return;
foreach (var r in _rows) r.IsSelected = false;
foreach (var r in _filteredRows.Take(AutoSelectTopN)) r.IsSelected = true;
}

private void ApplySortAndFilters()
{
IEnumerable<QueryStoreRow> source = _rows.Where(RowMatchesAllFilters);
Expand All @@ -952,6 +960,7 @@ private void ApplySortAndFilters()
foreach (var row in source)
_filteredRows.Add(row);

ReapplyTopNSelection();
UpdateStatusText();
UpdateBarRatios();
}
Expand Down Expand Up @@ -1046,7 +1055,7 @@ private static IComparable GetSortKey(string columnTag, QueryStoreRow r) =>

public class QueryStoreRow : INotifyPropertyChanged
{
private bool _isSelected = true;
private bool _isSelected = false;

// Bar ratios [0..1] per column
private double _execsRatio;
Expand Down
94 changes: 78 additions & 16 deletions src/PlanViewer.App/Controls/TimeRangeSlicerControl.axaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,26 +5,88 @@
BorderBrush="{DynamicResource SlicerBorderBrush}"
BorderThickness="0,0,0,1">
<Grid RowDefinitions="Auto,Auto">
<!-- Toggle header -->
<Button x:Name="ToggleButton" Grid.Row="0"
Background="Transparent" BorderThickness="0"
HorizontalAlignment="Stretch" HorizontalContentAlignment="Left"
Padding="8,4" Cursor="Hand"
Click="Toggle_Click">
<StackPanel Orientation="Horizontal" Spacing="6">
<TextBlock x:Name="ToggleIcon" Text="▾" FontSize="12"
Foreground="{DynamicResource SlicerToggleBrush}"
<!-- Header with range label button that opens date/time picker popup -->
<Panel Grid.Row="0">
<Grid ColumnDefinitions="Auto,Auto,*,Auto" Margin="8,4">
<TextBlock Grid.Column="0" Text="📅" FontSize="12"
VerticalAlignment="Center"/>
<TextBlock x:Name="ToggleLabel" Text="Time Range"
<TextBlock Grid.Column="1" x:Name="ToggleLabel" Text="Time Range"
FontSize="11" FontWeight="SemiBold"
Foreground="{DynamicResource SlicerToggleBrush}"
VerticalAlignment="Center"/>
<TextBlock x:Name="RangeLabel" Text=""
FontSize="11"
VerticalAlignment="Center" Margin="6,0,0,0"/>
<TextBlock Grid.Column="2" x:Name="RangeLabel" Text=""
FontSize="11" FontFamily="Cascadia Mono,Consolas,monospace"
Foreground="{DynamicResource SlicerLabelBrush}"
VerticalAlignment="Center" Margin="12,0,0,0"/>
</StackPanel>
</Button>
VerticalAlignment="Center" Margin="12,0,0,0"
TextTrimming="CharacterEllipsis"/>
<StackPanel Grid.Column="3" x:Name="QuickFilterPanel" Orientation="Horizontal" Spacing="2" Margin="12,0,0,0" VerticalAlignment="Center">
<Button x:Name="QF_3" Content="3h" Tag="3" Click="QuickFilter_Click" Height="20" MinWidth="32" Padding="6,0" FontSize="10" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" Background="Transparent" BorderThickness="1" BorderBrush="{DynamicResource SlicerBorderBrush}" Foreground="{DynamicResource SlicerLabelBrush}" Cursor="Hand"/>
<Button x:Name="QF_24" Content="24h" Tag="24" Click="QuickFilter_Click" Height="20" MinWidth="32" Padding="6,0" FontSize="10" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" Background="Transparent" BorderThickness="1" BorderBrush="{DynamicResource SlicerBorderBrush}" Foreground="{DynamicResource SlicerLabelBrush}" Cursor="Hand"/>
<Button x:Name="QF_48" Content="48h" Tag="48" Click="QuickFilter_Click" Height="20" MinWidth="32" Padding="6,0" FontSize="10" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" Background="Transparent" BorderThickness="1" BorderBrush="{DynamicResource SlicerBorderBrush}" Foreground="{DynamicResource SlicerLabelBrush}" Cursor="Hand"/>
<Button x:Name="QF_168" Content="7d" Tag="168" Click="QuickFilter_Click" Height="20" MinWidth="32" Padding="6,0" FontSize="10" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" Background="Transparent" BorderThickness="1" BorderBrush="{DynamicResource SlicerBorderBrush}" Foreground="{DynamicResource SlicerLabelBrush}" Cursor="Hand"/>
<Button x:Name="QF_720" Content="30d" Tag="720" Click="QuickFilter_Click" Height="20" MinWidth="32" Padding="6,0" FontSize="10" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" Background="Transparent" BorderThickness="1" BorderBrush="{DynamicResource SlicerBorderBrush}" Foreground="{DynamicResource SlicerLabelBrush}" Cursor="Hand"/>
<Button x:Name="QF_Custom" Content="Custom" Tag="0" Click="CustomFilter_Click" Height="20" MinWidth="42" Padding="6,0" FontSize="10" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" Background="Transparent" BorderThickness="1" BorderBrush="{DynamicResource SlicerBorderBrush}" Foreground="{DynamicResource SlicerLabelBrush}" Cursor="Hand"/>
</StackPanel>
</Grid>
<Popup x:Name="DateTimePopup"
PlacementTarget="{Binding #QF_Custom}"
Placement="BottomEdgeAlignedLeft"
IsLightDismissEnabled="True"
HorizontalOffset="0" VerticalOffset="2">
<Border Background="{DynamicResource SlicerBackgroundBrush}"
BorderBrush="{DynamicResource SlicerBorderBrush}"
BorderThickness="1" CornerRadius="6"
Padding="16" MinWidth="460">
<StackPanel Spacing="12">
<TextBlock Text="Custom Time Range"
FontSize="13" FontWeight="SemiBold"
Foreground="{DynamicResource ForegroundBrush}"/>
<!-- Start date/time row -->
<StackPanel Spacing="4">
<TextBlock Text="Start" FontSize="11"
Foreground="{DynamicResource SlicerLabelBrush}"/>
<StackPanel Orientation="Horizontal" Spacing="8">
<CalendarDatePicker x:Name="StartDatePicker"
Width="180" Height="30" FontSize="12"
DisplayDateStart="{x:Null}"
DisplayDateEnd="{x:Null}"
CustomDateFormatString="yyyy-MM-dd"
SelectedDateFormat="Custom"/>
<TimePicker x:Name="StartTimePicker"
Width="120" Height="30" FontSize="12"
ClockIdentifier="24HourClock"
MinuteIncrement="15"/>
</StackPanel>
</StackPanel>
<!-- End date/time row -->
<StackPanel Spacing="4">
<TextBlock Text="End" FontSize="11"
Foreground="{DynamicResource SlicerLabelBrush}"/>
<StackPanel Orientation="Horizontal" Spacing="8">
<CalendarDatePicker x:Name="EndDatePicker"
Width="180" Height="30" FontSize="12"
DisplayDateStart="{x:Null}"
DisplayDateEnd="{x:Null}"
CustomDateFormatString="yyyy-MM-dd"
SelectedDateFormat="Custom"/>
<TimePicker x:Name="EndTimePicker"
Width="120" Height="30" FontSize="12"
ClockIdentifier="24HourClock"
MinuteIncrement="15"/>
</StackPanel>
</StackPanel>
<!-- Action buttons -->
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right" Spacing="8"
Margin="0,4,0,0">
<Button Content="Cancel" Width="70" Height="28"
Click="PopupCancel_Click"/>
<Button Content="Apply" Width="70" Height="28"
Click="PopupApply_Click"/>
</StackPanel>
</StackPanel>
</Border>
</Popup>
</Panel>
<!-- Slicer canvas area -->
<Border x:Name="SlicerBorder" Grid.Row="1" Height="120" Margin="8,0,8,6"
Background="{DynamicResource SlicerBackgroundBrush}"
Expand Down
Loading
Loading