Skip to content

Commit f3be771

Browse files
committed
refactor(workspace): defer per-row balances to keep switcher parity with cloud
1 parent a186991 commit f3be771

7 files changed

Lines changed: 1 addition & 254 deletions

File tree

src/locales/en/main.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3337,7 +3337,6 @@
33373337
"nameValidationError": "Name must be 1–50 characters using letters, numbers, spaces, or common punctuation."
33383338
},
33393339
"workspaceSwitcher": {
3340-
"noCredits": "No credits",
33413340
"scopeCaption": "Workspaces only affect which credits you use.",
33423341
"scopeTooltip": "Runs that use partner nodes spend credits from this workspace. Unlike on Cloud, every workspace saves to your usual output folder.",
33433342
"switchWorkspace": "Switch workspace",

src/platform/workspace/api/workspaceApi.ts

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -446,24 +446,6 @@ export const workspaceApi = {
446446
}
447447
},
448448

449-
/**
450-
* Get credit balance for a specific workspace via an explicitly minted
451-
* token, without switching the active workspace context.
452-
*/
453-
async getBillingBalanceWithToken(
454-
accessToken: string
455-
): Promise<BillingBalanceResponse> {
456-
try {
457-
const response = await workspaceApiClient.get<BillingBalanceResponse>(
458-
workspaceApiUrl('/billing/balance'),
459-
{ headers: { Authorization: `Bearer ${accessToken}` } }
460-
)
461-
return response.data
462-
} catch (err) {
463-
handleAxiosError(err)
464-
}
465-
},
466-
467449
/**
468450
* Get available subscription plans
469451
* GET /api/billing/plans

src/platform/workspace/components/WorkspaceSwitcherPopover.test.ts

Lines changed: 0 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -23,20 +23,6 @@ const distributionMocks = vi.hoisted(() => ({ isCloud: true }))
2323

2424
vi.mock('@/platform/distribution/types', () => distributionMocks)
2525

26-
const balanceMocks = vi.hoisted(() => ({
27-
balanceByWorkspaceId: {} as Record<
28-
string,
29-
| { status: 'loading' }
30-
| { status: 'ready'; cents: number }
31-
| { status: 'error' }
32-
>,
33-
loadBalances: vi.fn()
34-
}))
35-
36-
vi.mock('@/platform/workspace/composables/useWorkspaceBalances', () => ({
37-
useWorkspaceBalances: () => balanceMocks
38-
}))
39-
4026
const LONG_WORKSPACE_NAME =
4127
'Quantum Renaissance Collective for Hyperdimensional Latent Diffusion Research and Experimental Workflow Engineering'
4228

@@ -49,7 +35,6 @@ const i18n = createI18n({
4935
personal: 'Personal',
5036
roleOwner: 'Owner',
5137
roleMember: 'Member',
52-
noCredits: 'No credits',
5338
scopeCaption: 'Workspaces only affect which credits you use.',
5439
scopeTooltip:
5540
'Runs that use partner nodes spend credits from this workspace. Unlike on Cloud, every workspace saves to your usual output folder.',
@@ -121,30 +106,6 @@ function renderComponent(
121106
}
122107

123108
describe('WorkspaceSwitcherPopover', () => {
124-
it('shows per-workspace balances on non-active rows and asks for them on mount', () => {
125-
balanceMocks.balanceByWorkspaceId['ws-team-long'] = {
126-
status: 'ready',
127-
cents: 1000
128-
}
129-
renderComponent()
130-
131-
// 1000 cents at the 2.11 credits-per-cent rate
132-
expect(screen.getByText('2,110')).toBeInTheDocument()
133-
expect(balanceMocks.loadBalances).toHaveBeenCalledWith(
134-
expect.arrayContaining(['ws-team-long'])
135-
)
136-
})
137-
138-
it('labels an empty workspace "No credits" instead of a number', () => {
139-
balanceMocks.balanceByWorkspaceId['ws-team-long'] = {
140-
status: 'ready',
141-
cents: 0
142-
}
143-
renderComponent()
144-
145-
expect(screen.getByText('No credits')).toBeInTheDocument()
146-
})
147-
148109
it('shows the credits-scope caption off cloud', () => {
149110
distributionMocks.isCloud = false
150111
renderComponent()

src/platform/workspace/components/WorkspaceSwitcherPopover.vue

Lines changed: 1 addition & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -64,12 +64,6 @@
6464
v-if="isCurrentWorkspace(workspace)"
6565
class="pi pi-check shrink-0 text-sm text-base-foreground"
6666
/>
67-
<span
68-
v-else-if="rowBalanceLabel(workspace)"
69-
class="shrink-0 text-sm text-muted-foreground tabular-nums"
70-
>
71-
{{ rowBalanceLabel(workspace) }}
72-
</span>
7367
</button>
7468
</div>
7569
</div>
@@ -129,14 +123,12 @@
129123

130124
<script setup lang="ts">
131125
import { storeToRefs } from 'pinia'
132-
import { computed, onMounted, watch } from 'vue'
126+
import { computed } from 'vue'
133127
import { useI18n } from 'vue-i18n'
134128
135129
import WorkspaceProfilePic from '@/platform/workspace/components/WorkspaceProfilePic.vue'
136130
import { useBillingContext } from '@/composables/billing/useBillingContext'
137131
import { isCloud } from '@/platform/distribution/types'
138-
import { formatCreditsFromCents } from '@/base/credits/comfyCredits'
139-
import { useWorkspaceBalances } from '@/platform/workspace/composables/useWorkspaceBalances'
140132
import { useWorkspaceSwitch } from '@/platform/workspace/composables/useWorkspaceSwitch'
141133
import { useWorkspaceTierLabel } from '@/platform/workspace/composables/useWorkspaceTierLabel'
142134
import type {
@@ -225,29 +217,4 @@ async function handleSelectWorkspace(workspace: AvailableWorkspace) {
225217
function handleCreateWorkspace() {
226218
emit('create')
227219
}
228-
229-
const { locale } = useI18n()
230-
const { balanceByWorkspaceId, loadBalances } = useWorkspaceBalances()
231-
232-
const peekableWorkspaceIds = computed(() =>
233-
availableWorkspaces.value
234-
.filter((w) => !isCurrentWorkspace(w))
235-
.map((w) => w.id)
236-
)
237-
238-
onMounted(() => loadBalances(peekableWorkspaceIds.value))
239-
watch(peekableWorkspaceIds, (ids) => loadBalances(ids))
240-
241-
function rowBalanceLabel(workspace: AvailableWorkspace): string {
242-
const state = balanceByWorkspaceId[workspace.id]
243-
if (!state || state.status === 'loading' || state.status === 'error') {
244-
return ''
245-
}
246-
if (state.cents <= 0) return t('workspaceSwitcher.noCredits')
247-
return formatCreditsFromCents({
248-
cents: state.cents,
249-
locale: locale.value,
250-
numberOptions: { minimumFractionDigits: 0, maximumFractionDigits: 0 }
251-
})
252-
}
253220
</script>

src/platform/workspace/composables/useWorkspaceBalances.test.ts

Lines changed: 0 additions & 88 deletions
This file was deleted.

src/platform/workspace/composables/useWorkspaceBalances.ts

Lines changed: 0 additions & 57 deletions
This file was deleted.

src/platform/workspace/stores/workspaceAuthStore.ts

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -555,22 +555,6 @@ export const useWorkspaceAuthStore = defineStore('workspaceAuth', () => {
555555
* callers onto a single in-flight mint, backs off after failure, and returns
556556
* null so callers fail closed rather than downgrade to the personal identity.
557557
*/
558-
/**
559-
* Read-only token mint for a workspace the user is not switched into, used
560-
* to peek at per-workspace data (e.g. switcher balances). Never touches the
561-
* active workspace context or the stored token state.
562-
*/
563-
async function peekWorkspaceToken(
564-
workspaceId: string
565-
): Promise<string | null> {
566-
try {
567-
const minted = await requestToken(workspaceId)
568-
return minted.token
569-
} catch {
570-
return null
571-
}
572-
}
573-
574558
async function ensureWorkspaceToken(
575559
preferredWorkspaceId?: string
576560
): Promise<string | null> {
@@ -1030,7 +1014,6 @@ export const useWorkspaceAuthStore = defineStore('workspaceAuth', () => {
10301014
getWorkspaceAuthHeader,
10311015
ensureWorkspaceAuthHeader,
10321016
ensureWorkspaceToken,
1033-
peekWorkspaceToken,
10341017
getWorkspaceToken,
10351018
getUnifiedToken,
10361019
clearWorkspaceContext

0 commit comments

Comments
 (0)