22import { computed , nextTick , onBeforeUnmount , onMounted , ref } from ' vue'
33import { useRouter } from ' vue-router'
44import * as echarts from ' echarts'
5+ import { message } from ' ant-design-vue'
56import {
67 BarChartOutlined ,
78 ClockCircleOutlined ,
89 DollarCircleOutlined ,
10+ FolderOpenOutlined ,
911 FunctionOutlined ,
12+ PlayCircleOutlined ,
13+ SettingOutlined ,
1014 TableOutlined ,
1115 ToolOutlined
1216} from ' @ant-design/icons-vue'
@@ -19,17 +23,22 @@ import {
1923 shortPath ,
2024 type ModelUsage ,
2125 type Overview ,
26+ type Settings ,
2227 type Session
2328} from ' ../api'
2429import { chartPalette , usageChartColors } from ' ../chartPalette'
30+ import { notifyAppDataChanged } from ' ../events'
2531
2632const router = useRouter ()
2733const loading = ref (true )
34+ const startupIndexing = ref (false )
2835const overview = ref <Overview | null >(null )
36+ const settings = ref <Settings | null >(null )
2937const chartEl = ref <HTMLDivElement | null >(null )
3038let chart: echarts .ECharts | null = null
3139
3240const hasIndexedData = computed (() => (overview .value ?.totalSessions || 0 ) > 0 )
41+ const sourcePathDisplay = computed (() => settings .value ?.sourcePath || settings .value ?.defaultSourcePath || ' ' )
3342const hasDailyUsage = computed (() => (overview .value ?.dailyUsage ?.length || 0 ) > 0 )
3443const rankedModelUsage = computed (() =>
3544 [... (overview .value ?.modelUsage || [])].sort ((left , right ) => right .totalTokens - left .totalTokens )
@@ -56,14 +65,30 @@ const recentColumns = [
5665async function load() {
5766 loading .value = true
5867 try {
59- overview .value = await api .getOverview ()
68+ const [settingsValue, overviewValue] = await Promise .all ([api .getSettings (), api .getOverview ()])
69+ settings .value = settingsValue
70+ overview .value = overviewValue
6071 } finally {
6172 loading .value = false
6273 }
6374 await nextTick ()
6475 renderChart ()
6576}
6677
78+ async function indexFromOverview() {
79+ startupIndexing .value = true
80+ try {
81+ const result = await api .indexNow (false )
82+ message .success (` ${result .indexed } indexed, ${result .skipped } skipped, ${result .failed } failed ` )
83+ await load ()
84+ notifyAppDataChanged (' index' )
85+ } catch (error ) {
86+ message .error (error instanceof Error ? error .message : ' Index failed' )
87+ } finally {
88+ startupIndexing .value = false
89+ }
90+ }
91+
6792function renderChart() {
6893 const dailyUsage = overview .value ?.dailyUsage || []
6994 if (! dailyUsage .length ) {
@@ -230,13 +255,33 @@ onBeforeUnmount(() => {
230255 </section >
231256
232257 <div v-if =" !loading && !hasIndexedData" class =" empty-callout overview-empty-callout" >
233- <div >
258+ <div class = " empty-callout-main " >
234259 <div class =" empty-callout-title" >No indexed sessions yet</div >
235260 <div class =" empty-callout-text" >
236- Configure a local source path, then run Index Now to populate usage, cost, and tool-call telemetry .
261+ AgentMeter can scan the configured Codex source now and refresh this dashboard when indexing completes .
237262 </div >
263+ <div class =" empty-source-line" >
264+ <FolderOpenOutlined />
265+ <span class =" source-label" >Source</span >
266+ <a-typography-text class =" empty-source-path" :ellipsis =" { tooltip: sourcePathDisplay }" >
267+ {{ sourcePathDisplay || 'Open Settings to choose a source path' }}
268+ </a-typography-text >
269+ </div >
270+ </div >
271+ <div class =" empty-callout-actions" >
272+ <a-button type =" primary" :loading =" startupIndexing" :disabled =" !sourcePathDisplay" @click =" indexFromOverview" >
273+ <template #icon >
274+ <PlayCircleOutlined />
275+ </template >
276+ Index Now
277+ </a-button >
278+ <a-button @click =" $router.push('/settings')" >
279+ <template #icon >
280+ <SettingOutlined />
281+ </template >
282+ Edit Source
283+ </a-button >
238284 </div >
239- <a-button type =" primary" @click =" $router.push('/settings')" >Open Settings</a-button >
240285 </div >
241286
242287 <div class =" content-grid overview-primary-grid" >
0 commit comments