@adaptabletools/adaptable
Version:
Powerful AG Grid extension which provides advanced, cutting-edge functionality to meet all DataGrid requirements
143 lines (142 loc) • 10 kB
JavaScript
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] }) })] }));
};