fix: auto-compute environment slug + respect environment filter globally
All checks were successful
CI / cleanup-branch (push) Has been skipped
CI / build (push) Successful in 1m26s
CI / docker (push) Successful in 1m6s
CI / deploy-feature (push) Has been skipped
CI / deploy (push) Successful in 37s

Part A: Environment creation slug is now auto-derived from display name
and shown read-only (matching app creation pattern). Removes manual slug
input.

Part B: All data queries now pass the selected environment to backend:
- Exchanges search, Dashboard L1/L2/L3 stats, Routes metrics, Route
  detail, correlation chains, and processor metrics all filter by
  selected environment.
- Backend RouteMetricsController now accepts environment parameter for
  both route and processor metrics endpoints.

Closes #XYZ

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
hsiegeln
2026-04-09 16:01:50 +02:00
parent f95a78a380
commit cb36d7936f
11 changed files with 81 additions and 43 deletions

View File

@@ -16,6 +16,7 @@ import { useGlobalFilters } from '@cameleer/design-system';
import { useRouteMetrics } from '../../api/queries/catalog';
import { useExecutionStats, useStatsTimeseries } from '../../api/queries/executions';
import { useTimeseriesByApp, useTopErrors, useAllAppSettings, usePunchcard } from '../../api/queries/dashboard';
import { useEnvironmentStore } from '../../api/environment-store';
import type { AppSettings } from '../../api/queries/dashboard';
import { Treemap } from './Treemap';
import type { TreemapItem } from './Treemap';
@@ -290,17 +291,18 @@ function buildKpiItems(
export default function DashboardL1() {
const navigate = useNavigate();
const selectedEnv = useEnvironmentStore((s) => s.environment);
const { timeRange } = useGlobalFilters();
const timeFrom = timeRange.start.toISOString();
const timeTo = timeRange.end.toISOString();
const windowSeconds = (timeRange.end.getTime() - timeRange.start.getTime()) / 1000;
const { data: metrics } = useRouteMetrics(timeFrom, timeTo);
const { data: stats } = useExecutionStats(timeFrom, timeTo);
const { data: timeseries } = useStatsTimeseries(timeFrom, timeTo);
const { data: timeseriesByApp } = useTimeseriesByApp(timeFrom, timeTo);
const { data: topErrors } = useTopErrors(timeFrom, timeTo);
const { data: punchcardData } = usePunchcard();
const { data: metrics } = useRouteMetrics(timeFrom, timeTo, undefined, selectedEnv);
const { data: stats } = useExecutionStats(timeFrom, timeTo, undefined, undefined, selectedEnv);
const { data: timeseries } = useStatsTimeseries(timeFrom, timeTo, undefined, undefined, selectedEnv);
const { data: timeseriesByApp } = useTimeseriesByApp(timeFrom, timeTo, selectedEnv);
const { data: topErrors } = useTopErrors(timeFrom, timeTo, undefined, undefined, selectedEnv);
const { data: punchcardData } = usePunchcard(undefined, selectedEnv);
const { data: allAppSettings } = useAllAppSettings();
// Build settings lookup map

View File

@@ -20,6 +20,7 @@ import {
useAppSettings,
usePunchcard,
} from '../../api/queries/dashboard';
import { useEnvironmentStore } from '../../api/environment-store';
import type { TopError } from '../../api/queries/dashboard';
import { Treemap } from './Treemap';
import type { TreemapItem } from './Treemap';
@@ -270,18 +271,19 @@ function buildKpiItems(
export default function DashboardL2() {
const { appId } = useParams<{ appId: string }>();
const navigate = useNavigate();
const selectedEnv = useEnvironmentStore((s) => s.environment);
const { timeRange } = useGlobalFilters();
const timeFrom = timeRange.start.toISOString();
const timeTo = timeRange.end.toISOString();
const windowSeconds = (timeRange.end.getTime() - timeRange.start.getTime()) / 1000;
// Data hooks
const { data: stats } = useExecutionStats(timeFrom, timeTo, undefined, appId);
const { data: timeseries } = useStatsTimeseries(timeFrom, timeTo, undefined, appId);
const { data: metrics } = useRouteMetrics(timeFrom, timeTo, appId);
const { data: timeseriesByRoute } = useTimeseriesByRoute(timeFrom, timeTo, appId);
const { data: errors } = useTopErrors(timeFrom, timeTo, appId);
const { data: punchcardData } = usePunchcard(appId);
const { data: stats } = useExecutionStats(timeFrom, timeTo, undefined, appId, selectedEnv);
const { data: timeseries } = useStatsTimeseries(timeFrom, timeTo, undefined, appId, selectedEnv);
const { data: metrics } = useRouteMetrics(timeFrom, timeTo, appId, selectedEnv);
const { data: timeseriesByRoute } = useTimeseriesByRoute(timeFrom, timeTo, appId, selectedEnv);
const { data: errors } = useTopErrors(timeFrom, timeTo, appId, undefined, selectedEnv);
const { data: punchcardData } = usePunchcard(appId, selectedEnv);
const { data: appSettings } = useAppSettings(appId);
const slaThresholdMs = appSettings?.slaThresholdMs ?? 300;

View File

@@ -14,6 +14,7 @@ import { useGlobalFilters } from '@cameleer/design-system';
import { useExecutionStats, useStatsTimeseries } from '../../api/queries/executions';
import { useProcessorMetrics } from '../../api/queries/processor-metrics';
import { useTopErrors, useAppSettings } from '../../api/queries/dashboard';
import { useEnvironmentStore } from '../../api/environment-store';
import type { TopError } from '../../api/queries/dashboard';
import { useDiagramByRoute } from '../../api/queries/diagrams';
import { ProcessDiagram } from '../../components/ProcessDiagram';
@@ -244,16 +245,17 @@ function buildKpiItems(
export default function DashboardL3() {
const { appId, routeId } = useParams<{ appId: string; routeId: string }>();
const selectedEnv = useEnvironmentStore((s) => s.environment);
const { timeRange } = useGlobalFilters();
const timeFrom = timeRange.start.toISOString();
const timeTo = timeRange.end.toISOString();
const windowSeconds = (timeRange.end.getTime() - timeRange.start.getTime()) / 1000;
// ── Data hooks ──────────────────────────────────────────────────────────
const { data: stats } = useExecutionStats(timeFrom, timeTo, routeId, appId);
const { data: timeseries } = useStatsTimeseries(timeFrom, timeTo, routeId, appId);
const { data: processorMetrics } = useProcessorMetrics(routeId ?? null, appId);
const { data: topErrors } = useTopErrors(timeFrom, timeTo, appId, routeId);
const { data: stats } = useExecutionStats(timeFrom, timeTo, routeId, appId, selectedEnv);
const { data: timeseries } = useStatsTimeseries(timeFrom, timeTo, routeId, appId, selectedEnv);
const { data: processorMetrics } = useProcessorMetrics(routeId ?? null, appId, selectedEnv);
const { data: topErrors } = useTopErrors(timeFrom, timeTo, appId, routeId, selectedEnv);
const { data: diagramLayout } = useDiagramByRoute(appId, routeId);
const { data: appSettings } = useAppSettings(appId);