fix(team): make launch summary copy honest
This commit is contained in:
parent
3e53391a73
commit
76fca31fb1
4 changed files with 62 additions and 2 deletions
|
|
@ -41,6 +41,7 @@ import { createChipFromSelection } from '@renderer/utils/chipUtils';
|
||||||
import { sumContextInjectionTokens } from '@renderer/utils/contextMath';
|
import { sumContextInjectionTokens } from '@renderer/utils/contextMath';
|
||||||
import { buildMemberColorMap } from '@renderer/utils/memberHelpers';
|
import { buildMemberColorMap } from '@renderer/utils/memberHelpers';
|
||||||
import { formatProjectPath } from '@renderer/utils/pathDisplay';
|
import { formatProjectPath } from '@renderer/utils/pathDisplay';
|
||||||
|
import { buildPendingRuntimeSummaryCopy } from '@renderer/utils/teamLaunchSummaryCopy';
|
||||||
import { buildTaskCountsByOwner, normalizePath } from '@renderer/utils/pathNormalize';
|
import { buildTaskCountsByOwner, normalizePath } from '@renderer/utils/pathNormalize';
|
||||||
import { nameColorSet } from '@renderer/utils/projectColor';
|
import { nameColorSet } from '@renderer/utils/projectColor';
|
||||||
import { resolveProjectIdByPath } from '@renderer/utils/projectLookup';
|
import { resolveProjectIdByPath } from '@renderer/utils/projectLookup';
|
||||||
|
|
@ -263,7 +264,12 @@ const TeamOfflineStatusBanner = memo(function TeamOfflineStatusBanner({
|
||||||
const message =
|
const message =
|
||||||
summary?.teamLaunchState === 'partial_pending'
|
summary?.teamLaunchState === 'partial_pending'
|
||||||
? summary.runtimeAlivePendingCount != null && summary.runtimeAlivePendingCount > 0
|
? summary.runtimeAlivePendingCount != null && summary.runtimeAlivePendingCount > 0
|
||||||
? `Last launch is still reconciling - ${summary.confirmedCount ?? 0}/${summary.expectedMemberCount ?? summary.memberCount} teammates confirmed alive, ${summary.runtimeAlivePendingCount} runtime${summary.runtimeAlivePendingCount === 1 ? '' : 's'} pending bootstrap`
|
? buildPendingRuntimeSummaryCopy({
|
||||||
|
confirmedCount: summary.confirmedCount,
|
||||||
|
expectedMemberCount: summary.expectedMemberCount,
|
||||||
|
memberCount: summary.memberCount,
|
||||||
|
runtimeAlivePendingCount: summary.runtimeAlivePendingCount,
|
||||||
|
})
|
||||||
: 'Last launch is still reconciling'
|
: 'Last launch is still reconciling'
|
||||||
: summary?.partialLaunchFailure
|
: summary?.partialLaunchFailure
|
||||||
? summary.missingMemberCount > 0
|
? summary.missingMemberCount > 0
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,7 @@ import { buildMemberColorMap } from '@renderer/utils/memberHelpers';
|
||||||
import { buildTaskCountsByTeam, normalizePath } from '@renderer/utils/pathNormalize';
|
import { buildTaskCountsByTeam, normalizePath } from '@renderer/utils/pathNormalize';
|
||||||
import { getBaseName } from '@renderer/utils/pathUtils';
|
import { getBaseName } from '@renderer/utils/pathUtils';
|
||||||
import { nameColorSet } from '@renderer/utils/projectColor';
|
import { nameColorSet } from '@renderer/utils/projectColor';
|
||||||
|
import { buildPendingRuntimeSummaryCopy } from '@renderer/utils/teamLaunchSummaryCopy';
|
||||||
import { isLeadMember } from '@shared/utils/leadDetection';
|
import { isLeadMember } from '@shared/utils/leadDetection';
|
||||||
import {
|
import {
|
||||||
CheckCircle,
|
CheckCircle,
|
||||||
|
|
@ -981,7 +982,13 @@ export const TeamListView = (): React.JSX.Element => {
|
||||||
{team.teamLaunchState === 'partial_pending' ? (
|
{team.teamLaunchState === 'partial_pending' ? (
|
||||||
<p className="mt-2 text-[11px] text-amber-300">
|
<p className="mt-2 text-[11px] text-amber-300">
|
||||||
{team.runtimeAlivePendingCount && team.runtimeAlivePendingCount > 0
|
{team.runtimeAlivePendingCount && team.runtimeAlivePendingCount > 0
|
||||||
? `Last launch is still reconciling — ${team.confirmedCount ?? 0}/${team.expectedMemberCount ?? team.memberCount} teammates confirmed alive, ${team.runtimeAlivePendingCount} runtime${team.runtimeAlivePendingCount === 1 ? '' : 's'} pending bootstrap.`
|
? buildPendingRuntimeSummaryCopy({
|
||||||
|
confirmedCount: team.confirmedCount,
|
||||||
|
expectedMemberCount: team.expectedMemberCount,
|
||||||
|
memberCount: team.memberCount,
|
||||||
|
runtimeAlivePendingCount: team.runtimeAlivePendingCount,
|
||||||
|
includePeriod: true,
|
||||||
|
})
|
||||||
: 'Last launch is still reconciling.'}
|
: 'Last launch is still reconciling.'}
|
||||||
</p>
|
</p>
|
||||||
) : team.partialLaunchFailure || team.teamLaunchState === 'partial_failure' ? (
|
) : team.partialLaunchFailure || team.teamLaunchState === 'partial_failure' ? (
|
||||||
|
|
|
||||||
17
src/renderer/utils/teamLaunchSummaryCopy.ts
Normal file
17
src/renderer/utils/teamLaunchSummaryCopy.ts
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
export function buildPendingRuntimeSummaryCopy(input: {
|
||||||
|
confirmedCount?: number | null;
|
||||||
|
expectedMemberCount?: number | null;
|
||||||
|
memberCount?: number | null;
|
||||||
|
runtimeAlivePendingCount?: number | null;
|
||||||
|
includePeriod?: boolean;
|
||||||
|
}): string {
|
||||||
|
const pendingCount = input.runtimeAlivePendingCount ?? 0;
|
||||||
|
if (pendingCount <= 0) {
|
||||||
|
return input.includePeriod
|
||||||
|
? 'Last launch is still reconciling.'
|
||||||
|
: 'Last launch is still reconciling';
|
||||||
|
}
|
||||||
|
const expectedCount = input.expectedMemberCount ?? input.memberCount ?? 0;
|
||||||
|
const message = `Last launch is still reconciling - ${input.confirmedCount ?? 0}/${expectedCount} teammates confirmed alive, ${pendingCount} runtime${pendingCount === 1 ? '' : 's'} still awaiting confirmation`;
|
||||||
|
return input.includePeriod ? `${message}.` : message;
|
||||||
|
}
|
||||||
30
test/renderer/utils/teamLaunchSummaryCopy.test.ts
Normal file
30
test/renderer/utils/teamLaunchSummaryCopy.test.ts
Normal file
|
|
@ -0,0 +1,30 @@
|
||||||
|
import { describe, expect, it } from 'vitest';
|
||||||
|
|
||||||
|
import { buildPendingRuntimeSummaryCopy } from '@renderer/utils/teamLaunchSummaryCopy';
|
||||||
|
|
||||||
|
describe('buildPendingRuntimeSummaryCopy', () => {
|
||||||
|
it('uses generic runtime confirmation wording instead of bootstrap-specific copy', () => {
|
||||||
|
expect(
|
||||||
|
buildPendingRuntimeSummaryCopy({
|
||||||
|
confirmedCount: 2,
|
||||||
|
expectedMemberCount: 4,
|
||||||
|
runtimeAlivePendingCount: 2,
|
||||||
|
})
|
||||||
|
).toBe(
|
||||||
|
'Last launch is still reconciling - 2/4 teammates confirmed alive, 2 runtimes still awaiting confirmation'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('can emit the punctuated list-card variant', () => {
|
||||||
|
expect(
|
||||||
|
buildPendingRuntimeSummaryCopy({
|
||||||
|
confirmedCount: 1,
|
||||||
|
expectedMemberCount: 3,
|
||||||
|
runtimeAlivePendingCount: 1,
|
||||||
|
includePeriod: true,
|
||||||
|
})
|
||||||
|
).toBe(
|
||||||
|
'Last launch is still reconciling - 1/3 teammates confirmed alive, 1 runtime still awaiting confirmation.'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
Loading…
Reference in a new issue