UNPKG

@adaptabletools/adaptable

Version:

Powerful AG Grid extension which provides advanced, cutting-edge functionality to meet all DataGrid requirements

143 lines (142 loc) 10 kB
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime"; import * as React from 'react'; import SimpleButton from '../../../components/SimpleButton'; import { ColumnFilterInputList } from './components/ColumnFilterInputList'; import { usePredicateDef } from './hooks'; import Radio from '../../../components/Radio'; import { useAdaptable } from '../../AdaptableContext'; import { mapQlPredicateToAdaptablePredicate } from './utils'; import { Box, Flex } from '../../../components/Flex'; import { twMerge } from '../../../twMerge'; import { SingleSelect } from '../../../components/NewSelect'; import { isEmbeddedColumnFilterLocation } from './columnFilterLocation'; import { cn, captureTab } from '../../../lib/utils'; const ColumnFilterPredicateDropdown = (props) => { const predicateDef = usePredicateDef(props.predicate?.operator, props.predicateDefs); const options = props.predicateDefs.map((predicateDef) => { return { label: (_jsxs(Box, { className: "twa:flex twa:items-center", children: [_jsx(SimpleButton, { as: "span", variant: "raised", className: "twa:mr-2 twa:p-0.5", tone: "accent", children: predicateDef.icon }), predicateDef.label] })), tooltip: predicateDef.label, value: predicateDef.operator, }; }); const operator = props.predicate?.operator; const isAndOr = operator === 'AND' || operator === 'OR'; return (_jsx(Box, { className: "twa:flex twa:items-center ab-ColumnFilterPredicateDropdown twa:p-0.5", style: { '--ab-color-input-background': 'var(--ab-color-primary)', }, children: _jsx(SingleSelect, { "data-name": "filter-predicate-dropdown", extraWidthChars: 8, stopMouseDownPropagation: true, showItemTooltip: true, className: predicateDef ? `twa:min-w-[10rem]` : null, onValueChange: (value) => { props.onPredicateChange({ operator: value, args: [], }); }, items: options, placeholder: "Add Condition", value: isAndOr ? null : props.predicate?.operator }) })); }; const ColumnFilterEditor = (props) => { return (_jsxs(Box, { className: "twa:mb-3 twa:overflow-x-hidden twa:p-0.5 twa:gap-1 twa:flex twa:flex-col", children: [_jsxs(Flex, { className: "twa:mb-1", children: [_jsx(ColumnFilterPredicateDropdown, { columnId: props.columnId, disabled: props.disabled, predicate: props.predicate, predicateDefs: props.predicateDefs, onPredicateChange: props.onPredicateChange }), _jsx(Flex, { alignItems: "center", className: "twa:ml-2", children: _jsx(SimpleButton, { disabled: props.deleteDisabled, onClick: props.onDelete, variant: "text", icon: "delete" }) })] }), _jsx(ColumnFilterInputList, { columnId: props.columnId, disabled: props.disabled, predicate: props.predicate, onPredicateChange: props.onPredicateChange, predicateDefs: props.predicateDefs })] })); }; const AndOrInput = (props) => { return (_jsxs(Flex, { className: "twa:flex-1", children: [_jsx(Radio, { className: "twa:mr-2", onClick: () => props.onChange('AND'), checked: props.operator === 'AND', children: "AND" }), _jsx(Radio, { className: "twa:mr-2", onClick: () => props.onChange('OR'), checked: props.operator === 'OR', children: "OR" })] })); }; export const ColumnFilterComponent = (props) => { const adaptable = useAdaptable(); const manuallyApplyColumnFilter = adaptable.api.filterApi.columnFilterApi.internalApi.shouldManuallyApplyColumnFilter(props.columnId); const rootRef = React.useRef(null); const contentWrapperRef = React.useRef(null); React.useEffect(() => { if (props.location !== 'columnMenu') return; const dropdown = contentWrapperRef.current?.querySelector('[data-name="filter-predicate-dropdown"]'); dropdown?.focus(); }, [props.location]); const handleFocusTrap = React.useCallback((e) => { if (props.location !== 'columnMenu') { return; } captureTab(rootRef.current, e); }, [props.location]); const [predicateNotYetApplied, setPredicateNotYetApplied] = React.useState(props.predicate); const applyFilter = () => { props.onPredicateChange(currentPredicateRef.current); setPredicateNotYetApplied(undefined); }; const onPredicateChange = (predicate) => { if (!manuallyApplyColumnFilter || !predicate) { props.onPredicateChange(predicate); } else { setPredicateNotYetApplied(predicate); } }; const clearAllFilters = () => { props.onPredicateChange(null); setPredicateNotYetApplied(undefined); }; const onNewPredicate = (predicateDef) => { const currentPredicate = currentPredicateRef.current; const newPredicate = { ...currentPredicate, args: [...currentPredicate.args, { operator: predicateDef.operator, args: [] }], }; onPredicateChange(newPredicate); }; const onCombineChange = (operator) => { const newPredicate = { ...currentPredicateRef.current, args: currentPredicateRef.current.args || [], operator, }; onPredicateChange(newPredicate); }; const currentPredicate = !manuallyApplyColumnFilter ? props.predicate : predicateNotYetApplied ?? props.predicate; const currentPredicateRef = React.useRef(currentPredicate); currentPredicateRef.current = currentPredicate; const isLastPredicateValid = true; const filterPredicateDropdown = (_jsx(ColumnFilterPredicateDropdown, { columnId: props.columnId, disabled: props.disabled, predicate: currentPredicate, predicateDefs: props.predicateDefs, onPredicateChange: (predicate) => { const predicateDef = props.predicateDefs.find((predicateDef) => predicateDef.operator === predicate.operator); if (!predicateDef) { return; } onNewPredicate(predicateDef); }, targetProps: { tone: 'neutral', variant: 'raised', children: 'Add Condition', } })); const isAtLeastOneColumnFilterValid = (qlPredicates) => { if (!qlPredicates?.length) { return false; } return qlPredicates .map((qlPredicate) => mapQlPredicateToAdaptablePredicate(qlPredicate)) .some((adaptablePredicate) => adaptable.api.predicateApi.isValidPredicate(adaptablePredicate)); }; return (_jsxs("div", { ref: rootRef, onKeyDown: handleFocusTrap, className: "twa:contents", children: [_jsxs(Flex, { flexDirection: "column", className: cn({ 'twa:pb-2': !props.hideActionButtons, 'twa:mb-2': isEmbeddedColumnFilterLocation(props.location), 'twa:mt-2 twa:ml-2 twa:mr-2': props.location === 'columnMenu', 'twa:mx-2': props.location === 'filtersToolPanel', 'twa:rounded-standard': true, }), children: [_jsx(Flex, { className: "twa:m-2", children: _jsx(AndOrInput, { onChange: onCombineChange, operator: currentPredicate.operator }) }), !props.hideActionButtons && (_jsxs(Flex, { className: "ab-ColumnFilter-actions twa:ml-2 twa:mr-2", justifyContent: "space-between", children: [_jsx(Box, { className: "ab-ColumnFilter-action-clearall", children: _jsx(SimpleButton, { "aria-label": 'Clear All Filters', onClick: () => clearAllFilters(), children: "Clear All" }) }), manuallyApplyColumnFilter ? (_jsxs(_Fragment, { children: [_jsx(Box, { className: "twa:flex-1", "data-name": "spacer" }), _jsx(Box, { className: "ab-ColumnFilter-action-reset twa:mr-2", children: _jsx(SimpleButton, { "aria-label": 'Reset All', tone: "neutral", variant: "raised", onClick: () => { setPredicateNotYetApplied(props.predicate); }, children: "Reset" }) }), _jsx(Box, { className: "ab-ColumnFilter-action-apply", children: _jsx(SimpleButton, { "aria-label": 'Apply Filter', tone: "accent", variant: "raised", onClick: applyFilter, disabled: !isAtLeastOneColumnFilterValid(predicateNotYetApplied?.args) && !isAtLeastOneColumnFilterValid(currentPredicate.args), children: "Apply" }) })] })) : null] }))] }), _jsx(Flex, { ref: contentWrapperRef, flexDirection: "column", style: props.wrapperProps?.style, className: twMerge(`ab-ColumnFilter twa:flex-1 twa:min-h-0`, props.wrapperProps?.className), children: _jsxs(Box, { className: "ab-ColumnFilter-content twa:overflow-auto", children: [currentPredicate.args.map((predicate, index) => { return (_jsx(ColumnFilterEditor, { deleteDisabled: currentPredicate.args.length < 2, onDelete: () => { const currentPredicate = currentPredicateRef.current; const newArgs = [...currentPredicate.args]; newArgs.splice(index, 1); onPredicateChange({ operator: currentPredicate.operator, args: newArgs, }); }, columnId: props.columnId, disabled: props.disabled, predicate: predicate, predicateDefs: props.predicateDefs, onPredicateChange: (predicate) => { const currentPredicate = currentPredicateRef.current; const newArgs = [...currentPredicate.args]; newArgs[index] = predicate; onPredicateChange({ operator: currentPredicate.operator, args: newArgs, }); } }, index)); }), isLastPredicateValid && filterPredicateDropdown] }) })] })); };