|
|
|
@@ -0,0 +1,186 @@
|
|
|
|
|
<Window xmlns="https://github.com/avaloniaui"
|
|
|
|
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
|
|
|
|
xmlns:vm="using:ClaudeDo.Ui.ViewModels.Modals"
|
|
|
|
|
xmlns:ctl="using:ClaudeDo.Ui.Views.Controls"
|
|
|
|
|
xmlns:loc="using:ClaudeDo.Ui.Localization"
|
|
|
|
|
xmlns:conv="using:Avalonia.Data.Converters"
|
|
|
|
|
x:Class="ClaudeDo.Ui.Views.Modals.UsageMonitorModalView"
|
|
|
|
|
x:DataType="vm:UsageMonitorModalViewModel"
|
|
|
|
|
Title="{loc:Tr modals.usageMonitor.windowTitle}"
|
|
|
|
|
Width="920" Height="680" MinWidth="700" MinHeight="480"
|
|
|
|
|
CanResize="True"
|
|
|
|
|
WindowStartupLocation="CenterOwner"
|
|
|
|
|
Background="{DynamicResource SurfaceBrush}"
|
|
|
|
|
WindowDecorations="BorderOnly"
|
|
|
|
|
ExtendClientAreaToDecorationsHint="True"
|
|
|
|
|
ExtendClientAreaTitleBarHeightHint="-1">
|
|
|
|
|
<Window.KeyBindings>
|
|
|
|
|
<KeyBinding Gesture="Escape" Command="{Binding CloseCommand}"/>
|
|
|
|
|
</Window.KeyBindings>
|
|
|
|
|
|
|
|
|
|
<Window.Styles>
|
|
|
|
|
<Style Selector="ProgressBar.usage-gauge">
|
|
|
|
|
<Setter Property="Height" Value="10"/>
|
|
|
|
|
<Setter Property="CornerRadius" Value="4"/>
|
|
|
|
|
<Setter Property="Minimum" Value="0"/>
|
|
|
|
|
<Setter Property="Maximum" Value="100"/>
|
|
|
|
|
<Setter Property="Foreground" Value="{DynamicResource AccentBrush}"/>
|
|
|
|
|
</Style>
|
|
|
|
|
<Style Selector="ProgressBar.usage-gauge.warn">
|
|
|
|
|
<Setter Property="Foreground" Value="{DynamicResource StatusReviewBrush}"/>
|
|
|
|
|
</Style>
|
|
|
|
|
</Window.Styles>
|
|
|
|
|
|
|
|
|
|
<ctl:ModalShell Title="{loc:Tr modals.usageMonitor.title}" CloseCommand="{Binding CloseCommand}">
|
|
|
|
|
<DockPanel>
|
|
|
|
|
|
|
|
|
|
<!-- Stale / gate bands -->
|
|
|
|
|
<StackPanel DockPanel.Dock="Top" Spacing="4" Margin="20,16,20,0">
|
|
|
|
|
<Border IsVisible="{Binding IsStale}"
|
|
|
|
|
Background="{DynamicResource ReviewTintBrush}"
|
|
|
|
|
BorderBrush="{DynamicResource StatusReviewBrush}"
|
|
|
|
|
BorderThickness="1" CornerRadius="6" Padding="12,8">
|
|
|
|
|
<StackPanel Spacing="2">
|
|
|
|
|
<TextBlock Classes="meta" Text="{Binding StaleBandText}"/>
|
|
|
|
|
<TextBlock Classes="meta" Text="{Binding LastError}" IsVisible="{Binding LastError, Converter={x:Static conv:StringConverters.IsNotNullOrEmpty}}"/>
|
|
|
|
|
<TextBlock Classes="meta" Text="{loc:Tr modals.usageMonitor.staleGateHint}"/>
|
|
|
|
|
</StackPanel>
|
|
|
|
|
</Border>
|
|
|
|
|
<Border IsVisible="{Binding IsGateBlocked}"
|
|
|
|
|
Background="{DynamicResource ErrorTintBrush}"
|
|
|
|
|
BorderBrush="{DynamicResource StatusErrorBrush}"
|
|
|
|
|
BorderThickness="1" CornerRadius="6" Padding="12,8">
|
|
|
|
|
<TextBlock Classes="meta" Text="{Binding GateBandText}"/>
|
|
|
|
|
</Border>
|
|
|
|
|
</StackPanel>
|
|
|
|
|
|
|
|
|
|
<!-- Gauges -->
|
|
|
|
|
<ItemsControl DockPanel.Dock="Top" Margin="20,12,20,0" ItemsSource="{Binding GaugeRows}">
|
|
|
|
|
<ItemsControl.ItemsPanel>
|
|
|
|
|
<ItemsPanelTemplate>
|
|
|
|
|
<WrapPanel Orientation="Horizontal"/>
|
|
|
|
|
</ItemsPanelTemplate>
|
|
|
|
|
</ItemsControl.ItemsPanel>
|
|
|
|
|
<ItemsControl.ItemTemplate>
|
|
|
|
|
<DataTemplate x:DataType="vm:UsageGaugeRowViewModel">
|
|
|
|
|
<Border Background="{DynamicResource DeepBrush}" BorderBrush="{DynamicResource LineBrush}"
|
|
|
|
|
BorderThickness="1" CornerRadius="6" Padding="12,10" Margin="0,0,10,10" Width="240">
|
|
|
|
|
<StackPanel Spacing="6">
|
|
|
|
|
<StackPanel Orientation="Horizontal" Spacing="6">
|
|
|
|
|
<TextBlock Classes="eyebrow" Text="{Binding Label}"/>
|
|
|
|
|
<TextBlock Classes="meta" Text="{Binding Percent, StringFormat={}{0:0}%}" HorizontalAlignment="Right"/>
|
|
|
|
|
</StackPanel>
|
|
|
|
|
<Grid Height="10">
|
|
|
|
|
<ProgressBar Classes="usage-gauge" Classes.warn="{Binding IsWarnSeverity}" Value="{Binding Percent}"/>
|
|
|
|
|
<Canvas IsHitTestVisible="False">
|
|
|
|
|
<Rectangle Canvas.Left="{Binding ThresholdMarkerLeftPx}" Width="2" Height="10"
|
|
|
|
|
Fill="{DynamicResource TextDimBrush}"
|
|
|
|
|
IsVisible="{Binding ThresholdPercent, Converter={x:Static conv:ObjectConverters.IsNotNull}}"/>
|
|
|
|
|
</Canvas>
|
|
|
|
|
</Grid>
|
|
|
|
|
<TextBlock Classes="meta" Text="{Binding ResetText}" IsVisible="{Binding ResetText, Converter={x:Static conv:StringConverters.IsNotNullOrEmpty}}"/>
|
|
|
|
|
</StackPanel>
|
|
|
|
|
</Border>
|
|
|
|
|
</DataTemplate>
|
|
|
|
|
</ItemsControl.ItemTemplate>
|
|
|
|
|
</ItemsControl>
|
|
|
|
|
<TextBlock DockPanel.Dock="Top" Margin="20,12,20,0" Classes="meta"
|
|
|
|
|
Text="{loc:Tr modals.usageMonitor.noGauges}"
|
|
|
|
|
IsVisible="{Binding !GaugeRows.Count}"/>
|
|
|
|
|
|
|
|
|
|
<!-- Period picker -->
|
|
|
|
|
<StackPanel DockPanel.Dock="Top" Orientation="Horizontal" Spacing="8" Margin="20,12,20,0">
|
|
|
|
|
<TextBlock Classes="meta" Text="{loc:Tr modals.usageMonitor.period}" VerticalAlignment="Center"/>
|
|
|
|
|
<Button Classes="btn" Content="{loc:Tr modals.usageMonitor.last7Days}"
|
|
|
|
|
Command="{Binding SetPresetCommand}" CommandParameter="7"/>
|
|
|
|
|
<Button Classes="btn" Content="{loc:Tr modals.usageMonitor.last30Days}"
|
|
|
|
|
Command="{Binding SetPresetCommand}" CommandParameter="30"/>
|
|
|
|
|
<TextBlock Classes="meta" Text="{loc:Tr modals.usageMonitor.fromDate}" VerticalAlignment="Center"/>
|
|
|
|
|
<ctl:ThemedDatePicker SelectedDate="{Binding StartDate}"/>
|
|
|
|
|
<TextBlock Classes="meta" Text="{loc:Tr modals.usageMonitor.toDate}" VerticalAlignment="Center"/>
|
|
|
|
|
<ctl:ThemedDatePicker SelectedDate="{Binding EndDate}"/>
|
|
|
|
|
</StackPanel>
|
|
|
|
|
|
|
|
|
|
<TabControl Padding="20,12" TabStripPlacement="Top">
|
|
|
|
|
|
|
|
|
|
<TabItem Header="{loc:Tr modals.usageMonitor.modelUsage}">
|
|
|
|
|
<ScrollViewer>
|
|
|
|
|
<StackPanel>
|
|
|
|
|
<TextBlock Classes="meta" Margin="0,16"
|
|
|
|
|
Text="{loc:Tr modals.usageMonitor.emptyStateHint}"
|
|
|
|
|
IsVisible="{Binding ModelsEmpty}"/>
|
|
|
|
|
<Grid ColumnDefinitions="*,80,80,80,80,80,80,60" Margin="12,0,12,4" IsVisible="{Binding !ModelsEmpty}">
|
|
|
|
|
<TextBlock Grid.Column="0" Classes="eyebrow" Text="{loc:Tr modals.usageMonitor.columnModel}"/>
|
|
|
|
|
<TextBlock Grid.Column="1" Classes="eyebrow" Text="{loc:Tr modals.usageMonitor.columnIn}"/>
|
|
|
|
|
<TextBlock Grid.Column="2" Classes="eyebrow" Text="{loc:Tr modals.usageMonitor.columnOut}"/>
|
|
|
|
|
<TextBlock Grid.Column="3" Classes="eyebrow" Text="{loc:Tr modals.usageMonitor.columnCache}"/>
|
|
|
|
|
<TextBlock Grid.Column="4" Classes="eyebrow" Text="{loc:Tr modals.usageMonitor.columnOtherIn}"/>
|
|
|
|
|
<TextBlock Grid.Column="5" Classes="eyebrow" Text="{loc:Tr modals.usageMonitor.columnOtherOut}"/>
|
|
|
|
|
<TextBlock Grid.Column="6" Classes="eyebrow" Text="{loc:Tr modals.usageMonitor.columnOtherCache}"/>
|
|
|
|
|
<TextBlock Grid.Column="7" Classes="eyebrow" Text="{loc:Tr modals.usageMonitor.columnShare}"/>
|
|
|
|
|
</Grid>
|
|
|
|
|
<Border Height="1" Background="{DynamicResource LineBrush}" Margin="0,0,0,8" IsVisible="{Binding !ModelsEmpty}"/>
|
|
|
|
|
<ItemsControl ItemsSource="{Binding ModelRows}">
|
|
|
|
|
<ItemsControl.ItemTemplate>
|
|
|
|
|
<DataTemplate x:DataType="vm:ModelUsageDisplayRow">
|
|
|
|
|
<Grid ColumnDefinitions="*,80,80,80,80,80,80,60" Margin="12,4">
|
|
|
|
|
<TextBlock Grid.Column="0" Classes="title" Text="{Binding Model}"/>
|
|
|
|
|
<TextBlock Grid.Column="1" Classes="meta" Text="{Binding ClaudeDoInputTokens}"/>
|
|
|
|
|
<TextBlock Grid.Column="2" Classes="meta" Text="{Binding ClaudeDoOutputTokens}"/>
|
|
|
|
|
<TextBlock Grid.Column="3" Classes="meta" Text="{Binding ClaudeDoCacheTokens}"/>
|
|
|
|
|
<TextBlock Grid.Column="4" Classes="meta" Text="{Binding OtherInputTokens}"/>
|
|
|
|
|
<TextBlock Grid.Column="5" Classes="meta" Text="{Binding OtherOutputTokens}"/>
|
|
|
|
|
<TextBlock Grid.Column="6" Classes="meta" Text="{Binding OtherCacheTokens}"/>
|
|
|
|
|
<TextBlock Grid.Column="7" Classes="meta" Text="{Binding SharePercent, StringFormat={}{0:0}%}"/>
|
|
|
|
|
</Grid>
|
|
|
|
|
</DataTemplate>
|
|
|
|
|
</ItemsControl.ItemTemplate>
|
|
|
|
|
</ItemsControl>
|
|
|
|
|
</StackPanel>
|
|
|
|
|
</ScrollViewer>
|
|
|
|
|
</TabItem>
|
|
|
|
|
|
|
|
|
|
<TabItem Header="{loc:Tr modals.usageMonitor.taskUsage}">
|
|
|
|
|
<ScrollViewer>
|
|
|
|
|
<StackPanel>
|
|
|
|
|
<TextBlock Classes="meta" Margin="0,16"
|
|
|
|
|
Text="{loc:Tr modals.usageMonitor.emptyStateHint}"
|
|
|
|
|
IsVisible="{Binding TasksEmpty}"/>
|
|
|
|
|
<Grid ColumnDefinitions="*,110,90,60,80,80,80" Margin="12,0,12,4" IsVisible="{Binding !TasksEmpty}">
|
|
|
|
|
<TextBlock Grid.Column="0" Classes="eyebrow" Text="{loc:Tr modals.usageMonitor.columnTask}"/>
|
|
|
|
|
<TextBlock Grid.Column="1" Classes="eyebrow" Text="{loc:Tr modals.usageMonitor.columnList}"/>
|
|
|
|
|
<TextBlock Grid.Column="2" Classes="eyebrow" Text="{loc:Tr modals.usageMonitor.columnModelShort}"/>
|
|
|
|
|
<TextBlock Grid.Column="3" Classes="eyebrow" Text="{loc:Tr modals.usageMonitor.columnRuns}"/>
|
|
|
|
|
<TextBlock Grid.Column="4" Classes="eyebrow" Text="{loc:Tr modals.usageMonitor.columnIn}"/>
|
|
|
|
|
<TextBlock Grid.Column="5" Classes="eyebrow" Text="{loc:Tr modals.usageMonitor.columnOut}"/>
|
|
|
|
|
<TextBlock Grid.Column="6" Classes="eyebrow" Text="{loc:Tr modals.usageMonitor.columnTotal}"/>
|
|
|
|
|
</Grid>
|
|
|
|
|
<Border Height="1" Background="{DynamicResource LineBrush}" Margin="0,0,0,8" IsVisible="{Binding !TasksEmpty}"/>
|
|
|
|
|
<ItemsControl ItemsSource="{Binding TaskRows}">
|
|
|
|
|
<ItemsControl.ItemTemplate>
|
|
|
|
|
<DataTemplate x:DataType="vm:TaskUsageDisplayRow">
|
|
|
|
|
<Grid ColumnDefinitions="*,110,90,60,80,80,80" Margin="12,4">
|
|
|
|
|
<TextBlock Grid.Column="0" Classes="title" Text="{Binding TaskTitle}"/>
|
|
|
|
|
<TextBlock Grid.Column="1" Classes="meta" Text="{Binding ListName}"/>
|
|
|
|
|
<TextBlock Grid.Column="2" Classes="meta" Text="{Binding Model}"/>
|
|
|
|
|
<TextBlock Grid.Column="3" Classes="meta" Text="{Binding Runs}"/>
|
|
|
|
|
<TextBlock Grid.Column="4" Classes="meta" Text="{Binding TokensIn}"/>
|
|
|
|
|
<TextBlock Grid.Column="5" Classes="meta" Text="{Binding TokensOut}"/>
|
|
|
|
|
<TextBlock Grid.Column="6" Classes="meta" Text="{Binding TotalTokens}"/>
|
|
|
|
|
</Grid>
|
|
|
|
|
</DataTemplate>
|
|
|
|
|
</ItemsControl.ItemTemplate>
|
|
|
|
|
</ItemsControl>
|
|
|
|
|
</StackPanel>
|
|
|
|
|
</ScrollViewer>
|
|
|
|
|
</TabItem>
|
|
|
|
|
|
|
|
|
|
</TabControl>
|
|
|
|
|
|
|
|
|
|
<Ellipse Classes="spinner" Width="20" Height="20" Margin="0,0,0,16"
|
|
|
|
|
HorizontalAlignment="Center" DockPanel.Dock="Bottom"
|
|
|
|
|
IsVisible="{Binding IsBusy}"/>
|
|
|
|
|
|
|
|
|
|
</DockPanel>
|
|
|
|
|
</ctl:ModalShell>
|
|
|
|
|
</Window>
|