diff --git a/src/components/Dashboard/common/FilterInput.jsx b/src/components/Dashboard/common/FilterInput.jsx index 9e2aaa0..c2ba552 100644 --- a/src/components/Dashboard/common/FilterInput.jsx +++ b/src/components/Dashboard/common/FilterInput.jsx @@ -1,5 +1,5 @@ -import { useCallback, useContext, useEffect, useRef, useState } from 'react' -import { ConfigProvider, Tag, theme } from 'antd' +import { useCallback, useContext, useEffect, useMemo, useRef, useState } from 'react' +import { ConfigProvider, Popover, Tag, theme } from 'antd' import { CloseCircleFilled } from '@ant-design/icons' import PropTypes from 'prop-types' import { createRoot } from 'react-dom/client' @@ -9,6 +9,8 @@ import useSize from 'antd/es/config-provider/hooks/useSize' import { useCompactItemContext } from 'antd/es/space/Compact' import useStyle, { useSharedStyle } from 'antd/es/input/style' import { useThemeContext } from '../context/ThemeContext' +import SimplePropertyFilter from './SimplePropertyFilter' +import ScrollBox from './ScrollBox' // Longer symbols first so ".." / "<>" / ">=" match before "." / "<" / ">". // Wildcards (* ?) and @ stay as plain text — they are not operands. @@ -327,6 +329,25 @@ const chipsHaveLiveRoots = (root, roots) => { return true } +const toFilterExpression = (values) => { + if (!values?.length) return '' + const parts = values.map((value) => { + if (value && typeof value === 'object') { + return String(value._id ?? value.type ?? JSON.stringify(value)) + } + return String(value) + }) + return parts.length === 1 ? parts[0] : parts.join('|') +} + +const fromFilterExpression = (expr) => { + if (expr === undefined || expr === null || expr === '') return [] + if (typeof expr === 'string' && expr.includes('|')) { + return expr.split('|').filter((part) => part !== '') + } + return [expr] +} + const FilterInput = ({ value = '', onChange, @@ -338,7 +359,8 @@ const FilterInput = ({ onFocus, onBlur, onPressEnter, - size + size, + propertyFilter = null }) => { const { getPrefixCls, direction } = useContext(ConfigProvider.ConfigContext) const prefixCls = getPrefixCls('input') @@ -734,6 +756,46 @@ const FilterInput = ({ editorRef.current?.focus() } + const propertyFilterEnabled = + !disabled && + propertyFilter?.modelType != null && + propertyFilter?.propertyName != null + + const propertyFilterValue = useMemo( + () => fromFilterExpression(internalValue), + [internalValue] + ) + + const handlePropertyFilterChange = useCallback( + (keys) => { + const next = toFilterExpression(keys) + paint(next, focusedRef.current ? next.length : null) + emitChange(next) + }, + [emitChange, paint] + ) + + const propertyFilterContent = propertyFilterEnabled ? ( +