From 4e29cf635535dfb4fa439b4d594a51e05b705253 Mon Sep 17 00:00:00 2001 From: andrewwallacespeckle Date: Fri, 3 Oct 2025 12:00:32 +0100 Subject: [PATCH] fix(fe): Ensure string properties with mixed numeric/UUID values are classified as string filters --- .../viewer/composables/filtering/dataStore.ts | 17 +++++++++++++++-- .../viewer/composables/filtering/filtering.ts | 18 ++++++++---------- .../lib/viewer/helpers/filters/utils.ts | 10 ++++++++++ 3 files changed, 33 insertions(+), 12 deletions(-) diff --git a/packages/frontend-2/lib/viewer/composables/filtering/dataStore.ts b/packages/frontend-2/lib/viewer/composables/filtering/dataStore.ts index 01f2aad60..fd7663e97 100644 --- a/packages/frontend-2/lib/viewer/composables/filtering/dataStore.ts +++ b/packages/frontend-2/lib/viewer/composables/filtering/dataStore.ts @@ -20,7 +20,8 @@ import { useInjectedViewerState } from '~~/lib/viewer/composables/setup' import { shouldExcludeFromFiltering, extractNestedProperties, - isParameter + isParameter, + isValueNumeric } from '~/lib/viewer/helpers/filters/utils' import { DEEP_EXTRACTION_CONFIG } from '~/lib/viewer/helpers/filters/constants' @@ -32,7 +33,9 @@ function processBatchedPropertyUpdates( propertyMap: Record ) { for (const update of updates) { - if (!propertyMap[update.path]) { + const existingProperty = propertyMap[update.path] + + if (!existingProperty) { // Convert string type to FilterType let filterType: FilterType if (update.type === 'number') { @@ -48,6 +51,15 @@ function processBatchedPropertyUpdates( value: update.value as string | number, type: filterType } + } else { + // Property exists - check if we need to update type due to conflicting evidence + if ( + existingProperty.type === FilterType.Numeric && + typeof update.value === 'string' && + !isValueNumeric(update.value) + ) { + existingProperty.type = FilterType.String + } } } } @@ -193,6 +205,7 @@ export function useCreateViewerFilteringDataStore() { if (pendingPropertyUpdates.length > 0) { processBatchedPropertyUpdates(pendingPropertyUpdates, propertyMap) + pendingPropertyUpdates.length = 0 } objectProperties[objectId] = objProps diff --git a/packages/frontend-2/lib/viewer/composables/filtering/filtering.ts b/packages/frontend-2/lib/viewer/composables/filtering/filtering.ts index 8302f6467..0f9bff02f 100644 --- a/packages/frontend-2/lib/viewer/composables/filtering/filtering.ts +++ b/packages/frontend-2/lib/viewer/composables/filtering/filtering.ts @@ -34,7 +34,8 @@ import { getPropertyName, isKvpFilterable, getFilterDisabledReason, - findFilterByKvp + findFilterByKvp, + isValueNumeric } from '~/lib/viewer/helpers/filters/utils' import { useFilterColoringHelpers } from '~/lib/viewer/composables/filtering/coloringHelpers' import { @@ -236,8 +237,7 @@ export function useFilterUtilities( uniqueValues.length <= 2 const isNumeric = - typeof firstValue === 'number' || - (!isNaN(Number(firstValue)) && String(firstValue) !== '') + typeof firstValue === 'number' || uniqueValues.every((v) => isValueNumeric(v)) if (isBooleanProperty) { return { @@ -829,19 +829,17 @@ export function useFilterUtilities( } const propertyInfo = dataSource.propertyMap[propertyKey] - const value = propertyInfo.value - const isBoolean = String(value) === 'true' || String(value) === 'false' - const isNumeric = - typeof value === 'number' || (!isNaN(Number(value)) && String(value) !== '') - if (isBoolean) { + const filterType = propertyInfo.type + + if (filterType === FilterType.Boolean) { allProperties.set(propertyKey, { key: propertyKey, type: 'boolean', objectCount: 0, valueGroups: [] } as BooleanPropertyInfo) - } else if (isNumeric) { + } else if (filterType === FilterType.Numeric) { allProperties.set(propertyKey, { key: propertyKey, type: 'number', @@ -856,7 +854,7 @@ export function useFilterUtilities( allProperties.set(propertyKey, { key: propertyKey, type: 'string', - objectCount: 0, // Not needed for selection + objectCount: 0, valueGroups: [] } as StringPropertyInfo) } diff --git a/packages/frontend-2/lib/viewer/helpers/filters/utils.ts b/packages/frontend-2/lib/viewer/helpers/filters/utils.ts index 346d78112..be7c0755e 100644 --- a/packages/frontend-2/lib/viewer/helpers/filters/utils.ts +++ b/packages/frontend-2/lib/viewer/helpers/filters/utils.ts @@ -266,6 +266,16 @@ export const isBooleanProperty = (filter: ExtendedPropertyInfo): boolean => { return 'type' in filter && (filter as { type: string }).type === 'boolean' } +/** + * Determines if a value should be treated as numeric for filtering + */ +export const isValueNumeric = (value: unknown): boolean => { + return ( + typeof value === 'number' || + (!isNaN(Number(value)) && String(value) !== '' && !/[a-zA-Z-]/.test(String(value))) + ) +} + /** * Get count for a specific filter value */