Skip to content
This repository was archived by the owner on Jun 4, 2024. It is now read-only.

Commit 7a12196

Browse files
committed
Case-insensitive option for filters
1 parent cd9c3e1 commit 7a12196

File tree

14 files changed

+381
-54
lines changed

14 files changed

+381
-54
lines changed

src/core/syntax-tree/lexicon.ts

+1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ export interface IUnboundedLexeme {
1616
resolve?: (target: any, tree: ISyntaxTree) => any;
1717
subType?: string;
1818
type: string;
19+
case?: string;
1920
nesting?: number;
2021
priority?: number;
2122
regexp: RegExp;

src/dash-table/components/FilterFactory.tsx

+10-7
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import memoizerCache from 'core/cache/memoizer';
77
import { memoizeOne } from 'core/memoizer';
88

99
import ColumnFilter from 'dash-table/components/Filter/Column';
10-
import { ColumnId, IColumn, TableAction, IFilterFactoryProps, SetFilter } from 'dash-table/components/Table/props';
10+
import { ColumnId, IColumn, TableAction, IFilterFactoryProps, SetFilter, Case } from 'dash-table/components/Table/props';
1111
import derivedFilterStyles, { derivedFilterOpStyles } from 'dash-table/derived/filter/wrapperStyles';
1212
import derivedHeaderOperations from 'dash-table/derived/header/operations';
1313
import { derivedRelevantFilterStyles } from 'dash-table/derived/style';
@@ -32,19 +32,20 @@ export default class FilterFactory {
3232

3333
}
3434

35-
private onChange = (column: IColumn, map: Map<string, SingleColumnSyntaxTree>, setFilter: SetFilter, ev: any) => {
35+
private onChange = (column: IColumn, map: Map<string, SingleColumnSyntaxTree>, setFilter: SetFilter, filter_case: Case, ev: any) => {
3636
Logger.debug('Filter -- onChange', column.id, ev.target.value && ev.target.value.trim());
3737

3838
const value = ev.target.value.trim();
3939

40-
updateColumnFilter(map, column, value, setFilter);
40+
updateColumnFilter(map, column, value, setFilter, filter_case);
4141
}
4242

4343
private filter = memoizerCache<[ColumnId, number]>()((
4444
column: IColumn,
4545
index: number,
4646
map: Map<string, SingleColumnSyntaxTree>,
47-
setFilter: SetFilter
47+
setFilter: SetFilter,
48+
filter_case: Case
4849
) => {
4950
const ast = map.get(column.id.toString());
5051

@@ -53,7 +54,7 @@ export default class FilterFactory {
5354
classes={`dash-filter column-${index}`}
5455
columnId={column.id}
5556
isValid={!ast || ast.isValid}
56-
setFilter={this.onChange.bind(this, column, map, setFilter)}
57+
setFilter={this.onChange.bind(this, column, map, setFilter, filter_case)}
5758
value={ast && ast.query}
5859
/>);
5960
});
@@ -83,7 +84,8 @@ export default class FilterFactory {
8384
style_cell_conditional,
8485
style_filter,
8586
style_filter_conditional,
86-
visibleColumns
87+
visibleColumns,
88+
filter_case
8789
} = this.props;
8890

8991
if (filter_action === TableAction.None) {
@@ -113,7 +115,8 @@ export default class FilterFactory {
113115
column,
114116
index,
115117
map,
116-
setFilter
118+
setFilter,
119+
filter_case
117120
);
118121
}, visibleColumns);
119122

src/dash-table/components/HeaderFactory.tsx

+4-2
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,8 @@ export default class HeaderFactory {
5656
style_cell_conditional,
5757
style_header,
5858
style_header_conditional,
59-
visibleColumns
59+
visibleColumns,
60+
filter_case
6061
} = props;
6162

6263
const labelsAndIndices = this.labelsAndIndices(columns, visibleColumns, merge_duplicate_headers);
@@ -109,7 +110,8 @@ export default class HeaderFactory {
109110
page_action,
110111
setFilter,
111112
setProps,
112-
merge_duplicate_headers
113+
merge_duplicate_headers,
114+
filter_case
113115
);
114116

115117
const ops = this.getHeaderOpCells(

src/dash-table/components/Table/index.tsx

+4-2
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,8 @@ export default class Table extends Component<SanitizedAndDerivedProps, Standalon
4040
map: this.filterMap(
4141
new Map<string, SingleColumnSyntaxTree>(),
4242
props.filter_query,
43-
props.visibleColumns
43+
props.visibleColumns,
44+
props.filter_case
4445
)
4546
},
4647
rawFilterQuery: '',
@@ -60,7 +61,8 @@ export default class Table extends Component<SanitizedAndDerivedProps, Standalon
6061
const map = this.filterMap(
6162
currentMap,
6263
nextProps.filter_query,
63-
nextProps.visibleColumns
64+
nextProps.visibleColumns,
65+
nextProps.filter_case
6466
);
6567

6668
return map !== currentMap ? { workFilter: { map, value} } : null;

src/dash-table/components/Table/props.ts

+11
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,12 @@ export enum SortMode {
4646
Multi = 'multi'
4747
}
4848

49+
export enum Case {
50+
Sensitive = 'sensitive',
51+
Insensitive = 'insensitive',
52+
Default = 'default'
53+
}
54+
4955
export enum TableAction {
5056
Custom = 'custom',
5157
Native = 'native',
@@ -177,6 +183,8 @@ export interface IBaseColumn {
177183
hideable?: boolean | boolean[] | 'first' | 'last';
178184
renamable?: boolean | boolean[] | 'first' | 'last';
179185
selectable?: boolean | boolean[] | 'first' | 'last';
186+
filter_case_sensitive?: boolean;
187+
filter_case_insensitive?: boolean;
180188
sort_as_null: SortAsNull;
181189
id: ColumnId;
182190
name: string | string[];
@@ -298,6 +306,7 @@ export interface IProps {
298306
fill_width?: boolean;
299307
filter_query?: string;
300308
filter_action?: TableAction;
309+
filter_case?: Case;
301310
hidden_columns?: string[];
302311
include_headers_on_copy_paste?: boolean;
303312
locale_format: INumberLocale;
@@ -351,6 +360,7 @@ interface IDefaultProps {
351360
fill_width: boolean;
352361
filter_query: string;
353362
filter_action: TableAction;
363+
filter_case: Case;
354364
include_headers_on_copy_paste: boolean;
355365
merge_duplicate_headers: boolean;
356366
fixed_columns: Fixed;
@@ -441,6 +451,7 @@ export type SetFilter = (
441451
export interface IFilterFactoryProps {
442452
filter_query: string;
443453
filter_action: TableAction;
454+
filter_case: Case;
444455
id: string;
445456
map: Map<string, SingleColumnSyntaxTree>;
446457
rawFilterQuery: string;

src/dash-table/dash/DataTable.js

+30-9
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ export const defaultProps = {
4747
css: [],
4848
filter_query: '',
4949
filter_action: 'none',
50+
filter_case: 'sensitive',
5051
sort_as_null: [],
5152
sort_action: 'none',
5253
sort_mode: 'single',
@@ -249,14 +250,25 @@ export const propTypes = {
249250
* will select *all* of the merged columns associated with it.
250251
* The table-level prop `column_selectable` is used to determine the type of column
251252
* selection to use.
252-
*
253253
*/
254254
selectable: PropTypes.oneOfType([
255255
PropTypes.oneOf(['first', 'last']),
256256
PropTypes.bool,
257257
PropTypes.arrayOf(PropTypes.bool)
258258
]),
259259

260+
/**
261+
* If true, the filter on the column will override the table setting and always be
262+
* case-sensitive, unless a case-insensitive operator is used.
263+
*/
264+
filter_case_sensitive: PropTypes.bool,
265+
266+
/**
267+
* If true, the filter on the column will override the table setting and will always be
268+
* case-insensitive, nless a case-sensitive operator is used.
269+
*/
270+
filter_case_insensitive: PropTypes.bool,
271+
260272
/**
261273
* The formatting applied to the column's data.
262274
* This prop is derived from the [d3-format](https://github.com/d3/d3-format) library specification. Apart from
@@ -944,13 +956,6 @@ export const propTypes = {
944956
*/
945957
tooltip_duration: PropTypes.number,
946958

947-
/**
948-
* If `filter_action` is enabled, then the current filtering
949-
* string is represented in this `filter_query`
950-
* property.
951-
*/
952-
filter_query: PropTypes.string,
953-
954959
/**
955960
* The `filter_action` property controls the behavior of the `filtering` UI.
956961
* If `'none'`, then the filtering UI is not displayed.
@@ -964,6 +969,22 @@ export const propTypes = {
964969
*/
965970
filter_action: PropTypes.oneOf(['custom', 'native', 'none']),
966971

972+
/**
973+
* If `filter_action` is enabled, then the current filtering
974+
* string is represented in this `filter_query`
975+
* property.
976+
*/
977+
filter_query: PropTypes.string,
978+
979+
/**
980+
* If `filter_action` is enabled, the `filter_case` property controls the case-sensitivity of
981+
* the filters.
982+
* If `'sensitive'`, filtering on all columns will be case-sensitive (default behavior).
983+
* If `'insensitive'`, filtering on all columns will be case-insensitive.
984+
* This setting can be overridden per column.
985+
*/
986+
filter_case: PropTypes.oneOf(['sensitive', 'insensitive']),
987+
967988
/**
968989
* The `sort_action` property enables data to be
969990
* sorted on a per-column basis.
@@ -1131,7 +1152,7 @@ export const propTypes = {
11311152
* subType (string; optional):
11321153
* 'open-block': '()',
11331154
* 'logical-operator': '&&', '||',
1134-
* 'relational-operator': '=', '>=', '>', '<=', '<', '!=', 'contains',
1155+
* 'relational-operator': '=', '>=', '>', '<=', '<', '!=', 'contains', 'i=', 'i>=', 'i>', 'i<=', 'i<', 'i!=', 'icontains', 's=', 's>=', 's>', 's<=', 's<', 's!=', 'scontains',
11351156
* 'unary-operator': '!', 'is bool', 'is even', 'is nil', 'is num', 'is object', 'is odd', 'is prime', 'is str',
11361157
* 'expression': 'value', 'field';
11371158
* value (any):

src/dash-table/derived/filter/map.ts

+12-9
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import * as R from 'ramda';
22

33
import { memoizeOneFactory } from 'core/memoizer';
44

5-
import { Columns, IColumn, SetFilter } from 'dash-table/components/Table/props';
5+
import { Columns, IColumn, SetFilter, Case } from 'dash-table/components/Table/props';
66
import { SingleColumnSyntaxTree, MultiColumnsSyntaxTree, getMultiColumnQueryString, getSingleColumnMap } from 'dash-table/syntax-tree';
77

88
const cloneIf = (
@@ -13,10 +13,11 @@ const cloneIf = (
1313
export default memoizeOneFactory((
1414
map: Map<string, SingleColumnSyntaxTree>,
1515
query: string,
16-
columns: Columns
16+
columns: Columns,
17+
filter_case: Case
1718
): Map<string, SingleColumnSyntaxTree> => {
1819
const multiQuery = new MultiColumnsSyntaxTree(query);
19-
const reversedMap = getSingleColumnMap(multiQuery, columns);
20+
const reversedMap = getSingleColumnMap(multiQuery, columns, filter_case);
2021

2122
/*
2223
* Couldn't process the query, just use the previous value.
@@ -61,12 +62,12 @@ export default memoizeOneFactory((
6162
return newMap;
6263
});
6364

64-
function updateMap(map: Map<string, SingleColumnSyntaxTree>, column: IColumn, value: any) {
65+
function updateMap(map: Map<string, SingleColumnSyntaxTree>, column: IColumn, value: any, filter_case: Case) {
6566
const id = column.id.toString();
6667
const newMap = new Map<string, SingleColumnSyntaxTree>(map);
6768

6869
if (value && value.length) {
69-
newMap.set(id, new SingleColumnSyntaxTree(value, column));
70+
newMap.set(id, new SingleColumnSyntaxTree(value, column, filter_case));
7071
} else {
7172
newMap.delete(id);
7273
}
@@ -90,19 +91,21 @@ export const updateColumnFilter = (
9091
map: Map<string, SingleColumnSyntaxTree>,
9192
column: IColumn,
9293
value: any,
93-
setFilter: SetFilter
94+
setFilter: SetFilter,
95+
filter_case: Case
9496
) => {
95-
map = updateMap(map, column, value);
97+
map = updateMap(map, column, value, filter_case);
9698
updateState(map, setFilter);
9799
};
98100

99101
export const clearColumnsFilter = (
100102
map: Map<string, SingleColumnSyntaxTree>,
101103
columns: Columns,
102-
setFilter: SetFilter
104+
setFilter: SetFilter,
105+
filter_case: Case
103106
) => {
104107
R.forEach(column => {
105-
map = updateMap(map, column, '');
108+
map = updateMap(map, column, '', filter_case);
106109
}, columns);
107110

108111
updateState(map, setFilter);

src/dash-table/derived/header/content.tsx

+9-6
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@ import {
1515
SetFilter,
1616
SetProps,
1717
SortMode,
18-
TableAction
18+
TableAction,
19+
Case
1920
} from 'dash-table/components/Table/props';
2021
import getColumnFlag from 'dash-table/derived/header/columnFlag';
2122
import * as actions from 'dash-table/utils/actions';
@@ -40,7 +41,8 @@ const doAction = (
4041
setFilter: SetFilter,
4142
setProps: SetProps,
4243
map: Map<string, SingleColumnSyntaxTree>,
43-
data: Data
44+
data: Data,
45+
filter_case: Case
4446
) => () => {
4547
const props = action(column, columns, visibleColumns, columnRowIndex, mergeDuplicateHeaders, data);
4648

@@ -64,7 +66,7 @@ const doAction = (
6466
}
6567
}, affectedColumIds);
6668

67-
clearColumnsFilter(map, affectedColumns, setFilter);
69+
clearColumnsFilter(map, affectedColumns, setFilter, filter_case);
6870
};
6971

7072
function doSort(columnId: ColumnId, sortBy: SortBy, mode: SortMode, setProps: SetProps) {
@@ -165,7 +167,8 @@ function getter(
165167
paginationMode: TableAction,
166168
setFilter: SetFilter,
167169
setProps: SetProps,
168-
mergeDuplicateHeaders: boolean
170+
mergeDuplicateHeaders: boolean,
171+
filter_case: Case
169172
): JSX.Element[][] {
170173
return R.addIndex<R.KeyValuePair<any[], number[]>, JSX.Element[]>(R.map)(
171174
([labels, indices], headerRowIndex) => {
@@ -263,7 +266,7 @@ function getter(
263266
null :
264267
(<span
265268
className='column-header--clear'
266-
onClick={doAction(actions.clearColumn, selected_columns, column, columns, visibleColumns, headerRowIndex, mergeDuplicateHeaders, setFilter, setProps, map, data)}
269+
onClick={doAction(actions.clearColumn, selected_columns, column, columns, visibleColumns, headerRowIndex, mergeDuplicateHeaders, setFilter, setProps, map, data, filter_case)}
267270
>
268271
<FontAwesomeIcon icon='eraser' />
269272
</span>)
@@ -275,7 +278,7 @@ function getter(
275278
className={'column-header--delete' + (spansAllColumns ? ' disabled' : '')}
276279
onClick={spansAllColumns ?
277280
undefined :
278-
doAction(actions.deleteColumn, selected_columns, column, columns, visibleColumns, headerRowIndex, mergeDuplicateHeaders, setFilter, setProps, map, data)
281+
doAction(actions.deleteColumn, selected_columns, column, columns, visibleColumns, headerRowIndex, mergeDuplicateHeaders, setFilter, setProps, map, data, filter_case)
279282
}
280283
>
281284
<FontAwesomeIcon icon={['far', 'trash-alt']} />

0 commit comments

Comments
 (0)