mirror of
https://github.com/tiennm99/ccs.git
synced 2026-07-16 02:11:28 +00:00
fix(ui): normalize grouped account audience order
This commit is contained in:
@@ -34,6 +34,12 @@ export interface AccountVisualGroup {
|
||||
variants?: AccountVisualVariant[];
|
||||
}
|
||||
|
||||
const AUDIENCE_ORDER: Record<AccountAudience, number> = {
|
||||
business: 0,
|
||||
personal: 1,
|
||||
unknown: 2,
|
||||
};
|
||||
|
||||
function getLatestTimestamp(current?: string, candidate?: string): string | undefined {
|
||||
if (!candidate) return current;
|
||||
if (!current) return candidate;
|
||||
@@ -64,6 +70,20 @@ function buildAccountVariant(
|
||||
};
|
||||
}
|
||||
|
||||
function sortAccountVariants(variants: AccountVisualVariant[]): AccountVisualVariant[] {
|
||||
return [...variants].sort((left, right) => {
|
||||
const audienceDelta = AUDIENCE_ORDER[left.audience] - AUDIENCE_ORDER[right.audience];
|
||||
if (audienceDelta !== 0) {
|
||||
return audienceDelta;
|
||||
}
|
||||
|
||||
const leftLabel = left.audienceLabel ?? left.detailLabel ?? left.id;
|
||||
const rightLabel = right.audienceLabel ?? right.detailLabel ?? right.id;
|
||||
|
||||
return leftLabel.localeCompare(rightLabel);
|
||||
});
|
||||
}
|
||||
|
||||
export function buildAccountVisualGroups(
|
||||
accounts: OAuthAccount[],
|
||||
statsData?: Pick<CliproxyStats, 'accountStats'> | null
|
||||
@@ -104,24 +124,25 @@ export function buildAccountVisualGroups(
|
||||
};
|
||||
}
|
||||
|
||||
const canonicalEmail = variants[0]?.email ?? bucketKey;
|
||||
const originalProvider = accountMeta.get(variants[0]?.id ?? '')?.provider ?? 'codex';
|
||||
const orderedVariants = sortAccountVariants(variants);
|
||||
const canonicalEmail = orderedVariants[0]?.email ?? bucketKey;
|
||||
const originalProvider = accountMeta.get(orderedVariants[0]?.id ?? '')?.provider ?? 'codex';
|
||||
|
||||
return {
|
||||
id: bucketKey,
|
||||
email: canonicalEmail,
|
||||
tokenFile: variants[0]?.tokenFile ?? '',
|
||||
tokenFile: orderedVariants[0]?.tokenFile ?? '',
|
||||
provider: originalProvider,
|
||||
isDefault: variants.some((variant) => variant.isDefault),
|
||||
successCount: variants.reduce((sum, variant) => sum + variant.successCount, 0),
|
||||
failureCount: variants.reduce((sum, variant) => sum + variant.failureCount, 0),
|
||||
lastUsedAt: variants.reduce<string | undefined>(
|
||||
isDefault: orderedVariants.some((variant) => variant.isDefault),
|
||||
successCount: orderedVariants.reduce((sum, variant) => sum + variant.successCount, 0),
|
||||
failureCount: orderedVariants.reduce((sum, variant) => sum + variant.failureCount, 0),
|
||||
lastUsedAt: orderedVariants.reduce<string | undefined>(
|
||||
(latest, variant) => getLatestTimestamp(latest, variant.lastUsedAt),
|
||||
undefined
|
||||
),
|
||||
paused: variants.every((variant) => Boolean(variant.paused)),
|
||||
memberIds: variants.map((variant) => variant.id),
|
||||
variants,
|
||||
paused: orderedVariants.every((variant) => Boolean(variant.paused)),
|
||||
memberIds: orderedVariants.map((variant) => variant.id),
|
||||
variants: orderedVariants,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
import { describe, expect, it } from 'vitest';
|
||||
|
||||
import type { OAuthAccount } from '@/lib/api-client';
|
||||
import { buildAccountVisualGroups } from '@/lib/account-visual-groups';
|
||||
|
||||
function makeAccount(overrides: Partial<OAuthAccount> & Pick<OAuthAccount, 'id' | 'tokenFile'>) {
|
||||
return {
|
||||
id: overrides.id,
|
||||
email: 'kaidu.kd@gmail.com',
|
||||
provider: 'codex',
|
||||
isDefault: false,
|
||||
tokenFile: overrides.tokenFile,
|
||||
createdAt: '2026-03-30T00:00:00.000Z',
|
||||
...overrides,
|
||||
} satisfies OAuthAccount;
|
||||
}
|
||||
|
||||
describe('buildAccountVisualGroups', () => {
|
||||
it('orders grouped codex variants by audience consistently', () => {
|
||||
const groups = buildAccountVisualGroups([
|
||||
makeAccount({
|
||||
id: 'kaidu.kd@gmail.com#free',
|
||||
tokenFile: 'codex-kaidu.kd@gmail.com-free.json',
|
||||
}),
|
||||
makeAccount({
|
||||
id: 'kaidu.kd@gmail.com#04a0f049-team',
|
||||
tokenFile: 'codex-04a0f049-kaidu.kd@gmail.com-team.json',
|
||||
}),
|
||||
]);
|
||||
|
||||
expect(groups).toHaveLength(1);
|
||||
expect(groups[0]?.variants?.map((variant) => variant.audience)).toEqual([
|
||||
'business',
|
||||
'personal',
|
||||
]);
|
||||
expect(groups[0]?.memberIds).toEqual([
|
||||
'kaidu.kd@gmail.com#04a0f049-team',
|
||||
'kaidu.kd@gmail.com#free',
|
||||
]);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user