Skip to content

Commit

Permalink
Merge pull request #45221 from Expensify/cmartins-createGetFilters
Browse files Browse the repository at this point in the history
  • Loading branch information
mountiny authored Jul 11, 2024
2 parents 5f00210 + 7c820d3 commit 58e2575
Show file tree
Hide file tree
Showing 3 changed files with 119 additions and 2 deletions.
33 changes: 33 additions & 0 deletions src/CONST.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5208,6 +5208,39 @@ const CONST = {
APPROVE: 'approve',
PAY: 'pay',
},
SYNTAX_OPERATORS: {
AND: 'and',
OR: 'or',
EQUAL_TO: 'eq',
NOT_EQUAL_TO: 'neq',
GREATER_THAN: 'gt',
GREATER_THAN_OR_EQUAL_TO: 'gte',
LOWER_THAN: 'lt',
LOWER_THAN_OR_EQUAL_TO: 'lte',
},
SYNTAX_ROOT_KEYS: {
TYPE: 'type',
STATUS: 'status',
SORT_BY: 'sortBy',
SORT_ORDER: 'sortOrder',
OFFSET: 'offset',
},
SYNTAX_FILTER_KEYS: {
DATE: 'date',
AMOUNT: 'amount',
EXPENSE_TYPE: 'expenseType',
CURRENCY: 'currency',
MERCHANT: 'merchant',
DESCRIPTION: 'description',
FROM: 'from',
TO: 'to',
CATEGORY: 'category',
TAG: 'tag',
TAX_RATE: 'taxRate',
CARD_ID: 'cardID',
REPORT_ID: 'reportID',
KEYWORD: 'keyword',
},
},

REFERRER: {
Expand Down
19 changes: 18 additions & 1 deletion src/components/Search/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,21 @@ type SearchContext = {
setSelectedTransactionIds: (selectedTransactionIds: string[]) => void;
};

export type {SelectedTransactionInfo, SelectedTransactions, SearchColumnType, SortOrder, SearchContext};
type ASTNode = {
operator: ValueOf<typeof CONST.SEARCH.SYNTAX_OPERATORS>;
left: ValueOf<typeof CONST.SEARCH.SYNTAX_FILTER_KEYS> | ASTNode;
right: string | ASTNode;
};

type QueryFilter = {
operator: ValueOf<typeof CONST.SEARCH.SYNTAX_OPERATORS>;
value: string | number;
};

type AllFieldKeys = ValueOf<typeof CONST.SEARCH.SYNTAX_FILTER_KEYS> | ValueOf<typeof CONST.SEARCH.SYNTAX_ROOT_KEYS>;

type QueryFilters = {
[K in AllFieldKeys]: QueryFilter | QueryFilter[];
};

export type {SelectedTransactionInfo, SelectedTransactions, SearchColumnType, SortOrder, SearchContext, ASTNode, QueryFilter, QueryFilters, AllFieldKeys};
69 changes: 68 additions & 1 deletion src/libs/SearchUtils.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import type {SearchColumnType, SortOrder} from '@components/Search/types';
import type {ValueOf} from 'type-fest';
import type {AllFieldKeys, ASTNode, QueryFilter, QueryFilters, SearchColumnType, SortOrder} from '@components/Search/types';
import ReportListItem from '@components/SelectionList/Search/ReportListItem';
import TransactionListItem from '@components/SelectionList/Search/TransactionListItem';
import type {ListItem, ReportListItemType, TransactionListItemType} from '@components/SelectionList/types';
Expand Down Expand Up @@ -309,6 +310,12 @@ function getQueryHashFromString(query: string): number {
type JSONQuery = {
input: string;
hash: number;
type: string;
status: string;
sortBy: string;
sortOrder: string;
offset: number;
filters: ASTNode;
};

function buildJSONQuery(query: string) {
Expand All @@ -323,6 +330,65 @@ function buildJSONQuery(query: string) {
}
}

function getFilters(query: string, fields: Array<Partial<AllFieldKeys>>) {
let jsonQuery;
try {
jsonQuery = searchParser.parse(query) as JSONQuery;
} catch (e) {
console.error(e);
return;
}

const filters = {} as QueryFilters;

fields.forEach((field) => {
const rootFieldKey = field as ValueOf<typeof CONST.SEARCH.SYNTAX_ROOT_KEYS>;
if (jsonQuery[rootFieldKey] === undefined) {
return;
}

filters[field] = {
operator: 'eq',
value: jsonQuery[rootFieldKey],
};
});

function traverse(node: ASTNode) {
if (!node.operator) {
return;
}

if (typeof node?.left === 'object') {
traverse(node.left);
}

if (typeof node?.right === 'object') {
traverse(node.right);
}

const nodeKey = node.left as ValueOf<typeof CONST.SEARCH.SYNTAX_FILTER_KEYS>;
if (!fields.includes(nodeKey)) {
return;
}

if (!filters[nodeKey]) {
filters[nodeKey] = [];
}

const filterArray = filters[nodeKey] as QueryFilter[];
filterArray.push({
operator: node.operator,
value: node.right as string | number,
});
}

if (jsonQuery.filters) {
traverse(jsonQuery.filters);
}

return filters;
}

export {
buildJSONQuery,
getListItem,
Expand All @@ -336,4 +402,5 @@ export {
isReportListItemType,
isTransactionListItemType,
isSearchResultsEmpty,
getFilters,
};

0 comments on commit 58e2575

Please sign in to comment.