diff --git a/frontend/src/components/account/AccountUsageCell.vue b/frontend/src/components/account/AccountUsageCell.vue index 0e5615120c..c1d7696b63 100644 --- a/frontend/src/components/account/AccountUsageCell.vue +++ b/frontend/src/components/account/AccountUsageCell.vue @@ -584,6 +584,7 @@
) => { + emit('account-updated', { ...props.account, opencode_go_usage: state }) +} + // ===== Key account today stats formatters ===== const formatKeyRequests = computed(() => { diff --git a/frontend/src/components/account/OpenCodeGoUsageCell.vue b/frontend/src/components/account/OpenCodeGoUsageCell.vue index 5dd7ee5c72..6ad8a8b736 100644 --- a/frontend/src/components/account/OpenCodeGoUsageCell.vue +++ b/frontend/src/components/account/OpenCodeGoUsageCell.vue @@ -38,23 +38,69 @@ > {{ statusLabel }} +
+ +
- diff --git a/frontend/src/components/account/__tests__/OpenCodeGoUsageCell.spec.ts b/frontend/src/components/account/__tests__/OpenCodeGoUsageCell.spec.ts index 0f7227993d..999b14ef1c 100644 --- a/frontend/src/components/account/__tests__/OpenCodeGoUsageCell.spec.ts +++ b/frontend/src/components/account/__tests__/OpenCodeGoUsageCell.spec.ts @@ -1,9 +1,21 @@ -import { mount } from '@vue/test-utils' -import { describe, expect, it, vi } from 'vitest' +import { flushPromises, mount } from '@vue/test-utils' +import { beforeEach, describe, expect, it, vi } from 'vitest' import OpenCodeGoUsageCell from '../OpenCodeGoUsageCell.vue' import UsageProgressBar from '../UsageProgressBar.vue' import type { Account, OpenCodeGoUsageState } from '@/types' +const { refreshOpenCodeGoUsage } = vi.hoisted(() => ({ + refreshOpenCodeGoUsage: vi.fn() +})) + +vi.mock('@/api/admin', () => ({ + adminAPI: { + accounts: { + refreshOpenCodeGoUsage + } + } +})) + vi.mock('vue-i18n', async () => { const actual = await vi.importActual('vue-i18n') return { @@ -12,8 +24,8 @@ vi.mock('vue-i18n', async () => { t: (key: string) => { const short: Record = { 'admin.accounts.opencodeGo.rollingShort': '5h', - 'admin.accounts.opencodeGo.weeklyShort': 'W', - 'admin.accounts.opencodeGo.monthlyShort': 'M', + 'admin.accounts.opencodeGo.weeklyShort': '7d', + 'admin.accounts.opencodeGo.monthlyShort': '1m', 'admin.accounts.opencodeGo.unauthorized': 'unauthorized', 'admin.accounts.opencodeGo.failed': 'failed', 'admin.accounts.opencodeGo.ok': 'ok' @@ -70,6 +82,10 @@ const account = (state = usageState()): Account => ({ }) describe('OpenCodeGoUsageCell', () => { + beforeEach(() => { + refreshOpenCodeGoUsage.mockReset() + }) + it('renders rolling, weekly and monthly windows in a shrinkable mobile-safe cell', () => { const wrapper = mount(OpenCodeGoUsageCell, { props: { account: account() } }) const cell = wrapper.get('[data-testid="opencode-go-usage-cell"]') @@ -85,20 +101,35 @@ describe('OpenCodeGoUsageCell', () => { color: 'indigo' }) expect(bars[1].props()).toMatchObject({ - label: 'W', + label: '7d', utilization: 14.2, resetsAt: '2026-07-29T00:00:00Z', color: 'emerald' }) expect(bars[2].props()).toMatchObject({ - label: 'M', + label: '1m', utilization: 33.3, resetsAt: '2026-08-01T00:00:00Z', color: 'amber' }) expect(wrapper.find('[data-testid="opencode-go-status-badge"]').exists()).toBe(false) - expect(wrapper.findAll('button')).toHaveLength(0) + const query = wrapper.get('[data-testid="opencode-go-usage-query"]') + expect(query.text()).toContain('admin.accounts.usageWindow.activeQuery') + }) + + it('refreshes usage on demand and emits the new state', async () => { + const next = usageState() + next.snapshot!.data!.rolling!.percent = 42 + refreshOpenCodeGoUsage.mockResolvedValueOnce(next) + const wrapper = mount(OpenCodeGoUsageCell, { props: { account: account() } }) + + await wrapper.get('[data-testid="opencode-go-usage-query"]').trigger('click') + await flushPromises() + + expect(refreshOpenCodeGoUsage).toHaveBeenCalledWith(7) + expect(wrapper.findAllComponents(UsageProgressBar)[0].props('utilization')).toBe(42) + expect(wrapper.emitted('updated')?.[0]?.[0]).toEqual(next) }) it('shows a status badge when the snapshot status is not ok', () => { diff --git a/frontend/src/i18n/locales/en/admin/accounts.ts b/frontend/src/i18n/locales/en/admin/accounts.ts index 01f86e9c6c..89cf72ef84 100644 --- a/frontend/src/i18n/locales/en/admin/accounts.ts +++ b/frontend/src/i18n/locales/en/admin/accounts.ts @@ -309,9 +309,9 @@ export default { rolling: '5 hour', rollingShort: '5h', weekly: 'Week', - weeklyShort: 'W', + weeklyShort: '7d', monthly: 'Month', - monthlyShort: 'M', + monthlyShort: '1m', status: 'Status', updatedAt: 'Updated', ok: 'Current', diff --git a/frontend/src/i18n/locales/zh/admin/accounts.ts b/frontend/src/i18n/locales/zh/admin/accounts.ts index ebf65505d2..690c68df85 100644 --- a/frontend/src/i18n/locales/zh/admin/accounts.ts +++ b/frontend/src/i18n/locales/zh/admin/accounts.ts @@ -185,9 +185,9 @@ export default { rolling: '5 小时', rollingShort: '5h', weekly: '周', - weeklyShort: '周', + weeklyShort: '7d', monthly: '月', - monthlyShort: '月', + monthlyShort: '1m', status: '状态', updatedAt: '更新时间', ok: '正常',