From fa6c7a68f8bab14d3adb1825619ab8724f8d5659 Mon Sep 17 00:00:00 2001 From: Drew Davis Date: Wed, 5 Aug 2026 11:43:14 -0400 Subject: [PATCH 1/2] fix: Only auto-detect metric tables when the database selection changes --- ...etric-table-autofill-on-database-change.md | 5 + .../SourceForm/MetricTableModelForm.tsx | 35 ++- .../Sources/SourceForm/SourceForm.tsx | 7 +- .../Sources/SourceForm/TableModelForm.tsx | 10 +- .../components/Sources/SourceForm/types.ts | 2 + .../__tests__/MetricTableModelForm.test.tsx | 260 ++++++++++++++++++ .../e2e/components/SourceFormComponent.ts | 68 +++++ .../features/metric-table-autofill.spec.ts | 165 +++++++++++ packages/app/tests/e2e/seed-clickhouse.ts | 25 ++ packages/app/tests/e2e/utils/constants.ts | 10 + 10 files changed, 582 insertions(+), 5 deletions(-) create mode 100644 .changeset/metric-table-autofill-on-database-change.md create mode 100644 packages/app/src/components/__tests__/MetricTableModelForm.test.tsx create mode 100644 packages/app/tests/e2e/features/metric-table-autofill.spec.ts diff --git a/.changeset/metric-table-autofill-on-database-change.md b/.changeset/metric-table-autofill-on-database-change.md new file mode 100644 index 0000000000..cd349fc59c --- /dev/null +++ b/.changeset/metric-table-autofill-on-database-change.md @@ -0,0 +1,5 @@ +--- +'@hyperdx/app': patch +--- + +fix: Only auto-detect metric tables when the database selection changes diff --git a/packages/app/src/components/Sources/SourceForm/MetricTableModelForm.tsx b/packages/app/src/components/Sources/SourceForm/MetricTableModelForm.tsx index 2a462bc988..5e4021d659 100644 --- a/packages/app/src/components/Sources/SourceForm/MetricTableModelForm.tsx +++ b/packages/app/src/components/Sources/SourceForm/MetricTableModelForm.tsx @@ -1,6 +1,6 @@ import { useEffect, useRef } from 'react'; import { useWatch } from 'react-hook-form'; -import { MetricsDataType } from '@hyperdx/common-utils/dist/types'; +import { MetricsDataType, SourceKind } from '@hyperdx/common-utils/dist/types'; import { Stack, Text } from '@mantine/core'; import { notifications } from '@mantine/notifications'; @@ -10,7 +10,7 @@ import { DBTableSelectControlled } from '@/components/DBTableSelect'; import { SourceSelectControlled } from '@/components/SourceSelect'; import { useMetadataWithSettings } from '@/hooks/useMetadata'; import { useMetricsSeriesTableAvailability } from '@/hooks/useMetricsSeriesTableAvailability'; -import { isValidMetricTable } from '@/source'; +import { isValidMetricTable, useSource } from '@/source'; import { useBrandDisplayName } from '@/theme/ThemeProvider'; import { matchMetricTables, @@ -21,7 +21,11 @@ import { DEFAULT_DATABASE, OTEL_CLICKHOUSE_EXPRESSIONS } from './constants'; import { FormRow } from './FormRow'; import { TableModelProps } from './types'; -export function MetricTableModelForm({ control, setValue }: TableModelProps) { +export function MetricTableModelForm({ + control, + setValue, + sourceId, +}: TableModelProps) { const brandName = useBrandDisplayName(); const { data: team } = api.useTeam(); const isMetricsSeriesTableEnabled = !!team?.isMetricsSeriesTableEnabled; @@ -143,10 +147,31 @@ export function MetricTableModelForm({ control, setValue }: TableModelProps) { { enabled: !!databaseName && !!connectionId }, ); + const { data: savedSource } = useSource({ id: sourceId }); + const savedDatabaseName = savedSource?.from?.databaseName; + const wasSavedAsMetricSource = savedSource?.kind === SourceKind.Metric; + const isExistingSource = !!sourceId; + const lastAutofillKeyRef = useRef(''); + const hasLoadedSavedSourceRef = useRef(false); useEffect(() => { const key = `${databaseName}:${connectionId}`; + + if (isExistingSource && !hasLoadedSavedSourceRef.current) { + // Until the saved source lands in the form the watched values are still + // the new-source defaults, so nothing here reflects a user choice yet. + if (!savedSource) return; + if (savedDatabaseName && databaseName !== savedDatabaseName) return; + hasLoadedSavedSourceRef.current = true; + if (wasSavedAsMetricSource) { + // Treat the saved database as already handled — only a later switch to + // a different database triggers autofill. + lastAutofillKeyRef.current = key; + return; + } + } + if (key === lastAutofillKeyRef.current) return; // already ran for this db const tableNames = tablesData?.data?.map((t: { name: string }) => t.name); @@ -230,6 +255,10 @@ export function MetricTableModelForm({ control, setValue }: TableModelProps) { connectionId, metadata, isMetricsSeriesTableEnabled, + isExistingSource, + savedSource, + savedDatabaseName, + wasSavedAsMetricSource, ]); return ( diff --git a/packages/app/src/components/Sources/SourceForm/SourceForm.tsx b/packages/app/src/components/Sources/SourceForm/SourceForm.tsx index e1d8a4c36f..4cb391eb76 100644 --- a/packages/app/src/components/Sources/SourceForm/SourceForm.tsx +++ b/packages/app/src/components/Sources/SourceForm/SourceForm.tsx @@ -728,7 +728,12 @@ export function TableSourceForm({ - + {onCancel && (