Skip to content
Open
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: 1 addition & 0 deletions src/api/catalog-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ 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 === 'support') return 'support_bullet_rows';
return 'task_delivery_bullet_rows';
}

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

IC_KPIS: "00000000-0000-0000-0001-000000000010",
IC_BULLET_DELIVERY: "00000000-0000-0000-0001-000000000011",
IC_BULLET_COLLAB: "00000000-0000-0000-0001-000000000012",
IC_BULLET_AI: "00000000-0000-0000-0001-000000000013",
IC_BULLET_SUPPORT: "00000000-0000-0000-0001-000000000008",
IC_CHART_LOC: "00000000-0000-0000-0001-000000000014",
IC_CHART_DELIVERY: "00000000-0000-0000-0001-000000000015",
IC_DRILL: "00000000-0000-0000-0001-000000000016",
Expand Down
51 changes: 50 additions & 1 deletion src/components/widgets/team-bullet-sections.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ type SectionId =
| "code_quality"
| "estimation"
| "ai_adoption"
| "collaboration";
| "collaboration"
| "support";

export interface TeamBulletSectionsProps {
sections: Record<SectionId, BulletMetric[] | undefined>;
Expand Down Expand Up @@ -235,6 +236,49 @@ function CollaborationSection({
);
}

function SupportSection({
metrics,
onDrillClick,
}: {
metrics: BulletMetric[];
onDrillClick?: (id: string) => void;
}) {
const left = metrics.filter((_, i) => i % 2 === 0);
const right = metrics.filter((_, i) => i % 2 !== 0);
return (
<CollapsibleSection
title="Support"
storageKey="insight:team-view:support"
>
<div className="px-4 py-3">
<Legend />
<div className="mt-2 grid grid-cols-1 gap-3.5 sm:grid-cols-2">
<div className="flex flex-col gap-4">
{left.map((m) => (
<BulletChart
key={m.metric_key}
metric={m}
onDrillClick={onDrillClick}
mode="chart"
/>
))}
</div>
<div className="flex flex-col gap-4">
{right.map((m) => (
<BulletChart
key={m.metric_key}
metric={m}
onDrillClick={onDrillClick}
mode="chart"
/>
))}
</div>
</div>
</div>
</CollapsibleSection>
);
}

function SectionPlaceholder({
title,
kind,
Expand Down Expand Up @@ -270,6 +314,7 @@ export function TeamBulletSections({
const estimation = sections.estimation;
const aiAdoption = sections.ai_adoption;
const collab = sections.collaboration;
const support = sections.support;

function renderSection(
sid: SectionId,
Expand Down Expand Up @@ -331,6 +376,10 @@ export function TeamBulletSections({
onDrillClick={onDrillClick}
/>
))}

{renderSection("support", "Support", () => (
<SupportSection metrics={support ?? []} onDrillClick={onDrillClick} />
))}
</div>
);
}
2 changes: 2 additions & 0 deletions src/components/widgets/team-metrics-table.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,15 @@ const META_FALLBACK = (metricKey: string): MetricMeta => ({
const SECTION_ORDER: ReadonlyArray<TeamMetricsSectionId> = [
"task_delivery",
"collaboration",
"support",
"ai_adoption",
"git_output",
];

const SECTION_LABEL_KEY: Record<TeamMetricsSectionId, string> = {
task_delivery: "team_metrics_modal.sections.task_delivery",
collaboration: "team_metrics_modal.sections.collaboration",
support: "team_metrics_modal.sections.support",
ai_adoption: "team_metrics_modal.sections.ai_adoption",
git_output: "team_metrics_modal.sections.git_output",
};
Expand Down
12 changes: 12 additions & 0 deletions src/components/widgets/v2/section-card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,12 @@ const COLLAB_PREVIEW_KEYS = [
"m365_emails_sent",
];

const SUPPORT_PREVIEW_KEYS = [
"support_updates",
"support_public_comments",
"support_solved",
];

function pickPreviewRows(
sectionId: string | undefined,
rows: BulletMetric[],
Expand All @@ -42,6 +48,12 @@ function pickPreviewRows(
(r): r is BulletMetric => r != null && hasBulletValue(r),
);
}
if (sectionId === "support") {
const byKey = new Map(rows.map((r) => [r.metric_key, r]));
return SUPPORT_PREVIEW_KEYS.map((k) => byKey.get(k)).filter(
(r): r is BulletMetric => r != null && hasBulletValue(r),
);
}
return rows.filter(hasBulletValue).slice(0, 3);
}

Expand Down
19 changes: 19 additions & 0 deletions src/components/widgets/v2/section-drilldown-sheet.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -358,5 +358,24 @@ function DrilldownExtras({
</div>
);
}
if (sectionId === "support") {
// CSAT is the section's quality metric (a percent). Surface it as a
// headline percent summary when present; otherwise the CountersBlock
// below renders it (and the always-NULL KB metric) as ComingSoon.
const csat = rows.find((r) => r.metric_key === "support_csat");
const csatValue = csat ? Number(csat.value) : NaN;
if (!csat || !Number.isFinite(csatValue)) return null;
return (
<div className="grid grid-cols-1 gap-3 md:grid-cols-2 lg:grid-cols-3">
<SummaryWithBreakdown
label={csat.label}
description={csat.sublabel}
value={csatValue}
unit={csat.unit || "%"}
breakdown={[]}
/>
</div>
);
}
return null;
}
9 changes: 9 additions & 0 deletions src/lib/insight/bullet-layout-groups.ts
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,15 @@ const BULLET_DISPLAY_ORDER: readonly string[] = [
'teams_meetings',
'zoom_meetings',
'meeting_free',

// support
'support_active',
'support_updates',
'support_public_comments',
'support_private_comments',
'support_solved',
'support_csat',
'support_kb',
];

const ORDER_INDEX = new Map(BULLET_DISPLAY_ORDER.map((k, i) => [k, i]));
Expand Down
9 changes: 9 additions & 0 deletions src/lib/insight/v2/metric-order.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,15 @@ export const METRIC_ORDER_BY_SECTION: Record<string, string[]> = {
"m365_emails_received",
"m365_emails_read",
],
support: [
"support_active",
"support_updates",
"support_public_comments",
"support_private_comments",
"support_solved",
"support_csat",
"support_kb",
],
ai_adoption: [
"active_ai_members",
"ai_loc_share2",
Expand Down
8 changes: 6 additions & 2 deletions src/lib/insight/v2/sections.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,25 @@ export type IcSectionId =
| "git_output"
| "code_quality"
| "collaboration"
| "ai_adoption";
| "ai_adoption"
| "support";

export type IcHeroSectionId = IcSectionId;

export type TeamSectionId =
| "task_delivery"
| "code_quality"
| "collaboration"
| "ai_adoption";
| "ai_adoption"
| "support";

export const IC_SECTIONS: ReadonlyArray<{ id: IcSectionId; label: string }> = [
{ id: "task_delivery", label: "Task delivery" },
{ id: "git_output", label: "Git output" },
{ id: "code_quality", label: "Code quality" },
{ id: "collaboration", label: "Collaboration" },
{ id: "ai_adoption", label: "AI dev tools" },
{ id: "support", label: "Support" },
] as const;

export const IC_HERO_SECTIONS: ReadonlyArray<{
Expand All @@ -34,4 +37,5 @@ export const TEAM_SECTIONS: ReadonlyArray<{
{ id: "code_quality", label: "Code quality" },
{ id: "collaboration", label: "Collaboration" },
{ id: "ai_adoption", label: "AI adoption" },
{ id: "support", label: "Support" },
] as const;
5 changes: 4 additions & 1 deletion src/locales/en/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
"git_output": "Git output",
"code_quality": "Code quality",
"collaboration": "Collaboration",
"support": "Support",
"ai_adoption": "AI adoption"
},
"section_blocks": {
Expand Down Expand Up @@ -140,6 +141,7 @@
"sections": {
"task_delivery": "Delivery",
"collaboration": "Collaboration",
"support": "Support",
"ai_adoption": "AI Adoption",
"git_output": "Git"
}
Expand All @@ -155,7 +157,8 @@
"delivery_trends_subtitle": "Jira + Bitbucket · activity counts · Commits, PRs and Tasks are independent signals",
"ai_dev_tools_title": "AI Dev Tools & AI Chat",
"ai_adoption": "AI Adoption",
"collaboration": "Collaboration"
"collaboration": "Collaboration",
"support": "Support"
}
},
"sales_dashboard": {
Expand Down
Loading