diff --git a/src/CONST.ts b/src/CONST.ts index e7d9411b619c..d8724d9c72b2 100755 --- a/src/CONST.ts +++ b/src/CONST.ts @@ -6106,6 +6106,33 @@ const CONST = { AUTOCOMPLETE_SUGGESTION: 'autocompleteSuggestion', SEARCH: 'searchItem', }, + SEARCH_USER_FRIENDLY_KEYS: { + TYPE: 'type', + STATUS: 'status', + SORT_BY: 'sort-by', + SORT_ORDER: 'sort-order', + POLICY_ID: 'workspace', + DATE: 'date', + AMOUNT: 'amount', + EXPENSE_TYPE: 'expense-type', + CURRENCY: 'currency', + MERCHANT: 'merchant', + DESCRIPTION: 'description', + FROM: 'from', + TO: 'to', + CATEGORY: 'category', + TAG: 'tag', + TAX_RATE: 'tax-rate', + CARD_ID: 'card', + REPORT_ID: 'reportid', + KEYWORD: 'keyword', + IN: 'in', + SUBMITTED: 'submitted', + APPROVED: 'approved', + PAID: 'paid', + EXPORTED: 'exported', + POSTED: 'posted', + }, DATE_MODIFIERS: { BEFORE: 'Before', AFTER: 'After', diff --git a/src/components/Search/SearchPageHeaderInput.tsx b/src/components/Search/SearchPageHeaderInput.tsx index c90dcb2330e1..d9884b1c1efe 100644 --- a/src/components/Search/SearchPageHeaderInput.tsx +++ b/src/components/Search/SearchPageHeaderInput.tsx @@ -160,8 +160,8 @@ function SearchPageHeaderInput({queryJSON, children}: SearchPageHeaderInputProps const trimmedUserSearchQuery = SearchAutocompleteUtils.getQueryWithoutAutocompletedPart(textInputValue); onSearchQueryChange(`${trimmedUserSearchQuery}${SearchQueryUtils.sanitizeSearchValue(item.searchQuery)} `); - if (item.text && item.autocompleteID) { - const substitutions = {...autocompleteSubstitutions, [item.text]: item.autocompleteID}; + if (item.mapKey && item.autocompleteID) { + const substitutions = {...autocompleteSubstitutions, [item.mapKey]: item.autocompleteID}; setAutocompleteSubstitutions(substitutions); } @@ -179,11 +179,11 @@ function SearchPageHeaderInput({queryJSON, children}: SearchPageHeaderInputProps const updateAutocompleteSubstitutions = useCallback( (item: SearchQueryItem) => { - if (!item.autocompleteID || !item.text) { + if (!item.autocompleteID || !item.mapKey) { return; } - const substitutions = {...autocompleteSubstitutions, [item.text]: item.autocompleteID}; + const substitutions = {...autocompleteSubstitutions, [item.mapKey]: item.autocompleteID}; setAutocompleteSubstitutions(substitutions); }, [autocompleteSubstitutions], diff --git a/src/components/Search/SearchRouter/SearchRouter.tsx b/src/components/Search/SearchRouter/SearchRouter.tsx index 78230380735a..4b800b637712 100644 --- a/src/components/Search/SearchRouter/SearchRouter.tsx +++ b/src/components/Search/SearchRouter/SearchRouter.tsx @@ -48,20 +48,20 @@ function getContextualSearchAutocompleteKey(item: SearchQueryItem) { } function getContextualSearchQuery(item: SearchQueryItem) { - const baseQuery = `${CONST.SEARCH.SYNTAX_ROOT_KEYS.TYPE}:${item.roomType}`; + const baseQuery = `${CONST.SEARCH.SEARCH_USER_FRIENDLY_KEYS.TYPE}:${item.roomType}`; let additionalQuery = ''; switch (item.roomType) { case CONST.SEARCH.DATA_TYPES.EXPENSE: case CONST.SEARCH.DATA_TYPES.INVOICE: - additionalQuery += ` ${CONST.SEARCH.SYNTAX_ROOT_KEYS.POLICY_ID}:${item.policyID}`; + additionalQuery += ` ${CONST.SEARCH.SEARCH_USER_FRIENDLY_KEYS.POLICY_ID}:${item.policyID}`; if (item.roomType === CONST.SEARCH.DATA_TYPES.INVOICE && item.autocompleteID) { - additionalQuery += ` ${CONST.SEARCH.SYNTAX_FILTER_KEYS.TO}:${SearchQueryUtils.sanitizeSearchValue(item.searchQuery ?? '')}`; + additionalQuery += ` ${CONST.SEARCH.SEARCH_USER_FRIENDLY_KEYS.TO}:${SearchQueryUtils.sanitizeSearchValue(item.searchQuery ?? '')}`; } break; case CONST.SEARCH.DATA_TYPES.CHAT: default: - additionalQuery = ` ${CONST.SEARCH.SYNTAX_FILTER_KEYS.IN}:${SearchQueryUtils.sanitizeSearchValue(item.searchQuery ?? '')}`; + additionalQuery = ` ${CONST.SEARCH.SEARCH_USER_FRIENDLY_KEYS.IN}:${SearchQueryUtils.sanitizeSearchValue(item.searchQuery ?? '')}`; break; } return baseQuery + additionalQuery; @@ -223,8 +223,8 @@ function SearchRouter({onRouterClose, shouldHideInputCaret}: SearchRouterProps) const trimmedUserSearchQuery = SearchAutocompleteUtils.getQueryWithoutAutocompletedPart(textInputValue); onSearchQueryChange(`${trimmedUserSearchQuery}${SearchQueryUtils.sanitizeSearchValue(item.searchQuery)} `); - if (item.text && item.autocompleteID) { - const substitutions = {...autocompleteSubstitutions, [item.text]: item.autocompleteID}; + if (item.mapKey && item.autocompleteID) { + const substitutions = {...autocompleteSubstitutions, [item.mapKey]: item.autocompleteID}; setAutocompleteSubstitutions(substitutions); } @@ -248,11 +248,11 @@ function SearchRouter({onRouterClose, shouldHideInputCaret}: SearchRouterProps) const updateAutocompleteSubstitutions = useCallback( (item: SearchQueryItem) => { - if (!item.autocompleteID || !item.text) { + if (!item.autocompleteID || !item.mapKey) { return; } - const substitutions = {...autocompleteSubstitutions, [item.text]: item.autocompleteID}; + const substitutions = {...autocompleteSubstitutions, [item.mapKey]: item.autocompleteID}; setAutocompleteSubstitutions(substitutions); }, [autocompleteSubstitutions], diff --git a/src/components/Search/SearchRouter/SearchRouterList.tsx b/src/components/Search/SearchRouter/SearchRouterList.tsx index 3fe7cc9e2de4..a53e49374d81 100644 --- a/src/components/Search/SearchRouter/SearchRouterList.tsx +++ b/src/components/Search/SearchRouter/SearchRouterList.tsx @@ -5,7 +5,7 @@ import {useOnyx} from 'react-native-onyx'; import * as Expensicons from '@components/Icon/Expensicons'; import {usePersonalDetails} from '@components/OnyxProvider'; import {useOptionsList} from '@components/OptionListContextProvider'; -import type {SearchFilterKey} from '@components/Search/types'; +import type {SearchFilterKey, UserFriendlyKey} from '@components/Search/types'; import SelectionList from '@components/SelectionList'; import SearchQueryListItem, {isSearchQueryItem} from '@components/SelectionList/Search/SearchQueryListItem'; import type {SearchQueryItem, SearchQueryListItemProps} from '@components/SelectionList/Search/SearchQueryListItem'; @@ -40,9 +40,10 @@ import type PersonalDetails from '@src/types/onyx/PersonalDetails'; import {getSubstitutionMapKey} from './getQueryWithSubstitutions'; type AutocompleteItemData = { - filterKey: SearchFilterKey; + filterKey: UserFriendlyKey; text: string; autocompleteID?: string; + mapKey?: SearchFilterKey; }; type SearchRouterListProps = { @@ -82,6 +83,10 @@ function isSearchQueryListItem(listItem: UserListItemProps | SearchQ return isSearchQueryItem(listItem.item); } +function getAutocompleteDisplayText(filterKey: UserFriendlyKey, value: string) { + return `${filterKey}:${value}`; +} + function getItemHeight(item: OptionData | SearchQueryItem) { if (isSearchQueryItem(item)) { return 44; @@ -223,7 +228,7 @@ function SearchRouterList( .slice(0, 10); return filteredTags.map((tagName) => ({ - filterKey: CONST.SEARCH.SYNTAX_FILTER_KEYS.TAG, + filterKey: CONST.SEARCH.SEARCH_USER_FRIENDLY_KEYS.TAG, text: tagName, })); } @@ -235,7 +240,7 @@ function SearchRouterList( .slice(0, 10); return filteredCategories.map((categoryName) => ({ - filterKey: CONST.SEARCH.SYNTAX_FILTER_KEYS.CATEGORY, + filterKey: CONST.SEARCH.SEARCH_USER_FRIENDLY_KEYS.CATEGORY, text: categoryName, })); } @@ -247,7 +252,7 @@ function SearchRouterList( .slice(0, 10); return filteredCurrencies.map((currencyName) => ({ - filterKey: CONST.SEARCH.SYNTAX_FILTER_KEYS.CURRENCY, + filterKey: CONST.SEARCH.SEARCH_USER_FRIENDLY_KEYS.CURRENCY, text: currencyName, })); } @@ -258,9 +263,10 @@ function SearchRouterList( .slice(0, 10); return filteredTaxRates.map((tax) => ({ - filterKey: CONST.SEARCH.SYNTAX_FILTER_KEYS.TAX_RATE, + filterKey: CONST.SEARCH.SEARCH_USER_FRIENDLY_KEYS.TAX_RATE, text: tax.taxRateName, autocompleteID: tax.taxRateIds.join(','), + mapKey: CONST.SEARCH.SYNTAX_FILTER_KEYS.TAX_RATE, })); } case CONST.SEARCH.SYNTAX_FILTER_KEYS.FROM: { @@ -269,9 +275,10 @@ function SearchRouterList( .slice(0, 10); return filteredParticipants.map((participant) => ({ - filterKey: CONST.SEARCH.SYNTAX_FILTER_KEYS.FROM, + filterKey: CONST.SEARCH.SEARCH_USER_FRIENDLY_KEYS.FROM, text: participant.name, autocompleteID: participant.accountID, + mapKey: CONST.SEARCH.SYNTAX_FILTER_KEYS.FROM, })); } case CONST.SEARCH.SYNTAX_FILTER_KEYS.TO: { @@ -280,9 +287,10 @@ function SearchRouterList( .slice(0, 10); return filteredParticipants.map((participant) => ({ - filterKey: CONST.SEARCH.SYNTAX_FILTER_KEYS.TO, + filterKey: CONST.SEARCH.SEARCH_USER_FRIENDLY_KEYS.TO, text: participant.name, autocompleteID: participant.accountID, + mapKey: CONST.SEARCH.SYNTAX_FILTER_KEYS.TO, })); } case CONST.SEARCH.SYNTAX_FILTER_KEYS.IN: { @@ -291,9 +299,10 @@ function SearchRouterList( .slice(0, 10); return filteredChats.map((chat) => ({ - filterKey: CONST.SEARCH.SYNTAX_FILTER_KEYS.IN, + filterKey: CONST.SEARCH.SEARCH_USER_FRIENDLY_KEYS.IN, text: chat.text ?? '', autocompleteID: chat.reportID, + mapKey: CONST.SEARCH.SYNTAX_FILTER_KEYS.IN, })); } case CONST.SEARCH.SYNTAX_ROOT_KEYS.TYPE: { @@ -301,7 +310,7 @@ function SearchRouterList( .filter((type) => type.toLowerCase().includes(autocompleteValue.toLowerCase()) && !alreadyAutocompletedKeys.includes(type.toLowerCase())) .sort(); - return filteredTypes.map((type) => ({filterKey: CONST.SEARCH.SYNTAX_ROOT_KEYS.TYPE, text: type})); + return filteredTypes.map((type) => ({filterKey: CONST.SEARCH.SEARCH_USER_FRIENDLY_KEYS.TYPE, text: type})); } case CONST.SEARCH.SYNTAX_ROOT_KEYS.STATUS: { const filteredStatuses = statusAutocompleteList @@ -309,7 +318,7 @@ function SearchRouterList( .sort() .slice(0, 10); - return filteredStatuses.map((status) => ({filterKey: CONST.SEARCH.SYNTAX_ROOT_KEYS.STATUS, text: status})); + return filteredStatuses.map((status) => ({filterKey: CONST.SEARCH.SEARCH_USER_FRIENDLY_KEYS.STATUS, text: status})); } case CONST.SEARCH.SYNTAX_FILTER_KEYS.EXPENSE_TYPE: { const filteredExpenseTypes = expenseTypes @@ -317,7 +326,7 @@ function SearchRouterList( .sort(); return filteredExpenseTypes.map((expenseType) => ({ - filterKey: CONST.SEARCH.SYNTAX_FILTER_KEYS.EXPENSE_TYPE, + filterKey: CONST.SEARCH.SEARCH_USER_FRIENDLY_KEYS.EXPENSE_TYPE, text: expenseType, })); } @@ -331,9 +340,10 @@ function SearchRouterList( .slice(0, 10); return filteredCards.map((card) => ({ - filterKey: CONST.SEARCH.SYNTAX_FILTER_KEYS.CARD_ID, + filterKey: CONST.SEARCH.SEARCH_USER_FRIENDLY_KEYS.CARD_ID, text: CardUtils.getCardDescription(card.cardID), autocompleteID: card.cardID.toString(), + mapKey: CONST.SEARCH.SYNTAX_FILTER_KEYS.CARD_ID, })); } default: { @@ -411,9 +421,10 @@ function SearchRouterList( sections.push({title: translate('search.recentChats'), data: styledRecentReports}); if (autocompleteSuggestions.length > 0) { - const autocompleteData = autocompleteSuggestions.map(({filterKey, text, autocompleteID}) => { + const autocompleteData = autocompleteSuggestions.map(({filterKey, text, autocompleteID, mapKey}) => { return { - text: getSubstitutionMapKey(filterKey, text), + text: getAutocompleteDisplayText(filterKey, text), + mapKey: mapKey ? getSubstitutionMapKey(mapKey, text) : undefined, singleIcon: Expensicons.MagnifyingGlass, searchQuery: text, autocompleteID, diff --git a/src/components/Search/types.ts b/src/components/Search/types.ts index b9579ed914ad..0a402358d73e 100644 --- a/src/components/Search/types.ts +++ b/src/components/Search/types.ts @@ -97,6 +97,8 @@ type SearchFilterKey = | typeof CONST.SEARCH.SYNTAX_ROOT_KEYS.STATUS | typeof CONST.SEARCH.SYNTAX_ROOT_KEYS.POLICY_ID; +type UserFriendlyKey = ValueOf; + type QueryFilters = Array<{ key: SearchFilterKey; filters: QueryFilter[]; @@ -148,6 +150,7 @@ export type { QueryFilter, QueryFilters, SearchFilterKey, + UserFriendlyKey, ExpenseSearchStatus, InvoiceSearchStatus, TripSearchStatus, diff --git a/src/components/SelectionList/Search/SearchQueryListItem.tsx b/src/components/SelectionList/Search/SearchQueryListItem.tsx index b5631e03c3d7..770bad4faa31 100644 --- a/src/components/SelectionList/Search/SearchQueryListItem.tsx +++ b/src/components/SelectionList/Search/SearchQueryListItem.tsx @@ -17,6 +17,7 @@ type SearchQueryItem = ListItem & { searchQuery?: string; autocompleteID?: string; roomType?: ValueOf; + mapKey?: string; }; type SearchQueryListItemProps = { diff --git a/src/libs/SearchParser/autocompleteParser.js b/src/libs/SearchParser/autocompleteParser.js index bd114b56e099..0b456b5823b1 100644 --- a/src/libs/SearchParser/autocompleteParser.js +++ b/src/libs/SearchParser/autocompleteParser.js @@ -176,23 +176,43 @@ function peg$parse(input, options) { var peg$startRuleFunction = peg$parsequery; var peg$c0 = ","; - var peg$c1 = "in"; - var peg$c2 = "currency"; - var peg$c3 = "tag"; - var peg$c4 = "category"; - var peg$c5 = "to"; - var peg$c6 = "taxRate"; - var peg$c7 = "from"; - var peg$c8 = "expenseType"; - var peg$c9 = "type"; - var peg$c10 = "status"; - var peg$c11 = "cardID"; - var peg$c12 = "!="; - var peg$c13 = ">="; - var peg$c14 = ">"; - var peg$c15 = "<="; - var peg$c16 = "<"; - var peg$c17 = "\""; + var peg$c1 = "date"; + var peg$c2 = "amount"; + var peg$c3 = "merchant"; + var peg$c4 = "description"; + var peg$c5 = "reportid"; + var peg$c6 = "keyword"; + var peg$c7 = "in"; + var peg$c8 = "currency"; + var peg$c9 = "tag"; + var peg$c10 = "category"; + var peg$c11 = "to"; + var peg$c12 = "taxrate"; + var peg$c13 = "tax-rate"; + var peg$c14 = "cardID"; + var peg$c15 = "card"; + var peg$c16 = "from"; + var peg$c17 = "expenseType"; + var peg$c18 = "expense-type"; + var peg$c19 = "type"; + var peg$c20 = "status"; + var peg$c21 = "sortBy"; + var peg$c22 = "sort-by"; + var peg$c23 = "sortOrder"; + var peg$c24 = "sort-order"; + var peg$c25 = "policyID"; + var peg$c26 = "workspace"; + var peg$c27 = "submitted"; + var peg$c28 = "approved"; + var peg$c29 = "paid"; + var peg$c30 = "exported"; + var peg$c31 = "posted"; + var peg$c32 = "!="; + var peg$c33 = ">="; + var peg$c34 = ">"; + var peg$c35 = "<="; + var peg$c36 = "<"; + var peg$c37 = "\""; var peg$r0 = /^[:=]/; var peg$r1 = /^[^ ,"\t\n\r]/; @@ -202,32 +222,52 @@ function peg$parse(input, options) { var peg$e0 = peg$literalExpectation(",", false); var peg$e1 = peg$otherExpectation("key"); - var peg$e2 = peg$literalExpectation("in", false); - var peg$e3 = peg$literalExpectation("currency", false); - var peg$e4 = peg$literalExpectation("tag", false); - var peg$e5 = peg$literalExpectation("category", false); - var peg$e6 = peg$literalExpectation("to", false); - var peg$e7 = peg$literalExpectation("taxRate", false); - var peg$e8 = peg$literalExpectation("from", false); - var peg$e9 = peg$literalExpectation("expenseType", false); - var peg$e10 = peg$literalExpectation("type", false); - var peg$e11 = peg$literalExpectation("status", false); - var peg$e12 = peg$literalExpectation("cardID", false); - var peg$e13 = peg$otherExpectation("operator"); - var peg$e14 = peg$classExpectation([":", "="], false, false); - var peg$e15 = peg$literalExpectation("!=", false); - var peg$e16 = peg$literalExpectation(">=", false); - var peg$e17 = peg$literalExpectation(">", false); - var peg$e18 = peg$literalExpectation("<=", false); - var peg$e19 = peg$literalExpectation("<", false); - var peg$e20 = peg$otherExpectation("quote"); - var peg$e21 = peg$classExpectation([" ", ",", "\"", "\t", "\n", "\r"], true, false); - var peg$e22 = peg$literalExpectation("\"", false); - var peg$e23 = peg$classExpectation(["\"", "\r", "\n"], true, false); - var peg$e24 = peg$classExpectation([" ", ",", "\t", "\n", "\r"], true, false); - var peg$e25 = peg$otherExpectation("word"); - var peg$e26 = peg$otherExpectation("whitespace"); - var peg$e27 = peg$classExpectation([" ", "\t", "\r", "\n"], false, false); + var peg$e2 = peg$literalExpectation("date", true); + var peg$e3 = peg$literalExpectation("amount", true); + var peg$e4 = peg$literalExpectation("merchant", true); + var peg$e5 = peg$literalExpectation("description", true); + var peg$e6 = peg$literalExpectation("reportid", true); + var peg$e7 = peg$literalExpectation("keyword", true); + var peg$e8 = peg$literalExpectation("in", true); + var peg$e9 = peg$literalExpectation("currency", true); + var peg$e10 = peg$literalExpectation("tag", true); + var peg$e11 = peg$literalExpectation("category", true); + var peg$e12 = peg$literalExpectation("to", true); + var peg$e13 = peg$literalExpectation("taxRate", true); + var peg$e14 = peg$literalExpectation("tax-rate", true); + var peg$e15 = peg$literalExpectation("cardID", false); + var peg$e16 = peg$literalExpectation("card", true); + var peg$e17 = peg$literalExpectation("from", true); + var peg$e18 = peg$literalExpectation("expenseType", false); + var peg$e19 = peg$literalExpectation("expense-type", true); + var peg$e20 = peg$literalExpectation("type", true); + var peg$e21 = peg$literalExpectation("status", true); + var peg$e22 = peg$literalExpectation("sortBy", false); + var peg$e23 = peg$literalExpectation("sort-by", true); + var peg$e24 = peg$literalExpectation("sortOrder", false); + var peg$e25 = peg$literalExpectation("sort-order", true); + var peg$e26 = peg$literalExpectation("policyID", false); + var peg$e27 = peg$literalExpectation("workspace", true); + var peg$e28 = peg$literalExpectation("submitted", true); + var peg$e29 = peg$literalExpectation("approved", true); + var peg$e30 = peg$literalExpectation("paid", true); + var peg$e31 = peg$literalExpectation("exported", true); + var peg$e32 = peg$literalExpectation("posted", true); + var peg$e33 = peg$otherExpectation("operator"); + var peg$e34 = peg$classExpectation([":", "="], false, false); + var peg$e35 = peg$literalExpectation("!=", false); + var peg$e36 = peg$literalExpectation(">=", false); + var peg$e37 = peg$literalExpectation(">", false); + var peg$e38 = peg$literalExpectation("<=", false); + var peg$e39 = peg$literalExpectation("<", false); + var peg$e40 = peg$otherExpectation("quote"); + var peg$e41 = peg$classExpectation([" ", ",", "\"", "\t", "\n", "\r"], true, false); + var peg$e42 = peg$literalExpectation("\"", false); + var peg$e43 = peg$classExpectation(["\"", "\r", "\n"], true, false); + var peg$e44 = peg$classExpectation([" ", ",", "\t", "\n", "\r"], true, false); + var peg$e45 = peg$otherExpectation("word"); + var peg$e46 = peg$otherExpectation("whitespace"); + var peg$e47 = peg$classExpectation([" ", "\t", "\r", "\n"], false, false); var peg$f0 = function(ranges) { return { autocomplete, ranges }; }; var peg$f1 = function(filters) { return filters.filter(Boolean).flat(); }; @@ -277,17 +317,42 @@ function peg$parse(input, options) { }); return result; }; - var peg$f5 = function() { return "eq"; }; - var peg$f6 = function() { return "neq"; }; - var peg$f7 = function() { return "gte"; }; - var peg$f8 = function() { return "gt"; }; - var peg$f9 = function() { return "lte"; }; - var peg$f10 = function() { return "lt"; }; - var peg$f11 = function(start, inner, end) { + var peg$f5 = function() { return "date"; }; + var peg$f6 = function() { return "amount"; }; + var peg$f7 = function() { return "merchant"; }; + var peg$f8 = function() { return "description"; }; + var peg$f9 = function() { return "reportID"; }; + var peg$f10 = function() { return "keyword"; }; + var peg$f11 = function() { return "in"; }; + var peg$f12 = function() { return "currency"; }; + var peg$f13 = function() { return "tag"; }; + var peg$f14 = function() { return "category"; }; + var peg$f15 = function() { return "to"; }; + var peg$f16 = function() { return "taxRate"; }; + var peg$f17 = function() { return "cardID"; }; + var peg$f18 = function() { return "from"; }; + var peg$f19 = function() { return "expenseType"; }; + var peg$f20 = function() { return "type"; }; + var peg$f21 = function() { return "status"; }; + var peg$f22 = function() { return "sortBy"; }; + var peg$f23 = function() { return "sortOrder"; }; + var peg$f24 = function() { return "policyID"; }; + var peg$f25 = function() { return "submitted"; }; + var peg$f26 = function() { return "approved"; }; + var peg$f27 = function() { return "paid"; }; + var peg$f28 = function() { return "exported"; }; + var peg$f29 = function() { return "posted"; }; + var peg$f30 = function() { return "eq"; }; + var peg$f31 = function() { return "neq"; }; + var peg$f32 = function() { return "gte"; }; + var peg$f33 = function() { return "gt"; }; + var peg$f34 = function() { return "lte"; }; + var peg$f35 = function() { return "lt"; }; + var peg$f36 = function(start, inner, end) { return [...start, '"', ...inner, '"', ...end].join(""); }; - var peg$f12 = function(chars) { return chars.join("").trim(); }; - var peg$f13 = function() { return "and"; }; + var peg$f37 = function(chars) { return chars.join("").trim(); }; + var peg$f38 = function() { return "and"; }; var peg$currPos = options.peg$currPos | 0; var peg$savedPos = peg$currPos; var peg$posDetailsCache = [{ line: 1, column: 1 }]; @@ -567,93 +632,27 @@ function peg$parse(input, options) { peg$silentFails++; s0 = peg$currPos; - if (input.substr(peg$currPos, 2) === peg$c1) { - s1 = peg$c1; - peg$currPos += 2; - } else { - s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e2); } - } + s1 = peg$parsein(); if (s1 === peg$FAILED) { - if (input.substr(peg$currPos, 8) === peg$c2) { - s1 = peg$c2; - peg$currPos += 8; - } else { - s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e3); } - } + s1 = peg$parsecurrency(); if (s1 === peg$FAILED) { - if (input.substr(peg$currPos, 3) === peg$c3) { - s1 = peg$c3; - peg$currPos += 3; - } else { - s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e4); } - } + s1 = peg$parsetag(); if (s1 === peg$FAILED) { - if (input.substr(peg$currPos, 8) === peg$c4) { - s1 = peg$c4; - peg$currPos += 8; - } else { - s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e5); } - } + s1 = peg$parsecategory(); if (s1 === peg$FAILED) { - if (input.substr(peg$currPos, 2) === peg$c5) { - s1 = peg$c5; - peg$currPos += 2; - } else { - s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e6); } - } + s1 = peg$parseto(); if (s1 === peg$FAILED) { - if (input.substr(peg$currPos, 7) === peg$c6) { - s1 = peg$c6; - peg$currPos += 7; - } else { - s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e7); } - } + s1 = peg$parsetaxRate(); if (s1 === peg$FAILED) { - if (input.substr(peg$currPos, 4) === peg$c7) { - s1 = peg$c7; - peg$currPos += 4; - } else { - s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e8); } - } + s1 = peg$parsefrom(); if (s1 === peg$FAILED) { - if (input.substr(peg$currPos, 11) === peg$c8) { - s1 = peg$c8; - peg$currPos += 11; - } else { - s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e9); } - } + s1 = peg$parseexpenseType(); if (s1 === peg$FAILED) { - if (input.substr(peg$currPos, 4) === peg$c9) { - s1 = peg$c9; - peg$currPos += 4; - } else { - s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e10); } - } + s1 = peg$parsetype(); if (s1 === peg$FAILED) { - if (input.substr(peg$currPos, 6) === peg$c10) { - s1 = peg$c10; - peg$currPos += 6; - } else { - s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e11); } - } + s1 = peg$parsestatus(); if (s1 === peg$FAILED) { - if (input.substr(peg$currPos, 6) === peg$c11) { - s1 = peg$c11; - peg$currPos += 6; - } else { - s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e12); } - } + s1 = peg$parsecardID(); } } } @@ -741,6 +740,560 @@ function peg$parse(input, options) { return s0; } + function peg$parsedate() { + var s0, s1; + + s0 = peg$currPos; + s1 = input.substr(peg$currPos, 4); + if (s1.toLowerCase() === peg$c1) { + peg$currPos += 4; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e2); } + } + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$f5(); + } + s0 = s1; + + return s0; + } + + function peg$parseamount() { + var s0, s1; + + s0 = peg$currPos; + s1 = input.substr(peg$currPos, 6); + if (s1.toLowerCase() === peg$c2) { + peg$currPos += 6; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e3); } + } + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$f6(); + } + s0 = s1; + + return s0; + } + + function peg$parsemerchant() { + var s0, s1; + + s0 = peg$currPos; + s1 = input.substr(peg$currPos, 8); + if (s1.toLowerCase() === peg$c3) { + peg$currPos += 8; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e4); } + } + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$f7(); + } + s0 = s1; + + return s0; + } + + function peg$parsedescription() { + var s0, s1; + + s0 = peg$currPos; + s1 = input.substr(peg$currPos, 11); + if (s1.toLowerCase() === peg$c4) { + peg$currPos += 11; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e5); } + } + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$f8(); + } + s0 = s1; + + return s0; + } + + function peg$parsereportID() { + var s0, s1; + + s0 = peg$currPos; + s1 = input.substr(peg$currPos, 8); + if (s1.toLowerCase() === peg$c5) { + peg$currPos += 8; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e6); } + } + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$f9(); + } + s0 = s1; + + return s0; + } + + function peg$parsekeyword() { + var s0, s1; + + s0 = peg$currPos; + s1 = input.substr(peg$currPos, 7); + if (s1.toLowerCase() === peg$c6) { + peg$currPos += 7; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e7); } + } + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$f10(); + } + s0 = s1; + + return s0; + } + + function peg$parsein() { + var s0, s1; + + s0 = peg$currPos; + s1 = input.substr(peg$currPos, 2); + if (s1.toLowerCase() === peg$c7) { + peg$currPos += 2; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e8); } + } + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$f11(); + } + s0 = s1; + + return s0; + } + + function peg$parsecurrency() { + var s0, s1; + + s0 = peg$currPos; + s1 = input.substr(peg$currPos, 8); + if (s1.toLowerCase() === peg$c8) { + peg$currPos += 8; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e9); } + } + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$f12(); + } + s0 = s1; + + return s0; + } + + function peg$parsetag() { + var s0, s1; + + s0 = peg$currPos; + s1 = input.substr(peg$currPos, 3); + if (s1.toLowerCase() === peg$c9) { + peg$currPos += 3; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e10); } + } + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$f13(); + } + s0 = s1; + + return s0; + } + + function peg$parsecategory() { + var s0, s1; + + s0 = peg$currPos; + s1 = input.substr(peg$currPos, 8); + if (s1.toLowerCase() === peg$c10) { + peg$currPos += 8; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e11); } + } + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$f14(); + } + s0 = s1; + + return s0; + } + + function peg$parseto() { + var s0, s1; + + s0 = peg$currPos; + s1 = input.substr(peg$currPos, 2); + if (s1.toLowerCase() === peg$c11) { + peg$currPos += 2; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e12); } + } + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$f15(); + } + s0 = s1; + + return s0; + } + + function peg$parsetaxRate() { + var s0, s1; + + s0 = input.substr(peg$currPos, 7); + if (s0.toLowerCase() === peg$c12) { + peg$currPos += 7; + } else { + s0 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e13); } + } + if (s0 === peg$FAILED) { + s0 = peg$currPos; + s1 = input.substr(peg$currPos, 8); + if (s1.toLowerCase() === peg$c13) { + peg$currPos += 8; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e14); } + } + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$f16(); + } + s0 = s1; + } + + return s0; + } + + function peg$parsecardID() { + var s0, s1; + + if (input.substr(peg$currPos, 6) === peg$c14) { + s0 = peg$c14; + peg$currPos += 6; + } else { + s0 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e15); } + } + if (s0 === peg$FAILED) { + s0 = peg$currPos; + s1 = input.substr(peg$currPos, 4); + if (s1.toLowerCase() === peg$c15) { + peg$currPos += 4; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e16); } + } + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$f17(); + } + s0 = s1; + } + + return s0; + } + + function peg$parsefrom() { + var s0, s1; + + s0 = peg$currPos; + s1 = input.substr(peg$currPos, 4); + if (s1.toLowerCase() === peg$c16) { + peg$currPos += 4; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e17); } + } + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$f18(); + } + s0 = s1; + + return s0; + } + + function peg$parseexpenseType() { + var s0, s1; + + if (input.substr(peg$currPos, 11) === peg$c17) { + s0 = peg$c17; + peg$currPos += 11; + } else { + s0 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e18); } + } + if (s0 === peg$FAILED) { + s0 = peg$currPos; + s1 = input.substr(peg$currPos, 12); + if (s1.toLowerCase() === peg$c18) { + peg$currPos += 12; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e19); } + } + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$f19(); + } + s0 = s1; + } + + return s0; + } + + function peg$parsetype() { + var s0, s1; + + s0 = peg$currPos; + s1 = input.substr(peg$currPos, 4); + if (s1.toLowerCase() === peg$c19) { + peg$currPos += 4; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e20); } + } + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$f20(); + } + s0 = s1; + + return s0; + } + + function peg$parsestatus() { + var s0, s1; + + s0 = peg$currPos; + s1 = input.substr(peg$currPos, 6); + if (s1.toLowerCase() === peg$c20) { + peg$currPos += 6; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e21); } + } + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$f21(); + } + s0 = s1; + + return s0; + } + + function peg$parsesortBy() { + var s0, s1; + + if (input.substr(peg$currPos, 6) === peg$c21) { + s0 = peg$c21; + peg$currPos += 6; + } else { + s0 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e22); } + } + if (s0 === peg$FAILED) { + s0 = peg$currPos; + s1 = input.substr(peg$currPos, 7); + if (s1.toLowerCase() === peg$c22) { + peg$currPos += 7; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e23); } + } + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$f22(); + } + s0 = s1; + } + + return s0; + } + + function peg$parsesortOrder() { + var s0, s1; + + if (input.substr(peg$currPos, 9) === peg$c23) { + s0 = peg$c23; + peg$currPos += 9; + } else { + s0 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e24); } + } + if (s0 === peg$FAILED) { + s0 = peg$currPos; + s1 = input.substr(peg$currPos, 10); + if (s1.toLowerCase() === peg$c24) { + peg$currPos += 10; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e25); } + } + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$f23(); + } + s0 = s1; + } + + return s0; + } + + function peg$parsepolicyID() { + var s0, s1; + + if (input.substr(peg$currPos, 8) === peg$c25) { + s0 = peg$c25; + peg$currPos += 8; + } else { + s0 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e26); } + } + if (s0 === peg$FAILED) { + s0 = peg$currPos; + s1 = input.substr(peg$currPos, 9); + if (s1.toLowerCase() === peg$c26) { + peg$currPos += 9; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e27); } + } + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$f24(); + } + s0 = s1; + } + + return s0; + } + + function peg$parsesubmitted() { + var s0, s1; + + s0 = peg$currPos; + s1 = input.substr(peg$currPos, 9); + if (s1.toLowerCase() === peg$c27) { + peg$currPos += 9; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e28); } + } + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$f25(); + } + s0 = s1; + + return s0; + } + + function peg$parseapproved() { + var s0, s1; + + s0 = peg$currPos; + s1 = input.substr(peg$currPos, 8); + if (s1.toLowerCase() === peg$c28) { + peg$currPos += 8; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e29); } + } + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$f26(); + } + s0 = s1; + + return s0; + } + + function peg$parsepaid() { + var s0, s1; + + s0 = peg$currPos; + s1 = input.substr(peg$currPos, 4); + if (s1.toLowerCase() === peg$c29) { + peg$currPos += 4; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e30); } + } + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$f27(); + } + s0 = s1; + + return s0; + } + + function peg$parseexported() { + var s0, s1; + + s0 = peg$currPos; + s1 = input.substr(peg$currPos, 8); + if (s1.toLowerCase() === peg$c30) { + peg$currPos += 8; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e31); } + } + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$f28(); + } + s0 = s1; + + return s0; + } + + function peg$parseposted() { + var s0, s1; + + s0 = peg$currPos; + s1 = input.substr(peg$currPos, 6); + if (s1.toLowerCase() === peg$c31) { + peg$currPos += 6; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e32); } + } + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$f29(); + } + s0 = s1; + + return s0; + } + function peg$parseoperator() { var s0, s1; @@ -751,81 +1304,81 @@ function peg$parse(input, options) { peg$currPos++; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e14); } + if (peg$silentFails === 0) { peg$fail(peg$e34); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f5(); + s1 = peg$f30(); } s0 = s1; if (s0 === peg$FAILED) { s0 = peg$currPos; - if (input.substr(peg$currPos, 2) === peg$c12) { - s1 = peg$c12; + if (input.substr(peg$currPos, 2) === peg$c32) { + s1 = peg$c32; peg$currPos += 2; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e15); } + if (peg$silentFails === 0) { peg$fail(peg$e35); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f6(); + s1 = peg$f31(); } s0 = s1; if (s0 === peg$FAILED) { s0 = peg$currPos; - if (input.substr(peg$currPos, 2) === peg$c13) { - s1 = peg$c13; + if (input.substr(peg$currPos, 2) === peg$c33) { + s1 = peg$c33; peg$currPos += 2; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e16); } + if (peg$silentFails === 0) { peg$fail(peg$e36); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f7(); + s1 = peg$f32(); } s0 = s1; if (s0 === peg$FAILED) { s0 = peg$currPos; if (input.charCodeAt(peg$currPos) === 62) { - s1 = peg$c14; + s1 = peg$c34; peg$currPos++; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e17); } + if (peg$silentFails === 0) { peg$fail(peg$e37); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f8(); + s1 = peg$f33(); } s0 = s1; if (s0 === peg$FAILED) { s0 = peg$currPos; - if (input.substr(peg$currPos, 2) === peg$c15) { - s1 = peg$c15; + if (input.substr(peg$currPos, 2) === peg$c35) { + s1 = peg$c35; peg$currPos += 2; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e18); } + if (peg$silentFails === 0) { peg$fail(peg$e38); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f9(); + s1 = peg$f34(); } s0 = s1; if (s0 === peg$FAILED) { s0 = peg$currPos; if (input.charCodeAt(peg$currPos) === 60) { - s1 = peg$c16; + s1 = peg$c36; peg$currPos++; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e19); } + if (peg$silentFails === 0) { peg$fail(peg$e39); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f10(); + s1 = peg$f35(); } s0 = s1; } @@ -836,7 +1389,7 @@ function peg$parse(input, options) { peg$silentFails--; if (s0 === peg$FAILED) { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e13); } + if (peg$silentFails === 0) { peg$fail(peg$e33); } } return s0; @@ -853,7 +1406,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e21); } + if (peg$silentFails === 0) { peg$fail(peg$e41); } } while (s2 !== peg$FAILED) { s1.push(s2); @@ -862,15 +1415,15 @@ function peg$parse(input, options) { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e21); } + if (peg$silentFails === 0) { peg$fail(peg$e41); } } } if (input.charCodeAt(peg$currPos) === 34) { - s2 = peg$c17; + s2 = peg$c37; peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e22); } + if (peg$silentFails === 0) { peg$fail(peg$e42); } } if (s2 !== peg$FAILED) { s3 = []; @@ -879,7 +1432,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s4 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e23); } + if (peg$silentFails === 0) { peg$fail(peg$e43); } } while (s4 !== peg$FAILED) { s3.push(s4); @@ -888,15 +1441,15 @@ function peg$parse(input, options) { peg$currPos++; } else { s4 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e23); } + if (peg$silentFails === 0) { peg$fail(peg$e43); } } } if (input.charCodeAt(peg$currPos) === 34) { - s4 = peg$c17; + s4 = peg$c37; peg$currPos++; } else { s4 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e22); } + if (peg$silentFails === 0) { peg$fail(peg$e42); } } if (s4 !== peg$FAILED) { s5 = []; @@ -905,7 +1458,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s6 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e24); } + if (peg$silentFails === 0) { peg$fail(peg$e44); } } while (s6 !== peg$FAILED) { s5.push(s6); @@ -914,11 +1467,11 @@ function peg$parse(input, options) { peg$currPos++; } else { s6 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e24); } + if (peg$silentFails === 0) { peg$fail(peg$e44); } } } peg$savedPos = s0; - s0 = peg$f11(s1, s3, s5); + s0 = peg$f36(s1, s3, s5); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -930,7 +1483,7 @@ function peg$parse(input, options) { peg$silentFails--; if (s0 === peg$FAILED) { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e20); } + if (peg$silentFails === 0) { peg$fail(peg$e40); } } return s0; @@ -947,7 +1500,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e24); } + if (peg$silentFails === 0) { peg$fail(peg$e44); } } if (s2 !== peg$FAILED) { while (s2 !== peg$FAILED) { @@ -957,7 +1510,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e24); } + if (peg$silentFails === 0) { peg$fail(peg$e44); } } } } else { @@ -965,13 +1518,13 @@ function peg$parse(input, options) { } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f12(s1); + s1 = peg$f37(s1); } s0 = s1; peg$silentFails--; if (s0 === peg$FAILED) { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e25); } + if (peg$silentFails === 0) { peg$fail(peg$e45); } } return s0; @@ -983,7 +1536,7 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = peg$parse_(); peg$savedPos = s0; - s1 = peg$f13(); + s1 = peg$f38(); s0 = s1; return s0; @@ -999,7 +1552,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e27); } + if (peg$silentFails === 0) { peg$fail(peg$e47); } } while (s1 !== peg$FAILED) { s0.push(s1); @@ -1008,12 +1561,12 @@ function peg$parse(input, options) { peg$currPos++; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e27); } + if (peg$silentFails === 0) { peg$fail(peg$e47); } } } peg$silentFails--; s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e26); } + if (peg$silentFails === 0) { peg$fail(peg$e46); } return s0; } diff --git a/src/libs/SearchParser/autocompleteParser.peggy b/src/libs/SearchParser/autocompleteParser.peggy index e2a8bed9a9cc..928d1751f8ce 100644 --- a/src/libs/SearchParser/autocompleteParser.peggy +++ b/src/libs/SearchParser/autocompleteParser.peggy @@ -51,17 +51,17 @@ freeTextFilter = _ (identifier/ ",") _ { autocomplete = null; } autocompleteKey "key" = @( - "in" - / "currency" - / "tag" - / "category" - / "to" - / "taxRate" - / "from" - / "expenseType" - / "type" - / "status" - / "cardID" + in + / currency + / tag + / category + / to + / taxRate + / from + / expenseType + / type + / status + / cardID ) identifier diff --git a/src/libs/SearchParser/baseRules.peggy b/src/libs/SearchParser/baseRules.peggy index 7605d888ba43..cc1305adc8b3 100644 --- a/src/libs/SearchParser/baseRules.peggy +++ b/src/libs/SearchParser/baseRules.peggy @@ -8,6 +8,45 @@ // logicalAnd: rule to match whitespace and return it as a logical 'and' operator. // whitespace: rule to match whitespaces. +// rules to match re-defined search syntax keys. +date = "date"i { return "date"; } +amount = "amount"i { return "amount"; } +merchant = "merchant"i { return "merchant"; } +description = "description"i { return "description"; } +reportID = "reportid"i { return "reportID"; } +keyword = "keyword"i { return "keyword"; } +in = "in"i { return "in"; } +currency = "currency"i { return "currency"; } +tag = "tag"i { return "tag"; } +category = "category"i { return "category"; } +to = "to"i { return "to"; } +taxRate + = "taxRate"i + / "tax-rate"i { return "taxRate"; } +cardID + = "cardID" + / "card"i { return "cardID"; } +from = "from"i { return "from"; } +expenseType + = "expenseType" + / "expense-type"i { return "expenseType"; } +type = "type"i { return "type"; } +status = "status"i { return "status"; } +sortBy + = "sortBy" + / "sort-by"i { return "sortBy"; } +sortOrder + = "sortOrder" + / "sort-order"i { return "sortOrder"; } +policyID + = "policyID" + / "workspace"i { return "policyID"; } +submitted = "submitted"i { return "submitted"; } +approved = "approved"i { return "approved"; } +paid = "paid"i { return "paid"; } +exported = "exported"i { return "exported"; } +posted = "posted"i { return "posted"; } + operator "operator" = (":" / "=") { return "eq"; } / "!=" { return "neq"; } diff --git a/src/libs/SearchParser/searchParser.js b/src/libs/SearchParser/searchParser.js index e7b087a969a8..47b534d32cad 100644 --- a/src/libs/SearchParser/searchParser.js +++ b/src/libs/SearchParser/searchParser.js @@ -180,38 +180,44 @@ function peg$parse(input, options) { var peg$startRuleFunctions = { query: peg$parsequery }; var peg$startRuleFunction = peg$parsequery; - var peg$c0 = "date"; - var peg$c1 = "amount"; - var peg$c2 = "merchant"; - var peg$c3 = "description"; - var peg$c4 = "reportID"; - var peg$c5 = "keyword"; - var peg$c6 = "in"; - var peg$c7 = "currency"; - var peg$c8 = "tag"; - var peg$c9 = "category"; - var peg$c10 = "to"; - var peg$c11 = "taxRate"; - var peg$c12 = "cardID"; - var peg$c13 = "from"; - var peg$c14 = "expenseType"; - var peg$c15 = "submitted"; - var peg$c16 = "approved"; - var peg$c17 = "paid"; - var peg$c18 = "exported"; - var peg$c19 = "posted"; - var peg$c20 = "type"; - var peg$c21 = "status"; - var peg$c22 = "sortBy"; + var peg$c0 = ","; + var peg$c1 = "date"; + var peg$c2 = "amount"; + var peg$c3 = "merchant"; + var peg$c4 = "description"; + var peg$c5 = "reportid"; + var peg$c6 = "keyword"; + var peg$c7 = "in"; + var peg$c8 = "currency"; + var peg$c9 = "tag"; + var peg$c10 = "category"; + var peg$c11 = "to"; + var peg$c12 = "taxrate"; + var peg$c13 = "tax-rate"; + var peg$c14 = "cardID"; + var peg$c15 = "card"; + var peg$c16 = "from"; + var peg$c17 = "expenseType"; + var peg$c18 = "expense-type"; + var peg$c19 = "type"; + var peg$c20 = "status"; + var peg$c21 = "sortBy"; + var peg$c22 = "sort-by"; var peg$c23 = "sortOrder"; - var peg$c24 = "policyID"; - var peg$c25 = ","; - var peg$c26 = "!="; - var peg$c27 = ">="; - var peg$c28 = ">"; - var peg$c29 = "<="; - var peg$c30 = "<"; - var peg$c31 = "\""; + var peg$c24 = "sort-order"; + var peg$c25 = "policyID"; + var peg$c26 = "workspace"; + var peg$c27 = "submitted"; + var peg$c28 = "approved"; + var peg$c29 = "paid"; + var peg$c30 = "exported"; + var peg$c31 = "posted"; + var peg$c32 = "!="; + var peg$c33 = ">="; + var peg$c34 = ">"; + var peg$c35 = "<="; + var peg$c36 = "<"; + var peg$c37 = "\""; var peg$r0 = /^[^ \t\r\n]/; var peg$r1 = /^[:=]/; @@ -222,48 +228,54 @@ function peg$parse(input, options) { var peg$e0 = peg$classExpectation([" ", "\t", "\r", "\n"], true, false); var peg$e1 = peg$otherExpectation("key"); - var peg$e2 = peg$literalExpectation("date", false); - var peg$e3 = peg$literalExpectation("amount", false); - var peg$e4 = peg$literalExpectation("merchant", false); - var peg$e5 = peg$literalExpectation("description", false); - var peg$e6 = peg$literalExpectation("reportID", false); - var peg$e7 = peg$literalExpectation("keyword", false); - var peg$e8 = peg$literalExpectation("in", false); - var peg$e9 = peg$literalExpectation("currency", false); - var peg$e10 = peg$literalExpectation("tag", false); - var peg$e11 = peg$literalExpectation("category", false); - var peg$e12 = peg$literalExpectation("to", false); - var peg$e13 = peg$literalExpectation("taxRate", false); - var peg$e14 = peg$literalExpectation("cardID", false); - var peg$e15 = peg$literalExpectation("from", false); - var peg$e16 = peg$literalExpectation("expenseType", false); - var peg$e17 = peg$literalExpectation("submitted", false); - var peg$e18 = peg$literalExpectation("approved", false); - var peg$e19 = peg$literalExpectation("paid", false); - var peg$e20 = peg$literalExpectation("exported", false); - var peg$e21 = peg$literalExpectation("posted", false); - var peg$e22 = peg$otherExpectation("default key"); - var peg$e23 = peg$literalExpectation("type", false); - var peg$e24 = peg$literalExpectation("status", false); - var peg$e25 = peg$literalExpectation("sortBy", false); + var peg$e2 = peg$otherExpectation("default key"); + var peg$e3 = peg$literalExpectation(",", false); + var peg$e4 = peg$literalExpectation("date", true); + var peg$e5 = peg$literalExpectation("amount", true); + var peg$e6 = peg$literalExpectation("merchant", true); + var peg$e7 = peg$literalExpectation("description", true); + var peg$e8 = peg$literalExpectation("reportid", true); + var peg$e9 = peg$literalExpectation("keyword", true); + var peg$e10 = peg$literalExpectation("in", true); + var peg$e11 = peg$literalExpectation("currency", true); + var peg$e12 = peg$literalExpectation("tag", true); + var peg$e13 = peg$literalExpectation("category", true); + var peg$e14 = peg$literalExpectation("to", true); + var peg$e15 = peg$literalExpectation("taxRate", true); + var peg$e16 = peg$literalExpectation("tax-rate", true); + var peg$e17 = peg$literalExpectation("cardID", false); + var peg$e18 = peg$literalExpectation("card", true); + var peg$e19 = peg$literalExpectation("from", true); + var peg$e20 = peg$literalExpectation("expenseType", false); + var peg$e21 = peg$literalExpectation("expense-type", true); + var peg$e22 = peg$literalExpectation("type", true); + var peg$e23 = peg$literalExpectation("status", true); + var peg$e24 = peg$literalExpectation("sortBy", false); + var peg$e25 = peg$literalExpectation("sort-by", true); var peg$e26 = peg$literalExpectation("sortOrder", false); - var peg$e27 = peg$literalExpectation("policyID", false); - var peg$e28 = peg$literalExpectation(",", false); - var peg$e29 = peg$otherExpectation("operator"); - var peg$e30 = peg$classExpectation([":", "="], false, false); - var peg$e31 = peg$literalExpectation("!=", false); - var peg$e32 = peg$literalExpectation(">=", false); - var peg$e33 = peg$literalExpectation(">", false); - var peg$e34 = peg$literalExpectation("<=", false); - var peg$e35 = peg$literalExpectation("<", false); - var peg$e36 = peg$otherExpectation("quote"); - var peg$e37 = peg$classExpectation([" ", ",", "\"", "\t", "\n", "\r"], true, false); - var peg$e38 = peg$literalExpectation("\"", false); - var peg$e39 = peg$classExpectation(["\"", "\r", "\n"], true, false); - var peg$e40 = peg$classExpectation([" ", ",", "\t", "\n", "\r"], true, false); - var peg$e41 = peg$otherExpectation("word"); - var peg$e42 = peg$otherExpectation("whitespace"); - var peg$e43 = peg$classExpectation([" ", "\t", "\r", "\n"], false, false); + var peg$e27 = peg$literalExpectation("sort-order", true); + var peg$e28 = peg$literalExpectation("policyID", false); + var peg$e29 = peg$literalExpectation("workspace", true); + var peg$e30 = peg$literalExpectation("submitted", true); + var peg$e31 = peg$literalExpectation("approved", true); + var peg$e32 = peg$literalExpectation("paid", true); + var peg$e33 = peg$literalExpectation("exported", true); + var peg$e34 = peg$literalExpectation("posted", true); + var peg$e35 = peg$otherExpectation("operator"); + var peg$e36 = peg$classExpectation([":", "="], false, false); + var peg$e37 = peg$literalExpectation("!=", false); + var peg$e38 = peg$literalExpectation(">=", false); + var peg$e39 = peg$literalExpectation(">", false); + var peg$e40 = peg$literalExpectation("<=", false); + var peg$e41 = peg$literalExpectation("<", false); + var peg$e42 = peg$otherExpectation("quote"); + var peg$e43 = peg$classExpectation([" ", ",", "\"", "\t", "\n", "\r"], true, false); + var peg$e44 = peg$literalExpectation("\"", false); + var peg$e45 = peg$classExpectation(["\"", "\r", "\n"], true, false); + var peg$e46 = peg$classExpectation([" ", ",", "\t", "\n", "\r"], true, false); + var peg$e47 = peg$otherExpectation("word"); + var peg$e48 = peg$otherExpectation("whitespace"); + var peg$e49 = peg$classExpectation([" ", "\t", "\r", "\n"], false, false); var peg$f0 = function(filters) { return applyDefaults(filters); }; var peg$f1 = function(head, tail) { @@ -319,17 +331,42 @@ function peg$parse(input, options) { } return value[0]; }; - var peg$f6 = function() { return "eq"; }; - var peg$f7 = function() { return "neq"; }; - var peg$f8 = function() { return "gte"; }; - var peg$f9 = function() { return "gt"; }; - var peg$f10 = function() { return "lte"; }; - var peg$f11 = function() { return "lt"; }; - var peg$f12 = function(start, inner, end) { + var peg$f6 = function() { return "date"; }; + var peg$f7 = function() { return "amount"; }; + var peg$f8 = function() { return "merchant"; }; + var peg$f9 = function() { return "description"; }; + var peg$f10 = function() { return "reportID"; }; + var peg$f11 = function() { return "keyword"; }; + var peg$f12 = function() { return "in"; }; + var peg$f13 = function() { return "currency"; }; + var peg$f14 = function() { return "tag"; }; + var peg$f15 = function() { return "category"; }; + var peg$f16 = function() { return "to"; }; + var peg$f17 = function() { return "taxRate"; }; + var peg$f18 = function() { return "cardID"; }; + var peg$f19 = function() { return "from"; }; + var peg$f20 = function() { return "expenseType"; }; + var peg$f21 = function() { return "type"; }; + var peg$f22 = function() { return "status"; }; + var peg$f23 = function() { return "sortBy"; }; + var peg$f24 = function() { return "sortOrder"; }; + var peg$f25 = function() { return "policyID"; }; + var peg$f26 = function() { return "submitted"; }; + var peg$f27 = function() { return "approved"; }; + var peg$f28 = function() { return "paid"; }; + var peg$f29 = function() { return "exported"; }; + var peg$f30 = function() { return "posted"; }; + var peg$f31 = function() { return "eq"; }; + var peg$f32 = function() { return "neq"; }; + var peg$f33 = function() { return "gte"; }; + var peg$f34 = function() { return "gt"; }; + var peg$f35 = function() { return "lte"; }; + var peg$f36 = function() { return "lt"; }; + var peg$f37 = function(start, inner, end) { return [...start, '"', ...inner, '"', ...end].join(""); }; - var peg$f13 = function(chars) { return chars.join("").trim(); }; - var peg$f14 = function() { return "and"; }; + var peg$f38 = function(chars) { return chars.join("").trim(); }; + var peg$f39 = function() { return "and"; }; var peg$currPos = options.peg$currPos | 0; var peg$savedPos = peg$currPos; var peg$posDetailsCache = [{ line: 1, column: 1 }]; @@ -678,165 +715,45 @@ function peg$parse(input, options) { peg$silentFails++; s0 = peg$currPos; - if (input.substr(peg$currPos, 4) === peg$c0) { - s1 = peg$c0; - peg$currPos += 4; - } else { - s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e2); } - } + s1 = peg$parsedate(); if (s1 === peg$FAILED) { - if (input.substr(peg$currPos, 6) === peg$c1) { - s1 = peg$c1; - peg$currPos += 6; - } else { - s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e3); } - } + s1 = peg$parseamount(); if (s1 === peg$FAILED) { - if (input.substr(peg$currPos, 8) === peg$c2) { - s1 = peg$c2; - peg$currPos += 8; - } else { - s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e4); } - } + s1 = peg$parsemerchant(); if (s1 === peg$FAILED) { - if (input.substr(peg$currPos, 11) === peg$c3) { - s1 = peg$c3; - peg$currPos += 11; - } else { - s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e5); } - } + s1 = peg$parsedescription(); if (s1 === peg$FAILED) { - if (input.substr(peg$currPos, 8) === peg$c4) { - s1 = peg$c4; - peg$currPos += 8; - } else { - s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e6); } - } + s1 = peg$parsereportID(); if (s1 === peg$FAILED) { - if (input.substr(peg$currPos, 7) === peg$c5) { - s1 = peg$c5; - peg$currPos += 7; - } else { - s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e7); } - } + s1 = peg$parsekeyword(); if (s1 === peg$FAILED) { - if (input.substr(peg$currPos, 2) === peg$c6) { - s1 = peg$c6; - peg$currPos += 2; - } else { - s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e8); } - } + s1 = peg$parsein(); if (s1 === peg$FAILED) { - if (input.substr(peg$currPos, 8) === peg$c7) { - s1 = peg$c7; - peg$currPos += 8; - } else { - s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e9); } - } + s1 = peg$parsecurrency(); if (s1 === peg$FAILED) { - if (input.substr(peg$currPos, 3) === peg$c8) { - s1 = peg$c8; - peg$currPos += 3; - } else { - s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e10); } - } + s1 = peg$parsetag(); if (s1 === peg$FAILED) { - if (input.substr(peg$currPos, 8) === peg$c9) { - s1 = peg$c9; - peg$currPos += 8; - } else { - s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e11); } - } + s1 = peg$parsecategory(); if (s1 === peg$FAILED) { - if (input.substr(peg$currPos, 2) === peg$c10) { - s1 = peg$c10; - peg$currPos += 2; - } else { - s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e12); } - } + s1 = peg$parseto(); if (s1 === peg$FAILED) { - if (input.substr(peg$currPos, 7) === peg$c11) { - s1 = peg$c11; - peg$currPos += 7; - } else { - s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e13); } - } + s1 = peg$parsetaxRate(); if (s1 === peg$FAILED) { - if (input.substr(peg$currPos, 6) === peg$c12) { - s1 = peg$c12; - peg$currPos += 6; - } else { - s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e14); } - } + s1 = peg$parsecardID(); if (s1 === peg$FAILED) { - if (input.substr(peg$currPos, 4) === peg$c13) { - s1 = peg$c13; - peg$currPos += 4; - } else { - s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e15); } - } + s1 = peg$parsefrom(); if (s1 === peg$FAILED) { - if (input.substr(peg$currPos, 11) === peg$c14) { - s1 = peg$c14; - peg$currPos += 11; - } else { - s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e16); } - } + s1 = peg$parseexpenseType(); if (s1 === peg$FAILED) { - if (input.substr(peg$currPos, 9) === peg$c15) { - s1 = peg$c15; - peg$currPos += 9; - } else { - s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e17); } - } + s1 = peg$parsesubmitted(); if (s1 === peg$FAILED) { - if (input.substr(peg$currPos, 8) === peg$c16) { - s1 = peg$c16; - peg$currPos += 8; - } else { - s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e18); } - } + s1 = peg$parseapproved(); if (s1 === peg$FAILED) { - if (input.substr(peg$currPos, 4) === peg$c17) { - s1 = peg$c17; - peg$currPos += 4; - } else { - s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e19); } - } + s1 = peg$parsepaid(); if (s1 === peg$FAILED) { - if (input.substr(peg$currPos, 8) === peg$c18) { - s1 = peg$c18; - peg$currPos += 8; - } else { - s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e20); } - } + s1 = peg$parseexported(); if (s1 === peg$FAILED) { - if (input.substr(peg$currPos, 6) === peg$c19) { - s1 = peg$c19; - peg$currPos += 6; - } else { - s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e21); } - } + s1 = peg$parseposted(); } } } @@ -876,45 +793,15 @@ function peg$parse(input, options) { peg$silentFails++; s0 = peg$currPos; - if (input.substr(peg$currPos, 4) === peg$c20) { - s1 = peg$c20; - peg$currPos += 4; - } else { - s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e23); } - } + s1 = peg$parsetype(); if (s1 === peg$FAILED) { - if (input.substr(peg$currPos, 6) === peg$c21) { - s1 = peg$c21; - peg$currPos += 6; - } else { - s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e24); } - } + s1 = peg$parsestatus(); if (s1 === peg$FAILED) { - if (input.substr(peg$currPos, 6) === peg$c22) { - s1 = peg$c22; - peg$currPos += 6; - } else { - s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e25); } - } + s1 = peg$parsesortBy(); if (s1 === peg$FAILED) { - if (input.substr(peg$currPos, 9) === peg$c23) { - s1 = peg$c23; - peg$currPos += 9; - } else { - s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e26); } - } + s1 = peg$parsesortOrder(); if (s1 === peg$FAILED) { - if (input.substr(peg$currPos, 8) === peg$c24) { - s1 = peg$c24; - peg$currPos += 8; - } else { - s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e27); } - } + s1 = peg$parsepolicyID(); } } } @@ -928,7 +815,7 @@ function peg$parse(input, options) { peg$silentFails--; if (s0 === peg$FAILED) { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e22); } + if (peg$silentFails === 0) { peg$fail(peg$e2); } } return s0; @@ -940,21 +827,21 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = []; if (input.charCodeAt(peg$currPos) === 44) { - s2 = peg$c25; + s2 = peg$c0; peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e28); } + if (peg$silentFails === 0) { peg$fail(peg$e3); } } if (s2 !== peg$FAILED) { while (s2 !== peg$FAILED) { s1.push(s2); if (input.charCodeAt(peg$currPos) === 44) { - s2 = peg$c25; + s2 = peg$c0; peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e28); } + if (peg$silentFails === 0) { peg$fail(peg$e3); } } } } else { @@ -974,21 +861,21 @@ function peg$parse(input, options) { s4 = peg$currPos; s5 = []; if (input.charCodeAt(peg$currPos) === 44) { - s6 = peg$c25; + s6 = peg$c0; peg$currPos++; } else { s6 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e28); } + if (peg$silentFails === 0) { peg$fail(peg$e3); } } if (s6 !== peg$FAILED) { while (s6 !== peg$FAILED) { s5.push(s6); if (input.charCodeAt(peg$currPos) === 44) { - s6 = peg$c25; + s6 = peg$c0; peg$currPos++; } else { s6 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e28); } + if (peg$silentFails === 0) { peg$fail(peg$e3); } } } } else { @@ -1018,21 +905,21 @@ function peg$parse(input, options) { if (s2 !== peg$FAILED) { s3 = []; if (input.charCodeAt(peg$currPos) === 44) { - s4 = peg$c25; + s4 = peg$c0; peg$currPos++; } else { s4 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e28); } + if (peg$silentFails === 0) { peg$fail(peg$e3); } } if (s4 !== peg$FAILED) { while (s4 !== peg$FAILED) { s3.push(s4); if (input.charCodeAt(peg$currPos) === 44) { - s4 = peg$c25; + s4 = peg$c0; peg$currPos++; } else { s4 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e28); } + if (peg$silentFails === 0) { peg$fail(peg$e3); } } } } else { @@ -1051,6 +938,560 @@ function peg$parse(input, options) { return s0; } + function peg$parsedate() { + var s0, s1; + + s0 = peg$currPos; + s1 = input.substr(peg$currPos, 4); + if (s1.toLowerCase() === peg$c1) { + peg$currPos += 4; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e4); } + } + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$f6(); + } + s0 = s1; + + return s0; + } + + function peg$parseamount() { + var s0, s1; + + s0 = peg$currPos; + s1 = input.substr(peg$currPos, 6); + if (s1.toLowerCase() === peg$c2) { + peg$currPos += 6; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e5); } + } + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$f7(); + } + s0 = s1; + + return s0; + } + + function peg$parsemerchant() { + var s0, s1; + + s0 = peg$currPos; + s1 = input.substr(peg$currPos, 8); + if (s1.toLowerCase() === peg$c3) { + peg$currPos += 8; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e6); } + } + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$f8(); + } + s0 = s1; + + return s0; + } + + function peg$parsedescription() { + var s0, s1; + + s0 = peg$currPos; + s1 = input.substr(peg$currPos, 11); + if (s1.toLowerCase() === peg$c4) { + peg$currPos += 11; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e7); } + } + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$f9(); + } + s0 = s1; + + return s0; + } + + function peg$parsereportID() { + var s0, s1; + + s0 = peg$currPos; + s1 = input.substr(peg$currPos, 8); + if (s1.toLowerCase() === peg$c5) { + peg$currPos += 8; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e8); } + } + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$f10(); + } + s0 = s1; + + return s0; + } + + function peg$parsekeyword() { + var s0, s1; + + s0 = peg$currPos; + s1 = input.substr(peg$currPos, 7); + if (s1.toLowerCase() === peg$c6) { + peg$currPos += 7; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e9); } + } + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$f11(); + } + s0 = s1; + + return s0; + } + + function peg$parsein() { + var s0, s1; + + s0 = peg$currPos; + s1 = input.substr(peg$currPos, 2); + if (s1.toLowerCase() === peg$c7) { + peg$currPos += 2; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e10); } + } + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$f12(); + } + s0 = s1; + + return s0; + } + + function peg$parsecurrency() { + var s0, s1; + + s0 = peg$currPos; + s1 = input.substr(peg$currPos, 8); + if (s1.toLowerCase() === peg$c8) { + peg$currPos += 8; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e11); } + } + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$f13(); + } + s0 = s1; + + return s0; + } + + function peg$parsetag() { + var s0, s1; + + s0 = peg$currPos; + s1 = input.substr(peg$currPos, 3); + if (s1.toLowerCase() === peg$c9) { + peg$currPos += 3; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e12); } + } + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$f14(); + } + s0 = s1; + + return s0; + } + + function peg$parsecategory() { + var s0, s1; + + s0 = peg$currPos; + s1 = input.substr(peg$currPos, 8); + if (s1.toLowerCase() === peg$c10) { + peg$currPos += 8; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e13); } + } + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$f15(); + } + s0 = s1; + + return s0; + } + + function peg$parseto() { + var s0, s1; + + s0 = peg$currPos; + s1 = input.substr(peg$currPos, 2); + if (s1.toLowerCase() === peg$c11) { + peg$currPos += 2; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e14); } + } + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$f16(); + } + s0 = s1; + + return s0; + } + + function peg$parsetaxRate() { + var s0, s1; + + s0 = input.substr(peg$currPos, 7); + if (s0.toLowerCase() === peg$c12) { + peg$currPos += 7; + } else { + s0 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e15); } + } + if (s0 === peg$FAILED) { + s0 = peg$currPos; + s1 = input.substr(peg$currPos, 8); + if (s1.toLowerCase() === peg$c13) { + peg$currPos += 8; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e16); } + } + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$f17(); + } + s0 = s1; + } + + return s0; + } + + function peg$parsecardID() { + var s0, s1; + + if (input.substr(peg$currPos, 6) === peg$c14) { + s0 = peg$c14; + peg$currPos += 6; + } else { + s0 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e17); } + } + if (s0 === peg$FAILED) { + s0 = peg$currPos; + s1 = input.substr(peg$currPos, 4); + if (s1.toLowerCase() === peg$c15) { + peg$currPos += 4; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e18); } + } + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$f18(); + } + s0 = s1; + } + + return s0; + } + + function peg$parsefrom() { + var s0, s1; + + s0 = peg$currPos; + s1 = input.substr(peg$currPos, 4); + if (s1.toLowerCase() === peg$c16) { + peg$currPos += 4; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e19); } + } + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$f19(); + } + s0 = s1; + + return s0; + } + + function peg$parseexpenseType() { + var s0, s1; + + if (input.substr(peg$currPos, 11) === peg$c17) { + s0 = peg$c17; + peg$currPos += 11; + } else { + s0 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e20); } + } + if (s0 === peg$FAILED) { + s0 = peg$currPos; + s1 = input.substr(peg$currPos, 12); + if (s1.toLowerCase() === peg$c18) { + peg$currPos += 12; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e21); } + } + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$f20(); + } + s0 = s1; + } + + return s0; + } + + function peg$parsetype() { + var s0, s1; + + s0 = peg$currPos; + s1 = input.substr(peg$currPos, 4); + if (s1.toLowerCase() === peg$c19) { + peg$currPos += 4; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e22); } + } + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$f21(); + } + s0 = s1; + + return s0; + } + + function peg$parsestatus() { + var s0, s1; + + s0 = peg$currPos; + s1 = input.substr(peg$currPos, 6); + if (s1.toLowerCase() === peg$c20) { + peg$currPos += 6; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e23); } + } + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$f22(); + } + s0 = s1; + + return s0; + } + + function peg$parsesortBy() { + var s0, s1; + + if (input.substr(peg$currPos, 6) === peg$c21) { + s0 = peg$c21; + peg$currPos += 6; + } else { + s0 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e24); } + } + if (s0 === peg$FAILED) { + s0 = peg$currPos; + s1 = input.substr(peg$currPos, 7); + if (s1.toLowerCase() === peg$c22) { + peg$currPos += 7; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e25); } + } + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$f23(); + } + s0 = s1; + } + + return s0; + } + + function peg$parsesortOrder() { + var s0, s1; + + if (input.substr(peg$currPos, 9) === peg$c23) { + s0 = peg$c23; + peg$currPos += 9; + } else { + s0 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e26); } + } + if (s0 === peg$FAILED) { + s0 = peg$currPos; + s1 = input.substr(peg$currPos, 10); + if (s1.toLowerCase() === peg$c24) { + peg$currPos += 10; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e27); } + } + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$f24(); + } + s0 = s1; + } + + return s0; + } + + function peg$parsepolicyID() { + var s0, s1; + + if (input.substr(peg$currPos, 8) === peg$c25) { + s0 = peg$c25; + peg$currPos += 8; + } else { + s0 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e28); } + } + if (s0 === peg$FAILED) { + s0 = peg$currPos; + s1 = input.substr(peg$currPos, 9); + if (s1.toLowerCase() === peg$c26) { + peg$currPos += 9; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e29); } + } + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$f25(); + } + s0 = s1; + } + + return s0; + } + + function peg$parsesubmitted() { + var s0, s1; + + s0 = peg$currPos; + s1 = input.substr(peg$currPos, 9); + if (s1.toLowerCase() === peg$c27) { + peg$currPos += 9; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e30); } + } + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$f26(); + } + s0 = s1; + + return s0; + } + + function peg$parseapproved() { + var s0, s1; + + s0 = peg$currPos; + s1 = input.substr(peg$currPos, 8); + if (s1.toLowerCase() === peg$c28) { + peg$currPos += 8; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e31); } + } + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$f27(); + } + s0 = s1; + + return s0; + } + + function peg$parsepaid() { + var s0, s1; + + s0 = peg$currPos; + s1 = input.substr(peg$currPos, 4); + if (s1.toLowerCase() === peg$c29) { + peg$currPos += 4; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e32); } + } + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$f28(); + } + s0 = s1; + + return s0; + } + + function peg$parseexported() { + var s0, s1; + + s0 = peg$currPos; + s1 = input.substr(peg$currPos, 8); + if (s1.toLowerCase() === peg$c30) { + peg$currPos += 8; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e33); } + } + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$f29(); + } + s0 = s1; + + return s0; + } + + function peg$parseposted() { + var s0, s1; + + s0 = peg$currPos; + s1 = input.substr(peg$currPos, 6); + if (s1.toLowerCase() === peg$c31) { + peg$currPos += 6; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e34); } + } + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$f30(); + } + s0 = s1; + + return s0; + } + function peg$parseoperator() { var s0, s1; @@ -1061,81 +1502,81 @@ function peg$parse(input, options) { peg$currPos++; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e30); } + if (peg$silentFails === 0) { peg$fail(peg$e36); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f6(); + s1 = peg$f31(); } s0 = s1; if (s0 === peg$FAILED) { s0 = peg$currPos; - if (input.substr(peg$currPos, 2) === peg$c26) { - s1 = peg$c26; + if (input.substr(peg$currPos, 2) === peg$c32) { + s1 = peg$c32; peg$currPos += 2; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e31); } + if (peg$silentFails === 0) { peg$fail(peg$e37); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f7(); + s1 = peg$f32(); } s0 = s1; if (s0 === peg$FAILED) { s0 = peg$currPos; - if (input.substr(peg$currPos, 2) === peg$c27) { - s1 = peg$c27; + if (input.substr(peg$currPos, 2) === peg$c33) { + s1 = peg$c33; peg$currPos += 2; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e32); } + if (peg$silentFails === 0) { peg$fail(peg$e38); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f8(); + s1 = peg$f33(); } s0 = s1; if (s0 === peg$FAILED) { s0 = peg$currPos; if (input.charCodeAt(peg$currPos) === 62) { - s1 = peg$c28; + s1 = peg$c34; peg$currPos++; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e33); } + if (peg$silentFails === 0) { peg$fail(peg$e39); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f9(); + s1 = peg$f34(); } s0 = s1; if (s0 === peg$FAILED) { s0 = peg$currPos; - if (input.substr(peg$currPos, 2) === peg$c29) { - s1 = peg$c29; + if (input.substr(peg$currPos, 2) === peg$c35) { + s1 = peg$c35; peg$currPos += 2; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e34); } + if (peg$silentFails === 0) { peg$fail(peg$e40); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f10(); + s1 = peg$f35(); } s0 = s1; if (s0 === peg$FAILED) { s0 = peg$currPos; if (input.charCodeAt(peg$currPos) === 60) { - s1 = peg$c30; + s1 = peg$c36; peg$currPos++; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e35); } + if (peg$silentFails === 0) { peg$fail(peg$e41); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f11(); + s1 = peg$f36(); } s0 = s1; } @@ -1146,7 +1587,7 @@ function peg$parse(input, options) { peg$silentFails--; if (s0 === peg$FAILED) { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e29); } + if (peg$silentFails === 0) { peg$fail(peg$e35); } } return s0; @@ -1163,7 +1604,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e37); } + if (peg$silentFails === 0) { peg$fail(peg$e43); } } while (s2 !== peg$FAILED) { s1.push(s2); @@ -1172,15 +1613,15 @@ function peg$parse(input, options) { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e37); } + if (peg$silentFails === 0) { peg$fail(peg$e43); } } } if (input.charCodeAt(peg$currPos) === 34) { - s2 = peg$c31; + s2 = peg$c37; peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e38); } + if (peg$silentFails === 0) { peg$fail(peg$e44); } } if (s2 !== peg$FAILED) { s3 = []; @@ -1189,7 +1630,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s4 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e39); } + if (peg$silentFails === 0) { peg$fail(peg$e45); } } while (s4 !== peg$FAILED) { s3.push(s4); @@ -1198,15 +1639,15 @@ function peg$parse(input, options) { peg$currPos++; } else { s4 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e39); } + if (peg$silentFails === 0) { peg$fail(peg$e45); } } } if (input.charCodeAt(peg$currPos) === 34) { - s4 = peg$c31; + s4 = peg$c37; peg$currPos++; } else { s4 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e38); } + if (peg$silentFails === 0) { peg$fail(peg$e44); } } if (s4 !== peg$FAILED) { s5 = []; @@ -1215,7 +1656,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s6 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e40); } + if (peg$silentFails === 0) { peg$fail(peg$e46); } } while (s6 !== peg$FAILED) { s5.push(s6); @@ -1224,11 +1665,11 @@ function peg$parse(input, options) { peg$currPos++; } else { s6 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e40); } + if (peg$silentFails === 0) { peg$fail(peg$e46); } } } peg$savedPos = s0; - s0 = peg$f12(s1, s3, s5); + s0 = peg$f37(s1, s3, s5); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -1240,7 +1681,7 @@ function peg$parse(input, options) { peg$silentFails--; if (s0 === peg$FAILED) { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e36); } + if (peg$silentFails === 0) { peg$fail(peg$e42); } } return s0; @@ -1257,7 +1698,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e40); } + if (peg$silentFails === 0) { peg$fail(peg$e46); } } if (s2 !== peg$FAILED) { while (s2 !== peg$FAILED) { @@ -1267,7 +1708,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e40); } + if (peg$silentFails === 0) { peg$fail(peg$e46); } } } } else { @@ -1275,13 +1716,13 @@ function peg$parse(input, options) { } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f13(s1); + s1 = peg$f38(s1); } s0 = s1; peg$silentFails--; if (s0 === peg$FAILED) { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e41); } + if (peg$silentFails === 0) { peg$fail(peg$e47); } } return s0; @@ -1293,7 +1734,7 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = peg$parse_(); peg$savedPos = s0; - s1 = peg$f14(); + s1 = peg$f39(); s0 = s1; return s0; @@ -1309,7 +1750,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e43); } + if (peg$silentFails === 0) { peg$fail(peg$e49); } } while (s1 !== peg$FAILED) { s0.push(s1); @@ -1318,12 +1759,12 @@ function peg$parse(input, options) { peg$currPos++; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e43); } + if (peg$silentFails === 0) { peg$fail(peg$e49); } } } peg$silentFails--; s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e42); } + if (peg$silentFails === 0) { peg$fail(peg$e48); } return s0; } diff --git a/src/libs/SearchParser/searchParser.peggy b/src/libs/SearchParser/searchParser.peggy index bf2d1fe36154..732bb430d526 100644 --- a/src/libs/SearchParser/searchParser.peggy +++ b/src/libs/SearchParser/searchParser.peggy @@ -98,30 +98,30 @@ standardFilter key "key" = @( - "date" - / "amount" - / "merchant" - / "description" - / "reportID" - / "keyword" - / "in" - / "currency" - / "tag" - / "category" - / "to" - / "taxRate" - / "cardID" - / "from" - / "expenseType" - / "submitted" - / "approved" - / "paid" - / "exported" - / "posted" + date + / amount + / merchant + / description + / reportID + / keyword + / in + / currency + / tag + / category + / to + / taxRate + / cardID + / from + / expenseType + / submitted + / approved + / paid + / exported + / posted ) defaultKey "default key" - = @("type" / "status" / "sortBy" / "sortOrder" / "policyID") + = @(type / status / sortBy / sortOrder / policyID) identifier = (","+)? parts:(quotedString / alphanumeric)|1.., ","+| empty:(","+)? { diff --git a/src/libs/SearchQueryUtils.ts b/src/libs/SearchQueryUtils.ts index cbf25b787d95..73c83cb33b83 100644 --- a/src/libs/SearchQueryUtils.ts +++ b/src/libs/SearchQueryUtils.ts @@ -1,7 +1,7 @@ import cloneDeep from 'lodash/cloneDeep'; import type {OnyxCollection} from 'react-native-onyx'; import type {ValueOf} from 'type-fest'; -import type {ASTNode, QueryFilter, QueryFilters, SearchDateFilterKeys, SearchQueryJSON, SearchQueryString, SearchStatus} from '@components/Search/types'; +import type {ASTNode, QueryFilter, QueryFilters, SearchDateFilterKeys, SearchFilterKey, SearchQueryJSON, SearchQueryString, SearchStatus, UserFriendlyKey} from '@components/Search/types'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import type {SearchAdvancedFiltersForm} from '@src/types/form'; @@ -34,6 +34,37 @@ const operatorToCharMap = { [CONST.SEARCH.SYNTAX_OPERATORS.OR]: ' ' as const, }; +/** + * A mapping object that maps filter names from the internal codebase format to user-friendly names. + */ +const UserFriendlyKeyMap: Record = { + type: 'type', + status: 'status', + sortBy: 'sort-by', + sortOrder: 'sort-order', + policyID: 'workspace', + date: 'date', + amount: 'amount', + expenseType: 'expense-type', + currency: 'currency', + merchant: 'merchant', + description: 'description', + from: 'from', + to: 'to', + category: 'category', + tag: 'tag', + taxRate: 'tax-rate', + cardID: 'card', + reportID: 'reportid', + keyword: 'keyword', + in: 'in', + submitted: 'submitted', + approved: 'approved', + paid: 'paid', + exported: 'exported', + posted: 'posted', +}; + /** * @private * Returns string value wrapped in quotes "", if the value contains special characters. @@ -572,7 +603,7 @@ function buildUserReadableQueryString( value: getFilterDisplayValue(key, filter.value.toString(), PersonalDetails, reports), })); } - title += buildFilterValuesString(key, displayQueryFilters); + title += buildFilterValuesString(getUserFriendlyKey(key), displayQueryFilters); } return title; @@ -661,6 +692,21 @@ function getQueryWithUpdatedValues(query: string, policyID?: string) { return buildSearchQueryString(standardizedQuery); } +/** + * Converts a filter key from old naming (camelCase) to user friendly naming (kebab-case). + * + * There are two types of keys used in the context of Search. + * The `camelCase` naming (ex: `sortBy`, `taxRate`) is more friendly to developers, but not nice to show to people. This was the default key naming in the past. + * The "user friendly" naming (ex: `sort-by`, `tax-rate`) was introduced at a later point, to offer better experience for the users. + * Currently search parsers support both versions as an input, but output the `camelCase` form. Whenever we display some query to the user however, we always do it in the newer pretty format. + * + * @example + * getUserFriendlyKey("taxRate") // returns "tax-rate" + */ +function getUserFriendlyKey(keyName: SearchFilterKey | typeof CONST.SEARCH.SYNTAX_ROOT_KEYS.SORT_BY | typeof CONST.SEARCH.SYNTAX_ROOT_KEYS.SORT_ORDER): UserFriendlyKey { + return UserFriendlyKeyMap[keyName]; +} + export { buildSearchQueryJSON, buildSearchQueryString, @@ -673,4 +719,5 @@ export { isCannedSearchQuery, sanitizeSearchValue, getQueryWithUpdatedValues, + getUserFriendlyKey, }; diff --git a/tests/unit/SearchAutocompleteParserTest.ts b/tests/unit/SearchAutocompleteParserTest.ts index 2571b03089b1..9e8fd6e872ad 100644 --- a/tests/unit/SearchAutocompleteParserTest.ts +++ b/tests/unit/SearchAutocompleteParserTest.ts @@ -1,43 +1,84 @@ import type {SearchQueryJSON} from '@components/Search/types'; import * as autocompleteParser from '@libs/SearchParser/autocompleteParser'; +import parserCommonTests from '../utils/fixtures/searchParsersCommonQueries'; const tests = [ { - query: 'date>2024-01-01 amount>100 merchant:"A B" description:A,B,C ,, reportID:123456789 word', + query: parserCommonTests.simple, expected: { - autocomplete: null, - ranges: [], + autocomplete: { + key: 'status', + value: 'all', + start: 20, + length: 3, + }, + ranges: [ + {key: 'type', value: 'expense', start: 5, length: 7}, + {key: 'status', value: 'all', start: 20, length: 3}, + ], }, }, { - query: ',', + query: parserCommonTests.userFriendlyNames, expected: { autocomplete: null, - ranges: [], + ranges: [ + {key: 'taxRate', value: 'rate1', start: 9, length: 5}, + {key: 'expenseType', value: 'card', start: 28, length: 4}, + {key: 'cardID', value: 'Big Bank', start: 38, length: 10}, + ], }, }, { - query: 'tag:,,', + query: parserCommonTests.oldNames, expected: { autocomplete: null, - ranges: [], + ranges: [ + {key: 'taxRate', value: 'rate1', start: 8, length: 5}, + {key: 'expenseType', value: 'card', start: 26, length: 4}, + {key: 'cardID', value: 'Big Bank', start: 38, length: 10}, + ], }, }, { - query: 'type:expense status:all', + query: parserCommonTests.complex, expected: { autocomplete: { - key: 'status', - value: 'all', - start: 20, - length: 3, + key: 'category', + length: 22, + start: 102, + value: 'meal & entertainment', }, ranges: [ - {key: 'type', value: 'expense', start: 5, length: 7}, - {key: 'status', value: 'all', start: 20, length: 3}, + {key: 'expenseType', length: 4, start: 24, value: 'cash'}, + {key: 'expenseType', length: 4, start: 29, value: 'card'}, + {key: 'category', length: 6, start: 89, value: 'travel'}, + {key: 'category', length: 5, start: 96, value: 'hotel'}, + {key: 'category', length: 22, start: 102, value: 'meal & entertainment'}, ], }, }, + { + query: 'date>2024-01-01 amount>100 merchant:"A B" description:A,B,C ,, reportid:123456789 word', + expected: { + autocomplete: null, + ranges: [], + }, + }, + { + query: ',', + expected: { + autocomplete: null, + ranges: [], + }, + }, + { + query: 'tag:,,', + expected: { + autocomplete: null, + ranges: [], + }, + }, { query: 'in:123456 currency:USD ', expected: { @@ -131,12 +172,12 @@ const tests = [ }, }, { - query: 'in:"Big Room" from:Friend category:Car,"Cell Phone" status:all expenseType:card,cash', + query: 'in:"Big Room" from:Friend category:Car,"Cell Phone" status:all expense-type:card,cash', expected: { autocomplete: { key: 'expenseType', value: 'cash', - start: 80, + start: 81, length: 4, }, ranges: [ @@ -145,28 +186,28 @@ const tests = [ {key: 'category', value: 'Car', start: 35, length: 3}, {key: 'category', value: 'Cell Phone', start: 39, length: 12}, {key: 'status', value: 'all', start: 59, length: 3}, - {key: 'expenseType', value: 'card', start: 75, length: 4}, - {key: 'expenseType', value: 'cash', start: 80, length: 4}, + {key: 'expenseType', value: 'card', start: 76, length: 4}, + {key: 'expenseType', value: 'cash', start: 81, length: 4}, ], }, }, { - query: 'currency:PLN,USD keyword taxRate:tax merchant:"Expensify, Inc." tag:"General Overhead",IT expenseType:card,distance', + query: 'currency:PLN,USD keyword tax-rate:tax merchant:"Expensify, Inc." tag:"General Overhead",IT expense-type:card,distance', expected: { autocomplete: { key: 'expenseType', value: 'distance', - start: 108, + start: 110, length: 8, }, ranges: [ {key: 'currency', value: 'PLN', start: 9, length: 3}, {key: 'currency', value: 'USD', start: 13, length: 3}, - {key: 'taxRate', value: 'tax', start: 33, length: 3}, - {key: 'tag', value: 'General Overhead', start: 69, length: 18}, - {key: 'tag', value: 'IT', start: 88, length: 2}, - {key: 'expenseType', value: 'card', start: 103, length: 4}, - {key: 'expenseType', value: 'distance', start: 108, length: 8}, + {key: 'taxRate', value: 'tax', start: 34, length: 3}, + {key: 'tag', value: 'General Overhead', start: 70, length: 18}, + {key: 'tag', value: 'IT', start: 89, length: 2}, + {key: 'expenseType', value: 'card', start: 105, length: 4}, + {key: 'expenseType', value: 'distance', start: 110, length: 8}, ], }, }, diff --git a/tests/unit/SearchParserTest.ts b/tests/unit/SearchParserTest.ts index 2964e406b512..8eaf012a3c4b 100644 --- a/tests/unit/SearchParserTest.ts +++ b/tests/unit/SearchParserTest.ts @@ -1,9 +1,10 @@ import type {SearchQueryJSON} from '@components/Search/types'; import * as searchParser from '@libs/SearchParser/searchParser'; +import parserCommonTests from '../utils/fixtures/searchParsersCommonQueries'; const tests = [ { - query: 'type:expense status:all', + query: parserCommonTests.simple, expected: { type: 'expense', status: 'all', @@ -12,6 +13,128 @@ const tests = [ filters: null, }, }, + { + query: parserCommonTests.userFriendlyNames, + expected: { + type: 'expense', + status: 'all', + sortBy: 'date', + sortOrder: 'desc', + filters: { + operator: 'and', + left: { + operator: 'and', + left: { + operator: 'and', + left: { + operator: 'eq', + left: 'taxRate', + right: 'rate1', + }, + right: { + operator: 'eq', + left: 'expenseType', + right: 'card', + }, + }, + right: { + operator: 'eq', + left: 'cardID', + right: 'Big Bank', + }, + }, + right: { + operator: 'eq', + left: 'reportID', + right: 'report', + }, + }, + }, + }, + { + query: parserCommonTests.oldNames, + expected: { + type: 'expense', + status: 'all', + sortBy: 'date', + sortOrder: 'desc', + filters: { + operator: 'and', + left: { + operator: 'and', + left: { + operator: 'and', + left: { + operator: 'eq', + left: 'taxRate', + right: 'rate1', + }, + right: { + operator: 'eq', + left: 'expenseType', + right: 'card', + }, + }, + right: { + operator: 'eq', + left: 'cardID', + right: 'Big Bank', + }, + }, + right: { + operator: 'eq', + left: 'reportID', + right: 'report', + }, + }, + }, + }, + { + query: parserCommonTests.complex, + expected: { + type: 'expense', + status: 'all', + sortBy: 'date', + sortOrder: 'desc', + filters: { + operator: 'and', + left: { + operator: 'and', + left: { + operator: 'and', + left: { + operator: 'and', + left: { + operator: 'gt', + left: 'amount', + right: '200', + }, + right: { + operator: 'eq', + left: 'expenseType', + right: ['cash', 'card'], + }, + }, + right: { + operator: 'eq', + left: 'description', + right: 'Las Vegas party', + }, + }, + right: { + operator: 'eq', + left: 'date', + right: '2024-06-01', + }, + }, + right: { + operator: 'eq', + left: 'category', + right: ['travel', 'hotel', 'meal & entertainment'], + }, + }, + }, + }, { query: ',', expected: { @@ -159,7 +282,7 @@ const tests = [ }, }, { - query: 'amount>100 amount<200 from:usera@user.com taxRate:1234 cardID:1234 reportID:12345 tag:ecx date>2023-01-01', + query: 'amount>100 amount<200 from:usera@user.com tax-rate:1234 card:1234 reportid:12345 tag:ecx date>2023-01-01', expected: { type: 'expense', status: 'all', @@ -228,52 +351,6 @@ const tests = [ }, }, }, - { - query: 'amount>200 expenseType:cash,card description:"Las Vegas party" date:2024-06-01 category:travel,hotel,"meal & entertainment"', - expected: { - type: 'expense', - status: 'all', - sortBy: 'date', - sortOrder: 'desc', - filters: { - operator: 'and', - left: { - operator: 'and', - left: { - operator: 'and', - left: { - operator: 'and', - left: { - operator: 'gt', - left: 'amount', - right: '200', - }, - right: { - operator: 'eq', - left: 'expenseType', - right: ['cash', 'card'], - }, - }, - right: { - operator: 'eq', - left: 'description', - right: 'Las Vegas party', - }, - }, - right: { - operator: 'eq', - left: 'date', - right: '2024-06-01', - }, - }, - right: { - operator: 'eq', - left: 'category', - right: ['travel', 'hotel', 'meal & entertainment'], - }, - }, - }, - }, { query: 'amount>200 las vegas', expected: { diff --git a/tests/utils/fixtures/searchParsersCommonQueries.ts b/tests/utils/fixtures/searchParsersCommonQueries.ts new file mode 100644 index 000000000000..1f398717d994 --- /dev/null +++ b/tests/utils/fixtures/searchParsersCommonQueries.ts @@ -0,0 +1,11 @@ +/** + * Tests to ensure that both parsers use the same set of base rules + */ +const parserCommonTests = { + simple: 'type:expense status:all', + userFriendlyNames: 'tax-rate:rate1 expense-type:card card:"Big Bank" reportid:report', + oldNames: 'taxRate:rate1 expenseType:card cardID:"Big Bank" reportID:report', + complex: 'amount>200 expense-type:cash,card description:"Las Vegas party" date:2024-06-01 category:travel,hotel,"meal & entertainment"', +}; + +export default parserCommonTests;