@miragon/pulse-analytics-connector 0.0.0-bootstrap.0 → 0.21.0
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/LICENSE +21 -0
- package/README.md +86 -3
- package/dist/bpmn-name-lookup.d.ts +72 -0
- package/dist/bpmn-name-lookup.d.ts.map +1 -0
- package/dist/bpmn-name-lookup.js +123 -0
- package/dist/bpmn-name-lookup.js.map +1 -0
- package/dist/bpmn-name-lookup.test.d.ts +2 -0
- package/dist/bpmn-name-lookup.test.d.ts.map +1 -0
- package/dist/bpmn-name-lookup.test.js +287 -0
- package/dist/bpmn-name-lookup.test.js.map +1 -0
- package/dist/bpmn-names.d.ts +38 -0
- package/dist/bpmn-names.d.ts.map +1 -0
- package/dist/bpmn-names.js +22 -0
- package/dist/bpmn-names.js.map +1 -0
- package/dist/brand-gates.test.d.ts +2 -0
- package/dist/brand-gates.test.d.ts.map +1 -0
- package/dist/brand-gates.test.js +58 -0
- package/dist/brand-gates.test.js.map +1 -0
- package/dist/builder-texts.d.ts +4 -0
- package/dist/builder-texts.d.ts.map +1 -0
- package/dist/builder-texts.js +14 -0
- package/dist/builder-texts.js.map +1 -0
- package/dist/builder-texts.test.d.ts +2 -0
- package/dist/builder-texts.test.d.ts.map +1 -0
- package/dist/builder-texts.test.js +32 -0
- package/dist/builder-texts.test.js.map +1 -0
- package/dist/definition.d.ts +3 -0
- package/dist/definition.d.ts.map +1 -0
- package/dist/definition.js +151 -0
- package/dist/definition.js.map +1 -0
- package/dist/engine-ids.d.ts +42 -0
- package/dist/engine-ids.d.ts.map +1 -0
- package/dist/engine-ids.js +50 -0
- package/dist/engine-ids.js.map +1 -0
- package/dist/engine-scope.test.d.ts +2 -0
- package/dist/engine-scope.test.d.ts.map +1 -0
- package/dist/engine-scope.test.js +260 -0
- package/dist/engine-scope.test.js.map +1 -0
- package/dist/heatmap-data.d.ts +15 -0
- package/dist/heatmap-data.d.ts.map +1 -0
- package/dist/heatmap-data.js +2 -0
- package/dist/heatmap-data.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -0
- package/dist/instructions.d.ts +8 -0
- package/dist/instructions.d.ts.map +1 -0
- package/dist/instructions.js +33 -0
- package/dist/instructions.js.map +1 -0
- package/dist/messages/de.ask-ai.d.ts +9 -0
- package/dist/messages/de.ask-ai.d.ts.map +1 -0
- package/dist/messages/de.ask-ai.js +18 -0
- package/dist/messages/de.ask-ai.js.map +1 -0
- package/dist/messages/de.builder.d.ts +12 -0
- package/dist/messages/de.builder.d.ts.map +1 -0
- package/dist/messages/de.builder.js +53 -0
- package/dist/messages/de.builder.js.map +1 -0
- package/dist/messages/de.server.d.ts +8 -0
- package/dist/messages/de.server.d.ts.map +1 -0
- package/dist/messages/de.server.js +26 -0
- package/dist/messages/de.server.js.map +1 -0
- package/dist/messages/de.sweep.d.ts +10 -0
- package/dist/messages/de.sweep.d.ts.map +1 -0
- package/dist/messages/de.sweep.js +203 -0
- package/dist/messages/de.sweep.js.map +1 -0
- package/dist/messages/en.ask-ai.d.ts +25 -0
- package/dist/messages/en.ask-ai.d.ts.map +1 -0
- package/dist/messages/en.ask-ai.js +24 -0
- package/dist/messages/en.ask-ai.js.map +1 -0
- package/dist/messages/en.builder.d.ts +12 -0
- package/dist/messages/en.builder.d.ts.map +1 -0
- package/dist/messages/en.builder.js +53 -0
- package/dist/messages/en.builder.js.map +1 -0
- package/dist/messages/en.server.d.ts +8 -0
- package/dist/messages/en.server.d.ts.map +1 -0
- package/dist/messages/en.server.js +26 -0
- package/dist/messages/en.server.js.map +1 -0
- package/dist/messages/en.sweep.d.ts +11 -0
- package/dist/messages/en.sweep.d.ts.map +1 -0
- package/dist/messages/en.sweep.js +204 -0
- package/dist/messages/en.sweep.js.map +1 -0
- package/dist/messages/glossary.d.ts +26 -0
- package/dist/messages/glossary.d.ts.map +1 -0
- package/dist/messages/glossary.js +37 -0
- package/dist/messages/glossary.js.map +1 -0
- package/dist/messages/glossary.test.d.ts +2 -0
- package/dist/messages/glossary.test.d.ts.map +1 -0
- package/dist/messages/glossary.test.js +109 -0
- package/dist/messages/glossary.test.js.map +1 -0
- package/dist/messages/index.d.ts +12 -0
- package/dist/messages/index.d.ts.map +1 -0
- package/dist/messages/index.js +23 -0
- package/dist/messages/index.js.map +1 -0
- package/dist/messages/plural.d.ts +10 -0
- package/dist/messages/plural.d.ts.map +1 -0
- package/dist/messages/plural.js +17 -0
- package/dist/messages/plural.js.map +1 -0
- package/dist/messages/use-t.d.ts +10 -0
- package/dist/messages/use-t.d.ts.map +1 -0
- package/dist/messages/use-t.js +10 -0
- package/dist/messages/use-t.js.map +1 -0
- package/dist/module.d.ts +48 -0
- package/dist/module.d.ts.map +1 -0
- package/dist/module.js +174 -0
- package/dist/module.js.map +1 -0
- package/dist/module.test.d.ts +2 -0
- package/dist/module.test.d.ts.map +1 -0
- package/dist/module.test.js +230 -0
- package/dist/module.test.js.map +1 -0
- package/dist/named-views.d.ts +27 -0
- package/dist/named-views.d.ts.map +1 -0
- package/dist/named-views.js +73 -0
- package/dist/named-views.js.map +1 -0
- package/dist/named-views.test.d.ts +2 -0
- package/dist/named-views.test.d.ts.map +1 -0
- package/dist/named-views.test.js +110 -0
- package/dist/named-views.test.js.map +1 -0
- package/dist/plugin.d.ts +44 -0
- package/dist/plugin.d.ts.map +1 -0
- package/dist/plugin.js +52 -0
- package/dist/plugin.js.map +1 -0
- package/dist/prometheus-wiring.test.d.ts +2 -0
- package/dist/prometheus-wiring.test.d.ts.map +1 -0
- package/dist/prometheus-wiring.test.js +142 -0
- package/dist/prometheus-wiring.test.js.map +1 -0
- package/dist/server-locale.d.ts +48 -0
- package/dist/server-locale.d.ts.map +1 -0
- package/dist/server-locale.js +33 -0
- package/dist/server-locale.js.map +1 -0
- package/dist/settings-tools.d.ts +23 -0
- package/dist/settings-tools.d.ts.map +1 -0
- package/dist/settings-tools.js +100 -0
- package/dist/settings-tools.js.map +1 -0
- package/dist/settings.d.ts +77 -0
- package/dist/settings.d.ts.map +1 -0
- package/dist/settings.js +99 -0
- package/dist/settings.js.map +1 -0
- package/dist/settings.test.d.ts +2 -0
- package/dist/settings.test.d.ts.map +1 -0
- package/dist/settings.test.js +299 -0
- package/dist/settings.test.js.map +1 -0
- package/dist/steps/app-config.d.ts +30 -0
- package/dist/steps/app-config.d.ts.map +1 -0
- package/dist/steps/app-config.js +46 -0
- package/dist/steps/app-config.js.map +1 -0
- package/dist/steps/dashboard.d.ts +12 -0
- package/dist/steps/dashboard.d.ts.map +1 -0
- package/dist/steps/dashboard.js +58 -0
- package/dist/steps/dashboard.js.map +1 -0
- package/dist/steps/failure-dashboard.d.ts +10 -0
- package/dist/steps/failure-dashboard.d.ts.map +1 -0
- package/dist/steps/failure-dashboard.js +32 -0
- package/dist/steps/failure-dashboard.js.map +1 -0
- package/dist/steps/index.d.ts +3 -0
- package/dist/steps/index.d.ts.map +1 -0
- package/dist/steps/index.js +3 -0
- package/dist/steps/index.js.map +1 -0
- package/dist/steps/steps.test.d.ts +2 -0
- package/dist/steps/steps.test.d.ts.map +1 -0
- package/dist/steps/steps.test.js +153 -0
- package/dist/steps/steps.test.js.map +1 -0
- package/dist/tool-names.d.ts +13 -0
- package/dist/tool-names.d.ts.map +1 -0
- package/dist/tool-names.js +27 -0
- package/dist/tool-names.js.map +1 -0
- package/dist/tools/cluster-compare.d.ts +8 -0
- package/dist/tools/cluster-compare.d.ts.map +1 -0
- package/dist/tools/cluster-compare.js +17 -0
- package/dist/tools/cluster-compare.js.map +1 -0
- package/dist/tools/element.d.ts +8 -0
- package/dist/tools/element.d.ts.map +1 -0
- package/dist/tools/element.js +25 -0
- package/dist/tools/element.js.map +1 -0
- package/dist/tools/engine-compare.d.ts +8 -0
- package/dist/tools/engine-compare.d.ts.map +1 -0
- package/dist/tools/engine-compare.js +18 -0
- package/dist/tools/engine-compare.js.map +1 -0
- package/dist/tools/engine-compare.test.d.ts +2 -0
- package/dist/tools/engine-compare.test.d.ts.map +1 -0
- package/dist/tools/engine-compare.test.js +166 -0
- package/dist/tools/engine-compare.test.js.map +1 -0
- package/dist/tools/engine-landscape.d.ts +7 -0
- package/dist/tools/engine-landscape.d.ts.map +1 -0
- package/dist/tools/engine-landscape.js +13 -0
- package/dist/tools/engine-landscape.js.map +1 -0
- package/dist/tools/engine-landscape.test.d.ts +2 -0
- package/dist/tools/engine-landscape.test.d.ts.map +1 -0
- package/dist/tools/engine-landscape.test.js +110 -0
- package/dist/tools/engine-landscape.test.js.map +1 -0
- package/dist/tools/failures.d.ts +7 -0
- package/dist/tools/failures.d.ts.map +1 -0
- package/dist/tools/failures.js +13 -0
- package/dist/tools/failures.js.map +1 -0
- package/dist/tools/health.d.ts +7 -0
- package/dist/tools/health.d.ts.map +1 -0
- package/dist/tools/health.js +23 -0
- package/dist/tools/health.js.map +1 -0
- package/dist/tools/health.test.d.ts +2 -0
- package/dist/tools/health.test.d.ts.map +1 -0
- package/dist/tools/health.test.js +119 -0
- package/dist/tools/health.test.js.map +1 -0
- package/dist/tools/index.d.ts +18 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +35 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/performance.d.ts +8 -0
- package/dist/tools/performance.d.ts.map +1 -0
- package/dist/tools/performance.js +25 -0
- package/dist/tools/performance.js.map +1 -0
- package/dist/tools/performance.test.d.ts +2 -0
- package/dist/tools/performance.test.d.ts.map +1 -0
- package/dist/tools/performance.test.js +176 -0
- package/dist/tools/performance.test.js.map +1 -0
- package/dist/tools/version-compare.d.ts +8 -0
- package/dist/tools/version-compare.d.ts.map +1 -0
- package/dist/tools/version-compare.js +17 -0
- package/dist/tools/version-compare.js.map +1 -0
- package/dist/tools/version-compare.test.d.ts +2 -0
- package/dist/tools/version-compare.test.d.ts.map +1 -0
- package/dist/tools/version-compare.test.js +82 -0
- package/dist/tools/version-compare.test.js.map +1 -0
- package/dist/toolsets.d.ts +17 -0
- package/dist/toolsets.d.ts.map +1 -0
- package/dist/toolsets.js +47 -0
- package/dist/toolsets.js.map +1 -0
- package/dist/toolsets.test.d.ts +2 -0
- package/dist/toolsets.test.d.ts.map +1 -0
- package/dist/toolsets.test.js +91 -0
- package/dist/toolsets.test.js.map +1 -0
- package/dist/view-title.test.d.ts +2 -0
- package/dist/view-title.test.d.ts.map +1 -0
- package/dist/view-title.test.js +91 -0
- package/dist/view-title.test.js.map +1 -0
- package/dist/widget-tools/comparisons.d.ts +13 -0
- package/dist/widget-tools/comparisons.d.ts.map +1 -0
- package/dist/widget-tools/comparisons.js +177 -0
- package/dist/widget-tools/comparisons.js.map +1 -0
- package/dist/widget-tools/comparisons.test.d.ts +2 -0
- package/dist/widget-tools/comparisons.test.d.ts.map +1 -0
- package/dist/widget-tools/comparisons.test.js +123 -0
- package/dist/widget-tools/comparisons.test.js.map +1 -0
- package/dist/widget-tools/shared.d.ts +36 -0
- package/dist/widget-tools/shared.d.ts.map +1 -0
- package/dist/widget-tools/shared.js +39 -0
- package/dist/widget-tools/shared.js.map +1 -0
- package/dist/widget-tools.d.ts +25 -0
- package/dist/widget-tools.d.ts.map +1 -0
- package/dist/widget-tools.js +269 -0
- package/dist/widget-tools.js.map +1 -0
- package/dist/widget-tools.test.d.ts +2 -0
- package/dist/widget-tools.test.d.ts.map +1 -0
- package/dist/widget-tools.test.js +272 -0
- package/dist/widget-tools.test.js.map +1 -0
- package/package.json +91 -5
- package/src/bpmn-name-lookup.test.ts +333 -0
- package/src/bpmn-name-lookup.ts +197 -0
- package/src/bpmn-names.ts +51 -0
- package/src/brand-gates.test.ts +69 -0
- package/src/builder-texts.test.ts +40 -0
- package/src/builder-texts.ts +15 -0
- package/src/definition.ts +181 -0
- package/src/engine-ids.ts +85 -0
- package/src/engine-scope.test.ts +324 -0
- package/src/heatmap-data.ts +14 -0
- package/src/index.ts +4 -0
- package/src/instructions.ts +33 -0
- package/src/messages/GLOSSARY.md +88 -0
- package/src/messages/de.ask-ai.ts +28 -0
- package/src/messages/de.builder.ts +77 -0
- package/src/messages/de.server.ts +39 -0
- package/src/messages/de.sweep.ts +244 -0
- package/src/messages/en.ask-ai.ts +34 -0
- package/src/messages/en.builder.ts +76 -0
- package/src/messages/en.server.ts +39 -0
- package/src/messages/en.sweep.ts +240 -0
- package/src/messages/glossary.test.ts +122 -0
- package/src/messages/glossary.ts +62 -0
- package/src/messages/index.ts +24 -0
- package/src/messages/plural.ts +18 -0
- package/src/messages/use-t.ts +12 -0
- package/src/module.test.ts +319 -0
- package/src/module.ts +211 -0
- package/src/named-views.test.ts +141 -0
- package/src/named-views.ts +97 -0
- package/src/plugin.ts +94 -0
- package/src/prometheus-wiring.test.ts +174 -0
- package/src/server-locale.ts +59 -0
- package/src/settings-tools.ts +170 -0
- package/src/settings.test.ts +402 -0
- package/src/settings.ts +114 -0
- package/src/steps/app-config.ts +75 -0
- package/src/steps/dashboard.ts +73 -0
- package/src/steps/failure-dashboard.ts +38 -0
- package/src/steps/index.ts +2 -0
- package/src/steps/steps.test.ts +216 -0
- package/src/tool-names.ts +26 -0
- package/src/tools/cluster-compare.ts +28 -0
- package/src/tools/element.ts +35 -0
- package/src/tools/engine-compare.test.ts +210 -0
- package/src/tools/engine-compare.ts +30 -0
- package/src/tools/engine-landscape.test.ts +138 -0
- package/src/tools/engine-landscape.ts +21 -0
- package/src/tools/failures.ts +19 -0
- package/src/tools/health.test.ts +156 -0
- package/src/tools/health.ts +29 -0
- package/src/tools/index.ts +44 -0
- package/src/tools/performance.test.ts +210 -0
- package/src/tools/performance.ts +38 -0
- package/src/tools/version-compare.test.ts +97 -0
- package/src/tools/version-compare.ts +28 -0
- package/src/toolsets.test.ts +107 -0
- package/src/toolsets.ts +56 -0
- package/src/view-title.test.ts +123 -0
- package/src/widget-tools/comparisons.test.ts +170 -0
- package/src/widget-tools/comparisons.ts +229 -0
- package/src/widget-tools/shared.ts +67 -0
- package/src/widget-tools.test.ts +306 -0
- package/src/widget-tools.ts +375 -0
- package/src/widgets/analytics-dashboard/activity-bottleneck-table.tsx +179 -0
- package/src/widgets/analytics-dashboard/definition-breakdown.tsx +108 -0
- package/src/widgets/analytics-dashboard/execution-performance-kpi.tsx +94 -0
- package/src/widgets/analytics-dashboard/execution-summary-kpi.tsx +122 -0
- package/src/widgets/analytics-dashboard/lib.ts +43 -0
- package/src/widgets/bpmn-heatmap.test.tsx +75 -0
- package/src/widgets/bpmn-heatmap.tsx +127 -0
- package/src/widgets/catalogue-sync.test.ts +16 -0
- package/src/widgets/cluster-compare.tsx +148 -0
- package/src/widgets/comparison-shared.test.ts +237 -0
- package/src/widgets/comparison-shared.tsx +371 -0
- package/src/widgets/comparison-widgets.test.tsx +307 -0
- package/src/widgets/dashboard-widgets.test.tsx +397 -0
- package/src/widgets/engine-compare.tsx +87 -0
- package/src/widgets/engine-landscape.tsx +352 -0
- package/src/widgets/failure-dashboard/error-patterns-table.tsx +122 -0
- package/src/widgets/failure-dashboard/failure-rate-table.test.ts +80 -0
- package/src/widgets/failure-dashboard/failure-rate-table.tsx +170 -0
- package/src/widgets/failure-dashboard/lib.ts +32 -0
- package/src/widgets/failure-dashboard/summary-kpi.tsx +122 -0
- package/src/widgets/failure-landscape-widgets.test.tsx +393 -0
- package/src/widgets/figure.tsx +79 -0
- package/src/widgets/hand-off.test.ts +126 -0
- package/src/widgets/hand-off.ts +102 -0
- package/src/widgets/index.ts +124 -0
- package/src/widgets/model-descriptions.dashboard.test.ts +280 -0
- package/src/widgets/model-descriptions.test.ts +251 -0
- package/src/widgets/model-descriptions.ts +428 -0
- package/src/widgets/names.test.ts +32 -0
- package/src/widgets/names.ts +39 -0
- package/src/widgets/query-gate.test.tsx +57 -0
- package/src/widgets/query-gate.tsx +50 -0
- package/src/widgets/settings-section.test.tsx +174 -0
- package/src/widgets/settings-section.tsx +244 -0
- package/src/widgets/version-compare.test.ts +68 -0
- package/src/widgets/version-compare.tsx +96 -0
- package/src/widgets/view-meta.ts +18 -0
- package/src/widgets/widget-render.test-support.tsx +103 -0
|
@@ -0,0 +1,397 @@
|
|
|
1
|
+
// @vitest-environment happy-dom
|
|
2
|
+
import { describe, expect, it } from "vitest"
|
|
3
|
+
import { cleanup, screen, within } from "@testing-library/react"
|
|
4
|
+
import type { AnalyticsDashboardData } from "@miragon/pulse-analytics-client"
|
|
5
|
+
import { ExecutionSummaryKpi } from "./analytics-dashboard/execution-summary-kpi.js"
|
|
6
|
+
import { ExecutionPerformanceKpi } from "./analytics-dashboard/execution-performance-kpi.js"
|
|
7
|
+
import { ProcessDefinitionBreakdown } from "./analytics-dashboard/definition-breakdown.js"
|
|
8
|
+
import { ActivityBottleneckTable } from "./analytics-dashboard/activity-bottleneck-table.js"
|
|
9
|
+
import { AnalyticsBpmnHeatmap, type AnalyticsBpmnHeatmapData } from "./bpmn-heatmap.js"
|
|
10
|
+
import type { Named } from "../bpmn-names.js"
|
|
11
|
+
import {
|
|
12
|
+
AS_OF,
|
|
13
|
+
headers,
|
|
14
|
+
iconOf,
|
|
15
|
+
kpiTone,
|
|
16
|
+
legendLines,
|
|
17
|
+
metaLine,
|
|
18
|
+
missing,
|
|
19
|
+
missingFigures,
|
|
20
|
+
plain,
|
|
21
|
+
renderIn,
|
|
22
|
+
withWidgetClock,
|
|
23
|
+
} from "./widget-render.test-support.js"
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* The analytics dashboard and the heatmap as a person reads them, in German
|
|
27
|
+
* and English: numbers in the view's locale, the reference frame under the
|
|
28
|
+
* title (U7), names before ids (U13), numbers neutral with the state as a dot
|
|
29
|
+
* (U14), and every hand-off named after its function and the chat (U4) with
|
|
30
|
+
* a Lucide icon. The failure dashboard and the landscape:
|
|
31
|
+
* `failure-landscape-widgets.test.tsx`.
|
|
32
|
+
*/
|
|
33
|
+
|
|
34
|
+
withWidgetClock()
|
|
35
|
+
|
|
36
|
+
const DASHBOARD: Named<AnalyticsDashboardData> = {
|
|
37
|
+
processDefinitionKey: null,
|
|
38
|
+
period: "7d",
|
|
39
|
+
engines: ["prod-a", "prod-b", "prod-c"],
|
|
40
|
+
reportingEngines: ["prod-a", "prod-c"],
|
|
41
|
+
asOf: AS_OF,
|
|
42
|
+
totalCount: 1629,
|
|
43
|
+
completedCount: 1482,
|
|
44
|
+
incidentsCreated: 55,
|
|
45
|
+
incidentsResolved: 34,
|
|
46
|
+
incidentRatePct: 3.38,
|
|
47
|
+
avgDurationMs: 30_840_000,
|
|
48
|
+
medianDurationMs: 24_600_000,
|
|
49
|
+
p95DurationMs: 73_860_000,
|
|
50
|
+
runningNow: 52,
|
|
51
|
+
openIncidentsNow: null,
|
|
52
|
+
previous: null,
|
|
53
|
+
activityBreakdown: [
|
|
54
|
+
{
|
|
55
|
+
processDefinitionKey: "miraveloLeasing",
|
|
56
|
+
activityId: "Activity_DecideOnApplication",
|
|
57
|
+
activityType: "userTask",
|
|
58
|
+
executionCount: 1240,
|
|
59
|
+
avgDurationMs: 187_000,
|
|
60
|
+
p95DurationMs: 420_000,
|
|
61
|
+
totalTimeMs: 231_880_000,
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
processDefinitionKey: "invoice",
|
|
65
|
+
activityId: "Event_Paid",
|
|
66
|
+
activityType: "noneEndEvent",
|
|
67
|
+
executionCount: 300,
|
|
68
|
+
avgDurationMs: 0,
|
|
69
|
+
p95DurationMs: null,
|
|
70
|
+
totalTimeMs: 0,
|
|
71
|
+
},
|
|
72
|
+
],
|
|
73
|
+
activityCount: 2,
|
|
74
|
+
definitionBreakdown: [
|
|
75
|
+
{
|
|
76
|
+
processDefinitionKey: "miraveloLeasing",
|
|
77
|
+
totalInstances: 1288,
|
|
78
|
+
completed: 1262,
|
|
79
|
+
runningNow: 1,
|
|
80
|
+
incidentsCreated: 1,
|
|
81
|
+
avgDurationMs: 8_340_000,
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
processDefinitionKey: "invoice",
|
|
85
|
+
totalInstances: 341,
|
|
86
|
+
completed: 220,
|
|
87
|
+
runningNow: null,
|
|
88
|
+
incidentsCreated: 0,
|
|
89
|
+
avgDurationMs: null,
|
|
90
|
+
},
|
|
91
|
+
],
|
|
92
|
+
names: {
|
|
93
|
+
miraveloLeasing: {
|
|
94
|
+
name: "Bike Leasing",
|
|
95
|
+
elements: { Activity_DecideOnApplication: "Decide on application" },
|
|
96
|
+
},
|
|
97
|
+
},
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
describe("the analytics dashboard in German", () => {
|
|
101
|
+
it("frames the figures under the title and hands off to the chat to assess them", () => {
|
|
102
|
+
renderIn("de", ExecutionSummaryKpi, DASHBOARD)
|
|
103
|
+
expect(screen.getByText("Prozessanalyse")).toBeTruthy()
|
|
104
|
+
expect(metaLine()).toBe("Letzte 7 Tage · 3 Engines (1 ohne Metriken) · Stand 14:32")
|
|
105
|
+
expect(screen.getByText("1.629")).toBeTruthy()
|
|
106
|
+
expect(screen.getByText("Neue Incidents")).toBeTruthy()
|
|
107
|
+
// A live gauge nobody reports is unknown, never a plausible 0.
|
|
108
|
+
expect(screen.getByText("—")).toBeTruthy()
|
|
109
|
+
const ask = screen.getByRole("button", { name: /Im Chat bewerten/ })
|
|
110
|
+
expect(iconOf(ask)).toContain("lucide-list-checks")
|
|
111
|
+
})
|
|
112
|
+
|
|
113
|
+
it("names the process a scoped dashboard is about first, by its name when known", () => {
|
|
114
|
+
renderIn("de", ExecutionSummaryKpi, {
|
|
115
|
+
...DASHBOARD,
|
|
116
|
+
processDefinitionKey: "order",
|
|
117
|
+
period: "1d",
|
|
118
|
+
})
|
|
119
|
+
expect(metaLine()).toBe("order · Letzte 24 Stunden · 3 Engines (1 ohne Metriken) · Stand 14:32")
|
|
120
|
+
cleanup()
|
|
121
|
+
renderIn("de", ExecutionSummaryKpi, { ...DASHBOARD, processDefinitionKey: "miraveloLeasing" })
|
|
122
|
+
expect(metaLine()).toMatch(/^Bike Leasing · Letzte 7 Tage/)
|
|
123
|
+
})
|
|
124
|
+
|
|
125
|
+
// U14: counts of what happened carry no state; only an open incident does.
|
|
126
|
+
it("keeps every count neutral and marks only open incidents", () => {
|
|
127
|
+
renderIn("de", ExecutionSummaryKpi, { ...DASHBOARD, openIncidentsNow: 21 })
|
|
128
|
+
for (const label of ["Gestartet", "Abgeschlossen", "Neue Incidents", "Laufen gerade"]) {
|
|
129
|
+
expect(kpiTone(label), label).toBeUndefined()
|
|
130
|
+
}
|
|
131
|
+
expect(kpiTone("Offene Incidents jetzt")).toBe("danger")
|
|
132
|
+
expect(document.querySelector("[class*='text-success'], [class*='text-info']")).toBeNull()
|
|
133
|
+
})
|
|
134
|
+
|
|
135
|
+
it("shows an incident rate as incidents per 100 starts, not as a share", () => {
|
|
136
|
+
renderIn("de", ExecutionPerformanceKpi, DASHBOARD)
|
|
137
|
+
expect(screen.getByText("Incidents je 100 Starts")).toBeTruthy()
|
|
138
|
+
expect(screen.getByText("3,4")).toBeTruthy()
|
|
139
|
+
expect(plain(screen.getByText(/^8 h/).textContent)).toBe("8 h 34 Min.")
|
|
140
|
+
// No previous period (a 30-day view): no verdict, no tone.
|
|
141
|
+
expect(kpiTone("Incidents je 100 Starts")).toBeUndefined()
|
|
142
|
+
expect(screen.queryByText(/Vorperiode/)).toBeNull()
|
|
143
|
+
})
|
|
144
|
+
|
|
145
|
+
it("judges the incident rate only against the previous period, from its threshold on", () => {
|
|
146
|
+
const previous = {
|
|
147
|
+
totalCount: 1500,
|
|
148
|
+
incidentsCreated: 20,
|
|
149
|
+
incidentRatePct: 1.3,
|
|
150
|
+
partial: false,
|
|
151
|
+
suppressed: false,
|
|
152
|
+
}
|
|
153
|
+
// The process held fixed: the only scope a change of the rate says something about.
|
|
154
|
+
const scoped = { ...DASHBOARD, processDefinitionKey: "miraveloLeasing" }
|
|
155
|
+
renderIn("de", ExecutionPerformanceKpi, { ...scoped, previous })
|
|
156
|
+
const worse = screen.getByText("Vorperiode: 1,3, schlechter")
|
|
157
|
+
expect(iconOf(worse.parentElement!)).toContain("lucide-trending-up")
|
|
158
|
+
expect(iconOf(worse.parentElement!)).toContain("text-danger")
|
|
159
|
+
// The rate itself stays neutral: the verdict is the trend, never the digit.
|
|
160
|
+
expect(kpiTone("Incidents je 100 Starts")).toBeUndefined()
|
|
161
|
+
cleanup()
|
|
162
|
+
|
|
163
|
+
// Below the threshold of 1 per 100 starts: the number, no verdict.
|
|
164
|
+
renderIn("de", ExecutionPerformanceKpi, {
|
|
165
|
+
...scoped,
|
|
166
|
+
previous: { ...previous, incidentRatePct: 3 },
|
|
167
|
+
})
|
|
168
|
+
const flat = screen.getByText("Vorperiode: 3")
|
|
169
|
+
expect(iconOf(flat.parentElement!)).toContain("lucide-minus")
|
|
170
|
+
expect(iconOf(flat.parentElement!)).not.toMatch(/text-(danger|success)/)
|
|
171
|
+
cleanup()
|
|
172
|
+
|
|
173
|
+
// Over too few starts: shown, not judged.
|
|
174
|
+
renderIn("en", ExecutionPerformanceKpi, {
|
|
175
|
+
...scoped,
|
|
176
|
+
previous: { ...previous, suppressed: true },
|
|
177
|
+
})
|
|
178
|
+
const noisy = screen.getByText("Previous period: 1.3, not reliable")
|
|
179
|
+
expect(iconOf(noisy.parentElement!)).not.toMatch(/text-(danger|success)/)
|
|
180
|
+
cleanup()
|
|
181
|
+
|
|
182
|
+
renderIn("en", ExecutionPerformanceKpi, {
|
|
183
|
+
...scoped,
|
|
184
|
+
previous: { ...previous, totalCount: 0, incidentsCreated: 0, incidentRatePct: null },
|
|
185
|
+
})
|
|
186
|
+
expect(screen.getByText("Previous period: no starts")).toBeTruthy()
|
|
187
|
+
})
|
|
188
|
+
|
|
189
|
+
// Simpson's paradox: over several processes the rate moves with their mix,
|
|
190
|
+
// even while no process changed, so its change is no verdict.
|
|
191
|
+
it("names the previous rate of a dashboard over several processes without judging it", () => {
|
|
192
|
+
const previous = {
|
|
193
|
+
totalCount: 1500,
|
|
194
|
+
incidentsCreated: 20,
|
|
195
|
+
incidentRatePct: 1.3,
|
|
196
|
+
partial: false,
|
|
197
|
+
suppressed: false,
|
|
198
|
+
}
|
|
199
|
+
renderIn("de", ExecutionPerformanceKpi, { ...DASHBOARD, previous })
|
|
200
|
+
const reference = screen.getByText("Vorperiode: 1,3")
|
|
201
|
+
const line = reference.parentElement!
|
|
202
|
+
expect(iconOf(line)).toBe("")
|
|
203
|
+
expect(line.querySelector("[class*='bg-danger'], [class*='bg-success']")).toBeNull()
|
|
204
|
+
expect(screen.queryByText(/schlechter|besser/)).toBeNull()
|
|
205
|
+
expect(kpiTone("Incidents je 100 Starts")).toBeUndefined()
|
|
206
|
+
})
|
|
207
|
+
|
|
208
|
+
it("lays the breakdown out as a table with right-aligned figures", () => {
|
|
209
|
+
renderIn("de", ProcessDefinitionBreakdown, DASHBOARD)
|
|
210
|
+
const table = screen.getByRole("table", {
|
|
211
|
+
name: "Starts, Abschlüsse, laufende Instanzen und Incidents je Prozess",
|
|
212
|
+
})
|
|
213
|
+
expect(headers(table)).toEqual([
|
|
214
|
+
"Prozess",
|
|
215
|
+
"Gestartet",
|
|
216
|
+
"Abgeschlossen",
|
|
217
|
+
"Laufen gerade",
|
|
218
|
+
"Neue Incidents",
|
|
219
|
+
"Durchschn. Dauer",
|
|
220
|
+
])
|
|
221
|
+
// The name first, the key below it, quiet and in mono.
|
|
222
|
+
expect(screen.getByText("Bike Leasing")).toBeTruthy()
|
|
223
|
+
const key = screen.getByText("miraveloLeasing")
|
|
224
|
+
expect(key.className).toContain("font-mono")
|
|
225
|
+
// Without a known name the key leads, still in mono.
|
|
226
|
+
expect(screen.getByText("invoice").className).toContain("font-mono")
|
|
227
|
+
const started = screen.getByText("1.288").closest("td")!
|
|
228
|
+
expect(started.className).toContain("text-right")
|
|
229
|
+
expect(started.className).toContain("tabular-nums")
|
|
230
|
+
// Not measured is "—", never 0, and it says why (U17): read out in its
|
|
231
|
+
// place, as the tooltip, and in the key under the table for everyone.
|
|
232
|
+
const invoiceRow = screen.getByText("invoice").closest("tr")!
|
|
233
|
+
expect(missingFigures(invoiceRow)).toEqual([
|
|
234
|
+
missing("Keine Engine meldet diesen Wert: unbekannt"),
|
|
235
|
+
missing("In diesem Zeitraum ist nichts beendet: keine Dauer"),
|
|
236
|
+
])
|
|
237
|
+
expect(legendLines()).toEqual([
|
|
238
|
+
"— Keine Engine meldet diesen Wert: unbekannt",
|
|
239
|
+
"— In diesem Zeitraum ist nichts beendet: keine Dauer",
|
|
240
|
+
])
|
|
241
|
+
})
|
|
242
|
+
|
|
243
|
+
it("shows no key under a breakdown without a missing figure", () => {
|
|
244
|
+
renderIn("de", ProcessDefinitionBreakdown, {
|
|
245
|
+
...DASHBOARD,
|
|
246
|
+
definitionBreakdown: [DASHBOARD.definitionBreakdown[0]],
|
|
247
|
+
})
|
|
248
|
+
expect(missingFigures(document.body)).toEqual([])
|
|
249
|
+
expect(legendLines()).toEqual([])
|
|
250
|
+
})
|
|
251
|
+
|
|
252
|
+
// CI §3.3, decisions f and o: new incidents are a volume of the period, as
|
|
253
|
+
// in the summary above, so no count in the breakdown carries a tone.
|
|
254
|
+
it("keeps every count neutral, new incidents included", () => {
|
|
255
|
+
const { container } = renderIn("de", ProcessDefinitionBreakdown, DASHBOARD)
|
|
256
|
+
const leasing = screen.getByText("Bike Leasing").closest("tr")!
|
|
257
|
+
// Running now and new incidents: both a plain tabular figure in its cell.
|
|
258
|
+
for (const figure of within(leasing).getAllByText("1")) {
|
|
259
|
+
expect(figure.tagName).toBe("TD")
|
|
260
|
+
expect(figure.className).toContain("tabular-nums")
|
|
261
|
+
}
|
|
262
|
+
expect(container.querySelector("[data-tone]")).toBeNull()
|
|
263
|
+
expect(container.querySelector("[class*='-ink']")).toBeNull()
|
|
264
|
+
expect(container.querySelector("[class*='text-success'], [class*='text-danger']")).toBeNull()
|
|
265
|
+
})
|
|
266
|
+
|
|
267
|
+
it("names the activities, keeps the sort key next to them and explains a bottleneck in the chat", () => {
|
|
268
|
+
renderIn("de", ActivityBottleneckTable, DASHBOARD)
|
|
269
|
+
expect(screen.getByText("Aktivitäten nach Gesamtzeit")).toBeTruthy()
|
|
270
|
+
const table = screen.getByRole("table", {
|
|
271
|
+
name: "Aktivitäten je Prozess, sortiert nach gesamter Ausführungszeit",
|
|
272
|
+
})
|
|
273
|
+
expect(headers(table).slice(0, 5)).toEqual([
|
|
274
|
+
"Aktivität",
|
|
275
|
+
"Gesamtzeit",
|
|
276
|
+
"Ausführungen",
|
|
277
|
+
"Durchschn.",
|
|
278
|
+
"P95",
|
|
279
|
+
])
|
|
280
|
+
const total = within(table).getAllByRole("columnheader")[1]
|
|
281
|
+
expect(total.getAttribute("aria-sort")).toBe("descending")
|
|
282
|
+
expect(iconOf(total)).toContain("lucide-arrow-down")
|
|
283
|
+
// Name first; id, type in words and (on a dashboard over several processes) the process below.
|
|
284
|
+
expect(screen.getByText("Decide on application")).toBeTruthy()
|
|
285
|
+
const row = screen.getByText("Decide on application").closest("tr")!
|
|
286
|
+
expect(plain(row.querySelector("td")?.textContent)).toBe(
|
|
287
|
+
"Decide on applicationActivity_DecideOnApplication · User-Task · Bike Leasing",
|
|
288
|
+
)
|
|
289
|
+
// An unknown name: the id leads; the engine's own type name folded into the BPMN element.
|
|
290
|
+
const paid = screen.getByText("Event_Paid").closest("td")!
|
|
291
|
+
expect(plain(paid.textContent)).toBe("Event_PaidEndereignis · invoice")
|
|
292
|
+
// A P95 over nothing that ended: "—" with its reason, never 0 ms, and
|
|
293
|
+
// the key under the table says it to readers who cannot hover.
|
|
294
|
+
expect(missingFigures(paid.closest("tr")!)).toEqual([
|
|
295
|
+
missing("In diesem Zeitraum ist nichts beendet: keine Dauer"),
|
|
296
|
+
])
|
|
297
|
+
expect(legendLines()).toEqual(["— In diesem Zeitraum ist nichts beendet: keine Dauer"])
|
|
298
|
+
expect(screen.getByText("1.240")).toBeTruthy()
|
|
299
|
+
const ask = screen.getAllByRole("button", { name: "Engpass im Chat erklären" })[0]
|
|
300
|
+
expect(iconOf(ask)).toContain("lucide-hourglass")
|
|
301
|
+
})
|
|
302
|
+
|
|
303
|
+
it("calls a cut list what it is: the top by total time, of how many", () => {
|
|
304
|
+
renderIn("de", ActivityBottleneckTable, { ...DASHBOARD, activityCount: 37 })
|
|
305
|
+
expect(screen.getByText("Top 2 nach Gesamtzeit")).toBeTruthy()
|
|
306
|
+
expect(screen.getByText("Die 2 Aktivitäten mit der meisten Gesamtzeit, von 37.")).toBeTruthy()
|
|
307
|
+
})
|
|
308
|
+
|
|
309
|
+
it("drops the process from the second line of a dashboard about one process", () => {
|
|
310
|
+
renderIn("en", ActivityBottleneckTable, {
|
|
311
|
+
...DASHBOARD,
|
|
312
|
+
processDefinitionKey: "miraveloLeasing",
|
|
313
|
+
})
|
|
314
|
+
const row = screen.getByText("Decide on application").closest("td")!
|
|
315
|
+
expect(plain(row.textContent)).toBe(
|
|
316
|
+
"Decide on applicationActivity_DecideOnApplication · User task",
|
|
317
|
+
)
|
|
318
|
+
})
|
|
319
|
+
|
|
320
|
+
it("says what to do when nothing ended, in a quiet empty state", () => {
|
|
321
|
+
renderIn("de", ActivityBottleneckTable, {
|
|
322
|
+
...DASHBOARD,
|
|
323
|
+
activityBreakdown: [],
|
|
324
|
+
activityCount: 0,
|
|
325
|
+
})
|
|
326
|
+
expect(screen.getByText("In diesem Zeitraum hat keine Aktivität geendet")).toBeTruthy()
|
|
327
|
+
expect(
|
|
328
|
+
screen.getByText("Wähl einen längeren Zeitraum oder prüf, ob die Engines Metriken melden."),
|
|
329
|
+
).toBeTruthy()
|
|
330
|
+
expect(screen.queryByRole("alert")).toBeNull()
|
|
331
|
+
})
|
|
332
|
+
})
|
|
333
|
+
|
|
334
|
+
describe("the analytics dashboard in English", () => {
|
|
335
|
+
it("frames the figures and keeps sentence case", () => {
|
|
336
|
+
renderIn("en", ExecutionSummaryKpi, { ...DASHBOARD, reportingEngines: undefined })
|
|
337
|
+
// Without the reporting engines the line says nothing about them.
|
|
338
|
+
expect(metaLine()).toBe("Last 7 days · 3 engines · As of 14:32")
|
|
339
|
+
expect(screen.getByText("1,629")).toBeTruthy()
|
|
340
|
+
expect(screen.getByText("Process analytics")).toBeTruthy()
|
|
341
|
+
expect(screen.getByRole("button", { name: /Assess in chat/ })).toBeTruthy()
|
|
342
|
+
})
|
|
343
|
+
})
|
|
344
|
+
|
|
345
|
+
const HEATMAP: AnalyticsBpmnHeatmapData = {
|
|
346
|
+
processDefinitionKey: "order",
|
|
347
|
+
period: "14d",
|
|
348
|
+
engines: ["prod-a", "prod-b"],
|
|
349
|
+
frequency: { Task_A: 12 },
|
|
350
|
+
durationSec: { Task_A: 3.5 },
|
|
351
|
+
asOf: AS_OF,
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
/** The heatmap's diagram feed: the view reads the XML from it, never from its payload. */
|
|
355
|
+
const diagram = (bpmnXml: string | null) => ({ analytics_bpmn_xml_data: { bpmnXml } })
|
|
356
|
+
|
|
357
|
+
describe("the BPMN heatmap", () => {
|
|
358
|
+
it("states period, engines and as-of in place of the period badge (de)", async () => {
|
|
359
|
+
renderIn("de", AnalyticsBpmnHeatmap, HEATMAP, diagram('<?xml version="1.0"?><definitions />'))
|
|
360
|
+
expect(await screen.findByText("BPMN-Heatmap")).toBeTruthy()
|
|
361
|
+
expect(metaLine()).toBe("Letzte 14 Tage · 2 Engines · Stand 14:32")
|
|
362
|
+
expect(screen.queryByText(/Zeitraum:/)).toBeNull()
|
|
363
|
+
})
|
|
364
|
+
|
|
365
|
+
it("blames the missing camunda7 module only when the server says so (en)", () => {
|
|
366
|
+
renderIn("en", AnalyticsBpmnHeatmap, { ...HEATMAP, bpmnMissing: "no-camunda7" })
|
|
367
|
+
expect(
|
|
368
|
+
screen.getByText(
|
|
369
|
+
"The diagram is not available here: without the camunda7 module, analytics cannot load BPMN files. Ask in the chat for the figures per activity instead.",
|
|
370
|
+
),
|
|
371
|
+
).toBeTruthy()
|
|
372
|
+
expect(document.querySelector("[data-view-meta]")).toBeNull()
|
|
373
|
+
})
|
|
374
|
+
|
|
375
|
+
it("names the engine lookup when camunda7 is there but found no diagram (de)", () => {
|
|
376
|
+
renderIn("de", AnalyticsBpmnHeatmap, { ...HEATMAP, bpmnMissing: "not-loaded" })
|
|
377
|
+
expect(
|
|
378
|
+
screen.getByText(
|
|
379
|
+
"Das Diagramm konnte nicht geladen werden: Keine Engine dieser Ansicht hat es geliefert. Prüf, ob die Engines erreichbar sind und der Prozess bereitgestellt ist, oder frag im Chat nach den Kennzahlen je Aktivität.",
|
|
380
|
+
),
|
|
381
|
+
).toBeTruthy()
|
|
382
|
+
expect(screen.queryByText(/camunda7-Modul/)).toBeNull()
|
|
383
|
+
})
|
|
384
|
+
|
|
385
|
+
it.each([undefined, "constructor"])(
|
|
386
|
+
"names no cause it does not know (bpmnMissing: %s)",
|
|
387
|
+
async (bpmnMissing) => {
|
|
388
|
+
// Without a known cause the view reads the diagram feed, which has none.
|
|
389
|
+
renderIn("en", AnalyticsBpmnHeatmap, { ...HEATMAP, bpmnMissing }, diagram(null))
|
|
390
|
+
expect(
|
|
391
|
+
await screen.findByText(
|
|
392
|
+
"Could not load the diagram. Ask in the chat for the figures per activity instead.",
|
|
393
|
+
),
|
|
394
|
+
).toBeTruthy()
|
|
395
|
+
},
|
|
396
|
+
)
|
|
397
|
+
})
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { Badge } from "@miragon/mcp-toolkit-ui"
|
|
2
|
+
import type { EngineCompareResult } from "@miragon/pulse-analytics-client"
|
|
3
|
+
import {
|
|
4
|
+
HandOffButton,
|
|
5
|
+
ViewMeta,
|
|
6
|
+
formatLookback,
|
|
7
|
+
formatNumber,
|
|
8
|
+
} from "@miragon/pulse-widget-shell/widgets"
|
|
9
|
+
import { useT } from "../messages/use-t.js"
|
|
10
|
+
import {
|
|
11
|
+
ComparisonCard,
|
|
12
|
+
ComparisonEmptyState,
|
|
13
|
+
SuppressedBadge,
|
|
14
|
+
buildComparisonMetrics,
|
|
15
|
+
deltaFacts,
|
|
16
|
+
} from "./comparison-shared.js"
|
|
17
|
+
import { useHandOff, type HandOff } from "./hand-off.js"
|
|
18
|
+
|
|
19
|
+
export type EngineCompareData = EngineCompareResult | null
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Interpret ONE process on two engines. The process is held fixed, so a real
|
|
23
|
+
* gap is the engine's (or its environment's) — confirmed by the comparison,
|
|
24
|
+
* then by each engine's live snapshot.
|
|
25
|
+
*/
|
|
26
|
+
export function engineCompareHandOff(data: EngineCompareResult): HandOff {
|
|
27
|
+
return {
|
|
28
|
+
intent: "askAi.engineCompare",
|
|
29
|
+
ids: {
|
|
30
|
+
processDefinitionKey: data.processDefinitionKey,
|
|
31
|
+
engineA: data.engineA,
|
|
32
|
+
engineB: data.engineB,
|
|
33
|
+
windowDays: data.windowDays,
|
|
34
|
+
activityId: data.activityId,
|
|
35
|
+
},
|
|
36
|
+
facts: deltaFacts(data.delta, data.suppressed),
|
|
37
|
+
tools: ["analytics_engine_compare", "analytics_engine_health"],
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export function EngineCompareWidget({ data }: { data: EngineCompareData }) {
|
|
42
|
+
const t = useT()
|
|
43
|
+
const { ask } = useHandOff()
|
|
44
|
+
if (!data) return <ComparisonEmptyState>{t("aEngineCompare.emptyNoData")}</ComparisonEmptyState>
|
|
45
|
+
|
|
46
|
+
const a = data.kpis.find((k) => k.bucket === "engineA")
|
|
47
|
+
const b = data.kpis.find((k) => k.bucket === "engineB")
|
|
48
|
+
if (!a || !b) {
|
|
49
|
+
return <ComparisonEmptyState>{t("aEngineCompare.emptyIncomplete")}</ComparisonEmptyState>
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const metrics = buildComparisonMetrics(t, a, b, data.delta)
|
|
53
|
+
|
|
54
|
+
return (
|
|
55
|
+
<ComparisonCard
|
|
56
|
+
title={t("aEngineCompare.title")}
|
|
57
|
+
tableLabel={t("aEngineCompare.tableLabel")}
|
|
58
|
+
beforeLabel={data.engineA}
|
|
59
|
+
afterLabel={data.engineB}
|
|
60
|
+
metrics={metrics}
|
|
61
|
+
suppressed={data.suppressed}
|
|
62
|
+
actions={
|
|
63
|
+
<HandOffButton action="assess" prompt={ask(engineCompareHandOff(data))} variant="primary" />
|
|
64
|
+
}
|
|
65
|
+
// The two engines head the columns; the line names the period and when.
|
|
66
|
+
meta={<ViewMeta period={formatLookback(`${data.windowDays}d`)} asOf={data.asOf} />}
|
|
67
|
+
badges={
|
|
68
|
+
<>
|
|
69
|
+
<Badge variant="secondary">
|
|
70
|
+
{t("aEngineCompare.enginesBadge", { engineA: data.engineA, engineB: data.engineB })}
|
|
71
|
+
</Badge>
|
|
72
|
+
<Badge>{data.processDefinitionKey}</Badge>
|
|
73
|
+
{data.activityId && (
|
|
74
|
+
<Badge variant="outline">
|
|
75
|
+
{t("aEngineCompare.elementBadge", { id: data.activityId })}
|
|
76
|
+
</Badge>
|
|
77
|
+
)}
|
|
78
|
+
{data.suppressed && (
|
|
79
|
+
<SuppressedBadge>
|
|
80
|
+
{t("aEngineCompare.suppressed", { min: formatNumber(data.minBucketSize) })}
|
|
81
|
+
</SuppressedBadge>
|
|
82
|
+
)}
|
|
83
|
+
</>
|
|
84
|
+
}
|
|
85
|
+
/>
|
|
86
|
+
)
|
|
87
|
+
}
|