Fix types
This commit is contained in:
@@ -87,9 +87,11 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useInjectedViewerInterfaceState } from '~~/lib/viewer/composables/setup'
|
||||
import type { PropertySelectOption } from '~/lib/viewer/helpers/filters/types'
|
||||
import type {
|
||||
PropertySelectOption,
|
||||
ExtendedPropertyInfo
|
||||
} from '~/lib/viewer/helpers/filters/types'
|
||||
import { FilterType } from '~/lib/viewer/helpers/filters/types'
|
||||
import type { PropertyInfo } from '@speckle/viewer'
|
||||
import { useMixpanel } from '~~/lib/core/composables/mp'
|
||||
import { X, Plus } from 'lucide-vue-next'
|
||||
import { FormButton } from '@speckle/ui-components'
|
||||
@@ -120,7 +122,8 @@ const filtersContainerRef = ref<HTMLElement>()
|
||||
const shouldScrollToNewFilter = ref(false)
|
||||
|
||||
const showLargePropertyWarning = ref(false)
|
||||
const pendingProperty = ref<Nullable<{ property: PropertyInfo; count: number }>>(null)
|
||||
const pendingProperty =
|
||||
ref<Nullable<{ property: ExtendedPropertyInfo; count: number }>>(null)
|
||||
|
||||
const propertySelectOptions = computed((): PropertySelectOption[] => {
|
||||
if (!showPropertySelection.value) {
|
||||
@@ -234,7 +237,10 @@ const selectProperty = async (propertyKey: string) => {
|
||||
processPropertySelection(property, propertyKey)
|
||||
}
|
||||
|
||||
const processPropertySelection = (property: PropertyInfo, propertyKey: string) => {
|
||||
const processPropertySelection = (
|
||||
property: ExtendedPropertyInfo,
|
||||
propertyKey: string
|
||||
) => {
|
||||
if (swappingFilterId.value) {
|
||||
updateFilterProperty(swappingFilterId.value, property)
|
||||
mp.track('Viewer Action', {
|
||||
|
||||
@@ -76,8 +76,10 @@ import { useFilterUtilities } from '~/lib/viewer/composables/filtering/filtering
|
||||
import { useInjectedViewerState } from '~~/lib/viewer/composables/setup'
|
||||
import type { KeyValuePair } from '~/components/viewer/selection/types'
|
||||
import { isNumericPropertyInfo } from '~/lib/viewer/helpers/sceneExplorer'
|
||||
import type { PropertyInfo } from '@speckle/viewer'
|
||||
import { BooleanFilterCondition } from '~/lib/viewer/helpers/filters/types'
|
||||
import {
|
||||
BooleanFilterCondition,
|
||||
type ExtendedPropertyInfo
|
||||
} from '~/lib/viewer/helpers/filters/types'
|
||||
import { isBooleanProperty } from '~/lib/viewer/helpers/filters/utils'
|
||||
|
||||
const props = defineProps<{
|
||||
@@ -103,13 +105,13 @@ const {
|
||||
} = useInjectedViewerState()
|
||||
|
||||
const availableFilters = computed(
|
||||
() => getPropertyOptionsFromDataStore() as PropertyInfo[]
|
||||
() => getPropertyOptionsFromDataStore() as ExtendedPropertyInfo[]
|
||||
)
|
||||
|
||||
const showActionsMenu = ref(false)
|
||||
|
||||
const showLargePropertyWarning = ref(false)
|
||||
const pendingFilter = ref<PropertyInfo | null>(null)
|
||||
const pendingFilter = ref<ExtendedPropertyInfo | null>(null)
|
||||
const pendingFilterCount = ref(0)
|
||||
|
||||
const isUrlString = (v: unknown) => typeof v === 'string' && VALID_HTTP_URL.test(v)
|
||||
@@ -152,7 +154,7 @@ const handleAddToFilters = (kvp: KeyValuePair) => {
|
||||
}
|
||||
}
|
||||
|
||||
const addFilterWithValue = (filter: PropertyInfo, kvp: KeyValuePair) => {
|
||||
const addFilterWithValue = (filter: ExtendedPropertyInfo, kvp: KeyValuePair) => {
|
||||
const filterId = addActiveFilter(filter)
|
||||
|
||||
if (isNumericPropertyInfo(filter)) {
|
||||
|
||||
@@ -1,8 +1,4 @@
|
||||
import type {
|
||||
PropertyInfo,
|
||||
NumericPropertyInfo,
|
||||
StringPropertyInfo
|
||||
} from '@speckle/viewer'
|
||||
import type { NumericPropertyInfo, StringPropertyInfo } from '@speckle/viewer'
|
||||
import { difference, uniq, partition } from 'lodash-es'
|
||||
import { whenever } from '@vueuse/core'
|
||||
import {
|
||||
@@ -28,7 +24,8 @@ import {
|
||||
BooleanFilterCondition,
|
||||
SortMode,
|
||||
type DataSlice,
|
||||
type QueryCriteria
|
||||
type QueryCriteria,
|
||||
type ExtendedPropertyInfo
|
||||
} from '~/lib/viewer/helpers/filters/types'
|
||||
import { getConditionLabel } from '~/lib/viewer/helpers/filters/constants'
|
||||
import { useFilteringDataStore } from '~/lib/viewer/composables/filtering/dataStore'
|
||||
@@ -128,11 +125,16 @@ export function useFilterUtilities(
|
||||
/**
|
||||
* Gets available values for the current property filter (used for UI display)
|
||||
*/
|
||||
const getAvailableFilterValues = (filter: PropertyInfo, limit?: number): string[] => {
|
||||
const getAvailableFilterValues = (
|
||||
filter: ExtendedPropertyInfo,
|
||||
limit?: number
|
||||
): string[] => {
|
||||
// Type guard to check if filter has valueGroups property
|
||||
const hasValueGroups = (
|
||||
f: PropertyInfo
|
||||
): f is PropertyInfo & { valueGroups: Array<{ value: string | number }> } => {
|
||||
f: ExtendedPropertyInfo
|
||||
): f is ExtendedPropertyInfo & {
|
||||
valueGroups: Array<{ value: string | number }>
|
||||
} => {
|
||||
return (
|
||||
'valueGroups' in f && Array.isArray((f as Record<string, unknown>).valueGroups)
|
||||
)
|
||||
@@ -187,7 +189,7 @@ export function useFilterUtilities(
|
||||
*/
|
||||
const computeFullPropertyData = (
|
||||
propertyKey: string
|
||||
): PropertyInfo | BooleanPropertyInfo | null => {
|
||||
): ExtendedPropertyInfo | null => {
|
||||
const valueToObjectIds = new Map<string, string[]>()
|
||||
|
||||
for (const dataSource of dataStore.dataSources.value) {
|
||||
@@ -273,7 +275,7 @@ export function useFilterUtilities(
|
||||
}
|
||||
|
||||
const isBooleanPropertyInfo = (
|
||||
prop: PropertyInfo | BooleanPropertyInfo
|
||||
prop: ExtendedPropertyInfo
|
||||
): prop is BooleanPropertyInfo => {
|
||||
return prop.type === 'boolean'
|
||||
}
|
||||
@@ -345,7 +347,7 @@ export function useFilterUtilities(
|
||||
}
|
||||
}
|
||||
|
||||
const addActiveFilter = (filter: PropertyInfo): string => {
|
||||
const addActiveFilter = (filter: ExtendedPropertyInfo): string => {
|
||||
const existingIndex = filters.propertyFilters.value.findIndex(
|
||||
(f) => f.filter?.key === filter.key
|
||||
)
|
||||
@@ -368,7 +370,7 @@ export function useFilterUtilities(
|
||||
*/
|
||||
const updateFilterProperty = (
|
||||
filterId: string,
|
||||
newProperty: PropertyInfo
|
||||
newProperty: ExtendedPropertyInfo
|
||||
): boolean => {
|
||||
const filterIndex = filters.propertyFilters.value.findIndex(
|
||||
(f) => f.id === filterId
|
||||
@@ -708,7 +710,7 @@ export function useFilterUtilities(
|
||||
|
||||
resetFilters() // Clear existing filters first
|
||||
|
||||
const availableProperties = getPropertyOptionsFromDataStore() as PropertyInfo[]
|
||||
const availableProperties = getPropertyOptionsFromDataStore()
|
||||
|
||||
// If data store is ready, restore immediately
|
||||
if (availableProperties.length > 0) {
|
||||
@@ -730,7 +732,7 @@ export function useFilterUtilities(
|
||||
id: string
|
||||
condition: 'AND' | 'OR'
|
||||
}>,
|
||||
availableProperties: PropertyInfo[]
|
||||
availableProperties: ExtendedPropertyInfo[]
|
||||
) => {
|
||||
for (const serializedFilter of serializedFilters) {
|
||||
if (serializedFilter.key) {
|
||||
@@ -756,9 +758,9 @@ export function useFilterUtilities(
|
||||
* Filters the available filters to only include relevant ones for the filter UI
|
||||
*/
|
||||
const getRelevantFilters = (
|
||||
allFilters: PropertyInfo[] | null | undefined
|
||||
): PropertyInfo[] => {
|
||||
return (allFilters || []).filter((f: PropertyInfo) => {
|
||||
allFilters: ExtendedPropertyInfo[] | null | undefined
|
||||
): ExtendedPropertyInfo[] => {
|
||||
return (allFilters || []).filter((f: ExtendedPropertyInfo) => {
|
||||
if (shouldExcludeFromFiltering(f.key)) {
|
||||
return false
|
||||
}
|
||||
@@ -770,10 +772,10 @@ export function useFilterUtilities(
|
||||
* Gets property options from the data store (optimized to use propertyMap)
|
||||
*/
|
||||
const getPropertyOptionsFromDataStore = (): (
|
||||
| PropertyInfo
|
||||
| ExtendedPropertyInfo
|
||||
| BooleanPropertyInfo
|
||||
)[] => {
|
||||
const allProperties = new Map<string, PropertyInfo | BooleanPropertyInfo>()
|
||||
const allProperties = new Map<string, ExtendedPropertyInfo | BooleanPropertyInfo>()
|
||||
|
||||
for (const dataSource of dataStore.dataSources.value) {
|
||||
const propertyKeys = Object.keys(dataSource.propertyMap)
|
||||
@@ -825,7 +827,7 @@ export function useFilterUtilities(
|
||||
* Gets filtered and sorted values for a string filter with search and sorting options
|
||||
*/
|
||||
const getFilteredFilterValues = (
|
||||
filter: PropertyInfo,
|
||||
filter: ExtendedPropertyInfo,
|
||||
options?: {
|
||||
searchQuery?: string
|
||||
sortMode?: SortMode
|
||||
@@ -866,7 +868,8 @@ export function useFilterUtilities(
|
||||
|
||||
whenever(shouldRestoreFilters, () => {
|
||||
if (pendingFiltersToRestore.value) {
|
||||
const availableProperties = getPropertyOptionsFromDataStore() as PropertyInfo[]
|
||||
const availableProperties =
|
||||
getPropertyOptionsFromDataStore() as ExtendedPropertyInfo[]
|
||||
applyFiltersFromSerialized(pendingFiltersToRestore.value, availableProperties)
|
||||
pendingFiltersToRestore.value = null
|
||||
}
|
||||
|
||||
@@ -77,10 +77,16 @@ export type StringFilterData = BaseFilterData & {
|
||||
isDefaultAllSelected?: boolean
|
||||
}
|
||||
|
||||
export type BooleanPropertyInfo = Omit<PropertyInfo, 'type'> & {
|
||||
type: 'boolean'
|
||||
valueGroups: { value: boolean; ids: string[] }[]
|
||||
}
|
||||
export type ExtendedPropertyInfo =
|
||||
| PropertyInfo
|
||||
| {
|
||||
key: string
|
||||
objectCount: number
|
||||
type: 'boolean'
|
||||
valueGroups: { value: boolean; ids: string[] }[]
|
||||
}
|
||||
|
||||
export type BooleanPropertyInfo = Extract<ExtendedPropertyInfo, { type: 'boolean' }>
|
||||
|
||||
export type BooleanFilterData = BaseFilterData & {
|
||||
type: FilterType.Boolean
|
||||
@@ -128,7 +134,7 @@ export type PropertySelectionListItem = {
|
||||
}
|
||||
|
||||
export type CreateFilterParams = {
|
||||
filter: PropertyInfo
|
||||
filter: ExtendedPropertyInfo
|
||||
id: string
|
||||
availableValues?: string[]
|
||||
}
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
import type { PropertyInfo } from '@speckle/viewer'
|
||||
import { isStringPropertyInfo } from '~/lib/viewer/helpers/sceneExplorer'
|
||||
import { ExistenceFilterCondition } from './types'
|
||||
import {
|
||||
ExistenceFilterCondition,
|
||||
type BooleanPropertyInfo,
|
||||
type ExtendedPropertyInfo
|
||||
} from '~/lib/viewer/helpers/filters/types'
|
||||
|
||||
export const revitPropertyRegex = /^parameters\./
|
||||
export const revitPropertyRegexDui3000InstanceProps = /^properties\.Instance/
|
||||
@@ -59,7 +62,7 @@ export const shouldExcludeFromFiltering = (key: string): boolean => {
|
||||
*/
|
||||
export const getPropertyName = (
|
||||
key: string,
|
||||
availableFilters?: PropertyInfo[] | null
|
||||
availableFilters?: ExtendedPropertyInfo[] | null
|
||||
): string => {
|
||||
if (!key) return 'Loading'
|
||||
|
||||
@@ -68,7 +71,7 @@ export const getPropertyName = (
|
||||
|
||||
if (isRevitProperty(key) && key.endsWith('.value')) {
|
||||
const correspondingProperty = (availableFilters || []).find(
|
||||
(f: PropertyInfo) => f.key === key.replace('.value', '.name')
|
||||
(f: ExtendedPropertyInfo) => f.key === key.replace('.value', '.name')
|
||||
)
|
||||
if (correspondingProperty && isStringPropertyInfo(correspondingProperty)) {
|
||||
return correspondingProperty.valueGroups[0]?.value || key.split('.').pop() || key
|
||||
@@ -83,8 +86,8 @@ export const getPropertyName = (
|
||||
*/
|
||||
export const findFilterByDisplayName = (
|
||||
displayKey: string,
|
||||
availableFilters: PropertyInfo[] | null | undefined
|
||||
): PropertyInfo | undefined => {
|
||||
availableFilters: ExtendedPropertyInfo[] | null | undefined
|
||||
): ExtendedPropertyInfo | undefined => {
|
||||
if (!availableFilters) return undefined
|
||||
|
||||
// First, try to find an exact display name match
|
||||
@@ -107,7 +110,7 @@ export const findFilterByDisplayName = (
|
||||
*/
|
||||
export const isKvpFilterable = (
|
||||
kvp: { key: string; backendPath?: string },
|
||||
availableFilters: PropertyInfo[] | null | undefined
|
||||
availableFilters: ExtendedPropertyInfo[] | null | undefined
|
||||
): boolean => {
|
||||
// Use backendPath for legacy compatibility, but prefer the direct key
|
||||
const propertyKey = kvp.backendPath || kvp.key
|
||||
@@ -132,7 +135,7 @@ export const isKvpFilterable = (
|
||||
*/
|
||||
export const getFilterDisabledReason = (
|
||||
kvp: { key: string; backendPath?: string },
|
||||
availableFilters: PropertyInfo[] | null | undefined
|
||||
availableFilters: ExtendedPropertyInfo[] | null | undefined
|
||||
): string => {
|
||||
const availableKeys = availableFilters?.map((f) => f.key) || []
|
||||
|
||||
@@ -187,20 +190,22 @@ export const getFilterDisabledReason = (
|
||||
*/
|
||||
export const findFilterByKvp = (
|
||||
kvp: { key: string; backendPath?: string },
|
||||
availableFilters: PropertyInfo[] | null | undefined
|
||||
): PropertyInfo | undefined => {
|
||||
availableFilters: ExtendedPropertyInfo[] | null | undefined
|
||||
): ExtendedPropertyInfo | undefined => {
|
||||
if (!availableFilters) return undefined
|
||||
|
||||
if (kvp.backendPath) {
|
||||
const exactMatch = availableFilters.find(
|
||||
(f: PropertyInfo) => f.key === kvp.backendPath
|
||||
(f: ExtendedPropertyInfo) => f.key === kvp.backendPath
|
||||
)
|
||||
if (exactMatch) {
|
||||
return exactMatch
|
||||
}
|
||||
}
|
||||
|
||||
const directMatch = availableFilters.find((f: PropertyInfo) => f.key === kvp.key)
|
||||
const directMatch = availableFilters.find(
|
||||
(f: ExtendedPropertyInfo) => f.key === kvp.key
|
||||
)
|
||||
if (directMatch) {
|
||||
return directMatch
|
||||
}
|
||||
@@ -208,7 +213,7 @@ export const findFilterByKvp = (
|
||||
// If we have a backendPath but no exact match, try partial matching
|
||||
if (kvp.backendPath) {
|
||||
const pathParts = kvp.backendPath.split('.')
|
||||
const partialMatches = availableFilters.filter((f: PropertyInfo) => {
|
||||
const partialMatches = availableFilters.filter((f: ExtendedPropertyInfo) => {
|
||||
const filterParts = f.key.split('.')
|
||||
|
||||
if (pathParts.length === 1) {
|
||||
@@ -241,14 +246,17 @@ export const findFilterByKvp = (
|
||||
return findFilterByDisplayName(displayKey, availableFilters)
|
||||
}
|
||||
|
||||
export const isBooleanProperty = (filter: PropertyInfo): boolean => {
|
||||
export const isBooleanProperty = (filter: ExtendedPropertyInfo): boolean => {
|
||||
return 'type' in filter && (filter as { type: string }).type === 'boolean'
|
||||
}
|
||||
|
||||
/**
|
||||
* Get count for a specific filter value
|
||||
*/
|
||||
export function getFilterValueCount(filter: PropertyInfo, value: string): number {
|
||||
export function getFilterValueCount(
|
||||
filter: ExtendedPropertyInfo,
|
||||
value: string
|
||||
): number {
|
||||
if (!('valueGroups' in filter) || !Array.isArray(filter.valueGroups)) {
|
||||
return 0
|
||||
}
|
||||
@@ -268,7 +276,7 @@ export function getFilterValueCount(filter: PropertyInfo, value: string): number
|
||||
* Get count for existence filters (objects that have/don't have a property set)
|
||||
*/
|
||||
export function getExistenceFilterCount(
|
||||
filter: PropertyInfo,
|
||||
filter: ExtendedPropertyInfo | BooleanPropertyInfo,
|
||||
condition: ExistenceFilterCondition,
|
||||
totalObjectCount?: number
|
||||
): number {
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
import type { MaybeNullOrUndefined } from '@speckle/shared'
|
||||
import type {
|
||||
NumericPropertyInfo,
|
||||
PropertyInfo,
|
||||
SpeckleObject,
|
||||
SpeckleReference,
|
||||
StringPropertyInfo
|
||||
} from '@speckle/viewer'
|
||||
import type { Raw } from 'vue'
|
||||
import type { ExtendedPropertyInfo } from '~/lib/viewer/helpers/filters/types'
|
||||
|
||||
export const isStringPropertyInfo = (
|
||||
info: MaybeNullOrUndefined<PropertyInfo>
|
||||
info: MaybeNullOrUndefined<ExtendedPropertyInfo>
|
||||
): info is StringPropertyInfo => info?.type === 'string'
|
||||
export const isNumericPropertyInfo = (
|
||||
info: MaybeNullOrUndefined<PropertyInfo>
|
||||
info: MaybeNullOrUndefined<ExtendedPropertyInfo>
|
||||
): info is NumericPropertyInfo => info?.type === 'number'
|
||||
|
||||
export type ExplorerNode = {
|
||||
|
||||
Reference in New Issue
Block a user