Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion src/api/catalog-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,6 @@ export function prefixForBulletSection(section: string): string {
if (section === 'code_quality') return 'code_quality_bullet_rows';
if (section === 'ai_adoption') return 'ai_bullet_rows';
if (section === 'collaboration') return 'collab_bullet_rows';
if (section === 'wiki') return 'wiki_bullet_rows';
return 'task_delivery_bullet_rows';
}

Expand Down
2 changes: 0 additions & 2 deletions src/api/metric-registry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ export const METRIC_REGISTRY = {
TEAM_BULLET_COLLAB: "00000000-0000-0000-0001-000000000005",
TEAM_BULLET_AI: "00000000-0000-0000-0001-000000000006",
TEAM_BULLET_GIT: "00000000-0000-0000-0001-000000000007",
TEAM_BULLET_WIKI: "00000000-0000-0000-0001-000000000040",

IC_KPIS: "00000000-0000-0000-0001-000000000010",
IC_BULLET_DELIVERY: "00000000-0000-0000-0001-000000000011",
Expand All @@ -17,7 +16,6 @@ export const METRIC_REGISTRY = {
IC_DRILL: "00000000-0000-0000-0001-000000000016",
IC_TIMEOFF: "00000000-0000-0000-0001-000000000017",
IC_BULLET_GIT: "00000000-0000-0000-0001-000000000018",
IC_BULLET_WIKI: "00000000-0000-0000-0001-000000000041",

CRM_KPIS: "00000000-0000-0000-0001-000000000020",
CRM_CHART_FLOW: "00000000-0000-0000-0001-000000000021",
Expand Down
8 changes: 6 additions & 2 deletions src/components/widgets/v2/group-drilldown-sheet.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,11 @@ const METRIC_DEF: GroupDef = {
card: { preview: [] },
drilldown: [],
};
const LEGACY_DEF: GroupDef = { kind: "legacy", id: "wiki", title: "Wiki" };
const LEGACY_DEF: GroupDef = {
kind: "legacy",
id: "wiki",
title: "Legacy section",
};

const EMPTY_RESULT: MetricCollectionResult = {
byKey: new Map(),
Expand Down Expand Up @@ -84,7 +88,7 @@ describe("GroupDrilldownSheet", () => {

it("routes a legacy group to the legacy body", () => {
renderSheet(LEGACY_DEF);
expect(screen.getByText("Wiki")).toBeInTheDocument();
expect(screen.getByText("Legacy section")).toBeInTheDocument();
expect(
screen.getByText(/No data for this section/i),
).toBeInTheDocument();
Expand Down
40 changes: 39 additions & 1 deletion src/lib/insight/groups.ts
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,29 @@ const COLLABORATION_COLLECTION: MetricCollectionConfig = {
],
};

const WIKI_COLLECTION: MetricCollectionConfig = {
metrics: [
{
key: "wiki.pages_created",
views: [
{ view: "period" },
{ view: "peer" },
{ view: "timeseries", bucket: "auto" },
],
},
{
key: "wiki.edits",
views: [
{ view: "period" },
{ view: "peer" },
{ view: "timeseries", bucket: "auto" },
],
},
{ key: "wiki.pages_edited", views: [{ view: "period" }, { view: "peer" }] },
{ key: "wiki.comments", views: [{ view: "period" }, { view: "peer" }] },
],
};

export const GROUPS: readonly GroupDef[] = [
{
kind: "metrics",
Expand Down Expand Up @@ -386,7 +409,22 @@ export const GROUPS: readonly GroupDef[] = [
},
],
},
{ kind: "legacy", id: "wiki", title: "Wiki" },
{
kind: "metrics",
id: "wiki",
title: "Wiki",
collection: WIKI_COLLECTION,
card: {
preview: ["wiki.pages_created", "wiki.edits", "wiki.comments"],
},
drilldown: [
{
chart: "line",
view: "timeseries",
metrics: ["wiki.pages_created", "wiki.edits"],
},
],
},
];

export function groupById(id: GroupId): GroupDef {
Expand Down
5 changes: 0 additions & 5 deletions src/lib/insight/v2/bullet-defs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,4 @@ export const BULLET_DESCRIPTION_BY_KEY: ReadonlyMap<string, string> = new Map<
build_success: "CI runs passed vs total",
pr_cycle_time: "Hours from PR open to merge",
bugs_fixed: "Bug-type issues closed",

wiki_pages_created: "Wiki pages authored (Confluence/Outline)",
wiki_edits: "Wiki page revisions authored",
wiki_comments: "Comments received on the person's wiki pages",
wiki_active_authors: "Members who authored or edited the wiki this period",
}));
6 changes: 0 additions & 6 deletions src/lib/insight/v2/metric-order.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,6 @@ export const METRIC_ORDER_BY_SECTION: Record<string, string[]> = {
"pr_cycle_time",
"prs_per_dev",
],
wiki: [
"wiki_active_authors",
"wiki_pages_created",
"wiki_edits",
"wiki_comments",
],
};

export function orderRowsForSection<T extends { metric_key: string }>(
Expand Down
17 changes: 0 additions & 17 deletions src/queries/ic-dashboard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,6 @@ const BULLET_SECTIONS = {
collaboration: METRIC_REGISTRY.IC_BULLET_COLLAB,
ai_adoption: METRIC_REGISTRY.IC_BULLET_AI,
git_output: METRIC_REGISTRY.IC_BULLET_GIT,
wiki: METRIC_REGISTRY.IC_BULLET_WIKI,
} as const;

export type IcBulletSectionId = keyof typeof BULLET_SECTIONS;
Expand Down Expand Up @@ -214,7 +213,6 @@ export type IcDashboardSection =
| "git_output"
| "ai_adoption"
| "collaboration"
| "wiki"
| "loc_trend"
| "delivery_trend"
| "time_off";
Expand All @@ -226,7 +224,6 @@ export interface IcDashboardData {
gitOutput: BulletMetric[];
aiAdoption: BulletMetric[];
collaboration: BulletMetric[];
wiki: BulletMetric[];
locTrend: LocDataPoint[];
deliveryTrend: DeliveryDataPoint[];
timeOff: TimeOffNotice | null;
Expand Down Expand Up @@ -295,11 +292,6 @@ export function useIcDashboardData(
metric_id: METRIC_REGISTRY.IC_BULLET_COLLAB,
$filter: filter,
},
{
id: "wiki",
metric_id: METRIC_REGISTRY.IC_BULLET_WIKI,
$filter: filter,
},
{
id: "loc_trend",
metric_id: METRIC_REGISTRY.IC_CHART_LOC,
Expand Down Expand Up @@ -391,14 +383,6 @@ export function useIcDashboardData(
"ic",
cat,
),
wiki: transformBulletMetrics(
get<RawBulletAggregateRow>("wiki") ?? [],
"wiki",
period,
undefined,
"ic",
cat,
),
locTrend: transformLocTrend(
get<RawLocTrendRow>("loc_trend") ?? [],
period,
Expand All @@ -418,7 +402,6 @@ export function useIcDashboardData(
git_output: sectionErrored("git_output"),
ai_adoption: sectionErrored("ai_adoption"),
collaboration: sectionErrored("collaboration"),
wiki: sectionErrored("wiki"),
loc_trend: sectionErrored("loc_trend"),
delivery_trend: sectionErrored("delivery_trend"),
time_off: sectionErrored("time_off"),
Expand Down
15 changes: 15 additions & 0 deletions src/queries/team-view.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { describe, expect, it } from "vitest";

import { isTeamBulletSectionId } from "@/queries/team-view";

describe("isTeamBulletSectionId", () => {
it("accepts ids backed by a team bullet section", () => {
expect(isTeamBulletSectionId("collaboration")).toBe(true);
expect(isTeamBulletSectionId("task_delivery")).toBe(true);
});

it("rejects ids with no team bullet section", () => {
expect(isTeamBulletSectionId("wiki")).toBe(false);
expect(isTeamBulletSectionId("nonsense")).toBe(false);
});
});
11 changes: 9 additions & 2 deletions src/queries/team-view.ts
Original file line number Diff line number Diff line change
Expand Up @@ -137,11 +137,14 @@ const TEAM_BULLET_SECTIONS = {
estimation: METRIC_REGISTRY.TEAM_BULLET_DELIVERY,
collaboration: METRIC_REGISTRY.TEAM_BULLET_COLLAB,
ai_adoption: METRIC_REGISTRY.TEAM_BULLET_AI,
wiki: METRIC_REGISTRY.TEAM_BULLET_WIKI,
} as const;

export type TeamBulletSectionId = keyof typeof TEAM_BULLET_SECTIONS;

export function isTeamBulletSectionId(id: string): id is TeamBulletSectionId {
return id in TEAM_BULLET_SECTIONS;
}

/**
* Scope a team bullet aggregate to the members actually shown — the
* identity-tree subtree the screen renders (transitive + active) — by
Expand Down Expand Up @@ -237,7 +240,11 @@ export function useTeamBulletSections(
range.to,
catalogKey,
],
enabled: Boolean(teamId) && Boolean(options?.roster?.length) && Boolean(catalog),
enabled:
sectionIds.length > 0 &&
Boolean(teamId) &&
Boolean(options?.roster?.length) &&
Boolean(catalog),
placeholderData: options?.keepPrevious ? keepPreviousData : undefined,
queryFn: async () => {
const roster = options?.roster;
Expand Down
26 changes: 17 additions & 9 deletions src/screens/ic-dashboard/engineering-dashboard-v2.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -64,14 +64,18 @@ const CLOSED_DRILLDOWN_DATA = {
refetch: () => {},
} as const;

// The one per-key seam that survives coexistence: which legacy batch field
// feeds each legacy group's rows. Dies with `LegacyGroup`.
const LEGACY_GROUP_ROWS: Record<
// The one per-key seam that survives coexistence: which legacy batch fields
// feed each legacy group's rows and error flag. Empty while no group is
// `kind: "legacy"`; dies with `LegacyGroup`.
/* v8 ignore start -- inert seam, populated only when a legacy group returns */
const LEGACY_GROUP_FEEDS: Record<
string,
(data: IcDashboardData | undefined) => BulletMetric[]
> = {
wiki: (data) => data?.wiki ?? [],
};
{
rows: (data: IcDashboardData | undefined) => BulletMetric[];
errored: (data: IcDashboardData | undefined) => boolean;
}
> = {};
/* v8 ignore stop */

export interface EngineeringDashboardV2Props {
personId: string;
Expand Down Expand Up @@ -128,7 +132,10 @@ export function EngineeringDashboardV2({
Object.fromEntries(
GROUPS.filter((def) => def.kind === "legacy").map((def) => [
def.id,
orderRowsForSection(def.id, LEGACY_GROUP_ROWS[def.id]?.(data) ?? []),
orderRowsForSection(
def.id,
LEGACY_GROUP_FEEDS[def.id]?.rows(data) ?? [],
),
]),
);

Expand Down Expand Up @@ -337,7 +344,8 @@ export function EngineeringDashboardV2({
/>
);
}
if (data?.errors[def.id]) {
/* v8 ignore next -- unreachable while no legacy group exists */
if (LEGACY_GROUP_FEEDS[def.id]?.errored(data)) {
return (
<SectionCard
key={def.id}
Expand Down
20 changes: 17 additions & 3 deletions src/screens/team-view-v2.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,10 @@ import { normalizePersonId } from "@/lib/metrics/entity";
import { useIcPerson } from "@/queries/ic-dashboard";
import { useMetricCollectionSet } from "@/queries/metric-results";
import {
isTeamBulletSectionId,
useTeamBulletSections,
useTeamMembers,
type TeamBulletSectionId,
} from "@/queries/team-view";
import {
useDeptDistributions,
Expand All @@ -48,7 +50,16 @@ import {
} from "@/queries/v2/team-extras";
import type { BulletMetric } from "@/types/insight";

const LEGACY_GROUP_IDS = legacyGroups().map((def) => def.id);
// The map/filter callbacks are inert while no group is `kind: "legacy"`
// (the array is empty) — retained so the legacy team-bullet path lights up
// again if a legacy group returns.
/* v8 ignore start -- map/filter callbacks run only when a legacy group exists */
const LEGACY_GROUP_IDS = legacyGroups()
.map((def) => def.id)
.filter((id): id is Extract<GroupId, TeamBulletSectionId> =>
isTeamBulletSectionId(id),
);
/* v8 ignore stop */

// Team surfaces request period + peer only: a per-member timeseries over a
// large roster would exceed the backend's all-or-nothing row limit and fail
Expand Down Expand Up @@ -181,8 +192,11 @@ export function TeamViewV2Screen({ teamId, viewerEmail }: TeamViewV2ScreenProps)
memberEntityIds,
);

const sectionsPending = sectionsQ.isPending;
const sectionsFetching = sectionsQ.isFetching;
// With no legacy groups the bullet query is disabled and never leaves
// TanStack's "pending" state — an empty section set is settled, not loading.
const hasLegacySections = LEGACY_GROUP_IDS.length > 0;
const sectionsPending = hasLegacySections && sectionsQ.isPending;
const sectionsFetching = hasLegacySections && sectionsQ.isFetching;
// Only a metric group's revalidation dims the page (replacing data already
// shown); its first load has no prior data and shows its own card spinner.
const isMetricsRevalidating = [...metricGroupData.values()].some(
Expand Down