Skip to content

Commit 2643aa8

Browse files
authored
Merge pull request Expensify#71495 from Expensify/jsenyitko-negation
Add negation to filters
2 parents 6b2a225 + c9e048d commit 2643aa8

9 files changed

Lines changed: 1378 additions & 947 deletions

File tree

src/CONST/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6709,6 +6709,7 @@ const CONST = {
67096709
[this.STATUS.EXPENSE.DRAFTS]: 'draft',
67106710
};
67116711
},
6712+
NOT_MODIFIER: 'Not',
67126713
DATE_MODIFIERS: {
67136714
ON: 'On',
67146715
AFTER: 'After',

src/components/Search/SearchPageHeader/SearchFiltersBar.tsx

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -41,14 +41,7 @@ import DateUtils from '@libs/DateUtils';
4141
import Navigation from '@libs/Navigation/Navigation';
4242
import {getActiveAdminWorkspaces, getAllTaxRates, isPaidGroupPolicy} from '@libs/PolicyUtils';
4343
import {isExpenseReport} from '@libs/ReportUtils';
44-
import {
45-
buildFilterFormValuesFromQuery,
46-
buildQueryStringFromFilterFormValues,
47-
buildSearchQueryJSON,
48-
buildSearchQueryString,
49-
isFilterSupported,
50-
isSearchDatePreset,
51-
} from '@libs/SearchQueryUtils';
44+
import {buildFilterFormValuesFromQuery, buildQueryStringFromFilterFormValues, isFilterSupported, isSearchDatePreset} from '@libs/SearchQueryUtils';
5245
import {getDatePresets, getFeedOptions, getGroupByOptions, getGroupCurrencyOptions, getHasOptions, getStatusOptions, getTypeOptions, getWithdrawalTypeOptions} from '@libs/SearchUIUtils';
5346
import CONST from '@src/CONST';
5447
import type {TranslationPaths} from '@src/languages/types';
@@ -254,9 +247,7 @@ function SearchFiltersBar({
254247
updatedFilterFormValues.status = CONST.SEARCH.STATUS.EXPENSE.ALL;
255248
}
256249

257-
const filterString = buildQueryStringFromFilterFormValues(updatedFilterFormValues);
258-
const searchQueryJSON = buildSearchQueryJSON(filterString);
259-
const queryString = buildSearchQueryString(searchQueryJSON);
250+
const queryString = buildQueryStringFromFilterFormValues(updatedFilterFormValues);
260251

261252
close(() => {
262253
Navigation.setParams({q: queryString});

src/libs/SearchParser/autocompleteParser.js

Lines changed: 409 additions & 385 deletions
Large diffs are not rendered by default.

src/libs/SearchParser/autocompleteParser.peggy

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,14 @@
1818
// Use the `generate-search-parser` and `generate-autocomplete-parser` scripts to regenerate parsers after modifications.
1919
}}
2020
// per-parser initializer (code executed before every parse).
21-
{ let autocomplete = null; }
21+
{
22+
let autocomplete = null;
23+
24+
// List fields where you cannot prefix it with "-" to negate it
25+
const nonNegatableKeys = new Set([
26+
"type", "keyword", "groupCurrency", "groupBy"
27+
]);
28+
}
2229

2330
query = _ ranges:filterList? _ { return { autocomplete, ranges }; }
2431

@@ -28,12 +35,15 @@ filterList
2835
filter = @(defaultFilter / freeTextFilter)
2936

3037
defaultFilter
31-
= _ key:filterKey _ op:filterOperator _ value:identifier? {
38+
= _ neg:"-"? key:filterKey _ op:filterOperator _ value:identifier? {
3239
expectingNestedQuote = false; nameOperator = false; // Reset string parser
3340

41+
const isNegated = !!neg && !nonNegatableKeys.has(key);
42+
3443
if (!value) {
3544
autocomplete = {
3645
key,
46+
negated: isNegated,
3747
value: "",
3848
start: location().end.offset,
3949
length: 0,
@@ -43,13 +53,15 @@ defaultFilter
4353

4454
autocomplete = {
4555
key,
56+
negated: isNegated,
4657
...value[value.length - 1],
4758
};
4859
return value
49-
.filter((filter) => filter.length > 0)
50-
.map((filter) => ({
60+
.filter((v) => v.length > 0)
61+
.map((v) => ({
5162
key,
52-
...filter,
63+
negated: isNegated,
64+
...v,
5365
}));
5466
}
5567

@@ -105,7 +117,7 @@ filterKey
105117
= k:autocompleteKey {
106118
nameOperator = (k === "from" || k === "to" || k === "payer" || k === "exporter" || k === "attendee" || k === "createdBy" || k === "assignee");
107119
return k;
108-
}
120+
}
109121

110122
identifier
111123
= parts:(quotedString / alphanumeric)|1.., ","| empty:","? {

0 commit comments

Comments
 (0)