feat(ui): show cost columns and the TokenTracker hint card in the usage monitor

This commit is contained in:
mika kuns
2026-08-24 16:16:39 +02:00
parent bac0d69a49
commit 074c0e4dbd
@@ -147,6 +147,41 @@
<ctl:ThemedDatePicker SelectedDate="{Binding EndDate}"/> <ctl:ThemedDatePicker SelectedDate="{Binding EndDate}"/>
</StackPanel> </StackPanel>
<!-- TokenTracker hint: shown instead of the analytics header while the CLI is missing -->
<Border DockPanel.Dock="Top" Margin="20,12,20,0"
IsVisible="{Binding TokenTrackerMissing}"
Background="{DynamicResource DeepBrush}"
BorderBrush="{DynamicResource StatusReviewBrush}"
BorderThickness="1" CornerRadius="6" Padding="12,10">
<StackPanel Spacing="6">
<TextBlock Classes="title" Text="{loc:Tr modals.usageMonitor.ttMissingTitle}"/>
<TextBlock Classes="meta" TextWrapping="Wrap"
Text="{loc:Tr modals.usageMonitor.ttMissingBody}"/>
<TextBlock Classes="meta" TextWrapping="Wrap"
IsVisible="{Binding !ShowInstallButton}"
Text="{Binding NodeHintText}"/>
<TextBlock Classes="meta" TextWrapping="Wrap"
IsVisible="{Binding HasTokenTrackerError}"
Text="{Binding TokenTrackerErrorText}"/>
<Button Classes="btn" HorizontalAlignment="Left"
IsVisible="{Binding ShowInstallButton}"
Content="{loc:Tr modals.usageMonitor.ttInstall}"
Command="{Binding InstallTokenTrackerCommand}"/>
<Ellipse Classes="spinner" Width="14" Height="14" HorizontalAlignment="Left"
IsVisible="{Binding IsInstalling}"/>
</StackPanel>
</Border>
<!-- Analytics header: totals, freshness stamp, manual refresh -->
<StackPanel DockPanel.Dock="Top" Orientation="Horizontal" Spacing="12"
Margin="20,12,20,0" VerticalAlignment="Center"
IsVisible="{Binding !TokenTrackerMissing}">
<TextBlock Classes="title" VerticalAlignment="Center" Text="{Binding TotalsText}"/>
<TextBlock Classes="meta" VerticalAlignment="Center" Text="{Binding AnalyticsStampText}"/>
<Button Classes="btn" Content="{loc:Tr modals.usageMonitor.analyticsRefresh}"
Command="{Binding RefreshAnalyticsCommand}"/>
</StackPanel>
<TabControl Padding="20,12" TabStripPlacement="Top"> <TabControl Padding="20,12" TabStripPlacement="Top">
<TabItem Header="{loc:Tr modals.usageMonitor.modelUsage}"> <TabItem Header="{loc:Tr modals.usageMonitor.modelUsage}">
@@ -155,7 +190,7 @@
<TextBlock Classes="meta" Margin="0,16" <TextBlock Classes="meta" Margin="0,16"
Text="{loc:Tr modals.usageMonitor.emptyStateHint}" Text="{loc:Tr modals.usageMonitor.emptyStateHint}"
IsVisible="{Binding ModelsEmpty}"/> IsVisible="{Binding ModelsEmpty}"/>
<Grid ColumnDefinitions="*,80,80,80,80,80,80,60" Margin="12,0,12,4" IsVisible="{Binding !ModelsEmpty}"> <Grid ColumnDefinitions="*,80,80,80,80,80,80,60,80" Margin="12,0,12,4" IsVisible="{Binding !ModelsEmpty}">
<TextBlock Grid.Column="0" Classes="eyebrow" Text="{loc:Tr modals.usageMonitor.columnModel}"/> <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="1" Classes="eyebrow" Text="{loc:Tr modals.usageMonitor.columnIn}"/>
<TextBlock Grid.Column="2" Classes="eyebrow" Text="{loc:Tr modals.usageMonitor.columnOut}"/> <TextBlock Grid.Column="2" Classes="eyebrow" Text="{loc:Tr modals.usageMonitor.columnOut}"/>
@@ -164,12 +199,13 @@
<TextBlock Grid.Column="5" Classes="eyebrow" Text="{loc:Tr modals.usageMonitor.columnOtherOut}"/> <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="6" Classes="eyebrow" Text="{loc:Tr modals.usageMonitor.columnOtherCache}"/>
<TextBlock Grid.Column="7" Classes="eyebrow" Text="{loc:Tr modals.usageMonitor.columnShare}"/> <TextBlock Grid.Column="7" Classes="eyebrow" Text="{loc:Tr modals.usageMonitor.columnShare}"/>
<TextBlock Grid.Column="8" Classes="eyebrow" Text="{loc:Tr modals.usageMonitor.columnCost}"/>
</Grid> </Grid>
<Border Height="1" Background="{DynamicResource LineBrush}" Margin="0,0,0,8" IsVisible="{Binding !ModelsEmpty}"/> <Border Height="1" Background="{DynamicResource LineBrush}" Margin="0,0,0,8" IsVisible="{Binding !ModelsEmpty}"/>
<ItemsControl ItemsSource="{Binding ModelRows}"> <ItemsControl ItemsSource="{Binding ModelRows}">
<ItemsControl.ItemTemplate> <ItemsControl.ItemTemplate>
<DataTemplate x:DataType="vm:ModelUsageDisplayRow"> <DataTemplate x:DataType="vm:ModelUsageDisplayRow">
<Grid ColumnDefinitions="*,80,80,80,80,80,80,60" Margin="12,4"> <Grid ColumnDefinitions="*,80,80,80,80,80,80,60,80" Margin="12,4">
<TextBlock Grid.Column="0" Classes="title" Text="{Binding Model}"/> <TextBlock Grid.Column="0" Classes="title" Text="{Binding Model}"/>
<TextBlock Grid.Column="1" Classes="meta" Text="{Binding ClaudeDoInputTokens}"/> <TextBlock Grid.Column="1" Classes="meta" Text="{Binding ClaudeDoInputTokens}"/>
<TextBlock Grid.Column="2" Classes="meta" Text="{Binding ClaudeDoOutputTokens}"/> <TextBlock Grid.Column="2" Classes="meta" Text="{Binding ClaudeDoOutputTokens}"/>
@@ -178,6 +214,7 @@
<TextBlock Grid.Column="5" Classes="meta" Text="{Binding OtherOutputTokens}"/> <TextBlock Grid.Column="5" Classes="meta" Text="{Binding OtherOutputTokens}"/>
<TextBlock Grid.Column="6" Classes="meta" Text="{Binding OtherCacheTokens}"/> <TextBlock Grid.Column="6" Classes="meta" Text="{Binding OtherCacheTokens}"/>
<TextBlock Grid.Column="7" Classes="meta" Text="{Binding SharePercent, StringFormat={}{0:0}%}"/> <TextBlock Grid.Column="7" Classes="meta" Text="{Binding SharePercent, StringFormat={}{0:0}%}"/>
<TextBlock Grid.Column="8" Classes="meta" Text="{Binding CostText}"/>
</Grid> </Grid>
</DataTemplate> </DataTemplate>
</ItemsControl.ItemTemplate> </ItemsControl.ItemTemplate>
@@ -192,7 +229,7 @@
<TextBlock Classes="meta" Margin="0,16" <TextBlock Classes="meta" Margin="0,16"
Text="{loc:Tr modals.usageMonitor.emptyStateHint}" Text="{loc:Tr modals.usageMonitor.emptyStateHint}"
IsVisible="{Binding TasksEmpty}"/> IsVisible="{Binding TasksEmpty}"/>
<Grid ColumnDefinitions="*,110,90,60,80,80,80" Margin="12,0,12,4" IsVisible="{Binding !TasksEmpty}"> <Grid ColumnDefinitions="*,110,90,60,80,80,80,80,70" Margin="12,0,12,4" IsVisible="{Binding !TasksEmpty}">
<TextBlock Grid.Column="0" Classes="eyebrow" Text="{loc:Tr modals.usageMonitor.columnTask}"/> <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="1" Classes="eyebrow" Text="{loc:Tr modals.usageMonitor.columnList}"/>
<TextBlock Grid.Column="2" Classes="eyebrow" Text="{loc:Tr modals.usageMonitor.columnModelShort}"/> <TextBlock Grid.Column="2" Classes="eyebrow" Text="{loc:Tr modals.usageMonitor.columnModelShort}"/>
@@ -200,12 +237,14 @@
<TextBlock Grid.Column="4" Classes="eyebrow" Text="{loc:Tr modals.usageMonitor.columnIn}"/> <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="5" Classes="eyebrow" Text="{loc:Tr modals.usageMonitor.columnOut}"/>
<TextBlock Grid.Column="6" Classes="eyebrow" Text="{loc:Tr modals.usageMonitor.columnTotal}"/> <TextBlock Grid.Column="6" Classes="eyebrow" Text="{loc:Tr modals.usageMonitor.columnTotal}"/>
<TextBlock Grid.Column="7" Classes="eyebrow" Text="{loc:Tr modals.usageMonitor.columnCost}"/>
<TextBlock Grid.Column="8" Classes="eyebrow" Text="{loc:Tr modals.usageMonitor.columnRetries}"/>
</Grid> </Grid>
<Border Height="1" Background="{DynamicResource LineBrush}" Margin="0,0,0,8" IsVisible="{Binding !TasksEmpty}"/> <Border Height="1" Background="{DynamicResource LineBrush}" Margin="0,0,0,8" IsVisible="{Binding !TasksEmpty}"/>
<ItemsControl ItemsSource="{Binding TaskRows}"> <ItemsControl ItemsSource="{Binding TaskRows}">
<ItemsControl.ItemTemplate> <ItemsControl.ItemTemplate>
<DataTemplate x:DataType="vm:TaskUsageDisplayRow"> <DataTemplate x:DataType="vm:TaskUsageDisplayRow">
<Grid ColumnDefinitions="*,110,90,60,80,80,80" Margin="12,4"> <Grid ColumnDefinitions="*,110,90,60,80,80,80,80,70" Margin="12,4">
<TextBlock Grid.Column="0" Classes="title" Text="{Binding TaskTitle}"/> <TextBlock Grid.Column="0" Classes="title" Text="{Binding TaskTitle}"/>
<TextBlock Grid.Column="1" Classes="meta" Text="{Binding ListName}"/> <TextBlock Grid.Column="1" Classes="meta" Text="{Binding ListName}"/>
<TextBlock Grid.Column="2" Classes="meta" Text="{Binding Model}"/> <TextBlock Grid.Column="2" Classes="meta" Text="{Binding Model}"/>
@@ -213,6 +252,8 @@
<TextBlock Grid.Column="4" Classes="meta" Text="{Binding TokensIn}"/> <TextBlock Grid.Column="4" Classes="meta" Text="{Binding TokensIn}"/>
<TextBlock Grid.Column="5" Classes="meta" Text="{Binding TokensOut}"/> <TextBlock Grid.Column="5" Classes="meta" Text="{Binding TokensOut}"/>
<TextBlock Grid.Column="6" Classes="meta" Text="{Binding TotalTokens}"/> <TextBlock Grid.Column="6" Classes="meta" Text="{Binding TotalTokens}"/>
<TextBlock Grid.Column="7" Classes="meta" Text="{Binding CostText}"/>
<TextBlock Grid.Column="8" Classes="meta" Text="{Binding RetriesText}"/>
</Grid> </Grid>
</DataTemplate> </DataTemplate>
</ItemsControl.ItemTemplate> </ItemsControl.ItemTemplate>