@c2l2c/backstage-plugin-dora-metrics 0.3.0 → 0.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,5 +1,9 @@
1
1
  # @c2l2c/backstage-plugin-dora-metrics
2
2
 
3
+ [![CI](https://github.com/C2L2C/backstage-plugin-dora-metrics/actions/workflows/ci.yml/badge.svg)](https://github.com/C2L2C/backstage-plugin-dora-metrics/actions/workflows/ci.yml)
4
+ [![Publish](https://github.com/C2L2C/backstage-plugin-dora-metrics/actions/workflows/publish.yml/badge.svg)](https://github.com/C2L2C/backstage-plugin-dora-metrics/actions/workflows/publish.yml)
5
+ [![npm](https://img.shields.io/npm/v/@c2l2c/backstage-plugin-dora-metrics)](https://www.npmjs.com/package/@c2l2c/backstage-plugin-dora-metrics)
6
+
3
7
  A Backstage frontend plugin that surfaces **DORA metrics per catalog entity** — scoped to the specific service you're viewing, not your whole org.
4
8
 
5
9
  For each catalog service annotated with a GitHub repo, this plugin adds a **DORA Metrics tab** that computes all four key metrics directly from GitHub PRs via OAuth — no extra backend or data pipeline required:
@@ -80,15 +84,24 @@ app:
80
84
  collection:
81
85
  initialDays: 30
82
86
 
83
- # Define the environments / branches to track
87
+ # Define the environments / branches to track.
88
+ # Exactly ONE environment may set isProduction: true.
84
89
  environments:
85
90
  - name: Production
86
- branch: main
91
+ branch: main # single branch name
87
92
  isProduction: true
88
- label: hotfix # PR label for production failures (used for CFR/MTTR)
93
+ label: hotfix # PR label for production failures (used for CFR/MTTR)
89
94
  - name: Staging
90
95
  branch: staging
91
96
  isProduction: false
97
+ - name: Any main
98
+ # Comma-separated list — PRs merged to any of these branches are included
99
+ branch: "main,master"
100
+ isProduction: false
101
+ - name: Release branches
102
+ # JavaScript regex — resolved against the repo's actual branch list at query time
103
+ branch: "^release/.*"
104
+ isProduction: false
92
105
 
93
106
  # Optional: override DORA benchmark targets
94
107
  targets:
@@ -96,8 +109,66 @@ app:
96
109
  leadTime: 24 # hours (Elite ≤ 24h)
97
110
  changeFailureRate: 5 # % (Elite ≤ 5%)
98
111
  mttr: 1 # hours (Elite ≤ 1h)
112
+
113
+ # Optional: enable mock data for local development (skips GitHub API calls)
114
+ debug: false
99
115
  ```
100
116
 
117
+ ### Branch and label patterns
118
+
119
+ Both the `branch` and `label` fields accept the same three formats:
120
+
121
+ | Format | Example | Behaviour |
122
+ |--------|---------|-----------|
123
+ | Single name | `main` / `hotfix` | Exact match |
124
+ | Comma-separated | `main,master` / `hotfix,fix,bug` | Matches any name in the list |
125
+ | JavaScript regex | `^release/.*` / `^hotfix` | Regex test against each value |
126
+
127
+ A string is treated as a regex if it contains any of these characters: `| ^ $ [ ] ( ) { } ? + * \`
128
+
129
+ For `branch`: when multiple branches match, PRs are fetched from all of them and deduplicated by PR number. Regex patterns are resolved against the repo's live branch list via the GitHub Branches API at query time.
130
+
131
+ For `label`: a PR is classified as a hotfix if **any** of its GitHub labels match the pattern.
132
+
133
+ ### Environment constraints
134
+
135
+ - You may define any number of environments.
136
+ - **Exactly one** environment may have `isProduction: true`. The plugin throws a configuration error at startup if this constraint is violated.
137
+ - Change Failure Rate, MTTR, and Hotfixes to Production are only calculated for the production environment.
138
+
139
+ ### Per-repo overrides via catalog annotations
140
+
141
+ You can override environments and targets on a per-service basis in `catalog-info.yaml` without changing the global config:
142
+
143
+ ```yaml
144
+ metadata:
145
+ annotations:
146
+ github.com/project-slug: my-org/my-repo
147
+
148
+ # Override the environments list for this repo only (JSON)
149
+ dora-metrics/environments: |
150
+ [
151
+ { "name": "Production", "branch": "main", "isProduction": true, "label": "hotfix" },
152
+ { "name": "Staging", "branch": "staging", "isProduction": false }
153
+ ]
154
+
155
+ # Override DORA targets for this repo only (JSON, partial overrides supported)
156
+ dora-metrics/targets: |
157
+ { "deploymentFrequency": 2, "leadTime": 48 }
158
+ ```
159
+
160
+ Annotation values are parsed as JSON. Partial `targets` overrides are merged with the global targets — only the keys you specify are replaced.
161
+
162
+ ### Example configs
163
+
164
+ Ready-to-use example configs are in the [`examples/`](examples/) directory:
165
+
166
+ | File | Description |
167
+ |------|-------------|
168
+ | [`app-config.regex-branch.yaml`](examples/app-config.regex-branch.yaml) | Production tracked with a regex branch pattern (`^release/.*`) and a comma-separated label pattern |
169
+ | [`app-config.multi-branch.yaml`](examples/app-config.multi-branch.yaml) | Production tracked across `main,master`; staging across `develop,dev`; hotfix label as regex |
170
+ | [`catalog-info.yaml`](examples/catalog-info.yaml) | Per-repo environment and target overrides via `catalog-info.yaml` annotations |
171
+
101
172
  ---
102
173
 
103
174
  ## How it works
package/config.d.ts CHANGED
@@ -36,7 +36,14 @@ export interface Config {
36
36
  * @visibility frontend
37
37
  */
38
38
  isProduction?: boolean;
39
- /** Label on PRs that represent production failures (hotfixes). Defaults to "hotfix". @visibility frontend */
39
+ /**
40
+ * Label(s) on PRs that represent production failures (hotfixes).
41
+ * Defaults to "hotfix". Accepts the same three formats as `branch`:
42
+ * - Single label: "hotfix"
43
+ * - Comma-separated: "hotfix,fix,bug"
44
+ * - JavaScript regex: "^(hotfix|fix)$"
45
+ * @visibility frontend
46
+ */
40
47
  label?: string;
41
48
  /** Label on PRs that represent planned feature deployments. @visibility frontend */
42
49
  featureLabel?: string;
package/dist/alpha.d.ts CHANGED
@@ -1,5 +1,60 @@
1
+ import * as _backstage_catalog_model from '@backstage/catalog-model';
2
+ import * as react from 'react';
3
+ import * as _backstage_filter_predicates from '@backstage/filter-predicates';
1
4
  import * as _backstage_frontend_plugin_api from '@backstage/frontend-plugin-api';
2
5
 
3
- declare const doraMetricsPlugin: _backstage_frontend_plugin_api.FrontendPlugin<{}, {}, {}>;
6
+ declare const doraMetricsPlugin: _backstage_frontend_plugin_api.OverridableFrontendPlugin<{}, {}, {
7
+ "api:dora-metrics/dora-metrics": _backstage_frontend_plugin_api.OverridableExtensionDefinition<{
8
+ kind: "api";
9
+ name: "dora-metrics";
10
+ config: {};
11
+ configInput: {};
12
+ output: _backstage_frontend_plugin_api.ExtensionDataRef<_backstage_frontend_plugin_api.AnyApiFactory, "core.api.factory", {}>;
13
+ inputs: {};
14
+ params: <TApi, TImpl extends TApi, TDeps extends { [name in string]: unknown; }>(params: _backstage_frontend_plugin_api.ApiFactory<TApi, TImpl, TDeps>) => _backstage_frontend_plugin_api.ExtensionBlueprintParams<_backstage_frontend_plugin_api.AnyApiFactory>;
15
+ }>;
16
+ "entity-content:dora-metrics": _backstage_frontend_plugin_api.OverridableExtensionDefinition<{
17
+ kind: "entity-content";
18
+ name: undefined;
19
+ config: {
20
+ path: string | undefined;
21
+ title: string | undefined;
22
+ filter: _backstage_filter_predicates.FilterPredicate | undefined;
23
+ group: string | false | undefined;
24
+ icon: string | undefined;
25
+ };
26
+ configInput: {
27
+ filter?: _backstage_filter_predicates.FilterPredicate | undefined;
28
+ title?: string | undefined;
29
+ path?: string | undefined;
30
+ group?: string | false | undefined;
31
+ icon?: string | undefined;
32
+ };
33
+ output: _backstage_frontend_plugin_api.ExtensionDataRef<string, "core.routing.path", {}> | _backstage_frontend_plugin_api.ExtensionDataRef<_backstage_frontend_plugin_api.RouteRef<_backstage_frontend_plugin_api.AnyRouteRefParams>, "core.routing.ref", {
34
+ optional: true;
35
+ }> | _backstage_frontend_plugin_api.ExtensionDataRef<react.JSX.Element, "core.reactElement", {}> | _backstage_frontend_plugin_api.ExtensionDataRef<(entity: _backstage_catalog_model.Entity) => boolean, "catalog.entity-filter-function", {
36
+ optional: true;
37
+ }> | _backstage_frontend_plugin_api.ExtensionDataRef<string, "catalog.entity-filter-expression", {
38
+ optional: true;
39
+ }> | _backstage_frontend_plugin_api.ExtensionDataRef<string, "catalog.entity-content-title", {}> | _backstage_frontend_plugin_api.ExtensionDataRef<string, "catalog.entity-content-group", {
40
+ optional: true;
41
+ }> | _backstage_frontend_plugin_api.ExtensionDataRef<string | react.ReactElement<any, string | react.JSXElementConstructor<any>>, "catalog.entity-content-icon", {
42
+ optional: true;
43
+ }>;
44
+ inputs: {};
45
+ params: {
46
+ defaultPath?: [Error: `Use the 'path' param instead`];
47
+ path: string;
48
+ defaultTitle?: [Error: `Use the 'title' param instead`];
49
+ title: string;
50
+ defaultGroup?: [Error: `Use the 'group' param instead`];
51
+ group?: ("overview" | "documentation" | "development" | "deployment" | "operation" | "observability") | (string & {});
52
+ icon?: string | react.ReactElement;
53
+ loader: () => Promise<JSX.Element>;
54
+ routeRef?: _backstage_frontend_plugin_api.RouteRef;
55
+ filter?: string | _backstage_filter_predicates.FilterPredicate | ((entity: _backstage_catalog_model.Entity) => boolean);
56
+ };
57
+ }>;
58
+ }>;
4
59
 
5
60
  export { doraMetricsPlugin as default };
@@ -30,6 +30,16 @@ function toPrDetail(pr, durationHours) {
30
30
  function isRegexPattern(pattern) {
31
31
  return /[|^$[\](){}?+*\\]/.test(pattern);
32
32
  }
33
+ function matchesLabel(prLabels, labelPattern) {
34
+ if (!labelPattern) return false;
35
+ const names = prLabels.map((l) => l.name);
36
+ if (isRegexPattern(labelPattern)) {
37
+ const regex = new RegExp(labelPattern);
38
+ return names.some((n) => regex.test(n));
39
+ }
40
+ const patterns = labelPattern.split(",").map((l) => l.trim()).filter(Boolean);
41
+ return names.some((n) => patterns.includes(n));
42
+ }
33
43
  async function resolveBranches(owner, repo, branchPattern, fetchFn) {
34
44
  if (isRegexPattern(branchPattern)) {
35
45
  const repoBranches = await fetchFn(
@@ -163,7 +173,7 @@ class DoraMetricsClient {
163
173
  };
164
174
  }
165
175
  const hotfixPRs = mergedPRs.filter(
166
- (pr) => (pr.labels ?? []).some((l) => l.name === env.label)
176
+ (pr) => matchesLabel(pr.labels ?? [], env.label)
167
177
  );
168
178
  const numberOfHotfixes = {
169
179
  value: hotfixPRs.length,
@@ -219,7 +229,7 @@ class DoraMetricsClient {
219
229
  let changeFailureRate;
220
230
  let mttrHours;
221
231
  if (env.isProduction) {
222
- const hotfixPRs = weekPRs.filter((pr) => pr.labels.some((l) => l.name === env.label));
232
+ const hotfixPRs = weekPRs.filter((pr) => matchesLabel(pr.labels, env.label));
223
233
  changeFailureRate = weekPRs.length > 0 ? Math.round(hotfixPRs.length / weekPRs.length * 1e3) / 10 : 0;
224
234
  const hotfixDurations = hotfixPRs.map(
225
235
  (pr) => (new Date(pr.merged_at).getTime() - new Date(pr.created_at).getTime()) / (1e3 * 60 * 60)
@@ -1 +1 @@
1
- {"version":3,"file":"DoraMetricsClient.esm.js","sources":["../../src/api/DoraMetricsClient.ts"],"sourcesContent":["import { ConfigApi, OAuthApi } from '@backstage/core-plugin-api';\nimport {\n DoraEnvironment,\n DoraHistoryPoint,\n DoraMetrics,\n DoraMetricValue,\n DoraMetricsApi,\n DoraRating,\n DoraTargets,\n PrDetail,\n} from './types';\n\ninterface GitHubPR {\n number: number;\n title: string;\n html_url: string;\n created_at: string;\n merged_at: string | null;\n closed_at: string | null;\n labels: Array<{ name: string }>;\n user: { login: string; avatar_url: string } | null;\n}\n\n/**\n * Compute a DORA rating based on the configured target.\n *\n * lowerIsBetter (lead time, CFR, MTTR, hotfix count):\n * elite = value <= target\n * high = value <= target * 2\n * medium = value <= target * 4\n * low = value > target * 4\n *\n * higherIsBetter (deployment frequency):\n * elite = value >= target\n * high = value >= target * 0.7\n * medium = value >= target * 0.4\n * low = value < target * 0.4\n *\n * Special case — target = 0 (hotfix count ideal = 0):\n * elite=0, high≤2, medium≤5, low>5\n */\nfunction computeRating(value: number, target: number, lowerIsBetter: boolean): DoraRating {\n if (lowerIsBetter) {\n if (target === 0) {\n if (value === 0) return 'elite';\n if (value <= 2) return 'high';\n if (value <= 5) return 'medium';\n return 'low';\n }\n if (value <= target) return 'elite';\n if (value <= target * 2) return 'high';\n if (value <= target * 4) return 'medium';\n return 'low';\n }\n if (value >= target) return 'elite';\n if (value >= target * 0.7) return 'high';\n if (value >= target * 0.4) return 'medium';\n return 'low';\n}\n\nfunction toPrDetail(pr: GitHubPR, durationHours: number): PrDetail {\n return {\n number: pr.number,\n title: pr.title,\n url: pr.html_url,\n durationHours: Math.round(durationHours * 10) / 10,\n mergedAt: pr.merged_at!,\n author: pr.user?.login,\n authorAvatar: pr.user?.avatar_url,\n };\n}\n\n/**\n * Determine whether a branch pattern string is a regex (vs a plain name or\n * comma-separated list of names). A string is treated as a regex if it\n * contains any regex meta-character: | ^ $ [ ] ( ) { } ? + * \\\n */\nfunction isRegexPattern(pattern: string): boolean {\n return /[|^$[\\](){}?+*\\\\]/.test(pattern);\n}\n\n/**\n * Resolve a branch pattern to a concrete list of branch names.\n *\n * - Single name \"main\" → [\"main\"]\n * - Comma-sep \"main,master\" → [\"main\", \"master\"]\n * - Regex \"^(main|master)$\"→ fetched from the repo's branch list and filtered\n */\nasync function resolveBranches(\n owner: string,\n repo: string,\n branchPattern: string,\n fetchFn: <T>(url: string) => Promise<T>,\n): Promise<string[]> {\n if (isRegexPattern(branchPattern)) {\n const repoBranches = await fetchFn<Array<{ name: string }>>(\n `https://api.github.com/repos/${owner}/${repo}/branches?per_page=100`,\n );\n const regex = new RegExp(branchPattern);\n return repoBranches.map(b => b.name).filter(name => regex.test(name));\n }\n // Comma-separated or single branch name\n return branchPattern.split(',').map(b => b.trim()).filter(Boolean);\n}\n\nexport class DoraMetricsClient implements DoraMetricsApi {\n private readonly githubAuthApi: OAuthApi;\n private readonly configApi: ConfigApi;\n\n constructor(githubAuthApi: OAuthApi, configApi: ConfigApi) {\n this.githubAuthApi = githubAuthApi;\n this.configApi = configApi;\n }\n\n private getConfig() {\n const appCfg = this.configApi.getConfig('app');\n const cfg = appCfg.getOptionalConfig('doraMetrics');\n\n const rawEnvs = cfg?.getOptionalConfigArray('environments') ?? [];\n const environments: DoraEnvironment[] = rawEnvs.map(e => ({\n name: e.getString('name'),\n branch: e.getString('branch'),\n isProduction: e.getOptionalBoolean('isProduction') ?? false,\n label: e.getOptionalString('label') ?? 'hotfix',\n }));\n\n // Validate: at most one isProduction environment\n const prodEnvs = environments.filter(e => e.isProduction);\n if (prodEnvs.length > 1) {\n throw new Error(\n `DORA metrics config error: only one environment may have isProduction: true, ` +\n `but found ${prodEnvs.length}: ${prodEnvs.map(e => e.name).join(', ')}`,\n );\n }\n\n const initialDays =\n cfg?.getOptionalConfig('collection')?.getOptionalNumber('initialDays') ?? 30;\n\n const targetsCfg = cfg?.getOptionalConfig('targets');\n const targets: DoraTargets = {\n deploymentFrequency: targetsCfg?.getOptionalNumber('deploymentFrequency') ?? 7,\n leadTime: targetsCfg?.getOptionalNumber('leadTime') ?? 24,\n changeFailureRate: targetsCfg?.getOptionalNumber('changeFailureRate') ?? 15,\n mttr: targetsCfg?.getOptionalNumber('mttr') ?? 1,\n };\n\n return { environments, initialDays, targets };\n }\n\n getEnvironments(): DoraEnvironment[] {\n return this.getConfig().environments;\n }\n\n getDefaultDays(): number {\n return this.getConfig().initialDays;\n }\n\n getTargets(): DoraTargets {\n return this.getConfig().targets;\n }\n\n private async fetchWithAuth<T>(url: string, token: string): Promise<T> {\n const response = await fetch(url, {\n headers: {\n Authorization: `token ${token}`,\n Accept: 'application/vnd.github.v3+json',\n },\n });\n\n if (!response.ok) {\n throw new Error(\n `GitHub API request failed: ${response.status} ${response.statusText} — ${url}`,\n );\n }\n\n return response.json() as Promise<T>;\n }\n\n /**\n * Fetch all merged PRs for an environment, resolving branch patterns and\n * deduplicating across multiple branches by PR number.\n */\n private async fetchMergedPRs(\n owner: string,\n repo: string,\n env: DoraEnvironment,\n cutoff: Date,\n token: string,\n ): Promise<GitHubPR[]> {\n const boundFetch = <T>(url: string) => this.fetchWithAuth<T>(url, token);\n\n const branches = await resolveBranches(owner, repo, env.branch, boundFetch);\n\n const allByNumber = new Map<number, GitHubPR>();\n\n await Promise.all(\n branches.map(async branch => {\n const url =\n `https://api.github.com/repos/${owner}/${repo}/pulls` +\n `?state=closed&base=${branch}&per_page=100`;\n const prs = await boundFetch<GitHubPR[]>(url);\n for (const pr of prs) {\n if (pr.merged_at && new Date(pr.merged_at) >= cutoff) {\n // Keep first occurrence (branches may share PRs — shouldn't happen\n // for base-branch-filtered queries, but guard anyway)\n if (!allByNumber.has(pr.number)) {\n allByNumber.set(pr.number, pr);\n }\n }\n }\n }),\n );\n\n return Array.from(allByNumber.values());\n }\n\n async getMetrics(\n projectSlug: string,\n env: DoraEnvironment,\n days: number,\n targetsOverride?: Partial<DoraTargets>,\n ): Promise<DoraMetrics> {\n const token = await this.githubAuthApi.getAccessToken('repo');\n const { targets: configTargets } = this.getConfig();\n const targets: DoraTargets = { ...configTargets, ...targetsOverride };\n\n const [owner, repo] = projectSlug.split('/');\n if (!owner || !repo) {\n throw new Error(`Invalid project slug \"${projectSlug}\". Expected \"owner/repo\".`);\n }\n\n const cutoff = new Date(Date.now() - days * 24 * 60 * 60 * 1000);\n const mergedPRs = await this.fetchMergedPRs(owner, repo, env, cutoff, token);\n\n // --- Deployment Frequency ---\n const deploymentsPerWeek = days > 0 ? (mergedPRs.length / days) * 7 : 0;\n\n const deploymentFrequency: DoraMetricValue = {\n value: Math.round(deploymentsPerWeek * 100) / 100,\n unit: 'per week',\n rating: computeRating(deploymentsPerWeek, targets.deploymentFrequency, false),\n target: targets.deploymentFrequency,\n // All merged PRs sorted newest-first — used in expanded view date table\n slowestPRs: [...mergedPRs]\n .sort((a, b) => new Date(b.merged_at!).getTime() - new Date(a.merged_at!).getTime())\n .map(pr => toPrDetail(pr,\n (new Date(pr.merged_at!).getTime() - new Date(pr.created_at).getTime()) / (1000 * 60 * 60)\n )),\n };\n\n // --- Lead Time ---\n const prsWithLeadTime = mergedPRs\n .map(pr => ({\n pr,\n durationHours:\n (new Date(pr.merged_at!).getTime() - new Date(pr.created_at).getTime()) /\n (1000 * 60 * 60),\n }))\n .sort((a, b) => b.durationHours - a.durationHours);\n\n const avgLeadTimeHours =\n prsWithLeadTime.length > 0\n ? prsWithLeadTime.reduce((sum, p) => sum + p.durationHours, 0) / prsWithLeadTime.length\n : 0;\n\n const leadTime: DoraMetricValue = {\n value: Math.round(avgLeadTimeHours * 10) / 10,\n unit: 'hours',\n rating: computeRating(avgLeadTimeHours, targets.leadTime, true),\n target: targets.leadTime,\n slowestPRs: prsWithLeadTime\n .slice(0, 10)\n .map(p => toPrDetail(p.pr, p.durationHours)),\n };\n\n // --- Production-only metrics ---\n if (!env.isProduction) {\n return {\n deploymentFrequency,\n leadTime,\n changeFailureRate: null,\n mttr: null,\n numberOfHotfixes: null,\n };\n }\n\n const hotfixPRs = mergedPRs.filter(pr =>\n (pr.labels ?? []).some(l => l.name === env.label),\n );\n\n // Number of Hotfixes — sorted newest-first for the expanded list\n const numberOfHotfixes: DoraMetricValue = {\n value: hotfixPRs.length,\n unit: 'PRs',\n rating: computeRating(hotfixPRs.length, 0, true),\n target: 0,\n slowestPRs: [...hotfixPRs]\n .sort((a, b) => new Date(b.merged_at!).getTime() - new Date(a.merged_at!).getTime())\n .map(pr => toPrDetail(pr,\n (new Date(pr.merged_at!).getTime() - new Date(pr.created_at).getTime()) / (1000 * 60 * 60)\n )),\n };\n\n // Change Failure Rate = fix PRs / all merged PRs (DORA standard: always 0–100%)\n const changeFailureRatePct =\n mergedPRs.length > 0 ? (hotfixPRs.length / mergedPRs.length) * 100 : 0;\n\n const changeFailureRate: DoraMetricValue = {\n value: Math.round(changeFailureRatePct * 10) / 10,\n unit: '%',\n rating: computeRating(changeFailureRatePct, targets.changeFailureRate, true),\n target: targets.changeFailureRate,\n };\n\n // MTTR\n const hotfixWithDuration = hotfixPRs\n .map(pr => ({\n pr,\n durationHours:\n (new Date(pr.merged_at!).getTime() - new Date(pr.created_at).getTime()) /\n (1000 * 60 * 60),\n }))\n .sort((a, b) => b.durationHours - a.durationHours);\n\n const avgMttrHours =\n hotfixWithDuration.length > 0\n ? hotfixWithDuration.reduce((sum, p) => sum + p.durationHours, 0) /\n hotfixWithDuration.length\n : 0;\n\n const mttr: DoraMetricValue = {\n value: Math.round(avgMttrHours * 10) / 10,\n unit: 'hours',\n rating: computeRating(avgMttrHours, targets.mttr, true),\n target: targets.mttr,\n slowestPRs: hotfixWithDuration\n .slice(0, 10)\n .map(p => toPrDetail(p.pr, p.durationHours)),\n };\n\n return { deploymentFrequency, leadTime, changeFailureRate, mttr, numberOfHotfixes };\n }\n\n async getHistory(\n projectSlug: string,\n env: DoraEnvironment,\n days: number,\n ): Promise<DoraHistoryPoint[]> {\n const token = await this.githubAuthApi.getAccessToken('repo');\n const [owner, repo] = projectSlug.split('/');\n if (!owner || !repo) throw new Error(`Invalid project slug \"${projectSlug}\".`);\n\n const cutoff = new Date(Date.now() - days * 24 * 60 * 60 * 1000);\n const mergedPRs = await this.fetchMergedPRs(owner, repo, env, cutoff, token);\n\n // Scale bucket size so we always get ~7 data points regardless of date range\n const bucketDays = Math.max(1, Math.round(days / 7));\n const numBuckets = Math.max(2, Math.ceil(days / bucketDays));\n const buckets: DoraHistoryPoint[] = [];\n\n for (let w = numBuckets - 1; w >= 0; w--) {\n const weekEnd = new Date(Date.now() - w * bucketDays * 24 * 60 * 60 * 1000);\n const weekStart = new Date(weekEnd.getTime() - bucketDays * 24 * 60 * 60 * 1000);\n\n const weekPRs = mergedPRs.filter(pr => {\n const t = new Date(pr.merged_at!).getTime();\n return t >= weekStart.getTime() && t < weekEnd.getTime();\n });\n\n const leadTimes = weekPRs.map(pr =>\n (new Date(pr.merged_at!).getTime() - new Date(pr.created_at).getTime()) / (1000 * 60 * 60),\n );\n const avgLeadTime =\n leadTimes.length > 0 ? leadTimes.reduce((a, b) => a + b, 0) / leadTimes.length : 0;\n\n let changeFailureRate: number | undefined;\n let mttrHours: number | undefined;\n\n if (env.isProduction) {\n const hotfixPRs = weekPRs.filter(pr => pr.labels.some(l => l.name === env.label));\n changeFailureRate =\n weekPRs.length > 0 ? Math.round((hotfixPRs.length / weekPRs.length) * 1000) / 10 : 0;\n const hotfixDurations = hotfixPRs.map(pr =>\n (new Date(pr.merged_at!).getTime() - new Date(pr.created_at).getTime()) / (1000 * 60 * 60),\n );\n mttrHours =\n hotfixDurations.length > 0\n ? Math.round((hotfixDurations.reduce((a, b) => a + b, 0) / hotfixDurations.length) * 10) / 10\n : 0;\n }\n\n buckets.push({\n weekLabel: weekStart.toLocaleDateString('en-US', { month: 'short', day: 'numeric' }),\n bucketMidMs: Math.round((weekStart.getTime() + weekEnd.getTime()) / 2),\n deploymentCount: weekPRs.length,\n leadTimeHours: Math.round(avgLeadTime * 10) / 10,\n changeFailureRate,\n mttrHours,\n });\n }\n\n return buckets;\n }\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"DoraMetricsClient.esm.js","sources":["../../src/api/DoraMetricsClient.ts"],"sourcesContent":["import { ConfigApi, OAuthApi } from '@backstage/core-plugin-api';\nimport {\n DoraEnvironment,\n DoraHistoryPoint,\n DoraMetrics,\n DoraMetricValue,\n DoraMetricsApi,\n DoraRating,\n DoraTargets,\n PrDetail,\n} from './types';\n\ninterface GitHubPR {\n number: number;\n title: string;\n html_url: string;\n created_at: string;\n merged_at: string | null;\n closed_at: string | null;\n labels: Array<{ name: string }>;\n user: { login: string; avatar_url: string } | null;\n}\n\n/**\n * Compute a DORA rating based on the configured target.\n *\n * lowerIsBetter (lead time, CFR, MTTR, hotfix count):\n * elite = value <= target\n * high = value <= target * 2\n * medium = value <= target * 4\n * low = value > target * 4\n *\n * higherIsBetter (deployment frequency):\n * elite = value >= target\n * high = value >= target * 0.7\n * medium = value >= target * 0.4\n * low = value < target * 0.4\n *\n * Special case — target = 0 (hotfix count ideal = 0):\n * elite=0, high≤2, medium≤5, low>5\n */\nfunction computeRating(value: number, target: number, lowerIsBetter: boolean): DoraRating {\n if (lowerIsBetter) {\n if (target === 0) {\n if (value === 0) return 'elite';\n if (value <= 2) return 'high';\n if (value <= 5) return 'medium';\n return 'low';\n }\n if (value <= target) return 'elite';\n if (value <= target * 2) return 'high';\n if (value <= target * 4) return 'medium';\n return 'low';\n }\n if (value >= target) return 'elite';\n if (value >= target * 0.7) return 'high';\n if (value >= target * 0.4) return 'medium';\n return 'low';\n}\n\nfunction toPrDetail(pr: GitHubPR, durationHours: number): PrDetail {\n return {\n number: pr.number,\n title: pr.title,\n url: pr.html_url,\n durationHours: Math.round(durationHours * 10) / 10,\n mergedAt: pr.merged_at!,\n author: pr.user?.login,\n authorAvatar: pr.user?.avatar_url,\n };\n}\n\n/**\n * Determine whether a pattern string is a regex (vs a plain name or\n * comma-separated list of names). A string is treated as a regex if it\n * contains any regex meta-character: | ^ $ [ ] ( ) { } ? + * \\\n */\nfunction isRegexPattern(pattern: string): boolean {\n return /[|^$[\\](){}?+*\\\\]/.test(pattern);\n}\n\n/**\n * Return true if any of the PR's labels match the label pattern.\n *\n * Supports the same three formats as branch patterns:\n * - Single name: \"hotfix\"\n * - Comma-separated: \"hotfix,fix,bug\"\n * - JavaScript regex: \"^(hotfix|fix)$\"\n */\nfunction matchesLabel(prLabels: Array<{ name: string }>, labelPattern: string): boolean {\n if (!labelPattern) return false;\n const names = prLabels.map(l => l.name);\n if (isRegexPattern(labelPattern)) {\n const regex = new RegExp(labelPattern);\n return names.some(n => regex.test(n));\n }\n const patterns = labelPattern.split(',').map(l => l.trim()).filter(Boolean);\n return names.some(n => patterns.includes(n));\n}\n\n/**\n * Resolve a branch pattern to a concrete list of branch names.\n *\n * - Single name \"main\" → [\"main\"]\n * - Comma-sep \"main,master\" → [\"main\", \"master\"]\n * - Regex \"^(main|master)$\"→ fetched from the repo's branch list and filtered\n */\nasync function resolveBranches(\n owner: string,\n repo: string,\n branchPattern: string,\n fetchFn: <T>(url: string) => Promise<T>,\n): Promise<string[]> {\n if (isRegexPattern(branchPattern)) {\n const repoBranches = await fetchFn<Array<{ name: string }>>(\n `https://api.github.com/repos/${owner}/${repo}/branches?per_page=100`,\n );\n const regex = new RegExp(branchPattern);\n return repoBranches.map(b => b.name).filter(name => regex.test(name));\n }\n // Comma-separated or single branch name\n return branchPattern.split(',').map(b => b.trim()).filter(Boolean);\n}\n\nexport class DoraMetricsClient implements DoraMetricsApi {\n private readonly githubAuthApi: OAuthApi;\n private readonly configApi: ConfigApi;\n\n constructor(githubAuthApi: OAuthApi, configApi: ConfigApi) {\n this.githubAuthApi = githubAuthApi;\n this.configApi = configApi;\n }\n\n private getConfig() {\n const appCfg = this.configApi.getConfig('app');\n const cfg = appCfg.getOptionalConfig('doraMetrics');\n\n const rawEnvs = cfg?.getOptionalConfigArray('environments') ?? [];\n const environments: DoraEnvironment[] = rawEnvs.map(e => ({\n name: e.getString('name'),\n branch: e.getString('branch'),\n isProduction: e.getOptionalBoolean('isProduction') ?? false,\n label: e.getOptionalString('label') ?? 'hotfix',\n }));\n\n // Validate: at most one isProduction environment\n const prodEnvs = environments.filter(e => e.isProduction);\n if (prodEnvs.length > 1) {\n throw new Error(\n `DORA metrics config error: only one environment may have isProduction: true, ` +\n `but found ${prodEnvs.length}: ${prodEnvs.map(e => e.name).join(', ')}`,\n );\n }\n\n const initialDays =\n cfg?.getOptionalConfig('collection')?.getOptionalNumber('initialDays') ?? 30;\n\n const targetsCfg = cfg?.getOptionalConfig('targets');\n const targets: DoraTargets = {\n deploymentFrequency: targetsCfg?.getOptionalNumber('deploymentFrequency') ?? 7,\n leadTime: targetsCfg?.getOptionalNumber('leadTime') ?? 24,\n changeFailureRate: targetsCfg?.getOptionalNumber('changeFailureRate') ?? 15,\n mttr: targetsCfg?.getOptionalNumber('mttr') ?? 1,\n };\n\n return { environments, initialDays, targets };\n }\n\n getEnvironments(): DoraEnvironment[] {\n return this.getConfig().environments;\n }\n\n getDefaultDays(): number {\n return this.getConfig().initialDays;\n }\n\n getTargets(): DoraTargets {\n return this.getConfig().targets;\n }\n\n private async fetchWithAuth<T>(url: string, token: string): Promise<T> {\n const response = await fetch(url, {\n headers: {\n Authorization: `token ${token}`,\n Accept: 'application/vnd.github.v3+json',\n },\n });\n\n if (!response.ok) {\n throw new Error(\n `GitHub API request failed: ${response.status} ${response.statusText} — ${url}`,\n );\n }\n\n return response.json() as Promise<T>;\n }\n\n /**\n * Fetch all merged PRs for an environment, resolving branch patterns and\n * deduplicating across multiple branches by PR number.\n */\n private async fetchMergedPRs(\n owner: string,\n repo: string,\n env: DoraEnvironment,\n cutoff: Date,\n token: string,\n ): Promise<GitHubPR[]> {\n const boundFetch = <T>(url: string) => this.fetchWithAuth<T>(url, token);\n\n const branches = await resolveBranches(owner, repo, env.branch, boundFetch);\n\n const allByNumber = new Map<number, GitHubPR>();\n\n await Promise.all(\n branches.map(async branch => {\n const url =\n `https://api.github.com/repos/${owner}/${repo}/pulls` +\n `?state=closed&base=${branch}&per_page=100`;\n const prs = await boundFetch<GitHubPR[]>(url);\n for (const pr of prs) {\n if (pr.merged_at && new Date(pr.merged_at) >= cutoff) {\n // Keep first occurrence (branches may share PRs — shouldn't happen\n // for base-branch-filtered queries, but guard anyway)\n if (!allByNumber.has(pr.number)) {\n allByNumber.set(pr.number, pr);\n }\n }\n }\n }),\n );\n\n return Array.from(allByNumber.values());\n }\n\n async getMetrics(\n projectSlug: string,\n env: DoraEnvironment,\n days: number,\n targetsOverride?: Partial<DoraTargets>,\n ): Promise<DoraMetrics> {\n const token = await this.githubAuthApi.getAccessToken('repo');\n const { targets: configTargets } = this.getConfig();\n const targets: DoraTargets = { ...configTargets, ...targetsOverride };\n\n const [owner, repo] = projectSlug.split('/');\n if (!owner || !repo) {\n throw new Error(`Invalid project slug \"${projectSlug}\". Expected \"owner/repo\".`);\n }\n\n const cutoff = new Date(Date.now() - days * 24 * 60 * 60 * 1000);\n const mergedPRs = await this.fetchMergedPRs(owner, repo, env, cutoff, token);\n\n // --- Deployment Frequency ---\n const deploymentsPerWeek = days > 0 ? (mergedPRs.length / days) * 7 : 0;\n\n const deploymentFrequency: DoraMetricValue = {\n value: Math.round(deploymentsPerWeek * 100) / 100,\n unit: 'per week',\n rating: computeRating(deploymentsPerWeek, targets.deploymentFrequency, false),\n target: targets.deploymentFrequency,\n // All merged PRs sorted newest-first — used in expanded view date table\n slowestPRs: [...mergedPRs]\n .sort((a, b) => new Date(b.merged_at!).getTime() - new Date(a.merged_at!).getTime())\n .map(pr => toPrDetail(pr,\n (new Date(pr.merged_at!).getTime() - new Date(pr.created_at).getTime()) / (1000 * 60 * 60)\n )),\n };\n\n // --- Lead Time ---\n const prsWithLeadTime = mergedPRs\n .map(pr => ({\n pr,\n durationHours:\n (new Date(pr.merged_at!).getTime() - new Date(pr.created_at).getTime()) /\n (1000 * 60 * 60),\n }))\n .sort((a, b) => b.durationHours - a.durationHours);\n\n const avgLeadTimeHours =\n prsWithLeadTime.length > 0\n ? prsWithLeadTime.reduce((sum, p) => sum + p.durationHours, 0) / prsWithLeadTime.length\n : 0;\n\n const leadTime: DoraMetricValue = {\n value: Math.round(avgLeadTimeHours * 10) / 10,\n unit: 'hours',\n rating: computeRating(avgLeadTimeHours, targets.leadTime, true),\n target: targets.leadTime,\n slowestPRs: prsWithLeadTime\n .slice(0, 10)\n .map(p => toPrDetail(p.pr, p.durationHours)),\n };\n\n // --- Production-only metrics ---\n if (!env.isProduction) {\n return {\n deploymentFrequency,\n leadTime,\n changeFailureRate: null,\n mttr: null,\n numberOfHotfixes: null,\n };\n }\n\n const hotfixPRs = mergedPRs.filter(pr =>\n matchesLabel(pr.labels ?? [], env.label),\n );\n\n // Number of Hotfixes — sorted newest-first for the expanded list\n const numberOfHotfixes: DoraMetricValue = {\n value: hotfixPRs.length,\n unit: 'PRs',\n rating: computeRating(hotfixPRs.length, 0, true),\n target: 0,\n slowestPRs: [...hotfixPRs]\n .sort((a, b) => new Date(b.merged_at!).getTime() - new Date(a.merged_at!).getTime())\n .map(pr => toPrDetail(pr,\n (new Date(pr.merged_at!).getTime() - new Date(pr.created_at).getTime()) / (1000 * 60 * 60)\n )),\n };\n\n // Change Failure Rate = fix PRs / all merged PRs (DORA standard: always 0–100%)\n const changeFailureRatePct =\n mergedPRs.length > 0 ? (hotfixPRs.length / mergedPRs.length) * 100 : 0;\n\n const changeFailureRate: DoraMetricValue = {\n value: Math.round(changeFailureRatePct * 10) / 10,\n unit: '%',\n rating: computeRating(changeFailureRatePct, targets.changeFailureRate, true),\n target: targets.changeFailureRate,\n };\n\n // MTTR\n const hotfixWithDuration = hotfixPRs\n .map(pr => ({\n pr,\n durationHours:\n (new Date(pr.merged_at!).getTime() - new Date(pr.created_at).getTime()) /\n (1000 * 60 * 60),\n }))\n .sort((a, b) => b.durationHours - a.durationHours);\n\n const avgMttrHours =\n hotfixWithDuration.length > 0\n ? hotfixWithDuration.reduce((sum, p) => sum + p.durationHours, 0) /\n hotfixWithDuration.length\n : 0;\n\n const mttr: DoraMetricValue = {\n value: Math.round(avgMttrHours * 10) / 10,\n unit: 'hours',\n rating: computeRating(avgMttrHours, targets.mttr, true),\n target: targets.mttr,\n slowestPRs: hotfixWithDuration\n .slice(0, 10)\n .map(p => toPrDetail(p.pr, p.durationHours)),\n };\n\n return { deploymentFrequency, leadTime, changeFailureRate, mttr, numberOfHotfixes };\n }\n\n async getHistory(\n projectSlug: string,\n env: DoraEnvironment,\n days: number,\n ): Promise<DoraHistoryPoint[]> {\n const token = await this.githubAuthApi.getAccessToken('repo');\n const [owner, repo] = projectSlug.split('/');\n if (!owner || !repo) throw new Error(`Invalid project slug \"${projectSlug}\".`);\n\n const cutoff = new Date(Date.now() - days * 24 * 60 * 60 * 1000);\n const mergedPRs = await this.fetchMergedPRs(owner, repo, env, cutoff, token);\n\n // Scale bucket size so we always get ~7 data points regardless of date range\n const bucketDays = Math.max(1, Math.round(days / 7));\n const numBuckets = Math.max(2, Math.ceil(days / bucketDays));\n const buckets: DoraHistoryPoint[] = [];\n\n for (let w = numBuckets - 1; w >= 0; w--) {\n const weekEnd = new Date(Date.now() - w * bucketDays * 24 * 60 * 60 * 1000);\n const weekStart = new Date(weekEnd.getTime() - bucketDays * 24 * 60 * 60 * 1000);\n\n const weekPRs = mergedPRs.filter(pr => {\n const t = new Date(pr.merged_at!).getTime();\n return t >= weekStart.getTime() && t < weekEnd.getTime();\n });\n\n const leadTimes = weekPRs.map(pr =>\n (new Date(pr.merged_at!).getTime() - new Date(pr.created_at).getTime()) / (1000 * 60 * 60),\n );\n const avgLeadTime =\n leadTimes.length > 0 ? leadTimes.reduce((a, b) => a + b, 0) / leadTimes.length : 0;\n\n let changeFailureRate: number | undefined;\n let mttrHours: number | undefined;\n\n if (env.isProduction) {\n const hotfixPRs = weekPRs.filter(pr => matchesLabel(pr.labels, env.label));\n changeFailureRate =\n weekPRs.length > 0 ? Math.round((hotfixPRs.length / weekPRs.length) * 1000) / 10 : 0;\n const hotfixDurations = hotfixPRs.map(pr =>\n (new Date(pr.merged_at!).getTime() - new Date(pr.created_at).getTime()) / (1000 * 60 * 60),\n );\n mttrHours =\n hotfixDurations.length > 0\n ? Math.round((hotfixDurations.reduce((a, b) => a + b, 0) / hotfixDurations.length) * 10) / 10\n : 0;\n }\n\n buckets.push({\n weekLabel: weekStart.toLocaleDateString('en-US', { month: 'short', day: 'numeric' }),\n bucketMidMs: Math.round((weekStart.getTime() + weekEnd.getTime()) / 2),\n deploymentCount: weekPRs.length,\n leadTimeHours: Math.round(avgLeadTime * 10) / 10,\n changeFailureRate,\n mttrHours,\n });\n }\n\n return buckets;\n }\n}\n"],"names":[],"mappings":"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"}
@@ -762,7 +762,7 @@ function DetailedOverlay({
762
762
  padding: "8px 12px",
763
763
  borderRadius: 8,
764
764
  background: isHov ? isDark ? "#18181f" : "#f0f0ff" : isDark ? "#111114" : "#f4f4f6",
765
- border: `1px solid ${isHov ? sparklineColor + "55" : borderColor}`,
765
+ border: `1px solid ${isHov ? `${sparklineColor}55` : borderColor}`,
766
766
  display: "flex",
767
767
  flexDirection: "column",
768
768
  gap: 5,
@@ -940,17 +940,21 @@ function DoraMetricsContent() {
940
940
  const [history, setHistory] = useState(null);
941
941
  const [expanded, setExpanded] = useState(null);
942
942
  useEffect(() => {
943
+ let cancelled = false;
943
944
  if (!projectSlug) {
944
945
  setError(new Error(`Entity is missing the "${ANNOTATION_PROJECT_SLUG}" annotation.`));
945
946
  setLoading(false);
946
- return;
947
+ return () => {
948
+ cancelled = true;
949
+ };
947
950
  }
948
951
  if (!selectedEnv) {
949
952
  setError(new Error("No environments configured for DORA metrics."));
950
953
  setLoading(false);
951
- return;
954
+ return () => {
955
+ cancelled = true;
956
+ };
952
957
  }
953
- let cancelled = false;
954
958
  setLoading(true);
955
959
  setError(null);
956
960
  setHistory(null);
@@ -972,7 +976,7 @@ function DoraMetricsContent() {
972
976
  return () => {
973
977
  cancelled = true;
974
978
  };
975
- }, [doraApi, projectSlug, selectedEnv?.name, days]);
979
+ }, [doraApi, projectSlug, selectedEnv?.name, days, annotationTargets]);
976
980
  if (loading) return /* @__PURE__ */ React.createElement(DoraLoadingOverlay, null);
977
981
  if (error) {
978
982
  return /* @__PURE__ */ React.createElement(InfoCard, { title: "DORA Metrics" }, /* @__PURE__ */ React.createElement("div", { style: { padding: 24, color: "#f87171" } }, /* @__PURE__ */ React.createElement("span", { style: { fontWeight: 600 } }, "Error: "), error.message));
@@ -1 +1 @@
1
- {"version":3,"file":"DoraMetricsContent.esm.js","sources":["../../src/components/DoraMetricsContent.tsx"],"sourcesContent":["import React, { useEffect, useRef, useState } from 'react';\nimport { useTheme } from '@material-ui/core/styles';\nimport { useApi } from '@backstage/core-plugin-api';\nimport { useEntity } from '@backstage/plugin-catalog-react';\nimport { InfoCard } from '@backstage/core-components';\nimport { doraMetricsApiRef } from '../api/types';\nimport type { DoraEnvironment, DoraHistoryPoint, DoraMetrics, DoraMetricValue, DoraTargets, PrDetail } from '../api/types';\nimport { RatingBadge } from './ui/badge';\nimport { Card, CardLabel, CardFooter, CardDescription } from './ui/card';\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from './ui/select';\nimport { ExternalLink } from 'lucide-react';\n\nconst ANNOTATION_PROJECT_SLUG = 'github.com/project-slug';\n/** Override the global environments list for this specific entity. JSON array of DoraEnvironment objects. */\nconst ANNOTATION_ENVIRONMENTS = 'dora-metrics/environments';\n/** Override the global performance targets for this specific entity. JSON object matching DoraTargets. */\nconst ANNOTATION_TARGETS = 'dora-metrics/targets';\n\n/** Parse entity annotation overrides. Returns undefined for malformed JSON to fail gracefully. */\nfunction parseAnnotationJson<T>(raw: string | undefined): T | undefined {\n if (!raw) return undefined;\n try { return JSON.parse(raw) as T; } catch { return undefined; }\n}\n\nconst DATE_RANGE_OPTIONS = [\n { value: '7', label: 'Last 7 days' },\n { value: '14', label: 'Last 14 days' },\n { value: '30', label: 'Last 30 days' },\n { value: '60', label: 'Last 60 days' },\n { value: '90', label: 'Last 90 days' },\n];\n\n// ─── Helpers ───────────────────────────────────────────────────────────────\n\nfunction formatDuration(hours: number): string {\n const totalMinutes = Math.round(hours * 60);\n const d = Math.floor(totalMinutes / (24 * 60));\n const h = Math.floor((totalMinutes % (24 * 60)) / 60);\n const m = totalMinutes % 60;\n if (d > 0) return h > 0 ? `${d}d ${h}h` : `${d}d`;\n if (h > 0) return m > 0 ? `${h}h ${m}m` : `${h}h`;\n return `${m}m`;\n}\n\n// Red → Orange → Yellow → Lime → Green gradient (slowest to fastest)\nconst DURATION_GRADIENT = ['#f87171', '#fb923c', '#fbbf24', '#a3e635', '#4ade80'];\n\nfunction durationColor(index: number, total: number): string {\n if (total <= 1) return DURATION_GRADIENT[0];\n const step = (DURATION_GRADIENT.length - 1) / (total - 1);\n return DURATION_GRADIENT[Math.round(index * step)];\n}\n\n// ─── Helpers ───────────────────────────────────────────────────────────────\n\n// Period-over-period delta — compares last bucket vs second-to-last bucket\nfunction buildDeltaLabel(\n values: number[],\n unit: string,\n lowerIsBetter: boolean,\n): { text: string; tooltip: string; good: boolean } | null {\n if (values.length < 2) return null;\n const curr = values[values.length - 1];\n const prev = values[values.length - 2];\n const diff = curr - prev;\n if (Math.abs(diff) < 0.001) return null;\n const good = lowerIsBetter ? diff < 0 : diff > 0;\n const arrow = diff > 0 ? '↑' : '↓';\n\n const fmt = (v: number) =>\n unit === 'hours' ? formatDuration(v) :\n unit === '%' ? `${Math.round(v * 10) / 10}%` :\n unit === 'per week' ? `${Math.round(v * 10) / 10}/wk` :\n `${Math.round(v * 10) / 10} ${unit}`;\n\n const direction = good ? 'improving' : 'worsening';\n return {\n text: `${arrow} ${fmt(Math.abs(diff))} ${direction}`,\n tooltip: `Latest period: ${fmt(curr)} · Previous period: ${fmt(prev)}\\nEach period = one time bucket (~1/7th of your selected date range)`,\n good,\n };\n}\n\n// ─── Loading overlay ────────────────────────────────────────────────────────\n\nconst LOADING_MESSAGES = [\n 'Establishing routes…',\n 'Syncing catalog…',\n 'Loading plugins…',\n 'Fetching PR data…',\n 'Reading entity graph…',\n];\nconst STAGES = ['FETCH', 'PARSE', 'SCORE', 'RENDER'] as const;\nconst FONT_IMPACT = '\"Impact\",\"Haettenschweiler\",\"Franklin Gothic Heavy\",\"Arial Black\",sans-serif';\nconst FONT_MONO = '\"JetBrains Mono\",\"Fira Code\",\"Consolas\",monospace';\n\nfunction DoraLoadingOverlay() {\n const theme = useTheme();\n const isDark = theme.palette.type === 'dark';\n\n const [activeStage, setActiveStage] = useState(0);\n const [msgKey, setMsgKey] = useState(0);\n const [msgIdx, setMsgIdx] = useState(0);\n\n useEffect(() => {\n const st = setInterval(() => setActiveStage(s => (s + 1) % STAGES.length), 800);\n return () => clearInterval(st);\n }, []);\n\n useEffect(() => {\n const mt = setInterval(() => { setMsgIdx(i => (i + 1) % LOADING_MESSAGES.length); setMsgKey(k => k + 1); }, 2200);\n return () => clearInterval(mt);\n }, []);\n\n const textShadow = isDark\n ? '3px 3px 0 #C24E00, 6px 6px 0 #902800, 9px 9px 0 #5A1800, 12px 12px 0 rgba(0,0,0,0.55), 0 0 60px rgba(250,100,0,0.45)'\n : '3px 3px 0 #C24E00, 6px 6px 0 #902800, 9px 9px 0 rgba(80,20,0,0.28), 0 0 32px rgba(250,100,0,0.22)';\n\n const mutedColor = isDark ? '#3f3f46' : '#a1a1aa';\n const subtitleColor = isDark ? '#52525b' : '#71717a';\n const borderColor = isDark ? 'rgba(255,255,255,0.07)' : 'rgba(0,0,0,0.08)';\n\n return (\n <>\n {/* Frosted glass backdrop — blurs whatever is behind */}\n <div aria-hidden style={{\n position: 'fixed', inset: 0, zIndex: 900,\n backdropFilter: 'blur(12px)',\n WebkitBackdropFilter: 'blur(12px)',\n background: isDark ? 'rgba(6,6,9,0.65)' : 'rgba(253,252,251,0.70)',\n }} />\n\n {/* Centered card */}\n <div style={{\n position: 'fixed', zIndex: 901,\n top: '50%', left: '50%',\n transform: 'translateX(-50%) translateY(-50%)',\n display: 'flex', flexDirection: 'column', alignItems: 'center',\n padding: '48px 56px 40px',\n borderRadius: 20,\n background: isDark ? 'rgba(9,9,12,0.82)' : 'rgba(255,255,255,0.88)',\n border: `1px solid ${borderColor}`,\n boxShadow: isDark\n ? '0 0 0 1px rgba(250,100,0,0.06), 0 32px 80px rgba(0,0,0,0.65)'\n : '0 32px 80px rgba(0,0,0,0.12)',\n backdropFilter: 'blur(20px)',\n WebkitBackdropFilter: 'blur(20px)',\n animation: 'dlsCardIn 0.35s cubic-bezier(0.34,1.2,0.64,1) both',\n overflow: 'visible',\n }}>\n\n {/* Breathing ambient glow — inside card */}\n <div aria-hidden style={{\n position: 'absolute', width: 500, height: 360,\n left: '50%', top: '50%',\n transform: 'translateX(-50%) translateY(-50%)',\n background: `radial-gradient(ellipse at center, ${isDark ? 'rgba(250,100,0,0.08)' : 'rgba(250,100,0,0.05)'} 0%, transparent 70%)`,\n animation: 'dlsBreath 3.2s ease-in-out infinite',\n pointerEvents: 'none', borderRadius: 20,\n }} />\n\n {/* DORA wordmark */}\n <div style={{ display: 'flex', lineHeight: 1, marginBottom: 6 }}>\n {['D','O','R','A'].map((letter, i) => (\n <span key={i} style={{\n fontFamily: FONT_IMPACT, fontWeight: 900, fontSize: 110,\n color: '#FA6400', letterSpacing: '0.04em', display: 'inline-block',\n transform: 'skewX(-6deg)', textShadow,\n WebkitTextStroke: '0.5px #C24E00',\n animation: `dlsLetterDrop 0.6s cubic-bezier(0.34,1.45,0.64,1) ${i * 0.1}s both`,\n }}>\n {letter}\n </span>\n ))}\n </div>\n\n {/* Subtitle */}\n <span style={{ fontFamily: 'Inter,system-ui,sans-serif', fontSize: 13, fontWeight: 400,\n letterSpacing: '0.06em', color: subtitleColor, marginBottom: 32,\n animation: 'dlsFadeUp 0.4s ease 0.55s both' }}>\n Metrics\n </span>\n\n {/* Pipeline stages */}\n <div style={{ display: 'flex', alignItems: 'center', gap: 0, marginBottom: 20, animation: 'dlsFadeUp 0.4s ease 0.7s both' }}>\n {STAGES.map((stage, i) => {\n const isActive = i === activeStage;\n const isComplete = i < activeStage;\n return (\n <div key={stage} style={{ display: 'flex', alignItems: 'center', gap: 0 }}>\n <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 5, width: 64 }}>\n <div style={{ position: 'relative', width: 12, height: 12 }}>\n {isActive && (\n <div style={{ position: 'absolute', inset: -6, borderRadius: '50%',\n border: '1.5px solid rgba(250,100,0,0.5)', animation: 'dlsPulse 1s ease-out infinite' }} />\n )}\n <div style={{\n width: 12, height: 12, borderRadius: '50%',\n background: (isActive || isComplete) ? '#FA6400' : (isDark ? '#27272a' : '#e4e4e7'),\n border: `2px solid ${(isActive || isComplete) ? '#C24E00' : (isDark ? '#3f3f46' : '#d4d4d8')}`,\n boxShadow: isActive ? '0 0 14px rgba(250,100,0,0.7)' : 'none',\n transition: 'background 0.3s, box-shadow 0.3s',\n }} />\n </div>\n <span style={{ fontFamily: 'Inter,system-ui,sans-serif', fontSize: 8, fontWeight: 700,\n letterSpacing: '0.12em', textTransform: 'uppercase',\n color: isActive ? '#FA6400' : isComplete ? mutedColor : mutedColor,\n transition: 'color 0.3s' }}>\n {stage}\n </span>\n </div>\n {i < STAGES.length - 1 && (\n <div style={{ width: 32, height: 2, marginBottom: 14, position: 'relative', overflow: 'hidden',\n background: isDark ? '#27272a' : '#e4e4e7', borderRadius: 2 }}>\n <div style={{\n position: 'absolute', inset: 0, borderRadius: 2, background: '#FA6400',\n transformOrigin: 'left center',\n transform: `scaleX(${i < activeStage ? 1 : isActive ? 0.5 : 0})`,\n transition: 'transform 0.4s ease',\n }} />\n </div>\n )}\n </div>\n );\n })}\n </div>\n\n {/* Status message */}\n <span key={msgKey} style={{ fontFamily: FONT_MONO, fontSize: 11,\n color: mutedColor, letterSpacing: '0.04em', animation: 'dlsFadeUp 0.3s ease both' }}>\n {LOADING_MESSAGES[msgIdx]}\n </span>\n\n </div>{/* end card */}\n\n <style>{`\n @keyframes dlsLetterDrop {\n from { opacity: 0; transform: skewX(-6deg) translateY(-32px) scale(1.1); }\n 65% { transform: skewX(-6deg) translateY(6px) scale(0.95); }\n to { opacity: 1; transform: skewX(-6deg) translateY(0) scale(1); }\n }\n @keyframes dlsFadeUp {\n from { opacity: 0; transform: translateY(10px); }\n to { opacity: 1; transform: translateY(0); }\n }\n @keyframes dlsBreath {\n 0%, 100% { transform: translateX(-50%) translateY(-50%) scale(0.85); opacity: 0.6; }\n 50% { transform: translateX(-50%) translateY(-50%) scale(1.2); opacity: 1; }\n }\n @keyframes dlsPulse {\n from { transform: scale(0.6); opacity: 0.9; }\n to { transform: scale(2.2); opacity: 0; }\n }\n @keyframes dlsCardIn {\n from { opacity: 0; transform: translateX(-50%) translateY(-46%); }\n to { opacity: 1; transform: translateX(-50%) translateY(-50%); }\n }\n `}</style>\n </>\n );\n}\n\n// ─── Compact sparkline (with hover tooltip + date axis) ────────────────────\n\nfunction CompactSparkline({\n values,\n weekLabels,\n color,\n type,\n formatValue,\n height = 36,\n}: {\n values: number[];\n weekLabels: string[];\n color: string;\n type: 'bar' | 'line';\n formatValue: (v: number) => string;\n height?: number;\n}) {\n const theme = useTheme();\n const isDark = theme.palette.type === 'dark';\n const [hoverIdx, setHoverIdx] = useState<number | null>(null);\n\n const VW = 400; // viewBox units\n const mutedBorder = isDark ? 'rgba(255,255,255,0.06)' : 'rgba(0,0,0,0.06)';\n const tooltipBg = isDark ? '#1c1c20' : '#ffffff';\n const tooltipBdr = isDark ? '#3f3f46' : '#e4e4e7';\n const tooltipText = isDark ? '#ededef' : '#111114';\n const font = 'Inter,system-ui,sans-serif';\n\n const handleMouseMove = (e: React.MouseEvent<SVGSVGElement>) => {\n const rect = e.currentTarget.getBoundingClientRect();\n const relX = (e.clientX - rect.left) / rect.width;\n setHoverIdx(Math.max(0, Math.min(values.length - 1, Math.round(relX * (values.length - 1)))));\n };\n\n if (type === 'bar') {\n const max = Math.max(...values, 1);\n const gap = 4;\n const barW = (VW - gap * (values.length - 1)) / values.length;\n\n const hoverX = hoverIdx !== null\n ? hoverIdx * (barW + gap) + barW / 2\n : null;\n const tooltipX = hoverX !== null ? Math.min(hoverX - 34, VW - 72) : 0;\n\n return (\n <div>\n <svg viewBox={`0 0 ${VW} ${height}`} width=\"100%\" style={{ display: 'block', overflow: 'visible' }}\n onMouseMove={handleMouseMove} onMouseLeave={() => setHoverIdx(null)}>\n {values.map((v, i) => {\n const h = Math.max(2, (v / max) * (height - 4));\n return (\n <rect key={i} x={i * (barW + gap)} y={height - h} width={barW} height={h} rx={1.5}\n fill={color} opacity={i === hoverIdx ? 1 : 0.3 + (i / values.length) * 0.55} />\n );\n })}\n <line x1={0} y1={height - 0.5} x2={VW} y2={height - 0.5} stroke={mutedBorder} strokeWidth={1} />\n {hoverIdx !== null && hoverX !== null && (\n <>\n <rect x={tooltipX} y={2} width={72} height={22} rx={4} fill={tooltipBg} stroke={tooltipBdr} strokeWidth={1} />\n <text x={tooltipX + 36} y={17} textAnchor=\"middle\" fill={tooltipText} fontSize={9} fontWeight={600} fontFamily={font}>\n {weekLabels[hoverIdx]}: {formatValue(values[hoverIdx])}\n </text>\n </>\n )}\n </svg>\n <div style={{ display: 'flex', justifyContent: 'space-between', marginTop: 3 }}>\n <span style={{ fontSize: 9, color: isDark ? '#3f3f46' : '#a1a1aa' }}>{weekLabels[0]}</span>\n <span style={{ fontSize: 9, color: isDark ? '#3f3f46' : '#a1a1aa' }}>{weekLabels[weekLabels.length - 1]}</span>\n </div>\n </div>\n );\n }\n\n if (values.length < 2) return null;\n const max = Math.max(...values, 0.01);\n const min = Math.min(...values);\n const range = max - min || max || 1;\n const pad = 3;\n const pts = values.map((v, i): [number, number] => [\n (i / (values.length - 1)) * (VW - pad * 2) + pad,\n (height - pad * 2) - ((v - min) / range) * (height - pad * 2 - 2) + pad,\n ]);\n const d = pts.map(([x, y], i) => `${i === 0 ? 'M' : 'L'}${x.toFixed(1)},${y.toFixed(1)}`).join(' ');\n const area = `${d} L${pts[pts.length-1][0]},${height} L${pts[0][0]},${height} Z`;\n const hoverPt = hoverIdx !== null ? pts[hoverIdx] : null;\n const tooltipX2 = hoverPt ? Math.min(hoverPt[0] - 34, VW - 72) : 0;\n\n return (\n <div>\n <svg viewBox={`0 0 ${VW} ${height}`} width=\"100%\" style={{ display: 'block', overflow: 'visible' }}\n onMouseMove={handleMouseMove} onMouseLeave={() => setHoverIdx(null)}>\n <path d={area} fill={color} opacity={0.07} />\n <path d={d} fill=\"none\" stroke={color} strokeWidth={1.5} strokeLinejoin=\"round\" strokeLinecap=\"round\" />\n {pts.map(([x, y], i) => (\n <circle key={i} cx={x} cy={y} r={i === hoverIdx ? 3.5 : i === pts.length - 1 ? 2.5 : 0} fill={color} />\n ))}\n <line x1={0} y1={height - 0.5} x2={VW} y2={height - 0.5} stroke={mutedBorder} strokeWidth={1} />\n {hoverPt && hoverIdx !== null && (\n <>\n <line x1={hoverPt[0]} y1={0} x2={hoverPt[0]} y2={height} stroke={color} strokeWidth={1} strokeDasharray=\"2 2\" opacity={0.4} />\n <rect x={tooltipX2} y={2} width={72} height={22} rx={4} fill={tooltipBg} stroke={tooltipBdr} strokeWidth={1} />\n <text x={tooltipX2 + 36} y={17} textAnchor=\"middle\" fill={tooltipText} fontSize={9} fontWeight={600} fontFamily={font}>\n {weekLabels[hoverIdx]}: {formatValue(values[hoverIdx])}\n </text>\n </>\n )}\n </svg>\n <div style={{ display: 'flex', justifyContent: 'space-between', marginTop: 3 }}>\n <span style={{ fontSize: 9, color: isDark ? '#3f3f46' : '#a1a1aa' }}>{weekLabels[0]}</span>\n <span style={{ fontSize: 9, color: isDark ? '#3f3f46' : '#a1a1aa' }}>{weekLabels[weekLabels.length - 1]}</span>\n </div>\n </div>\n );\n}\n\n// ─── Detailed interactive chart ────────────────────────────────────────────\n\ninterface ChartTooltipState {\n x: number;\n y: number;\n primary: string;\n secondary?: string;\n}\n\nfunction DetailedChart({\n values,\n weekLabels,\n bucketMidMs,\n color,\n type,\n formatValue,\n prs,\n days,\n hoveredPrNumber,\n onPrHover,\n}: {\n values: number[];\n weekLabels: string[];\n bucketMidMs: number[];\n color: string;\n type: 'bar' | 'line';\n formatValue: (v: number) => string;\n prs?: PrDetail[];\n days: number;\n hoveredPrNumber?: number | null;\n onPrHover?: (num: number | null) => void;\n}) {\n const theme = useTheme();\n const isDark = theme.palette.type === 'dark';\n const [hoverIdx, setHoverIdx] = useState<number | null>(null);\n const [tooltip, setTooltip] = useState<ChartTooltipState | null>(null);\n const containerRef = useRef<HTMLDivElement>(null);\n\n const W = 800, H = 260;\n const PAD = { top: 16, right: 16, bottom: 36, left: 56 };\n const cW = W - PAD.left - PAD.right;\n const cH = H - PAD.top - PAD.bottom;\n\n // Y scale: based on bucket values only so the trend line is clearly readable.\n // PR dots that fall outside this range are rendered clamped to chart area.\n const dataMax = Math.max(...values, 0.01);\n const dataMin = type === 'line' ? Math.min(...values, 0) : 0;\n const dataRange = dataMax - dataMin || dataMax || 1;\n const yScale = (v: number) => cH - ((v - dataMin) / dataRange) * cH;\n\n // Shared timestamp-based x-axis\n const cutoffMs = Date.now() - days * 24 * 60 * 60 * 1000;\n const rangeMs = days * 24 * 60 * 60 * 1000;\n const xTime = (ms: number) => Math.max(0, Math.min(cW, ((ms - cutoffMs) / rangeMs) * cW));\n\n const xIdx = (i: number) => bucketMidMs.length === values.length\n ? xTime(bucketMidMs[i])\n : (values.length > 1 ? (i / (values.length - 1)) * cW : cW / 2);\n\n const pts: [number, number][] = values.map((v, i) => [PAD.left + xIdx(i), PAD.top + yScale(v)]);\n const linePath = pts.map(([x, y], i) => `${i === 0 ? 'M' : 'L'}${x.toFixed(1)},${y.toFixed(1)}`).join(' ');\n const areaPath = pts.length > 1\n ? `${linePath} L${pts[pts.length-1][0]},${PAD.top+cH} L${pts[0][0]},${PAD.top+cH} Z`\n : '';\n\n const gap = 6;\n const barW = values.length > 1 ? (cW - gap * (values.length - 1)) / values.length : cW;\n\n const yTicks = [0, 0.25, 0.5, 0.75, 1].map(t => dataMin + t * dataRange);\n const gridColor = isDark ? 'rgba(255,255,255,0.05)' : 'rgba(0,0,0,0.05)';\n const axisColor = isDark ? '#3f3f46' : '#d4d4d8';\n const labelColor = isDark ? '#52525b' : '#a1a1aa';\n const font = 'Inter,system-ui,sans-serif';\n const gradId = `dg_${color.replace('#','')}`;\n\n // Find the nearest bucket index for a given timestamp\n const nearestBucket = (ms: number): number => {\n if (bucketMidMs.length === 0) return 0;\n let best = 0, bestDist = Infinity;\n bucketMidMs.forEach((mid, i) => {\n const d = Math.abs(ms - mid);\n if (d < bestDist) { bestDist = d; best = i; }\n });\n return best;\n };\n\n const handleSvgMouseMove = (e: React.MouseEvent<SVGSVGElement>) => {\n const rect = e.currentTarget.getBoundingClientRect();\n const relX = (e.clientX - rect.left - PAD.left * (rect.width / W)) / (rect.width * cW / W);\n const idx = Math.max(0, Math.min(values.length - 1, Math.round(relX * (values.length - 1))));\n setHoverIdx(idx);\n const cRect = containerRef.current?.getBoundingClientRect();\n const x = cRect ? e.clientX - cRect.left : 0;\n const y = cRect ? e.clientY - cRect.top : 0;\n setTooltip({ x, y, primary: formatValue(values[idx]), secondary: weekLabels[idx] });\n };\n\n return (\n <div ref={containerRef} style={{ position: 'relative' }}>\n <svg viewBox={`0 0 ${W} ${H}`} width=\"100%\" style={{ display: 'block' }}\n onMouseMove={handleSvgMouseMove}\n onMouseLeave={() => { setHoverIdx(null); setTooltip(null); }}>\n <defs>\n <linearGradient id={gradId} x1=\"0\" y1=\"0\" x2=\"0\" y2=\"1\">\n <stop offset=\"0%\" stopColor={color} stopOpacity={0.28} />\n <stop offset=\"100%\" stopColor={color} stopOpacity={0} />\n </linearGradient>\n {/* Clip PR dots to the chart area */}\n <clipPath id={`prClip_${gradId}`}>\n <rect x={PAD.left} y={PAD.top - 8} width={cW} height={cH + 16} />\n </clipPath>\n </defs>\n\n {/* Grid + Y-axis */}\n {yTicks.map((v, i) => {\n const y = PAD.top + yScale(v);\n return (\n <g key={i}>\n {i > 0 && <line x1={PAD.left} y1={y} x2={PAD.left+cW} y2={y} stroke={gridColor} strokeWidth={1} strokeDasharray=\"3 4\" />}\n <text x={PAD.left - 6} y={y + 4} textAnchor=\"end\" fill={labelColor} fontSize={10} fontFamily={font}>\n {formatValue(v)}\n </text>\n </g>\n );\n })}\n <line x1={PAD.left} y1={PAD.top+cH} x2={PAD.left+cW} y2={PAD.top+cH} stroke={axisColor} strokeWidth={1} />\n\n {/* Chart body */}\n {type === 'bar' ? (\n values.map((v, i) => {\n const bH = Math.max(2, ((v - dataMin) / dataRange) * cH);\n const x = PAD.left + i * (barW + gap);\n return (\n <rect key={i} x={x} y={PAD.top+cH-bH} width={barW} height={bH} rx={3}\n fill={color} opacity={i === hoverIdx ? 0.95 : 0.4 + (i / Math.max(values.length - 1, 1)) * 0.45} />\n );\n })\n ) : (\n <>\n {areaPath && <path d={areaPath} fill={`url(#${gradId})`} />}\n <path d={linePath} fill=\"none\" stroke={color} strokeWidth={2.5} strokeLinejoin=\"round\" strokeLinecap=\"round\" />\n {pts.map(([x, y], i) => (\n <circle key={i} cx={x} cy={y}\n r={i === hoverIdx ? 5.5 : 4}\n fill={isDark ? '#0f0f12' : '#ffffff'} stroke={color}\n strokeWidth={i === hoverIdx ? 2.5 : 1.5} />\n ))}\n </>\n )}\n\n {/* PR data-point dots — x at bucket midpoint, y at actual duration (clamped to chart) */}\n {prs && type === 'line' && (\n <g clipPath={`url(#prClip_${gradId})`}>\n {prs.map((pr, dotIdx) => {\n const mergedMs = new Date(pr.mergedAt).getTime();\n const bIdx = nearestBucket(mergedMs);\n // Small deterministic jitter within the bucket to avoid overlap\n const jitter = ((pr.number * 17 + dotIdx * 11) % 13 - 6) * 5;\n const px = PAD.left + xIdx(bIdx) + jitter;\n // Clamp y: PR may be faster or slower than bucket avg; always visible\n const rawPy = PAD.top + yScale(pr.durationHours);\n const py = Math.max(PAD.top + 4, Math.min(PAD.top + cH - 4, rawPy));\n const isHov = pr.number === hoveredPrNumber;\n\n // Thin connector from dot to the bucket trend point\n const trendPt = pts[bIdx];\n\n return (\n <g key={pr.number} style={{ cursor: 'pointer' }}\n onMouseEnter={e => {\n e.stopPropagation();\n const cRect = containerRef.current?.getBoundingClientRect();\n const x = cRect ? e.clientX - cRect.left : 0;\n const y = cRect ? e.clientY - cRect.top : 0;\n setTooltip({ x, y,\n primary: `#${pr.number}: ${pr.title}`,\n secondary: `${formatValue(pr.durationHours)} · ${new Date(pr.mergedAt).toLocaleDateString('en-US', { month: 'short', day: 'numeric' })}` });\n onPrHover?.(pr.number);\n }}\n onMouseLeave={() => { setTooltip(null); onPrHover?.(null); }}>\n {trendPt && (\n <line x1={px} y1={py} x2={trendPt[0]} y2={trendPt[1]}\n stroke={color} strokeWidth={isHov ? 1 : 0.5}\n strokeDasharray=\"2 3\" opacity={isHov ? 0.5 : 0.2} />\n )}\n <circle cx={px} cy={py} r={isHov ? 11 : 7} fill={color} opacity={isHov ? 0.2 : 0.1} />\n <circle cx={px} cy={py} r={isHov ? 5.5 : 3.5}\n fill={isHov ? color : (isDark ? '#1a1a20' : '#fff')}\n stroke={color} strokeWidth={isHov ? 0 : 1.5}\n opacity={isHov ? 1 : 0.8} />\n </g>\n );\n })}\n </g>\n )}\n\n {/* Hover crosshair */}\n {hoverIdx !== null && type === 'line' && pts[hoverIdx] && (\n <>\n <line x1={pts[hoverIdx][0]} y1={PAD.top} x2={pts[hoverIdx][0]} y2={PAD.top+cH}\n stroke={color} strokeWidth={1} strokeDasharray=\"3 3\" opacity={0.3} />\n <line x1={PAD.left} y1={pts[hoverIdx][1]} x2={PAD.left+cW} y2={pts[hoverIdx][1]}\n stroke={color} strokeWidth={1} strokeDasharray=\"3 3\" opacity={0.2} />\n </>\n )}\n\n {/* X-axis labels */}\n {weekLabels.map((lbl, i) => {\n const total = weekLabels.length;\n const step = Math.max(1, Math.floor(total / 5));\n if (i !== 0 && i !== total - 1 && i % step !== 0) return null;\n const x = type === 'bar'\n ? PAD.left + i * (barW + gap) + barW / 2\n : PAD.left + xIdx(i);\n return (\n <text key={i} x={x} y={H - 8} textAnchor=\"middle\" fill={labelColor} fontSize={10} fontFamily={font}>\n {lbl}\n </text>\n );\n })}\n </svg>\n\n {/* Absolute tooltip — positioned relative to the chart container */}\n {tooltip && (() => {\n const TW = 220;\n const cW2 = containerRef.current?.offsetWidth ?? 800;\n const nearRight = tooltip.x + TW + 12 > cW2;\n return (\n <div style={{\n position: 'absolute',\n left: nearRight ? tooltip.x - TW - 8 : tooltip.x + 8,\n top: tooltip.y - 36,\n zIndex: 9999, pointerEvents: 'none',\n background: isDark ? '#18181b' : '#ffffff',\n border: `1px solid ${isDark ? '#3f3f46' : '#e4e4e7'}`,\n borderRadius: 7, padding: '7px 10px',\n boxShadow: isDark ? '0 6px 20px rgba(0,0,0,0.55)' : '0 6px 20px rgba(0,0,0,0.10)',\n width: TW,\n }}>\n <div style={{ fontSize: 12, fontWeight: 600, color: isDark ? '#ededef' : '#111114',\n fontFamily: font, lineHeight: 1.4 }}>\n {tooltip.primary}\n </div>\n {tooltip.secondary && (\n <div style={{ fontSize: 11, color: isDark ? '#71717a' : '#a1a1aa', fontFamily: font, marginTop: 2 }}>\n {tooltip.secondary}\n </div>\n )}\n </div>\n );\n })()}\n </div>\n );\n}\n\n// ─── Detailed overlay ──────────────────────────────────────────────────────\n\ninterface ExpandedCardData {\n title: string;\n metric: DoraMetricValue;\n description: string;\n lowerIsBetter: boolean;\n sparklineValues: number[];\n sparklineType: 'bar' | 'line';\n sparklineColor: string;\n weekLabels: string[];\n bucketMidMs: number[];\n prs?: PrDetail[];\n /** Override the section header above the PR list (default: \"All deployments\"). */\n prListLabel?: string;\n}\n\nfunction DetailedOverlay({\n data,\n days,\n onClose,\n}: {\n data: ExpandedCardData;\n days: number;\n onClose: () => void;\n}) {\n const theme = useTheme();\n const isDark = theme.palette.type === 'dark';\n const [hoveredPrNumber, setHoveredPrNumber] = useState<number | null>(null);\n const prRowRefs = useRef<Map<number, HTMLDivElement>>(new Map());\n\n useEffect(() => {\n const onKey = (e: KeyboardEvent) => { if (e.key === 'Escape') onClose(); };\n window.addEventListener('keydown', onKey);\n return () => window.removeEventListener('keydown', onKey);\n }, [onClose]);\n\n // Auto-scroll to the highlighted PR row when hover comes from the chart\n useEffect(() => {\n if (hoveredPrNumber !== null) {\n const el = prRowRefs.current.get(hoveredPrNumber);\n if (el) el.scrollIntoView({ behavior: 'smooth', block: 'nearest' });\n }\n }, [hoveredPrNumber]);\n\n const { title, metric, description, lowerIsBetter, sparklineValues, sparklineType, sparklineColor, weekLabels, bucketMidMs, prs, prListLabel } = data;\n const isDeployFreq = sparklineType === 'bar';\n const displayValue = metric.unit === 'hours' ? formatDuration(metric.value) : String(metric.value);\n const displayUnit = metric.unit === 'hours' ? '' : metric.unit;\n const formatVal = (v: number) => metric.unit === 'hours' ? formatDuration(v) : `${Math.round(v * 10) / 10}`;\n const borderColor = isDark ? '#27272a' : '#e4e4e7';\n const mutedColor = isDark ? '#52525b' : '#a1a1aa';\n const targetLabel = lowerIsBetter\n ? `Target: < ${metric.unit === 'hours' ? formatDuration(metric.target) : metric.target} ${displayUnit}`\n : `Target: ≥ ${metric.target} ${displayUnit}`;\n\n // Group deployment PRs by date (for the date table)\n const prsByDate = isDeployFreq && prs ? prs.reduce((acc, pr) => {\n const date = new Date(pr.mergedAt).toLocaleDateString('en-US', { weekday: 'short', month: 'short', day: 'numeric' });\n if (!acc[date]) acc[date] = [];\n acc[date].push(pr);\n return acc;\n }, {} as Record<string, PrDetail[]>) : {};\n const sortedDates = Object.keys(prsByDate).sort(\n (a, b) => new Date(prsByDate[b][0].mergedAt).getTime() - new Date(prsByDate[a][0].mergedAt).getTime()\n );\n\n return (\n <>\n {/* Backdrop */}\n <div onClick={onClose} style={{\n position: 'fixed', inset: 0, zIndex: 499,\n background: isDark ? 'rgba(0,0,0,0.6)' : 'rgba(0,0,0,0.3)',\n backdropFilter: 'blur(4px)',\n }} />\n\n {/* Panel */}\n <div style={{\n position: 'fixed',\n top: '50%', left: '50%',\n transform: 'translateX(-50%) translateY(-50%)',\n width: 'min(92vw, 960px)',\n maxHeight: 'calc(100vh - 80px)',\n zIndex: 500,\n background: isDark ? '#09090c' : '#fafafa',\n border: `1px solid ${borderColor}`,\n borderRadius: 14,\n display: 'flex', flexDirection: 'column',\n overflow: 'hidden',\n animation: 'detailExpandIn 0.2s cubic-bezier(0.34,1.2,0.64,1)',\n boxShadow: isDark ? '0 24px 64px rgba(0,0,0,0.7)' : '0 24px 64px rgba(0,0,0,0.18)',\n }}>\n {/* Header */}\n <div style={{\n display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start',\n padding: '20px 24px 16px',\n borderBottom: `1px solid ${borderColor}`,\n flexShrink: 0,\n }}>\n <div>\n <div style={{ fontSize: 10, fontWeight: 700, color: mutedColor, textTransform: 'uppercase', letterSpacing: '0.12em', marginBottom: 8 }}>\n {title} · {weekLabels[0]} – {weekLabels[weekLabels.length - 1]}\n </div>\n <div style={{ display: 'flex', alignItems: 'baseline', gap: 8, flexWrap: 'wrap' }}>\n <span style={{ fontSize: 52, fontWeight: 700, color: theme.palette.text.primary, lineHeight: 1, letterSpacing: '-0.02em' }}>\n {displayValue}\n </span>\n {displayUnit && (\n <span style={{ fontSize: 18, color: mutedColor, fontWeight: 500 }}>{displayUnit}</span>\n )}\n <RatingBadge rating={metric.rating} />\n </div>\n <div style={{ fontSize: 12, color: mutedColor, marginTop: 6 }}>\n {description} · <span style={{ fontStyle: 'italic' }}>{targetLabel}</span>\n </div>\n </div>\n <button type=\"button\" onClick={onClose} style={{\n all: 'unset', cursor: 'pointer', width: 30, height: 30,\n display: 'flex', alignItems: 'center', justifyContent: 'center',\n borderRadius: '50%', background: isDark ? 'rgba(255,255,255,0.06)' : 'rgba(0,0,0,0.06)',\n color: mutedColor, fontSize: 18, fontWeight: 300, transition: 'all 0.12s', flexShrink: 0,\n }}\n onMouseEnter={e => { (e.currentTarget as HTMLElement).style.background = isDark ? 'rgba(255,255,255,0.12)' : 'rgba(0,0,0,0.1)'; }}\n onMouseLeave={e => { (e.currentTarget as HTMLElement).style.background = isDark ? 'rgba(255,255,255,0.06)' : 'rgba(0,0,0,0.06)'; }}>\n ✕\n </button>\n </div>\n\n {/* Body — scrollable */}\n <div style={{ flex: 1, overflow: 'auto', padding: '20px 24px', display: 'flex', flexDirection: 'column', gap: 20 }}>\n\n {/* Chart */}\n {weekLabels.length >= 2 ? (\n <DetailedChart\n values={sparklineValues} weekLabels={weekLabels}\n bucketMidMs={bucketMidMs}\n color={sparklineColor} type={sparklineType}\n formatValue={formatVal} prs={isDeployFreq ? undefined : prs} days={days}\n hoveredPrNumber={hoveredPrNumber} onPrHover={setHoveredPrNumber}\n />\n ) : (\n <div style={{ color: mutedColor, fontSize: 13, textAlign: 'center', padding: '48px 0' }}>\n Not enough data — select a wider date range.\n </div>\n )}\n\n {/* === Deployment Frequency: PRs grouped by date === */}\n {isDeployFreq && prs && prs.length > 0 && (\n <div>\n <div style={{ fontSize: 10, fontWeight: 700, color: mutedColor, textTransform: 'uppercase',\n letterSpacing: '0.12em', marginBottom: 12,\n borderTop: `1px solid ${borderColor}`, paddingTop: 12 }}>\n {prListLabel ?? 'All deployments'} · {prs.length} PR{prs.length !== 1 ? 's' : ''}\n </div>\n <div style={{ display: 'flex', flexDirection: 'column', gap: 16 }}>\n {sortedDates.map(date => (\n <div key={date}>\n {/* Date header */}\n <div style={{\n fontSize: 11, fontWeight: 700, color: sparklineColor,\n marginBottom: 6, display: 'flex', alignItems: 'center', gap: 8,\n }}>\n <span>{date}</span>\n <span style={{ color: mutedColor, fontWeight: 500 }}>· {prsByDate[date].length} PR{prsByDate[date].length > 1 ? 's' : ''}</span>\n </div>\n {/* PR rows */}\n <div style={{ display: 'flex', flexDirection: 'column', gap: 4, paddingLeft: 12,\n borderLeft: `2px solid ${sparklineColor}22` }}>\n {prsByDate[date].map(pr => (\n <div key={pr.number} style={{\n display: 'flex', flexDirection: 'column', gap: 5,\n padding: '7px 10px', borderRadius: 7,\n background: isDark ? '#0d0d10' : '#f7f7f9',\n border: `1px solid ${borderColor}`,\n transition: 'background 0.12s',\n }}>\n {/* Row 1: number + title + lead time + link */}\n <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>\n <span style={{ fontSize: 10, fontWeight: 700, color: mutedColor, flexShrink: 0, minWidth: 36 }}>\n #{pr.number}\n </span>\n <span style={{ fontSize: 12, color: theme.palette.text.primary, flex: 1,\n whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }} title={pr.title}>\n {pr.title}\n </span>\n <span style={{ fontSize: 10, color: mutedColor, flexShrink: 0 }}>\n {formatDuration(pr.durationHours)} lead\n </span>\n <a href={pr.url} target=\"_blank\" rel=\"noopener noreferrer\"\n style={{ color: mutedColor, flexShrink: 0 }}>\n <ExternalLink size={11} />\n </a>\n </div>\n {/* Row 2: author badge */}\n {pr.author && (\n <div style={{ display: 'flex', alignItems: 'center', gap: 5 }}>\n {pr.authorAvatar ? (\n <img src={pr.authorAvatar} alt={pr.author}\n style={{ width: 16, height: 16, borderRadius: '50%', flexShrink: 0,\n border: `1px solid ${isDark ? '#3f3f46' : '#e4e4e7'}` }} />\n ) : (\n <div style={{ width: 16, height: 16, borderRadius: '50%', flexShrink: 0,\n background: isDark ? '#27272a' : '#e4e4e7',\n display: 'flex', alignItems: 'center', justifyContent: 'center',\n fontSize: 8, fontWeight: 700, color: mutedColor }}>\n {pr.author[0].toUpperCase()}\n </div>\n )}\n <a href={`https://github.com/${pr.author}`} target=\"_blank\" rel=\"noopener noreferrer\"\n style={{ fontSize: 10, fontWeight: 500, color: mutedColor,\n textDecoration: 'none', letterSpacing: '0.01em' }}\n onMouseEnter={e => { (e.currentTarget as HTMLElement).style.color = '#FA6400'; }}\n onMouseLeave={e => { (e.currentTarget as HTMLElement).style.color = mutedColor; }}>\n @{pr.author}\n </a>\n </div>\n )}\n </div>\n ))}\n </div>\n </div>\n ))}\n </div>\n </div>\n )}\n\n {/* === Lead Time / MTTR: duration-ranked PR list with hover linking === */}\n {!isDeployFreq && prs && prs.length > 0 && (\n <div>\n <div style={{ fontSize: 10, fontWeight: 700, color: mutedColor, textTransform: 'uppercase',\n letterSpacing: '0.12em', marginBottom: 10,\n borderTop: `1px solid ${borderColor}`, paddingTop: 12 }}>\n {title.toLowerCase().includes('restore') ? 'Slowest Hotfix PRs' : 'Slowest PRs'}\n {' '}· hover a row to highlight on chart\n </div>\n <div style={{ display: 'flex', flexDirection: 'column', gap: 6 }}>\n {prs.map((pr, i) => {\n const col = durationColor(i, prs.length);\n const maxDur = prs[0].durationHours;\n const barPct = maxDur > 0 ? (pr.durationHours / maxDur) * 100 : 0;\n const isHov = pr.number === hoveredPrNumber;\n return (\n <div key={pr.number}\n ref={(el) => {\n if (el) prRowRefs.current.set(pr.number, el);\n else prRowRefs.current.delete(pr.number);\n }}\n onMouseEnter={() => setHoveredPrNumber(pr.number)}\n onMouseLeave={() => setHoveredPrNumber(null)}\n style={{\n padding: '8px 12px', borderRadius: 8,\n background: isHov\n ? (isDark ? '#18181f' : '#f0f0ff')\n : (isDark ? '#111114' : '#f4f4f6'),\n border: `1px solid ${isHov ? sparklineColor + '55' : borderColor}`,\n display: 'flex', flexDirection: 'column', gap: 5,\n transition: 'background 0.12s, border-color 0.12s',\n cursor: 'default',\n }}>\n <div style={{ display: 'flex', alignItems: 'center', gap: 6, minWidth: 0 }}>\n <span style={{ fontSize: 10, fontWeight: 700, color: col, flexShrink: 0 }}>#{pr.number}</span>\n <span style={{ fontSize: 12, color: theme.palette.text.primary, flex: 1,\n whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }} title={pr.title}>\n {pr.title}\n </span>\n <span style={{ fontSize: 10, color: mutedColor, flexShrink: 0 }}>\n {new Date(pr.mergedAt).toLocaleDateString('en-US', { month: 'short', day: 'numeric' })}\n </span>\n <a href={pr.url} target=\"_blank\" rel=\"noopener noreferrer\"\n style={{ color: mutedColor, flexShrink: 0, transition: 'color 0.12s' }}>\n <ExternalLink size={11} />\n </a>\n </div>\n <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>\n <AnimatedBar widthPct={barPct} color={col} />\n <span style={{ fontSize: 11, fontWeight: 700, color: col, minWidth: 52, textAlign: 'right', flexShrink: 0 }}>\n {formatDuration(pr.durationHours)}\n </span>\n </div>\n </div>\n );\n })}\n </div>\n </div>\n )}\n </div>\n </div>\n <style>{`\n @keyframes detailExpandIn {\n from { opacity: 0; transform: translateX(-50%) translateY(-46%); }\n to { opacity: 1; transform: translateX(-50%) translateY(-50%); }\n }\n `}</style>\n </>\n );\n}\n\n// ─── Animated bar ──────────────────────────────────────────────────────────\n\nfunction AnimatedBar({ widthPct, color }: { widthPct: number; color: string }) {\n const [width, setWidth] = useState(0);\n const ref = useRef<HTMLDivElement>(null);\n const theme = useTheme();\n const isDark = theme.palette.type === 'dark';\n\n useEffect(() => {\n const timer = setTimeout(() => setWidth(widthPct), 80);\n return () => clearTimeout(timer);\n }, [widthPct]);\n\n return (\n <div\n ref={ref}\n style={{\n background: isDark ? '#1a1a1e' : '#f0f0f2',\n borderRadius: 4,\n height: 5,\n overflow: 'hidden',\n flex: 1,\n minWidth: 40,\n }}\n >\n <div\n style={{\n height: '100%',\n width: `${width}%`,\n background: color,\n borderRadius: 4,\n transition: 'width 0.55s cubic-bezier(0.4, 0, 0.2, 1)',\n boxShadow: `0 0 6px ${color}88`,\n }}\n />\n </div>\n );\n}\n\n// ─── Metric cards ──────────────────────────────────────────────────────────\n\nfunction MetricCard({\n title,\n metric,\n description,\n lowerIsBetter = false,\n sparklineData,\n sparklineType = 'line',\n sparklineColor,\n weekLabels,\n onExpand,\n expandLabel,\n}: {\n title: string;\n metric: DoraMetricValue;\n description: string;\n lowerIsBetter?: boolean;\n sparklineData?: number[];\n sparklineType?: 'bar' | 'line';\n sparklineColor?: string;\n weekLabels?: string[];\n onExpand?: () => void;\n /** Persistent label shown in the card footer (instead of the hover-only \"expand ↗\"). */\n expandLabel?: string;\n}) {\n const theme = useTheme();\n const isDark = theme.palette.type === 'dark';\n const [hovered, setHovered] = useState(false);\n\n const displayValue = metric.unit === 'hours' ? formatDuration(metric.value) : metric.value;\n const displayUnit = metric.unit === 'hours' ? '' : metric.unit;\n const targetValue = metric.unit === 'hours' ? formatDuration(metric.target) : metric.target;\n const targetLabel = lowerIsBetter\n ? `Target: < ${targetValue} ${displayUnit}`.trim()\n : `Target: ≥ ${targetValue} ${displayUnit}`.trim();\n\n const hasSparkline = sparklineData && sparklineData.length >= 2 && weekLabels && weekLabels.length >= 2;\n const delta = hasSparkline ? buildDeltaLabel(sparklineData!, metric.unit, lowerIsBetter) : null;\n const formatVal = (v: number) => metric.unit === 'hours' ? formatDuration(v) : `${Math.round(v * 10) / 10}`;\n\n return (\n <Card\n style={{ cursor: onExpand ? 'pointer' : undefined }}\n onClick={onExpand}\n onMouseEnter={() => setHovered(true)}\n onMouseLeave={() => setHovered(false)}\n >\n <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start', gap: 8 }}>\n <CardLabel>{title}</CardLabel>\n {onExpand && (\n <span style={{\n fontSize: 9, fontWeight: 600, color: isDark ? '#3f3f46' : '#d4d4d8',\n opacity: hovered ? 1 : 0, transition: 'opacity 0.15s',\n letterSpacing: '0.05em', textTransform: 'uppercase', flexShrink: 0,\n }}>\n expand ↗\n </span>\n )}\n </div>\n {/* Right-aligned column: delta trend + direction hint stacked */}\n <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'flex-end', gap: 4 }}>\n {delta && (\n <span title={delta.tooltip} style={{\n fontSize: 10, fontWeight: 600, cursor: 'help',\n color: delta.good ? '#4ade80' : '#f87171',\n background: delta.good\n ? (isDark ? 'rgba(74,222,128,0.08)' : 'rgba(74,222,128,0.12)')\n : (isDark ? 'rgba(248,113,113,0.08)' : 'rgba(248,113,113,0.12)'),\n padding: '2px 8px', borderRadius: 4, whiteSpace: 'nowrap',\n }}>\n {delta.text}\n </span>\n )}\n <span style={{\n fontSize: 10, fontWeight: 600,\n color: isDark ? '#3f3f46' : '#d4d4d8',\n whiteSpace: 'nowrap',\n }}>\n {lowerIsBetter ? '↓ lower = better' : '↑ higher = better'}\n </span>\n </div>\n {/* Value row: big number + unit */}\n <div style={{ display: 'flex', alignItems: 'baseline', gap: 6 }}>\n <span style={{ fontSize: 36, fontWeight: 700, color: isDark ? '#f4f4f5' : '#111114', lineHeight: 1 }}>\n {displayValue}\n </span>\n {displayUnit && (\n <span style={{ fontSize: 14, color: isDark ? '#71717a' : '#71717a', fontWeight: 500 }}>\n {displayUnit}\n </span>\n )}\n </div>\n <RatingBadge rating={metric.rating} />\n {hasSparkline && (\n <div style={{ marginTop: 2 }}>\n <CompactSparkline\n values={sparklineData!}\n weekLabels={weekLabels!}\n color={sparklineColor ?? '#FA6400'}\n type={sparklineType}\n formatValue={formatVal}\n />\n </div>\n )}\n <CardDescription>{description}</CardDescription>\n <CardFooter>\n <span style={{ fontWeight: 600, color: isDark ? '#a1a1aa' : '#52525b' }}>\n {targetLabel}\n </span>\n {expandLabel && onExpand && (\n <span style={{\n fontSize: 10, fontWeight: 700,\n color: '#FA6400',\n letterSpacing: '0.04em',\n marginLeft: 'auto',\n }}>\n {expandLabel}\n </span>\n )}\n </CardFooter>\n </Card>\n );\n}\n\nfunction NaCard({ title, description }: { title: string; description: string }) {\n return (\n <Card>\n <CardLabel>{title}</CardLabel>\n <div style={{ display: 'flex', alignItems: 'baseline', gap: 6 }}>\n <span style={{ fontSize: 36, fontWeight: 700, color: '#52525b', lineHeight: 1 }}>N/A</span>\n </div>\n <CardDescription muted>{description}</CardDescription>\n </Card>\n );\n}\n\n// ─── Filter label ──────────────────────────────────────────────────────────\n\nfunction FilterLabel({ children }: { children: React.ReactNode }) {\n const theme = useTheme();\n return (\n <div style={{ fontSize: 11, fontWeight: 600, color: theme.palette.text.primary, marginBottom: 4, textTransform: 'uppercase', letterSpacing: '0.06em' }}>\n {children}\n </div>\n );\n}\n\n// ─── Main component ────────────────────────────────────────────────────────\n\nexport function DoraMetricsContent() {\n const { entity } = useEntity();\n const doraApi = useApi(doraMetricsApiRef);\n const muiTheme = useTheme();\n const textPrimary = muiTheme.palette.text.primary;\n const textSecondary = muiTheme.palette.text.secondary;\n\n const projectSlug = entity.metadata.annotations?.[ANNOTATION_PROJECT_SLUG] ?? '';\n const annotations = entity.metadata.annotations ?? {};\n\n // Per-repo overrides from catalog-info.yaml annotations\n const annotationEnvs = parseAnnotationJson<DoraEnvironment[]>(annotations[ANNOTATION_ENVIRONMENTS]);\n const annotationTargets = parseAnnotationJson<Partial<DoraTargets>>(annotations[ANNOTATION_TARGETS]);\n\n const environments: DoraEnvironment[] = annotationEnvs ?? doraApi.getEnvironments();\n const defaultEnv = environments[0];\n const defaultDays = doraApi.getDefaultDays();\n\n // Use environment name as the selection key (branch can be a multi-value pattern)\n const [selectedEnvName, setSelectedEnvName] = useState<string>(defaultEnv?.name ?? '');\n const [selectedDays, setSelectedDays] = useState<string>(String(defaultDays));\n\n const selectedEnv = environments.find(e => e.name === selectedEnvName) ?? defaultEnv;\n const days = parseInt(selectedDays, 10);\n\n const [metrics, setMetrics] = useState<DoraMetrics | null>(null);\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<Error | null>(null);\n\n const [history, setHistory] = useState<DoraHistoryPoint[] | null>(null);\n const [expanded, setExpanded] = useState<ExpandedCardData | null>(null);\n\n useEffect(() => {\n if (!projectSlug) {\n setError(new Error(`Entity is missing the \"${ANNOTATION_PROJECT_SLUG}\" annotation.`));\n setLoading(false);\n return;\n }\n if (!selectedEnv) {\n setError(new Error('No environments configured for DORA metrics.'));\n setLoading(false);\n return;\n }\n\n let cancelled = false;\n setLoading(true);\n setError(null);\n setHistory(null);\n\n doraApi\n .getMetrics(projectSlug, selectedEnv, days, annotationTargets ?? undefined)\n .then(data => {\n if (!cancelled) { setMetrics(data); setLoading(false); }\n })\n .catch((err: Error) => {\n if (!cancelled) { setError(err); setLoading(false); }\n });\n\n doraApi\n .getHistory(projectSlug, selectedEnv, days)\n .then(data => { if (!cancelled) setHistory(data); })\n .catch(() => { /* history is optional — fail silently */ });\n\n return () => { cancelled = true; };\n }, [doraApi, projectSlug, selectedEnv?.name, days]);\n\n if (loading) return <DoraLoadingOverlay />;\n\n if (error) {\n return (\n <InfoCard title=\"DORA Metrics\">\n <div style={{ padding: 24, color: '#f87171' }}>\n <span style={{ fontWeight: 600 }}>Error: </span>{error.message}\n </div>\n </InfoCard>\n );\n }\n\n if (!metrics) return null;\n\n return (\n <InfoCard title=\" \">\n <div style={{ padding: '4px 0', position: 'relative' }}>\n {/* Detailed overlay */}\n {expanded && (\n <DetailedOverlay data={expanded} days={days} onClose={() => setExpanded(null)} />\n )}\n\n {/* Title */}\n <div style={{ marginBottom: 16 }}>\n <div style={{ fontSize: 22, fontWeight: 700, color: textPrimary, letterSpacing: '-0.02em' }}>DORA Metrics</div>\n {selectedEnv && (\n <div style={{ fontSize: 12, color: textSecondary, marginTop: 5 }}>\n Showing metrics for{' '}\n <strong style={{ color: textPrimary }}>{selectedEnv.name}</strong>\n {' '}—{' '}\n <span style={{ fontFamily: 'monospace' }}>{selectedEnv.branch}</span>\n </div>\n )}\n </div>\n\n {/* Filters row — left aligned */}\n <div style={{ display: 'flex', alignItems: 'flex-end', gap: 16, flexWrap: 'wrap', marginBottom: 20 }}>\n {environments.length > 1 && (\n <div>\n <FilterLabel>Environment</FilterLabel>\n <Select value={selectedEnvName} onValueChange={setSelectedEnvName}>\n <SelectTrigger><SelectValue placeholder=\"Select environment\" /></SelectTrigger>\n <SelectContent>\n {environments.map(env => (\n <SelectItem key={env.name} value={env.name}>\n {env.name} ({env.branch})\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n )}\n\n <div>\n <FilterLabel>Date Range</FilterLabel>\n <Select value={selectedDays} onValueChange={setSelectedDays}>\n <SelectTrigger><SelectValue placeholder=\"Select date range\" /></SelectTrigger>\n <SelectContent>\n {DATE_RANGE_OPTIONS.map(opt => (\n <SelectItem key={opt.value} value={opt.value}>{opt.label}</SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n </div>\n\n {/* Metric cards — sparklines inline, click to expand */}\n {(() => {\n const wkLabels = history?.map(h => h.weekLabel) ?? [];\n const deployData = history?.map(h => h.deploymentCount) ?? [];\n const leadData = history?.map(h => h.leadTimeHours) ?? [];\n const cfrData = history?.map(h => h.changeFailureRate ?? 0) ?? [];\n const mttrData = history?.map(h => h.mttrHours ?? 0) ?? [];\n\n const bmMs = history?.map(h => h.bucketMidMs) ?? [];\n\n const mkExpand = (\n title: string, metric: DoraMetricValue, description: string,\n lowerIsBetter: boolean, sparklineValues: number[],\n sparklineType: 'bar' | 'line', sparklineColor: string, prs?: PrDetail[],\n prListLabel?: string,\n ) => () => setExpanded({\n title, metric, description, lowerIsBetter,\n sparklineValues, sparklineType, sparklineColor,\n weekLabels: wkLabels, bucketMidMs: bmMs, prs, prListLabel,\n });\n\n return (\n <div style={{ display: 'flex', flexWrap: 'wrap', gap: 12 }}>\n <MetricCard\n title=\"Deployment Frequency\"\n metric={metrics.deploymentFrequency}\n description=\"How often code is deployed to this branch\"\n sparklineData={deployData}\n sparklineType=\"bar\"\n sparklineColor=\"#FA6400\"\n weekLabels={wkLabels}\n onExpand={mkExpand('Deployment Frequency', metrics.deploymentFrequency,\n 'How often code is deployed to this branch', false, deployData, 'bar', '#FA6400',\n metrics.deploymentFrequency.slowestPRs)}\n />\n <MetricCard\n title=\"Lead Time for Changes\"\n metric={metrics.leadTime}\n description=\"Average time from PR creation to merge\"\n lowerIsBetter\n sparklineData={leadData}\n sparklineType=\"line\"\n sparklineColor=\"#818cf8\"\n weekLabels={wkLabels}\n onExpand={mkExpand('Lead Time for Changes', metrics.leadTime,\n 'Average time from PR creation to merge', true, leadData, 'line', '#818cf8', metrics.leadTime.slowestPRs)}\n />\n {metrics.changeFailureRate !== null ? (\n <MetricCard\n title=\"Change Failure Rate\"\n metric={metrics.changeFailureRate}\n description=\"% of all merged PRs that were hotfixes\"\n lowerIsBetter\n sparklineData={cfrData}\n sparklineType=\"line\"\n sparklineColor=\"#f87171\"\n weekLabels={wkLabels}\n onExpand={mkExpand('Change Failure Rate', metrics.changeFailureRate,\n '% of all merged PRs that were hotfixes', true, cfrData, 'line', '#f87171')}\n />\n ) : (\n <NaCard title=\"Change Failure Rate\" description=\"Only tracked on production branches\" />\n )}\n {metrics.mttr !== null ? (\n <MetricCard\n title=\"Mean Time to Restore\"\n metric={metrics.mttr}\n description=\"Avg time from hotfix PR open to merge\"\n lowerIsBetter\n sparklineData={mttrData}\n sparklineType=\"line\"\n sparklineColor=\"#fbbf24\"\n weekLabels={wkLabels}\n onExpand={mkExpand('Mean Time to Restore', metrics.mttr,\n 'Avg time from hotfix PR open to merge', true, mttrData, 'line', '#fbbf24', metrics.mttr.slowestPRs)}\n />\n ) : (\n <NaCard title=\"Mean Time to Restore\" description=\"Only tracked on production branches\" />\n )}\n {metrics.numberOfHotfixes !== null ? (\n <MetricCard\n title=\"Hotfixes to Production\"\n metric={metrics.numberOfHotfixes}\n description={`PRs labeled '${selectedEnv?.label ?? 'hotfix'}' merged to production`}\n lowerIsBetter\n expandLabel={metrics.numberOfHotfixes.value > 0 ? `View ${metrics.numberOfHotfixes.value} PR${metrics.numberOfHotfixes.value !== 1 ? 's' : ''} →` : undefined}\n onExpand={mkExpand(\n 'Hotfixes to Production',\n metrics.numberOfHotfixes,\n `PRs labeled '${selectedEnv?.label ?? 'hotfix'}' merged to production`,\n true,\n [],\n 'bar',\n '#f87171',\n metrics.numberOfHotfixes.slowestPRs,\n 'All hotfixes',\n )}\n />\n ) : (\n <NaCard title=\"Hotfixes to Production\" description=\"Only tracked on production branches\" />\n )}\n </div>\n );\n })()}\n\n </div>\n </InfoCard>\n );\n}\n"],"names":["max"],"mappings":"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"}
1
+ {"version":3,"file":"DoraMetricsContent.esm.js","sources":["../../src/components/DoraMetricsContent.tsx"],"sourcesContent":["import React, { useEffect, useRef, useState } from 'react';\nimport { useTheme } from '@material-ui/core/styles';\nimport { useApi } from '@backstage/core-plugin-api';\nimport { useEntity } from '@backstage/plugin-catalog-react';\nimport { InfoCard } from '@backstage/core-components';\nimport { doraMetricsApiRef } from '../api/types';\nimport type { DoraEnvironment, DoraHistoryPoint, DoraMetrics, DoraMetricValue, DoraTargets, PrDetail } from '../api/types';\nimport { RatingBadge } from './ui/badge';\nimport { Card, CardLabel, CardFooter, CardDescription } from './ui/card';\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from './ui/select';\nimport { ExternalLink } from 'lucide-react';\n\nconst ANNOTATION_PROJECT_SLUG = 'github.com/project-slug';\n/** Override the global environments list for this specific entity. JSON array of DoraEnvironment objects. */\nconst ANNOTATION_ENVIRONMENTS = 'dora-metrics/environments';\n/** Override the global performance targets for this specific entity. JSON object matching DoraTargets. */\nconst ANNOTATION_TARGETS = 'dora-metrics/targets';\n\n/** Parse entity annotation overrides. Returns undefined for malformed JSON to fail gracefully. */\nfunction parseAnnotationJson<T>(raw: string | undefined): T | undefined {\n if (!raw) return undefined;\n try { return JSON.parse(raw) as T; } catch { return undefined; }\n}\n\nconst DATE_RANGE_OPTIONS = [\n { value: '7', label: 'Last 7 days' },\n { value: '14', label: 'Last 14 days' },\n { value: '30', label: 'Last 30 days' },\n { value: '60', label: 'Last 60 days' },\n { value: '90', label: 'Last 90 days' },\n];\n\n// ─── Helpers ───────────────────────────────────────────────────────────────\n\nfunction formatDuration(hours: number): string {\n const totalMinutes = Math.round(hours * 60);\n const d = Math.floor(totalMinutes / (24 * 60));\n const h = Math.floor((totalMinutes % (24 * 60)) / 60);\n const m = totalMinutes % 60;\n if (d > 0) return h > 0 ? `${d}d ${h}h` : `${d}d`;\n if (h > 0) return m > 0 ? `${h}h ${m}m` : `${h}h`;\n return `${m}m`;\n}\n\n// Red → Orange → Yellow → Lime → Green gradient (slowest to fastest)\nconst DURATION_GRADIENT = ['#f87171', '#fb923c', '#fbbf24', '#a3e635', '#4ade80'];\n\nfunction durationColor(index: number, total: number): string {\n if (total <= 1) return DURATION_GRADIENT[0];\n const step = (DURATION_GRADIENT.length - 1) / (total - 1);\n return DURATION_GRADIENT[Math.round(index * step)];\n}\n\n// ─── Helpers ───────────────────────────────────────────────────────────────\n\n// Period-over-period delta — compares last bucket vs second-to-last bucket\nfunction buildDeltaLabel(\n values: number[],\n unit: string,\n lowerIsBetter: boolean,\n): { text: string; tooltip: string; good: boolean } | null {\n if (values.length < 2) return null;\n const curr = values[values.length - 1];\n const prev = values[values.length - 2];\n const diff = curr - prev;\n if (Math.abs(diff) < 0.001) return null;\n const good = lowerIsBetter ? diff < 0 : diff > 0;\n const arrow = diff > 0 ? '↑' : '↓';\n\n const fmt = (v: number) =>\n unit === 'hours' ? formatDuration(v) :\n unit === '%' ? `${Math.round(v * 10) / 10}%` :\n unit === 'per week' ? `${Math.round(v * 10) / 10}/wk` :\n `${Math.round(v * 10) / 10} ${unit}`;\n\n const direction = good ? 'improving' : 'worsening';\n return {\n text: `${arrow} ${fmt(Math.abs(diff))} ${direction}`,\n tooltip: `Latest period: ${fmt(curr)} · Previous period: ${fmt(prev)}\\nEach period = one time bucket (~1/7th of your selected date range)`,\n good,\n };\n}\n\n// ─── Loading overlay ────────────────────────────────────────────────────────\n\nconst LOADING_MESSAGES = [\n 'Establishing routes…',\n 'Syncing catalog…',\n 'Loading plugins…',\n 'Fetching PR data…',\n 'Reading entity graph…',\n];\nconst STAGES = ['FETCH', 'PARSE', 'SCORE', 'RENDER'] as const;\nconst FONT_IMPACT = '\"Impact\",\"Haettenschweiler\",\"Franklin Gothic Heavy\",\"Arial Black\",sans-serif';\nconst FONT_MONO = '\"JetBrains Mono\",\"Fira Code\",\"Consolas\",monospace';\n\nfunction DoraLoadingOverlay() {\n const theme = useTheme();\n const isDark = theme.palette.type === 'dark';\n\n const [activeStage, setActiveStage] = useState(0);\n const [msgKey, setMsgKey] = useState(0);\n const [msgIdx, setMsgIdx] = useState(0);\n\n useEffect(() => {\n const st = setInterval(() => setActiveStage(s => (s + 1) % STAGES.length), 800);\n return () => clearInterval(st);\n }, []);\n\n useEffect(() => {\n const mt = setInterval(() => { setMsgIdx(i => (i + 1) % LOADING_MESSAGES.length); setMsgKey(k => k + 1); }, 2200);\n return () => clearInterval(mt);\n }, []);\n\n const textShadow = isDark\n ? '3px 3px 0 #C24E00, 6px 6px 0 #902800, 9px 9px 0 #5A1800, 12px 12px 0 rgba(0,0,0,0.55), 0 0 60px rgba(250,100,0,0.45)'\n : '3px 3px 0 #C24E00, 6px 6px 0 #902800, 9px 9px 0 rgba(80,20,0,0.28), 0 0 32px rgba(250,100,0,0.22)';\n\n const mutedColor = isDark ? '#3f3f46' : '#a1a1aa';\n const subtitleColor = isDark ? '#52525b' : '#71717a';\n const borderColor = isDark ? 'rgba(255,255,255,0.07)' : 'rgba(0,0,0,0.08)';\n\n return (\n <>\n {/* Frosted glass backdrop — blurs whatever is behind */}\n <div aria-hidden style={{\n position: 'fixed', inset: 0, zIndex: 900,\n backdropFilter: 'blur(12px)',\n WebkitBackdropFilter: 'blur(12px)',\n background: isDark ? 'rgba(6,6,9,0.65)' : 'rgba(253,252,251,0.70)',\n }} />\n\n {/* Centered card */}\n <div style={{\n position: 'fixed', zIndex: 901,\n top: '50%', left: '50%',\n transform: 'translateX(-50%) translateY(-50%)',\n display: 'flex', flexDirection: 'column', alignItems: 'center',\n padding: '48px 56px 40px',\n borderRadius: 20,\n background: isDark ? 'rgba(9,9,12,0.82)' : 'rgba(255,255,255,0.88)',\n border: `1px solid ${borderColor}`,\n boxShadow: isDark\n ? '0 0 0 1px rgba(250,100,0,0.06), 0 32px 80px rgba(0,0,0,0.65)'\n : '0 32px 80px rgba(0,0,0,0.12)',\n backdropFilter: 'blur(20px)',\n WebkitBackdropFilter: 'blur(20px)',\n animation: 'dlsCardIn 0.35s cubic-bezier(0.34,1.2,0.64,1) both',\n overflow: 'visible',\n }}>\n\n {/* Breathing ambient glow — inside card */}\n <div aria-hidden style={{\n position: 'absolute', width: 500, height: 360,\n left: '50%', top: '50%',\n transform: 'translateX(-50%) translateY(-50%)',\n background: `radial-gradient(ellipse at center, ${isDark ? 'rgba(250,100,0,0.08)' : 'rgba(250,100,0,0.05)'} 0%, transparent 70%)`,\n animation: 'dlsBreath 3.2s ease-in-out infinite',\n pointerEvents: 'none', borderRadius: 20,\n }} />\n\n {/* DORA wordmark */}\n <div style={{ display: 'flex', lineHeight: 1, marginBottom: 6 }}>\n {['D','O','R','A'].map((letter, i) => (\n <span key={i} style={{\n fontFamily: FONT_IMPACT, fontWeight: 900, fontSize: 110,\n color: '#FA6400', letterSpacing: '0.04em', display: 'inline-block',\n transform: 'skewX(-6deg)', textShadow,\n WebkitTextStroke: '0.5px #C24E00',\n animation: `dlsLetterDrop 0.6s cubic-bezier(0.34,1.45,0.64,1) ${i * 0.1}s both`,\n }}>\n {letter}\n </span>\n ))}\n </div>\n\n {/* Subtitle */}\n <span style={{ fontFamily: 'Inter,system-ui,sans-serif', fontSize: 13, fontWeight: 400,\n letterSpacing: '0.06em', color: subtitleColor, marginBottom: 32,\n animation: 'dlsFadeUp 0.4s ease 0.55s both' }}>\n Metrics\n </span>\n\n {/* Pipeline stages */}\n <div style={{ display: 'flex', alignItems: 'center', gap: 0, marginBottom: 20, animation: 'dlsFadeUp 0.4s ease 0.7s both' }}>\n {STAGES.map((stage, i) => {\n const isActive = i === activeStage;\n const isComplete = i < activeStage;\n return (\n <div key={stage} style={{ display: 'flex', alignItems: 'center', gap: 0 }}>\n <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 5, width: 64 }}>\n <div style={{ position: 'relative', width: 12, height: 12 }}>\n {isActive && (\n <div style={{ position: 'absolute', inset: -6, borderRadius: '50%',\n border: '1.5px solid rgba(250,100,0,0.5)', animation: 'dlsPulse 1s ease-out infinite' }} />\n )}\n <div style={{\n width: 12, height: 12, borderRadius: '50%',\n background: (isActive || isComplete) ? '#FA6400' : (isDark ? '#27272a' : '#e4e4e7'),\n border: `2px solid ${(isActive || isComplete) ? '#C24E00' : (isDark ? '#3f3f46' : '#d4d4d8')}`,\n boxShadow: isActive ? '0 0 14px rgba(250,100,0,0.7)' : 'none',\n transition: 'background 0.3s, box-shadow 0.3s',\n }} />\n </div>\n <span style={{ fontFamily: 'Inter,system-ui,sans-serif', fontSize: 8, fontWeight: 700,\n letterSpacing: '0.12em', textTransform: 'uppercase',\n color: isActive ? '#FA6400' : isComplete ? mutedColor : mutedColor,\n transition: 'color 0.3s' }}>\n {stage}\n </span>\n </div>\n {i < STAGES.length - 1 && (\n <div style={{ width: 32, height: 2, marginBottom: 14, position: 'relative', overflow: 'hidden',\n background: isDark ? '#27272a' : '#e4e4e7', borderRadius: 2 }}>\n <div style={{\n position: 'absolute', inset: 0, borderRadius: 2, background: '#FA6400',\n transformOrigin: 'left center',\n transform: `scaleX(${i < activeStage ? 1 : isActive ? 0.5 : 0})`,\n transition: 'transform 0.4s ease',\n }} />\n </div>\n )}\n </div>\n );\n })}\n </div>\n\n {/* Status message */}\n <span key={msgKey} style={{ fontFamily: FONT_MONO, fontSize: 11,\n color: mutedColor, letterSpacing: '0.04em', animation: 'dlsFadeUp 0.3s ease both' }}>\n {LOADING_MESSAGES[msgIdx]}\n </span>\n\n </div>{/* end card */}\n\n <style>{`\n @keyframes dlsLetterDrop {\n from { opacity: 0; transform: skewX(-6deg) translateY(-32px) scale(1.1); }\n 65% { transform: skewX(-6deg) translateY(6px) scale(0.95); }\n to { opacity: 1; transform: skewX(-6deg) translateY(0) scale(1); }\n }\n @keyframes dlsFadeUp {\n from { opacity: 0; transform: translateY(10px); }\n to { opacity: 1; transform: translateY(0); }\n }\n @keyframes dlsBreath {\n 0%, 100% { transform: translateX(-50%) translateY(-50%) scale(0.85); opacity: 0.6; }\n 50% { transform: translateX(-50%) translateY(-50%) scale(1.2); opacity: 1; }\n }\n @keyframes dlsPulse {\n from { transform: scale(0.6); opacity: 0.9; }\n to { transform: scale(2.2); opacity: 0; }\n }\n @keyframes dlsCardIn {\n from { opacity: 0; transform: translateX(-50%) translateY(-46%); }\n to { opacity: 1; transform: translateX(-50%) translateY(-50%); }\n }\n `}</style>\n </>\n );\n}\n\n// ─── Compact sparkline (with hover tooltip + date axis) ────────────────────\n\nfunction CompactSparkline({\n values,\n weekLabels,\n color,\n type,\n formatValue,\n height = 36,\n}: {\n values: number[];\n weekLabels: string[];\n color: string;\n type: 'bar' | 'line';\n formatValue: (v: number) => string;\n height?: number;\n}) {\n const theme = useTheme();\n const isDark = theme.palette.type === 'dark';\n const [hoverIdx, setHoverIdx] = useState<number | null>(null);\n\n const VW = 400; // viewBox units\n const mutedBorder = isDark ? 'rgba(255,255,255,0.06)' : 'rgba(0,0,0,0.06)';\n const tooltipBg = isDark ? '#1c1c20' : '#ffffff';\n const tooltipBdr = isDark ? '#3f3f46' : '#e4e4e7';\n const tooltipText = isDark ? '#ededef' : '#111114';\n const font = 'Inter,system-ui,sans-serif';\n\n const handleMouseMove = (e: React.MouseEvent<SVGSVGElement>) => {\n const rect = e.currentTarget.getBoundingClientRect();\n const relX = (e.clientX - rect.left) / rect.width;\n setHoverIdx(Math.max(0, Math.min(values.length - 1, Math.round(relX * (values.length - 1)))));\n };\n\n if (type === 'bar') {\n const max = Math.max(...values, 1);\n const gap = 4;\n const barW = (VW - gap * (values.length - 1)) / values.length;\n\n const hoverX = hoverIdx !== null\n ? hoverIdx * (barW + gap) + barW / 2\n : null;\n const tooltipX = hoverX !== null ? Math.min(hoverX - 34, VW - 72) : 0;\n\n return (\n <div>\n <svg viewBox={`0 0 ${VW} ${height}`} width=\"100%\" style={{ display: 'block', overflow: 'visible' }}\n onMouseMove={handleMouseMove} onMouseLeave={() => setHoverIdx(null)}>\n {values.map((v, i) => {\n const h = Math.max(2, (v / max) * (height - 4));\n return (\n <rect key={i} x={i * (barW + gap)} y={height - h} width={barW} height={h} rx={1.5}\n fill={color} opacity={i === hoverIdx ? 1 : 0.3 + (i / values.length) * 0.55} />\n );\n })}\n <line x1={0} y1={height - 0.5} x2={VW} y2={height - 0.5} stroke={mutedBorder} strokeWidth={1} />\n {hoverIdx !== null && hoverX !== null && (\n <>\n <rect x={tooltipX} y={2} width={72} height={22} rx={4} fill={tooltipBg} stroke={tooltipBdr} strokeWidth={1} />\n <text x={tooltipX + 36} y={17} textAnchor=\"middle\" fill={tooltipText} fontSize={9} fontWeight={600} fontFamily={font}>\n {weekLabels[hoverIdx]}: {formatValue(values[hoverIdx])}\n </text>\n </>\n )}\n </svg>\n <div style={{ display: 'flex', justifyContent: 'space-between', marginTop: 3 }}>\n <span style={{ fontSize: 9, color: isDark ? '#3f3f46' : '#a1a1aa' }}>{weekLabels[0]}</span>\n <span style={{ fontSize: 9, color: isDark ? '#3f3f46' : '#a1a1aa' }}>{weekLabels[weekLabels.length - 1]}</span>\n </div>\n </div>\n );\n }\n\n if (values.length < 2) return null;\n const max = Math.max(...values, 0.01);\n const min = Math.min(...values);\n const range = max - min || max || 1;\n const pad = 3;\n const pts = values.map((v, i): [number, number] => [\n (i / (values.length - 1)) * (VW - pad * 2) + pad,\n (height - pad * 2) - ((v - min) / range) * (height - pad * 2 - 2) + pad,\n ]);\n const d = pts.map(([x, y], i) => `${i === 0 ? 'M' : 'L'}${x.toFixed(1)},${y.toFixed(1)}`).join(' ');\n const area = `${d} L${pts[pts.length-1][0]},${height} L${pts[0][0]},${height} Z`;\n const hoverPt = hoverIdx !== null ? pts[hoverIdx] : null;\n const tooltipX2 = hoverPt ? Math.min(hoverPt[0] - 34, VW - 72) : 0;\n\n return (\n <div>\n <svg viewBox={`0 0 ${VW} ${height}`} width=\"100%\" style={{ display: 'block', overflow: 'visible' }}\n onMouseMove={handleMouseMove} onMouseLeave={() => setHoverIdx(null)}>\n <path d={area} fill={color} opacity={0.07} />\n <path d={d} fill=\"none\" stroke={color} strokeWidth={1.5} strokeLinejoin=\"round\" strokeLinecap=\"round\" />\n {pts.map(([x, y], i) => (\n <circle key={i} cx={x} cy={y} r={i === hoverIdx ? 3.5 : i === pts.length - 1 ? 2.5 : 0} fill={color} />\n ))}\n <line x1={0} y1={height - 0.5} x2={VW} y2={height - 0.5} stroke={mutedBorder} strokeWidth={1} />\n {hoverPt && hoverIdx !== null && (\n <>\n <line x1={hoverPt[0]} y1={0} x2={hoverPt[0]} y2={height} stroke={color} strokeWidth={1} strokeDasharray=\"2 2\" opacity={0.4} />\n <rect x={tooltipX2} y={2} width={72} height={22} rx={4} fill={tooltipBg} stroke={tooltipBdr} strokeWidth={1} />\n <text x={tooltipX2 + 36} y={17} textAnchor=\"middle\" fill={tooltipText} fontSize={9} fontWeight={600} fontFamily={font}>\n {weekLabels[hoverIdx]}: {formatValue(values[hoverIdx])}\n </text>\n </>\n )}\n </svg>\n <div style={{ display: 'flex', justifyContent: 'space-between', marginTop: 3 }}>\n <span style={{ fontSize: 9, color: isDark ? '#3f3f46' : '#a1a1aa' }}>{weekLabels[0]}</span>\n <span style={{ fontSize: 9, color: isDark ? '#3f3f46' : '#a1a1aa' }}>{weekLabels[weekLabels.length - 1]}</span>\n </div>\n </div>\n );\n}\n\n// ─── Detailed interactive chart ────────────────────────────────────────────\n\ninterface ChartTooltipState {\n x: number;\n y: number;\n primary: string;\n secondary?: string;\n}\n\nfunction DetailedChart({\n values,\n weekLabels,\n bucketMidMs,\n color,\n type,\n formatValue,\n prs,\n days,\n hoveredPrNumber,\n onPrHover,\n}: {\n values: number[];\n weekLabels: string[];\n bucketMidMs: number[];\n color: string;\n type: 'bar' | 'line';\n formatValue: (v: number) => string;\n prs?: PrDetail[];\n days: number;\n hoveredPrNumber?: number | null;\n onPrHover?: (num: number | null) => void;\n}) {\n const theme = useTheme();\n const isDark = theme.palette.type === 'dark';\n const [hoverIdx, setHoverIdx] = useState<number | null>(null);\n const [tooltip, setTooltip] = useState<ChartTooltipState | null>(null);\n const containerRef = useRef<HTMLDivElement>(null);\n\n const W = 800, H = 260;\n const PAD = { top: 16, right: 16, bottom: 36, left: 56 };\n const cW = W - PAD.left - PAD.right;\n const cH = H - PAD.top - PAD.bottom;\n\n // Y scale: based on bucket values only so the trend line is clearly readable.\n // PR dots that fall outside this range are rendered clamped to chart area.\n const dataMax = Math.max(...values, 0.01);\n const dataMin = type === 'line' ? Math.min(...values, 0) : 0;\n const dataRange = dataMax - dataMin || dataMax || 1;\n const yScale = (v: number) => cH - ((v - dataMin) / dataRange) * cH;\n\n // Shared timestamp-based x-axis\n const cutoffMs = Date.now() - days * 24 * 60 * 60 * 1000;\n const rangeMs = days * 24 * 60 * 60 * 1000;\n const xTime = (ms: number) => Math.max(0, Math.min(cW, ((ms - cutoffMs) / rangeMs) * cW));\n\n const xIdx = (i: number) => bucketMidMs.length === values.length\n ? xTime(bucketMidMs[i])\n : (values.length > 1 ? (i / (values.length - 1)) * cW : cW / 2);\n\n const pts: [number, number][] = values.map((v, i) => [PAD.left + xIdx(i), PAD.top + yScale(v)]);\n const linePath = pts.map(([x, y], i) => `${i === 0 ? 'M' : 'L'}${x.toFixed(1)},${y.toFixed(1)}`).join(' ');\n const areaPath = pts.length > 1\n ? `${linePath} L${pts[pts.length-1][0]},${PAD.top+cH} L${pts[0][0]},${PAD.top+cH} Z`\n : '';\n\n const gap = 6;\n const barW = values.length > 1 ? (cW - gap * (values.length - 1)) / values.length : cW;\n\n const yTicks = [0, 0.25, 0.5, 0.75, 1].map(t => dataMin + t * dataRange);\n const gridColor = isDark ? 'rgba(255,255,255,0.05)' : 'rgba(0,0,0,0.05)';\n const axisColor = isDark ? '#3f3f46' : '#d4d4d8';\n const labelColor = isDark ? '#52525b' : '#a1a1aa';\n const font = 'Inter,system-ui,sans-serif';\n const gradId = `dg_${color.replace('#','')}`;\n\n // Find the nearest bucket index for a given timestamp\n const nearestBucket = (ms: number): number => {\n if (bucketMidMs.length === 0) return 0;\n let best = 0, bestDist = Infinity;\n bucketMidMs.forEach((mid, i) => {\n const d = Math.abs(ms - mid);\n if (d < bestDist) { bestDist = d; best = i; }\n });\n return best;\n };\n\n const handleSvgMouseMove = (e: React.MouseEvent<SVGSVGElement>) => {\n const rect = e.currentTarget.getBoundingClientRect();\n const relX = (e.clientX - rect.left - PAD.left * (rect.width / W)) / (rect.width * cW / W);\n const idx = Math.max(0, Math.min(values.length - 1, Math.round(relX * (values.length - 1))));\n setHoverIdx(idx);\n const cRect = containerRef.current?.getBoundingClientRect();\n const x = cRect ? e.clientX - cRect.left : 0;\n const y = cRect ? e.clientY - cRect.top : 0;\n setTooltip({ x, y, primary: formatValue(values[idx]), secondary: weekLabels[idx] });\n };\n\n return (\n <div ref={containerRef} style={{ position: 'relative' }}>\n <svg viewBox={`0 0 ${W} ${H}`} width=\"100%\" style={{ display: 'block' }}\n onMouseMove={handleSvgMouseMove}\n onMouseLeave={() => { setHoverIdx(null); setTooltip(null); }}>\n <defs>\n <linearGradient id={gradId} x1=\"0\" y1=\"0\" x2=\"0\" y2=\"1\">\n <stop offset=\"0%\" stopColor={color} stopOpacity={0.28} />\n <stop offset=\"100%\" stopColor={color} stopOpacity={0} />\n </linearGradient>\n {/* Clip PR dots to the chart area */}\n <clipPath id={`prClip_${gradId}`}>\n <rect x={PAD.left} y={PAD.top - 8} width={cW} height={cH + 16} />\n </clipPath>\n </defs>\n\n {/* Grid + Y-axis */}\n {yTicks.map((v, i) => {\n const y = PAD.top + yScale(v);\n return (\n <g key={i}>\n {i > 0 && <line x1={PAD.left} y1={y} x2={PAD.left+cW} y2={y} stroke={gridColor} strokeWidth={1} strokeDasharray=\"3 4\" />}\n <text x={PAD.left - 6} y={y + 4} textAnchor=\"end\" fill={labelColor} fontSize={10} fontFamily={font}>\n {formatValue(v)}\n </text>\n </g>\n );\n })}\n <line x1={PAD.left} y1={PAD.top+cH} x2={PAD.left+cW} y2={PAD.top+cH} stroke={axisColor} strokeWidth={1} />\n\n {/* Chart body */}\n {type === 'bar' ? (\n values.map((v, i) => {\n const bH = Math.max(2, ((v - dataMin) / dataRange) * cH);\n const x = PAD.left + i * (barW + gap);\n return (\n <rect key={i} x={x} y={PAD.top+cH-bH} width={barW} height={bH} rx={3}\n fill={color} opacity={i === hoverIdx ? 0.95 : 0.4 + (i / Math.max(values.length - 1, 1)) * 0.45} />\n );\n })\n ) : (\n <>\n {areaPath && <path d={areaPath} fill={`url(#${gradId})`} />}\n <path d={linePath} fill=\"none\" stroke={color} strokeWidth={2.5} strokeLinejoin=\"round\" strokeLinecap=\"round\" />\n {pts.map(([x, y], i) => (\n <circle key={i} cx={x} cy={y}\n r={i === hoverIdx ? 5.5 : 4}\n fill={isDark ? '#0f0f12' : '#ffffff'} stroke={color}\n strokeWidth={i === hoverIdx ? 2.5 : 1.5} />\n ))}\n </>\n )}\n\n {/* PR data-point dots — x at bucket midpoint, y at actual duration (clamped to chart) */}\n {prs && type === 'line' && (\n <g clipPath={`url(#prClip_${gradId})`}>\n {prs.map((pr, dotIdx) => {\n const mergedMs = new Date(pr.mergedAt).getTime();\n const bIdx = nearestBucket(mergedMs);\n // Small deterministic jitter within the bucket to avoid overlap\n const jitter = ((pr.number * 17 + dotIdx * 11) % 13 - 6) * 5;\n const px = PAD.left + xIdx(bIdx) + jitter;\n // Clamp y: PR may be faster or slower than bucket avg; always visible\n const rawPy = PAD.top + yScale(pr.durationHours);\n const py = Math.max(PAD.top + 4, Math.min(PAD.top + cH - 4, rawPy));\n const isHov = pr.number === hoveredPrNumber;\n\n // Thin connector from dot to the bucket trend point\n const trendPt = pts[bIdx];\n\n return (\n <g key={pr.number} style={{ cursor: 'pointer' }}\n onMouseEnter={e => {\n e.stopPropagation();\n const cRect = containerRef.current?.getBoundingClientRect();\n const x = cRect ? e.clientX - cRect.left : 0;\n const y = cRect ? e.clientY - cRect.top : 0;\n setTooltip({ x, y,\n primary: `#${pr.number}: ${pr.title}`,\n secondary: `${formatValue(pr.durationHours)} · ${new Date(pr.mergedAt).toLocaleDateString('en-US', { month: 'short', day: 'numeric' })}` });\n onPrHover?.(pr.number);\n }}\n onMouseLeave={() => { setTooltip(null); onPrHover?.(null); }}>\n {trendPt && (\n <line x1={px} y1={py} x2={trendPt[0]} y2={trendPt[1]}\n stroke={color} strokeWidth={isHov ? 1 : 0.5}\n strokeDasharray=\"2 3\" opacity={isHov ? 0.5 : 0.2} />\n )}\n <circle cx={px} cy={py} r={isHov ? 11 : 7} fill={color} opacity={isHov ? 0.2 : 0.1} />\n <circle cx={px} cy={py} r={isHov ? 5.5 : 3.5}\n fill={isHov ? color : (isDark ? '#1a1a20' : '#fff')}\n stroke={color} strokeWidth={isHov ? 0 : 1.5}\n opacity={isHov ? 1 : 0.8} />\n </g>\n );\n })}\n </g>\n )}\n\n {/* Hover crosshair */}\n {hoverIdx !== null && type === 'line' && pts[hoverIdx] && (\n <>\n <line x1={pts[hoverIdx][0]} y1={PAD.top} x2={pts[hoverIdx][0]} y2={PAD.top+cH}\n stroke={color} strokeWidth={1} strokeDasharray=\"3 3\" opacity={0.3} />\n <line x1={PAD.left} y1={pts[hoverIdx][1]} x2={PAD.left+cW} y2={pts[hoverIdx][1]}\n stroke={color} strokeWidth={1} strokeDasharray=\"3 3\" opacity={0.2} />\n </>\n )}\n\n {/* X-axis labels */}\n {weekLabels.map((lbl, i) => {\n const total = weekLabels.length;\n const step = Math.max(1, Math.floor(total / 5));\n if (i !== 0 && i !== total - 1 && i % step !== 0) return null;\n const x = type === 'bar'\n ? PAD.left + i * (barW + gap) + barW / 2\n : PAD.left + xIdx(i);\n return (\n <text key={i} x={x} y={H - 8} textAnchor=\"middle\" fill={labelColor} fontSize={10} fontFamily={font}>\n {lbl}\n </text>\n );\n })}\n </svg>\n\n {/* Absolute tooltip — positioned relative to the chart container */}\n {tooltip && (() => {\n const TW = 220;\n const cW2 = containerRef.current?.offsetWidth ?? 800;\n const nearRight = tooltip.x + TW + 12 > cW2;\n return (\n <div style={{\n position: 'absolute',\n left: nearRight ? tooltip.x - TW - 8 : tooltip.x + 8,\n top: tooltip.y - 36,\n zIndex: 9999, pointerEvents: 'none',\n background: isDark ? '#18181b' : '#ffffff',\n border: `1px solid ${isDark ? '#3f3f46' : '#e4e4e7'}`,\n borderRadius: 7, padding: '7px 10px',\n boxShadow: isDark ? '0 6px 20px rgba(0,0,0,0.55)' : '0 6px 20px rgba(0,0,0,0.10)',\n width: TW,\n }}>\n <div style={{ fontSize: 12, fontWeight: 600, color: isDark ? '#ededef' : '#111114',\n fontFamily: font, lineHeight: 1.4 }}>\n {tooltip.primary}\n </div>\n {tooltip.secondary && (\n <div style={{ fontSize: 11, color: isDark ? '#71717a' : '#a1a1aa', fontFamily: font, marginTop: 2 }}>\n {tooltip.secondary}\n </div>\n )}\n </div>\n );\n })()}\n </div>\n );\n}\n\n// ─── Detailed overlay ──────────────────────────────────────────────────────\n\ninterface ExpandedCardData {\n title: string;\n metric: DoraMetricValue;\n description: string;\n lowerIsBetter: boolean;\n sparklineValues: number[];\n sparklineType: 'bar' | 'line';\n sparklineColor: string;\n weekLabels: string[];\n bucketMidMs: number[];\n prs?: PrDetail[];\n /** Override the section header above the PR list (default: \"All deployments\"). */\n prListLabel?: string;\n}\n\nfunction DetailedOverlay({\n data,\n days,\n onClose,\n}: {\n data: ExpandedCardData;\n days: number;\n onClose: () => void;\n}) {\n const theme = useTheme();\n const isDark = theme.palette.type === 'dark';\n const [hoveredPrNumber, setHoveredPrNumber] = useState<number | null>(null);\n const prRowRefs = useRef<Map<number, HTMLDivElement>>(new Map());\n\n useEffect(() => {\n const onKey = (e: KeyboardEvent) => { if (e.key === 'Escape') onClose(); };\n window.addEventListener('keydown', onKey);\n return () => window.removeEventListener('keydown', onKey);\n }, [onClose]);\n\n // Auto-scroll to the highlighted PR row when hover comes from the chart\n useEffect(() => {\n if (hoveredPrNumber !== null) {\n const el = prRowRefs.current.get(hoveredPrNumber);\n if (el) el.scrollIntoView({ behavior: 'smooth', block: 'nearest' });\n }\n }, [hoveredPrNumber]);\n\n const { title, metric, description, lowerIsBetter, sparklineValues, sparklineType, sparklineColor, weekLabels, bucketMidMs, prs, prListLabel } = data;\n const isDeployFreq = sparklineType === 'bar';\n const displayValue = metric.unit === 'hours' ? formatDuration(metric.value) : String(metric.value);\n const displayUnit = metric.unit === 'hours' ? '' : metric.unit;\n const formatVal = (v: number) => metric.unit === 'hours' ? formatDuration(v) : `${Math.round(v * 10) / 10}`;\n const borderColor = isDark ? '#27272a' : '#e4e4e7';\n const mutedColor = isDark ? '#52525b' : '#a1a1aa';\n const targetLabel = lowerIsBetter\n ? `Target: < ${metric.unit === 'hours' ? formatDuration(metric.target) : metric.target} ${displayUnit}`\n : `Target: ≥ ${metric.target} ${displayUnit}`;\n\n // Group deployment PRs by date (for the date table)\n const prsByDate = isDeployFreq && prs ? prs.reduce((acc, pr) => {\n const date = new Date(pr.mergedAt).toLocaleDateString('en-US', { weekday: 'short', month: 'short', day: 'numeric' });\n if (!acc[date]) acc[date] = [];\n acc[date].push(pr);\n return acc;\n }, {} as Record<string, PrDetail[]>) : {};\n const sortedDates = Object.keys(prsByDate).sort(\n (a, b) => new Date(prsByDate[b][0].mergedAt).getTime() - new Date(prsByDate[a][0].mergedAt).getTime()\n );\n\n return (\n <>\n {/* Backdrop */}\n <div onClick={onClose} style={{\n position: 'fixed', inset: 0, zIndex: 499,\n background: isDark ? 'rgba(0,0,0,0.6)' : 'rgba(0,0,0,0.3)',\n backdropFilter: 'blur(4px)',\n }} />\n\n {/* Panel */}\n <div style={{\n position: 'fixed',\n top: '50%', left: '50%',\n transform: 'translateX(-50%) translateY(-50%)',\n width: 'min(92vw, 960px)',\n maxHeight: 'calc(100vh - 80px)',\n zIndex: 500,\n background: isDark ? '#09090c' : '#fafafa',\n border: `1px solid ${borderColor}`,\n borderRadius: 14,\n display: 'flex', flexDirection: 'column',\n overflow: 'hidden',\n animation: 'detailExpandIn 0.2s cubic-bezier(0.34,1.2,0.64,1)',\n boxShadow: isDark ? '0 24px 64px rgba(0,0,0,0.7)' : '0 24px 64px rgba(0,0,0,0.18)',\n }}>\n {/* Header */}\n <div style={{\n display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start',\n padding: '20px 24px 16px',\n borderBottom: `1px solid ${borderColor}`,\n flexShrink: 0,\n }}>\n <div>\n <div style={{ fontSize: 10, fontWeight: 700, color: mutedColor, textTransform: 'uppercase', letterSpacing: '0.12em', marginBottom: 8 }}>\n {title} · {weekLabels[0]} – {weekLabels[weekLabels.length - 1]}\n </div>\n <div style={{ display: 'flex', alignItems: 'baseline', gap: 8, flexWrap: 'wrap' }}>\n <span style={{ fontSize: 52, fontWeight: 700, color: theme.palette.text.primary, lineHeight: 1, letterSpacing: '-0.02em' }}>\n {displayValue}\n </span>\n {displayUnit && (\n <span style={{ fontSize: 18, color: mutedColor, fontWeight: 500 }}>{displayUnit}</span>\n )}\n <RatingBadge rating={metric.rating} />\n </div>\n <div style={{ fontSize: 12, color: mutedColor, marginTop: 6 }}>\n {description} · <span style={{ fontStyle: 'italic' }}>{targetLabel}</span>\n </div>\n </div>\n <button type=\"button\" onClick={onClose} style={{\n all: 'unset', cursor: 'pointer', width: 30, height: 30,\n display: 'flex', alignItems: 'center', justifyContent: 'center',\n borderRadius: '50%', background: isDark ? 'rgba(255,255,255,0.06)' : 'rgba(0,0,0,0.06)',\n color: mutedColor, fontSize: 18, fontWeight: 300, transition: 'all 0.12s', flexShrink: 0,\n }}\n onMouseEnter={e => { (e.currentTarget as HTMLElement).style.background = isDark ? 'rgba(255,255,255,0.12)' : 'rgba(0,0,0,0.1)'; }}\n onMouseLeave={e => { (e.currentTarget as HTMLElement).style.background = isDark ? 'rgba(255,255,255,0.06)' : 'rgba(0,0,0,0.06)'; }}>\n ✕\n </button>\n </div>\n\n {/* Body — scrollable */}\n <div style={{ flex: 1, overflow: 'auto', padding: '20px 24px', display: 'flex', flexDirection: 'column', gap: 20 }}>\n\n {/* Chart */}\n {weekLabels.length >= 2 ? (\n <DetailedChart\n values={sparklineValues} weekLabels={weekLabels}\n bucketMidMs={bucketMidMs}\n color={sparklineColor} type={sparklineType}\n formatValue={formatVal} prs={isDeployFreq ? undefined : prs} days={days}\n hoveredPrNumber={hoveredPrNumber} onPrHover={setHoveredPrNumber}\n />\n ) : (\n <div style={{ color: mutedColor, fontSize: 13, textAlign: 'center', padding: '48px 0' }}>\n Not enough data — select a wider date range.\n </div>\n )}\n\n {/* === Deployment Frequency: PRs grouped by date === */}\n {isDeployFreq && prs && prs.length > 0 && (\n <div>\n <div style={{ fontSize: 10, fontWeight: 700, color: mutedColor, textTransform: 'uppercase',\n letterSpacing: '0.12em', marginBottom: 12,\n borderTop: `1px solid ${borderColor}`, paddingTop: 12 }}>\n {prListLabel ?? 'All deployments'} · {prs.length} PR{prs.length !== 1 ? 's' : ''}\n </div>\n <div style={{ display: 'flex', flexDirection: 'column', gap: 16 }}>\n {sortedDates.map(date => (\n <div key={date}>\n {/* Date header */}\n <div style={{\n fontSize: 11, fontWeight: 700, color: sparklineColor,\n marginBottom: 6, display: 'flex', alignItems: 'center', gap: 8,\n }}>\n <span>{date}</span>\n <span style={{ color: mutedColor, fontWeight: 500 }}>· {prsByDate[date].length} PR{prsByDate[date].length > 1 ? 's' : ''}</span>\n </div>\n {/* PR rows */}\n <div style={{ display: 'flex', flexDirection: 'column', gap: 4, paddingLeft: 12,\n borderLeft: `2px solid ${sparklineColor}22` }}>\n {prsByDate[date].map(pr => (\n <div key={pr.number} style={{\n display: 'flex', flexDirection: 'column', gap: 5,\n padding: '7px 10px', borderRadius: 7,\n background: isDark ? '#0d0d10' : '#f7f7f9',\n border: `1px solid ${borderColor}`,\n transition: 'background 0.12s',\n }}>\n {/* Row 1: number + title + lead time + link */}\n <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>\n <span style={{ fontSize: 10, fontWeight: 700, color: mutedColor, flexShrink: 0, minWidth: 36 }}>\n #{pr.number}\n </span>\n <span style={{ fontSize: 12, color: theme.palette.text.primary, flex: 1,\n whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }} title={pr.title}>\n {pr.title}\n </span>\n <span style={{ fontSize: 10, color: mutedColor, flexShrink: 0 }}>\n {formatDuration(pr.durationHours)} lead\n </span>\n <a href={pr.url} target=\"_blank\" rel=\"noopener noreferrer\"\n style={{ color: mutedColor, flexShrink: 0 }}>\n <ExternalLink size={11} />\n </a>\n </div>\n {/* Row 2: author badge */}\n {pr.author && (\n <div style={{ display: 'flex', alignItems: 'center', gap: 5 }}>\n {pr.authorAvatar ? (\n <img src={pr.authorAvatar} alt={pr.author}\n style={{ width: 16, height: 16, borderRadius: '50%', flexShrink: 0,\n border: `1px solid ${isDark ? '#3f3f46' : '#e4e4e7'}` }} />\n ) : (\n <div style={{ width: 16, height: 16, borderRadius: '50%', flexShrink: 0,\n background: isDark ? '#27272a' : '#e4e4e7',\n display: 'flex', alignItems: 'center', justifyContent: 'center',\n fontSize: 8, fontWeight: 700, color: mutedColor }}>\n {pr.author[0].toUpperCase()}\n </div>\n )}\n <a href={`https://github.com/${pr.author}`} target=\"_blank\" rel=\"noopener noreferrer\"\n style={{ fontSize: 10, fontWeight: 500, color: mutedColor,\n textDecoration: 'none', letterSpacing: '0.01em' }}\n onMouseEnter={e => { (e.currentTarget as HTMLElement).style.color = '#FA6400'; }}\n onMouseLeave={e => { (e.currentTarget as HTMLElement).style.color = mutedColor; }}>\n @{pr.author}\n </a>\n </div>\n )}\n </div>\n ))}\n </div>\n </div>\n ))}\n </div>\n </div>\n )}\n\n {/* === Lead Time / MTTR: duration-ranked PR list with hover linking === */}\n {!isDeployFreq && prs && prs.length > 0 && (\n <div>\n <div style={{ fontSize: 10, fontWeight: 700, color: mutedColor, textTransform: 'uppercase',\n letterSpacing: '0.12em', marginBottom: 10,\n borderTop: `1px solid ${borderColor}`, paddingTop: 12 }}>\n {title.toLowerCase().includes('restore') ? 'Slowest Hotfix PRs' : 'Slowest PRs'}\n {' '}· hover a row to highlight on chart\n </div>\n <div style={{ display: 'flex', flexDirection: 'column', gap: 6 }}>\n {prs.map((pr, i) => {\n const col = durationColor(i, prs.length);\n const maxDur = prs[0].durationHours;\n const barPct = maxDur > 0 ? (pr.durationHours / maxDur) * 100 : 0;\n const isHov = pr.number === hoveredPrNumber;\n return (\n <div key={pr.number}\n ref={(el) => {\n if (el) prRowRefs.current.set(pr.number, el);\n else prRowRefs.current.delete(pr.number);\n }}\n onMouseEnter={() => setHoveredPrNumber(pr.number)}\n onMouseLeave={() => setHoveredPrNumber(null)}\n style={{\n padding: '8px 12px', borderRadius: 8,\n background: isHov\n ? (isDark ? '#18181f' : '#f0f0ff')\n : (isDark ? '#111114' : '#f4f4f6'),\n border: `1px solid ${isHov ? `${sparklineColor}55` : borderColor}`,\n display: 'flex', flexDirection: 'column', gap: 5,\n transition: 'background 0.12s, border-color 0.12s',\n cursor: 'default',\n }}>\n <div style={{ display: 'flex', alignItems: 'center', gap: 6, minWidth: 0 }}>\n <span style={{ fontSize: 10, fontWeight: 700, color: col, flexShrink: 0 }}>#{pr.number}</span>\n <span style={{ fontSize: 12, color: theme.palette.text.primary, flex: 1,\n whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }} title={pr.title}>\n {pr.title}\n </span>\n <span style={{ fontSize: 10, color: mutedColor, flexShrink: 0 }}>\n {new Date(pr.mergedAt).toLocaleDateString('en-US', { month: 'short', day: 'numeric' })}\n </span>\n <a href={pr.url} target=\"_blank\" rel=\"noopener noreferrer\"\n style={{ color: mutedColor, flexShrink: 0, transition: 'color 0.12s' }}>\n <ExternalLink size={11} />\n </a>\n </div>\n <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>\n <AnimatedBar widthPct={barPct} color={col} />\n <span style={{ fontSize: 11, fontWeight: 700, color: col, minWidth: 52, textAlign: 'right', flexShrink: 0 }}>\n {formatDuration(pr.durationHours)}\n </span>\n </div>\n </div>\n );\n })}\n </div>\n </div>\n )}\n </div>\n </div>\n <style>{`\n @keyframes detailExpandIn {\n from { opacity: 0; transform: translateX(-50%) translateY(-46%); }\n to { opacity: 1; transform: translateX(-50%) translateY(-50%); }\n }\n `}</style>\n </>\n );\n}\n\n// ─── Animated bar ──────────────────────────────────────────────────────────\n\nfunction AnimatedBar({ widthPct, color }: { widthPct: number; color: string }) {\n const [width, setWidth] = useState(0);\n const ref = useRef<HTMLDivElement>(null);\n const theme = useTheme();\n const isDark = theme.palette.type === 'dark';\n\n useEffect(() => {\n const timer = setTimeout(() => setWidth(widthPct), 80);\n return () => clearTimeout(timer);\n }, [widthPct]);\n\n return (\n <div\n ref={ref}\n style={{\n background: isDark ? '#1a1a1e' : '#f0f0f2',\n borderRadius: 4,\n height: 5,\n overflow: 'hidden',\n flex: 1,\n minWidth: 40,\n }}\n >\n <div\n style={{\n height: '100%',\n width: `${width}%`,\n background: color,\n borderRadius: 4,\n transition: 'width 0.55s cubic-bezier(0.4, 0, 0.2, 1)',\n boxShadow: `0 0 6px ${color}88`,\n }}\n />\n </div>\n );\n}\n\n// ─── Metric cards ──────────────────────────────────────────────────────────\n\nfunction MetricCard({\n title,\n metric,\n description,\n lowerIsBetter = false,\n sparklineData,\n sparklineType = 'line',\n sparklineColor,\n weekLabels,\n onExpand,\n expandLabel,\n}: {\n title: string;\n metric: DoraMetricValue;\n description: string;\n lowerIsBetter?: boolean;\n sparklineData?: number[];\n sparklineType?: 'bar' | 'line';\n sparklineColor?: string;\n weekLabels?: string[];\n onExpand?: () => void;\n /** Persistent label shown in the card footer (instead of the hover-only \"expand ↗\"). */\n expandLabel?: string;\n}) {\n const theme = useTheme();\n const isDark = theme.palette.type === 'dark';\n const [hovered, setHovered] = useState(false);\n\n const displayValue = metric.unit === 'hours' ? formatDuration(metric.value) : metric.value;\n const displayUnit = metric.unit === 'hours' ? '' : metric.unit;\n const targetValue = metric.unit === 'hours' ? formatDuration(metric.target) : metric.target;\n const targetLabel = lowerIsBetter\n ? `Target: < ${targetValue} ${displayUnit}`.trim()\n : `Target: ≥ ${targetValue} ${displayUnit}`.trim();\n\n const hasSparkline = sparklineData && sparklineData.length >= 2 && weekLabels && weekLabels.length >= 2;\n const delta = hasSparkline ? buildDeltaLabel(sparklineData!, metric.unit, lowerIsBetter) : null;\n const formatVal = (v: number) => metric.unit === 'hours' ? formatDuration(v) : `${Math.round(v * 10) / 10}`;\n\n return (\n <Card\n style={{ cursor: onExpand ? 'pointer' : undefined }}\n onClick={onExpand}\n onMouseEnter={() => setHovered(true)}\n onMouseLeave={() => setHovered(false)}\n >\n <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start', gap: 8 }}>\n <CardLabel>{title}</CardLabel>\n {onExpand && (\n <span style={{\n fontSize: 9, fontWeight: 600, color: isDark ? '#3f3f46' : '#d4d4d8',\n opacity: hovered ? 1 : 0, transition: 'opacity 0.15s',\n letterSpacing: '0.05em', textTransform: 'uppercase', flexShrink: 0,\n }}>\n expand ↗\n </span>\n )}\n </div>\n {/* Right-aligned column: delta trend + direction hint stacked */}\n <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'flex-end', gap: 4 }}>\n {delta && (\n <span title={delta.tooltip} style={{\n fontSize: 10, fontWeight: 600, cursor: 'help',\n color: delta.good ? '#4ade80' : '#f87171',\n background: delta.good\n ? (isDark ? 'rgba(74,222,128,0.08)' : 'rgba(74,222,128,0.12)')\n : (isDark ? 'rgba(248,113,113,0.08)' : 'rgba(248,113,113,0.12)'),\n padding: '2px 8px', borderRadius: 4, whiteSpace: 'nowrap',\n }}>\n {delta.text}\n </span>\n )}\n <span style={{\n fontSize: 10, fontWeight: 600,\n color: isDark ? '#3f3f46' : '#d4d4d8',\n whiteSpace: 'nowrap',\n }}>\n {lowerIsBetter ? '↓ lower = better' : '↑ higher = better'}\n </span>\n </div>\n {/* Value row: big number + unit */}\n <div style={{ display: 'flex', alignItems: 'baseline', gap: 6 }}>\n <span style={{ fontSize: 36, fontWeight: 700, color: isDark ? '#f4f4f5' : '#111114', lineHeight: 1 }}>\n {displayValue}\n </span>\n {displayUnit && (\n <span style={{ fontSize: 14, color: isDark ? '#71717a' : '#71717a', fontWeight: 500 }}>\n {displayUnit}\n </span>\n )}\n </div>\n <RatingBadge rating={metric.rating} />\n {hasSparkline && (\n <div style={{ marginTop: 2 }}>\n <CompactSparkline\n values={sparklineData!}\n weekLabels={weekLabels!}\n color={sparklineColor ?? '#FA6400'}\n type={sparklineType}\n formatValue={formatVal}\n />\n </div>\n )}\n <CardDescription>{description}</CardDescription>\n <CardFooter>\n <span style={{ fontWeight: 600, color: isDark ? '#a1a1aa' : '#52525b' }}>\n {targetLabel}\n </span>\n {expandLabel && onExpand && (\n <span style={{\n fontSize: 10, fontWeight: 700,\n color: '#FA6400',\n letterSpacing: '0.04em',\n marginLeft: 'auto',\n }}>\n {expandLabel}\n </span>\n )}\n </CardFooter>\n </Card>\n );\n}\n\nfunction NaCard({ title, description }: { title: string; description: string }) {\n return (\n <Card>\n <CardLabel>{title}</CardLabel>\n <div style={{ display: 'flex', alignItems: 'baseline', gap: 6 }}>\n <span style={{ fontSize: 36, fontWeight: 700, color: '#52525b', lineHeight: 1 }}>N/A</span>\n </div>\n <CardDescription muted>{description}</CardDescription>\n </Card>\n );\n}\n\n// ─── Filter label ──────────────────────────────────────────────────────────\n\nfunction FilterLabel({ children }: { children: React.ReactNode }) {\n const theme = useTheme();\n return (\n <div style={{ fontSize: 11, fontWeight: 600, color: theme.palette.text.primary, marginBottom: 4, textTransform: 'uppercase', letterSpacing: '0.06em' }}>\n {children}\n </div>\n );\n}\n\n// ─── Main component ────────────────────────────────────────────────────────\n\nexport function DoraMetricsContent() {\n const { entity } = useEntity();\n const doraApi = useApi(doraMetricsApiRef);\n const muiTheme = useTheme();\n const textPrimary = muiTheme.palette.text.primary;\n const textSecondary = muiTheme.palette.text.secondary;\n\n const projectSlug = entity.metadata.annotations?.[ANNOTATION_PROJECT_SLUG] ?? '';\n const annotations = entity.metadata.annotations ?? {};\n\n // Per-repo overrides from catalog-info.yaml annotations\n const annotationEnvs = parseAnnotationJson<DoraEnvironment[]>(annotations[ANNOTATION_ENVIRONMENTS]);\n const annotationTargets = parseAnnotationJson<Partial<DoraTargets>>(annotations[ANNOTATION_TARGETS]);\n\n const environments: DoraEnvironment[] = annotationEnvs ?? doraApi.getEnvironments();\n const defaultEnv = environments[0];\n const defaultDays = doraApi.getDefaultDays();\n\n // Use environment name as the selection key (branch can be a multi-value pattern)\n const [selectedEnvName, setSelectedEnvName] = useState<string>(defaultEnv?.name ?? '');\n const [selectedDays, setSelectedDays] = useState<string>(String(defaultDays));\n\n const selectedEnv = environments.find(e => e.name === selectedEnvName) ?? defaultEnv;\n const days = parseInt(selectedDays, 10);\n\n const [metrics, setMetrics] = useState<DoraMetrics | null>(null);\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<Error | null>(null);\n\n const [history, setHistory] = useState<DoraHistoryPoint[] | null>(null);\n const [expanded, setExpanded] = useState<ExpandedCardData | null>(null);\n\n useEffect(() => {\n let cancelled = false;\n\n if (!projectSlug) {\n setError(new Error(`Entity is missing the \"${ANNOTATION_PROJECT_SLUG}\" annotation.`));\n setLoading(false);\n return () => { cancelled = true; };\n }\n if (!selectedEnv) {\n setError(new Error('No environments configured for DORA metrics.'));\n setLoading(false);\n return () => { cancelled = true; };\n }\n\n setLoading(true);\n setError(null);\n setHistory(null);\n\n doraApi\n .getMetrics(projectSlug, selectedEnv, days, annotationTargets ?? undefined)\n .then(data => {\n if (!cancelled) { setMetrics(data); setLoading(false); }\n })\n .catch((err: Error) => {\n if (!cancelled) { setError(err); setLoading(false); }\n });\n\n doraApi\n .getHistory(projectSlug, selectedEnv, days)\n .then(data => { if (!cancelled) setHistory(data); })\n .catch(() => { /* history is optional — fail silently */ });\n\n return () => { cancelled = true; };\n // selectedEnv?.name is intentional — avoids re-render loops from object identity changes\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [doraApi, projectSlug, selectedEnv?.name, days, annotationTargets]);\n\n if (loading) return <DoraLoadingOverlay />;\n\n if (error) {\n return (\n <InfoCard title=\"DORA Metrics\">\n <div style={{ padding: 24, color: '#f87171' }}>\n <span style={{ fontWeight: 600 }}>Error: </span>{error.message}\n </div>\n </InfoCard>\n );\n }\n\n if (!metrics) return null;\n\n return (\n <InfoCard title=\" \">\n <div style={{ padding: '4px 0', position: 'relative' }}>\n {/* Detailed overlay */}\n {expanded && (\n <DetailedOverlay data={expanded} days={days} onClose={() => setExpanded(null)} />\n )}\n\n {/* Title */}\n <div style={{ marginBottom: 16 }}>\n <div style={{ fontSize: 22, fontWeight: 700, color: textPrimary, letterSpacing: '-0.02em' }}>DORA Metrics</div>\n {selectedEnv && (\n <div style={{ fontSize: 12, color: textSecondary, marginTop: 5 }}>\n Showing metrics for{' '}\n <strong style={{ color: textPrimary }}>{selectedEnv.name}</strong>\n {' '}—{' '}\n <span style={{ fontFamily: 'monospace' }}>{selectedEnv.branch}</span>\n </div>\n )}\n </div>\n\n {/* Filters row — left aligned */}\n <div style={{ display: 'flex', alignItems: 'flex-end', gap: 16, flexWrap: 'wrap', marginBottom: 20 }}>\n {environments.length > 1 && (\n <div>\n <FilterLabel>Environment</FilterLabel>\n <Select value={selectedEnvName} onValueChange={setSelectedEnvName}>\n <SelectTrigger><SelectValue placeholder=\"Select environment\" /></SelectTrigger>\n <SelectContent>\n {environments.map(env => (\n <SelectItem key={env.name} value={env.name}>\n {env.name} ({env.branch})\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n )}\n\n <div>\n <FilterLabel>Date Range</FilterLabel>\n <Select value={selectedDays} onValueChange={setSelectedDays}>\n <SelectTrigger><SelectValue placeholder=\"Select date range\" /></SelectTrigger>\n <SelectContent>\n {DATE_RANGE_OPTIONS.map(opt => (\n <SelectItem key={opt.value} value={opt.value}>{opt.label}</SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n </div>\n\n {/* Metric cards — sparklines inline, click to expand */}\n {(() => {\n const wkLabels = history?.map(h => h.weekLabel) ?? [];\n const deployData = history?.map(h => h.deploymentCount) ?? [];\n const leadData = history?.map(h => h.leadTimeHours) ?? [];\n const cfrData = history?.map(h => h.changeFailureRate ?? 0) ?? [];\n const mttrData = history?.map(h => h.mttrHours ?? 0) ?? [];\n\n const bmMs = history?.map(h => h.bucketMidMs) ?? [];\n\n const mkExpand = (\n title: string, metric: DoraMetricValue, description: string,\n lowerIsBetter: boolean, sparklineValues: number[],\n sparklineType: 'bar' | 'line', sparklineColor: string, prs?: PrDetail[],\n prListLabel?: string,\n ) => () => setExpanded({\n title, metric, description, lowerIsBetter,\n sparklineValues, sparklineType, sparklineColor,\n weekLabels: wkLabels, bucketMidMs: bmMs, prs, prListLabel,\n });\n\n return (\n <div style={{ display: 'flex', flexWrap: 'wrap', gap: 12 }}>\n <MetricCard\n title=\"Deployment Frequency\"\n metric={metrics.deploymentFrequency}\n description=\"How often code is deployed to this branch\"\n sparklineData={deployData}\n sparklineType=\"bar\"\n sparklineColor=\"#FA6400\"\n weekLabels={wkLabels}\n onExpand={mkExpand('Deployment Frequency', metrics.deploymentFrequency,\n 'How often code is deployed to this branch', false, deployData, 'bar', '#FA6400',\n metrics.deploymentFrequency.slowestPRs)}\n />\n <MetricCard\n title=\"Lead Time for Changes\"\n metric={metrics.leadTime}\n description=\"Average time from PR creation to merge\"\n lowerIsBetter\n sparklineData={leadData}\n sparklineType=\"line\"\n sparklineColor=\"#818cf8\"\n weekLabels={wkLabels}\n onExpand={mkExpand('Lead Time for Changes', metrics.leadTime,\n 'Average time from PR creation to merge', true, leadData, 'line', '#818cf8', metrics.leadTime.slowestPRs)}\n />\n {metrics.changeFailureRate !== null ? (\n <MetricCard\n title=\"Change Failure Rate\"\n metric={metrics.changeFailureRate}\n description=\"% of all merged PRs that were hotfixes\"\n lowerIsBetter\n sparklineData={cfrData}\n sparklineType=\"line\"\n sparklineColor=\"#f87171\"\n weekLabels={wkLabels}\n onExpand={mkExpand('Change Failure Rate', metrics.changeFailureRate,\n '% of all merged PRs that were hotfixes', true, cfrData, 'line', '#f87171')}\n />\n ) : (\n <NaCard title=\"Change Failure Rate\" description=\"Only tracked on production branches\" />\n )}\n {metrics.mttr !== null ? (\n <MetricCard\n title=\"Mean Time to Restore\"\n metric={metrics.mttr}\n description=\"Avg time from hotfix PR open to merge\"\n lowerIsBetter\n sparklineData={mttrData}\n sparklineType=\"line\"\n sparklineColor=\"#fbbf24\"\n weekLabels={wkLabels}\n onExpand={mkExpand('Mean Time to Restore', metrics.mttr,\n 'Avg time from hotfix PR open to merge', true, mttrData, 'line', '#fbbf24', metrics.mttr.slowestPRs)}\n />\n ) : (\n <NaCard title=\"Mean Time to Restore\" description=\"Only tracked on production branches\" />\n )}\n {metrics.numberOfHotfixes !== null ? (\n <MetricCard\n title=\"Hotfixes to Production\"\n metric={metrics.numberOfHotfixes}\n description={`PRs labeled '${selectedEnv?.label ?? 'hotfix'}' merged to production`}\n lowerIsBetter\n expandLabel={metrics.numberOfHotfixes.value > 0 ? `View ${metrics.numberOfHotfixes.value} PR${metrics.numberOfHotfixes.value !== 1 ? 's' : ''} →` : undefined}\n onExpand={mkExpand(\n 'Hotfixes to Production',\n metrics.numberOfHotfixes,\n `PRs labeled '${selectedEnv?.label ?? 'hotfix'}' merged to production`,\n true,\n [],\n 'bar',\n '#f87171',\n metrics.numberOfHotfixes.slowestPRs,\n 'All hotfixes',\n )}\n />\n ) : (\n <NaCard title=\"Hotfixes to Production\" description=\"Only tracked on production branches\" />\n )}\n </div>\n );\n })()}\n\n </div>\n </InfoCard>\n );\n}\n"],"names":["max"],"mappings":"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"}
@@ -1,3 +1,5 @@
1
+ import React from 'react';
2
+
1
3
  const RATING_STYLES = {
2
4
  elite: { background: "#14532d", color: "#86efac", border: "#166534" },
3
5
  high: { background: "#1e3a5f", color: "#93c5fd", border: "#1d4ed8" },
@@ -1 +1 @@
1
- {"version":3,"file":"badge.esm.js","sources":["../../../src/components/ui/badge.tsx"],"sourcesContent":["import type { DoraRating } from '../../api/types';\n\nconst RATING_STYLES: Record<DoraRating, { background: string; color: string; border: string }> = {\n elite: { background: '#14532d', color: '#86efac', border: '#166534' },\n high: { background: '#1e3a5f', color: '#93c5fd', border: '#1d4ed8' },\n medium:{ background: '#451a03', color: '#fdba74', border: '#92400e' },\n low: { background: '#450a0a', color: '#fca5a5', border: '#991b1b' },\n};\n\nexport function RatingBadge({ rating }: { rating: DoraRating }) {\n const s = RATING_STYLES[rating];\n return (\n <span\n style={{\n display: 'inline-flex',\n alignItems: 'center',\n padding: '2px 8px',\n borderRadius: 9999,\n background: s.background,\n color: s.color,\n border: `1px solid ${s.border}`,\n fontSize: 11,\n fontWeight: 600,\n letterSpacing: '0.06em',\n textTransform: 'uppercase',\n }}\n >\n {rating}\n </span>\n );\n}\n"],"names":[],"mappings":"AAEA,MAAM,aAAA,GAA2F;AAAA,EAC/F,OAAO,EAAE,UAAA,EAAY,WAAW,KAAA,EAAO,SAAA,EAAW,QAAQ,SAAA,EAAU;AAAA,EACpE,MAAO,EAAE,UAAA,EAAY,WAAW,KAAA,EAAO,SAAA,EAAW,QAAQ,SAAA,EAAU;AAAA,EACpE,QAAO,EAAE,UAAA,EAAY,WAAW,KAAA,EAAO,SAAA,EAAW,QAAQ,SAAA,EAAU;AAAA,EACpE,KAAO,EAAE,UAAA,EAAY,WAAW,KAAA,EAAO,SAAA,EAAW,QAAQ,SAAA;AAC5D,CAAA;AAEO,SAAS,WAAA,CAAY,EAAE,MAAA,EAAO,EAA2B;AAC9D,EAAA,MAAM,CAAA,GAAI,cAAc,MAAM,CAAA;AAC9B,EAAA,uBACE,KAAA,CAAA,aAAA;AAAA,IAAC,MAAA;AAAA,IAAA;AAAA,MACC,KAAA,EAAO;AAAA,QACL,OAAA,EAAS,aAAA;AAAA,QACT,UAAA,EAAY,QAAA;AAAA,QACZ,OAAA,EAAS,SAAA;AAAA,QACT,YAAA,EAAc,IAAA;AAAA,QACd,YAAY,CAAA,CAAE,UAAA;AAAA,QACd,OAAO,CAAA,CAAE,KAAA;AAAA,QACT,MAAA,EAAQ,CAAA,UAAA,EAAa,CAAA,CAAE,MAAM,CAAA,CAAA;AAAA,QAC7B,QAAA,EAAU,EAAA;AAAA,QACV,UAAA,EAAY,GAAA;AAAA,QACZ,aAAA,EAAe,QAAA;AAAA,QACf,aAAA,EAAe;AAAA;AACjB,KAAA;AAAA,IAEC;AAAA,GACH;AAEJ;;;;"}
1
+ {"version":3,"file":"badge.esm.js","sources":["../../../src/components/ui/badge.tsx"],"sourcesContent":["import React from 'react';\nimport type { DoraRating } from '../../api/types';\n\nconst RATING_STYLES: Record<DoraRating, { background: string; color: string; border: string }> = {\n elite: { background: '#14532d', color: '#86efac', border: '#166534' },\n high: { background: '#1e3a5f', color: '#93c5fd', border: '#1d4ed8' },\n medium:{ background: '#451a03', color: '#fdba74', border: '#92400e' },\n low: { background: '#450a0a', color: '#fca5a5', border: '#991b1b' },\n};\n\nexport function RatingBadge({ rating }: { rating: DoraRating }) {\n const s = RATING_STYLES[rating];\n return (\n <span\n style={{\n display: 'inline-flex',\n alignItems: 'center',\n padding: '2px 8px',\n borderRadius: 9999,\n background: s.background,\n color: s.color,\n border: `1px solid ${s.border}`,\n fontSize: 11,\n fontWeight: 600,\n letterSpacing: '0.06em',\n textTransform: 'uppercase',\n }}\n >\n {rating}\n </span>\n );\n}\n"],"names":[],"mappings":";;AAGA,MAAM,aAAA,GAA2F;AAAA,EAC/F,OAAO,EAAE,UAAA,EAAY,WAAW,KAAA,EAAO,SAAA,EAAW,QAAQ,SAAA,EAAU;AAAA,EACpE,MAAO,EAAE,UAAA,EAAY,WAAW,KAAA,EAAO,SAAA,EAAW,QAAQ,SAAA,EAAU;AAAA,EACpE,QAAO,EAAE,UAAA,EAAY,WAAW,KAAA,EAAO,SAAA,EAAW,QAAQ,SAAA,EAAU;AAAA,EACpE,KAAO,EAAE,UAAA,EAAY,WAAW,KAAA,EAAO,SAAA,EAAW,QAAQ,SAAA;AAC5D,CAAA;AAEO,SAAS,WAAA,CAAY,EAAE,MAAA,EAAO,EAA2B;AAC9D,EAAA,MAAM,CAAA,GAAI,cAAc,MAAM,CAAA;AAC9B,EAAA,uBACE,KAAA,CAAA,aAAA;AAAA,IAAC,MAAA;AAAA,IAAA;AAAA,MACC,KAAA,EAAO;AAAA,QACL,OAAA,EAAS,aAAA;AAAA,QACT,UAAA,EAAY,QAAA;AAAA,QACZ,OAAA,EAAS,SAAA;AAAA,QACT,YAAA,EAAc,IAAA;AAAA,QACd,YAAY,CAAA,CAAE,UAAA;AAAA,QACd,OAAO,CAAA,CAAE,KAAA;AAAA,QACT,MAAA,EAAQ,CAAA,UAAA,EAAa,CAAA,CAAE,MAAM,CAAA,CAAA;AAAA,QAC7B,QAAA,EAAU,EAAA;AAAA,QACV,UAAA,EAAY,GAAA;AAAA,QACZ,aAAA,EAAe,QAAA;AAAA,QACf,aAAA,EAAe;AAAA;AACjB,KAAA;AAAA,IAEC;AAAA,GACH;AAEJ;;;;"}
@@ -1,3 +1,4 @@
1
+ import React from 'react';
1
2
  import { EntityContentBlueprint } from '@backstage/plugin-catalog-react/alpha';
2
3
 
3
4
  const doraMetricsEntityContentExtension = EntityContentBlueprint.make({
@@ -1 +1 @@
1
- {"version":3,"file":"entityContent.esm.js","sources":["../../src/extensions/entityContent.tsx"],"sourcesContent":["import { EntityContentBlueprint } from '@backstage/plugin-catalog-react/alpha';\n\nexport const doraMetricsEntityContentExtension = EntityContentBlueprint.make({\n params: {\n path: 'dora-metrics',\n title: 'DORA Metrics',\n filter: entity =>\n entity.spec?.type === 'service' ||\n Boolean(entity.metadata.annotations?.['github.com/project-slug']),\n loader: () =>\n import('../components/DoraMetricsContent').then(m => (\n <m.DoraMetricsContent />\n )),\n },\n});\n"],"names":[],"mappings":";;AAEO,MAAM,iCAAA,GAAoC,uBAAuB,IAAA,CAAK;AAAA,EAC3E,MAAA,EAAQ;AAAA,IACN,IAAA,EAAM,cAAA;AAAA,IACN,KAAA,EAAO,cAAA;AAAA,IACP,MAAA,EAAQ,CAAA,MAAA,KACN,MAAA,CAAO,IAAA,EAAM,IAAA,KAAS,SAAA,IACtB,OAAA,CAAQ,MAAA,CAAO,QAAA,CAAS,WAAA,GAAc,yBAAyB,CAAC,CAAA;AAAA,IAClE,MAAA,EAAQ,MACN,OAAO,yCAAkC,CAAA,CAAE,IAAA,CAAK,CAAA,CAAA,qBAC9C,KAAA,CAAA,aAAA,CAAC,CAAA,CAAE,kBAAA,EAAF,IAAqB,CACvB;AAAA;AAEP,CAAC;;;;"}
1
+ {"version":3,"file":"entityContent.esm.js","sources":["../../src/extensions/entityContent.tsx"],"sourcesContent":["import React from 'react';\nimport { EntityContentBlueprint } from '@backstage/plugin-catalog-react/alpha';\n\nexport const doraMetricsEntityContentExtension = EntityContentBlueprint.make({\n params: {\n path: 'dora-metrics',\n title: 'DORA Metrics',\n filter: entity =>\n entity.spec?.type === 'service' ||\n Boolean(entity.metadata.annotations?.['github.com/project-slug']),\n loader: () =>\n import('../components/DoraMetricsContent').then(m => (\n <m.DoraMetricsContent />\n )),\n },\n});\n"],"names":[],"mappings":";;;AAGO,MAAM,iCAAA,GAAoC,uBAAuB,IAAA,CAAK;AAAA,EAC3E,MAAA,EAAQ;AAAA,IACN,IAAA,EAAM,cAAA;AAAA,IACN,KAAA,EAAO,cAAA;AAAA,IACP,MAAA,EAAQ,CAAA,MAAA,KACN,MAAA,CAAO,IAAA,EAAM,IAAA,KAAS,SAAA,IACtB,OAAA,CAAQ,MAAA,CAAO,QAAA,CAAS,WAAA,GAAc,yBAAyB,CAAC,CAAA;AAAA,IAClE,MAAA,EAAQ,MACN,OAAO,yCAAkC,CAAA,CAAE,IAAA,CAAK,CAAA,CAAA,qBAC9C,KAAA,CAAA,aAAA,CAAC,CAAA,CAAE,kBAAA,EAAF,IAAqB,CACvB;AAAA;AAEP,CAAC;;;;"}
package/dist/index.d.ts CHANGED
@@ -1,7 +1,10 @@
1
1
  export { default as doraMetricsPlugin } from './alpha.js';
2
2
  import * as _backstage_core_plugin_api from '@backstage/core-plugin-api';
3
3
  import { OAuthApi, ConfigApi } from '@backstage/core-plugin-api';
4
- import React from 'react';
4
+ import * as react_jsx_runtime from 'react/jsx-runtime';
5
+ import '@backstage/catalog-model';
6
+ import 'react';
7
+ import '@backstage/filter-predicates';
5
8
  import '@backstage/frontend-plugin-api';
6
9
 
7
10
  type DoraRating = 'elite' | 'high' | 'medium' | 'low';
@@ -91,7 +94,7 @@ declare class MockDoraMetricsClient implements DoraMetricsApi {
91
94
  getHistory(_projectSlug: string, env: DoraEnvironment, _days: number): Promise<DoraHistoryPoint[]>;
92
95
  }
93
96
 
94
- declare function DoraMetricsContent(): React.JSX.Element | null;
97
+ declare function DoraMetricsContent(): react_jsx_runtime.JSX.Element | null;
95
98
 
96
99
  export { DoraMetricsClient, DoraMetricsContent, MockDoraMetricsClient, doraMetricsApiRef };
97
100
  export type { DoraEnvironment, DoraMetricValue, DoraMetrics, DoraMetricsApi, DoraRating, DoraTargets, PrDetail };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@c2l2c/backstage-plugin-dora-metrics",
3
- "version": "0.3.0",
3
+ "version": "0.3.2",
4
4
  "description": "A Backstage frontend plugin that displays DORA metrics (Deployment Frequency, Lead Time, Change Failure Rate, MTTR) for catalog entities via the GitHub API.",
5
5
  "main": "dist/index.cjs.js",
6
6
  "module": "dist/index.esm.js",
@@ -54,17 +54,23 @@
54
54
  "@backstage/config": "^1.3.2",
55
55
  "@backstage/core-components": "^0.18.7",
56
56
  "@backstage/core-plugin-api": "^1.12.3",
57
- "@backstage/frontend-plugin-api": "^0.9.5",
57
+ "@backstage/frontend-plugin-api": "^0.15.1",
58
58
  "@backstage/plugin-catalog-react": "^2.0.0",
59
+ "@material-ui/core": "^4.12.4",
59
60
  "@radix-ui/react-select": "^2.2.6",
60
- "lucide-react": "^0.577.0"
61
+ "lucide-react": "^1.7.0"
61
62
  },
62
63
  "devDependencies": {
63
- "@backstage/cli": "^0.35.4",
64
+ "@backstage/cli": "^0.36.0",
65
+ "@backstage/cli-defaults": "^0.1.0",
66
+ "@types/react": "^18",
64
67
  "jest": "^30",
65
68
  "jest-environment-jsdom": "^30"
66
69
  },
67
70
  "peerDependencies": {
68
71
  "react": "^17.0.0 || ^18.0.0"
72
+ },
73
+ "engines": {
74
+ "node": ">=20"
69
75
  }
70
76
  }