diff --git a/src/CONST/index.ts b/src/CONST/index.ts index ac194f55a87a..bb5c45368d7a 100755 --- a/src/CONST/index.ts +++ b/src/CONST/index.ts @@ -6489,6 +6489,13 @@ const CONST = { BILLABLE: 'billable', ACTION: 'action', }, + + // Maps an internal search value to the user friendly display text, e.g. `perDiem` -> `per-diem` + get SEARCH_USER_FRIENDLY_VALUES_MAP() { + return { + [this.TRANSACTION_TYPE.PER_DIEM]: 'per-diem', + }; + }, DATE_MODIFIERS: { ON: 'On', AFTER: 'After', diff --git a/src/components/Search/SearchAutocompleteList.tsx b/src/components/Search/SearchAutocompleteList.tsx index f12c5c808252..8b182a46061a 100644 --- a/src/components/Search/SearchAutocompleteList.tsx +++ b/src/components/Search/SearchAutocompleteList.tsx @@ -31,7 +31,15 @@ import { getQueryWithoutAutocompletedPart, parseForAutocomplete, } from '@libs/SearchAutocompleteUtils'; -import {buildSearchQueryJSON, buildUserReadableQueryString, getQueryWithoutFilters, getUserFriendlyKey, sanitizeSearchValue, shouldHighlight} from '@libs/SearchQueryUtils'; +import { + buildSearchQueryJSON, + buildUserReadableQueryString, + getQueryWithoutFilters, + getUserFriendlyKey, + getUserFriendlyValue, + sanitizeSearchValue, + shouldHighlight, +} from '@libs/SearchQueryUtils'; import {getDatePresets} from '@libs/SearchUIUtils'; import StringUtils from '@libs/StringUtils'; import Timing from '@userActions/Timing'; @@ -382,6 +390,7 @@ function SearchAutocompleteList( } case CONST.SEARCH.SYNTAX_FILTER_KEYS.EXPENSE_TYPE: { const filteredExpenseTypes = expenseTypes + .map((value) => getUserFriendlyValue(value)) .filter((expenseType) => expenseType.includes(autocompleteValue.toLowerCase()) && !alreadyAutocompletedKeys.includes(expenseType)) .sort(); diff --git a/src/components/Search/types.ts b/src/components/Search/types.ts index 8dc163398ca6..2b1f2348c941 100644 --- a/src/components/Search/types.ts +++ b/src/components/Search/types.ts @@ -133,6 +133,7 @@ type SearchFilterKey = | typeof CONST.SEARCH.SYNTAX_ROOT_KEYS.GROUP_BY; type UserFriendlyKey = ValueOf; +type UserFriendlyValue = ValueOf; type QueryFilters = Array<{ key: SearchFilterKey; @@ -211,4 +212,5 @@ export type { SingularSearchStatus, SearchDatePreset, SearchWithdrawalType, + UserFriendlyValue, }; diff --git a/src/libs/SearchAutocompleteUtils.ts b/src/libs/SearchAutocompleteUtils.ts index 91f3f94d61cb..b525854dd9a3 100644 --- a/src/libs/SearchAutocompleteUtils.ts +++ b/src/libs/SearchAutocompleteUtils.ts @@ -7,6 +7,7 @@ import CONST from '@src/CONST'; import type {PolicyCategories, PolicyTagLists, RecentlyUsedCategories, RecentlyUsedTags} from '@src/types/onyx'; import {getTagNamesFromTagsLists} from './PolicyUtils'; import {parse} from './SearchParser/autocompleteParser'; +import {getUserFriendlyValue} from './SearchQueryUtils'; /** * Parses given query using the autocomplete parser. @@ -109,6 +110,8 @@ function getAutocompleteQueryWithComma(prevQuery: string, newQuery: string) { return newQuery; } +const userFriendlyExpenseTypeList = Object.values(CONST.SEARCH.TRANSACTION_TYPE).map((value) => getUserFriendlyValue(value)); + /** * @private */ @@ -123,7 +126,7 @@ function filterOutRangesWithCorrectValue( 'worklet'; const typeList = Object.values(CONST.SEARCH.DATA_TYPES) as string[]; - const expenseTypeList = Object.values(CONST.SEARCH.TRANSACTION_TYPE) as string[]; + const expenseTypeList = userFriendlyExpenseTypeList; const withdrawalTypeList = Object.values(CONST.SEARCH.WITHDRAWAL_TYPE) as string[]; const statusList = Object.values({ ...CONST.SEARCH.STATUS.EXPENSE, diff --git a/src/libs/SearchParser/autocompleteParser.js b/src/libs/SearchParser/autocompleteParser.js index 4eabd0a71a7a..a6982151ad59 100644 --- a/src/libs/SearchParser/autocompleteParser.js +++ b/src/libs/SearchParser/autocompleteParser.js @@ -233,14 +233,16 @@ function peg$parse(input, options) { var peg$c47 = "createdby"; var peg$c48 = "created-by"; var peg$c49 = "action"; - var peg$c50 = "!="; - var peg$c51 = ">="; - var peg$c52 = ">"; - var peg$c53 = "<="; - var peg$c54 = "<"; - var peg$c55 = "\u201C"; - var peg$c56 = "\u201D"; - var peg$c57 = "\""; + var peg$c50 = "perdiem"; + var peg$c51 = "per-diem"; + var peg$c52 = "!="; + var peg$c53 = ">="; + var peg$c54 = ">"; + var peg$c55 = "<="; + var peg$c56 = "<"; + var peg$c57 = "\u201C"; + var peg$c58 = "\u201D"; + var peg$c59 = "\""; var peg$r0 = /^[:=]/; var peg$r1 = /^[^ ,\t\n\r\xA0]/; @@ -305,30 +307,32 @@ function peg$parse(input, options) { var peg$e48 = peg$literalExpectation("createdBy", true); var peg$e49 = peg$literalExpectation("created-by", true); var peg$e50 = peg$literalExpectation("action", true); - var peg$e51 = peg$otherExpectation("operator"); - var peg$e52 = peg$classExpectation([":", "="], false, false); - var peg$e53 = peg$literalExpectation("!=", false); - var peg$e54 = peg$literalExpectation(">=", false); - var peg$e55 = peg$literalExpectation(">", false); - var peg$e56 = peg$literalExpectation("<=", false); - var peg$e57 = peg$literalExpectation("<", false); - var peg$e58 = peg$otherExpectation("word"); - var peg$e59 = peg$classExpectation([" ", ",", "\t", "\n", "\r", "\xA0"], true, false); - var peg$e60 = peg$otherExpectation("whitespace"); - var peg$e61 = peg$classExpectation([" ", "\t", "\r", "\n", "\xA0"], false, false); - var peg$e62 = peg$otherExpectation("quote"); - var peg$e63 = peg$classExpectation([" ", ",", "\"", "\u201D", "\u201C", "\t", "\n", "\r", "\xA0"], true, false); - var peg$e64 = peg$classExpectation(["\"", ["\u201C", "\u201D"]], false, false); - var peg$e65 = peg$classExpectation(["\"", "\u201D", "\u201C", "\r", "\n"], true, false); - var peg$e66 = peg$literalExpectation("\u201C", false); - var peg$e67 = peg$literalExpectation("\u201D", false); - var peg$e68 = peg$literalExpectation("\"", false); - var peg$e69 = peg$classExpectation([" ", "\t", "\n", "\r", "\xA0", ["a", "z"], ["A", "Z"], ["0", "9"]], false, false); - var peg$e70 = peg$classExpectation([["a", "z"], ["A", "Z"], ["0", "9"]], false, false); - var peg$e71 = peg$classExpectation([" ", "\t", "\n", "\r", "\xA0"], false, false); - var peg$e72 = peg$classExpectation([" ", "\t", "\n", "\r", "\xA0", ["a", "z"], ["A", "Z"]], false, false); - var peg$e73 = peg$anyExpectation(); - var peg$e74 = peg$classExpectation([","], false, false); + var peg$e51 = peg$literalExpectation("perDiem", true); + var peg$e52 = peg$literalExpectation("per-diem", true); + var peg$e53 = peg$otherExpectation("operator"); + var peg$e54 = peg$classExpectation([":", "="], false, false); + var peg$e55 = peg$literalExpectation("!=", false); + var peg$e56 = peg$literalExpectation(">=", false); + var peg$e57 = peg$literalExpectation(">", false); + var peg$e58 = peg$literalExpectation("<=", false); + var peg$e59 = peg$literalExpectation("<", false); + var peg$e60 = peg$otherExpectation("word"); + var peg$e61 = peg$classExpectation([" ", ",", "\t", "\n", "\r", "\xA0"], true, false); + var peg$e62 = peg$otherExpectation("whitespace"); + var peg$e63 = peg$classExpectation([" ", "\t", "\r", "\n", "\xA0"], false, false); + var peg$e64 = peg$otherExpectation("quote"); + var peg$e65 = peg$classExpectation([" ", ",", "\"", "\u201D", "\u201C", "\t", "\n", "\r", "\xA0"], true, false); + var peg$e66 = peg$classExpectation(["\"", ["\u201C", "\u201D"]], false, false); + var peg$e67 = peg$classExpectation(["\"", "\u201D", "\u201C", "\r", "\n"], true, false); + var peg$e68 = peg$literalExpectation("\u201C", false); + var peg$e69 = peg$literalExpectation("\u201D", false); + var peg$e70 = peg$literalExpectation("\"", false); + var peg$e71 = peg$classExpectation([" ", "\t", "\n", "\r", "\xA0", ["a", "z"], ["A", "Z"], ["0", "9"]], false, false); + var peg$e72 = peg$classExpectation([["a", "z"], ["A", "Z"], ["0", "9"]], false, false); + var peg$e73 = peg$classExpectation([" ", "\t", "\n", "\r", "\xA0"], false, false); + var peg$e74 = peg$classExpectation([" ", "\t", "\n", "\r", "\xA0", ["a", "z"], ["A", "Z"]], false, false); + var peg$e75 = peg$anyExpectation(); + var peg$e76 = peg$classExpectation([","], false, false); var peg$f0 = function(ranges) { return { autocomplete, ranges }; }; var peg$f1 = function(filters) { return filters.filter(Boolean).flat(); }; @@ -421,28 +425,29 @@ function peg$parse(input, options) { var peg$f41 = function() { return "assignee"; }; var peg$f42 = function() { return "createdBy"; }; var peg$f43 = function() { return "action"; }; - var peg$f44 = function() { return "eq"; }; - var peg$f45 = function() { return "neq"; }; - var peg$f46 = function() { return "gte"; }; - var peg$f47 = function() { return "gt"; }; - var peg$f48 = function() { return "lte"; }; - var peg$f49 = function() { return "lt"; }; - var peg$f50 = function(o) { + var peg$f44 = function() { return "perDiem"; }; + var peg$f45 = function() { return "eq"; }; + var peg$f46 = function() { return "neq"; }; + var peg$f47 = function() { return "gte"; }; + var peg$f48 = function() { return "gt"; }; + var peg$f49 = function() { return "lte"; }; + var peg$f50 = function() { return "lt"; }; + var peg$f51 = function(o) { if (nameOperator) { expectingNestedQuote = (o === "eq"); // Use simple parser if no valid operator is found } return o; }; - var peg$f51 = function(chars) { return chars.join("").trim(); }; - var peg$f52 = function() { return "and"; }; - var peg$f53 = function() { return expectingNestedQuote; }; - var peg$f54 = function(start, inner, end) { //handle no-breaking space + var peg$f52 = function(chars) { return chars.join("").trim(); }; + var peg$f53 = function() { return "and"; }; + var peg$f54 = function() { return expectingNestedQuote; }; + var peg$f55 = function(start, inner, end) { //handle no-breaking space return [...start, '"', ...inner, '"', ...end].join(""); }; - var peg$f55 = function(start) {return "“"}; - var peg$f56 = function(start) {return "”"}; - var peg$f57 = function(start) {return "\""}; - var peg$f58 = function(start, inner, end) { + var peg$f56 = function(start) {return "“"}; + var peg$f57 = function(start) {return "”"}; + var peg$f58 = function(start) {return "\""}; + var peg$f59 = function(start, inner, end) { return [...start, '"', ...inner, '"'].join(""); }; var peg$currPos = options.peg$currPos | 0; @@ -1762,6 +1767,35 @@ function peg$parse(input, options) { return s0; } + function peg$parseperDiem() { + var s0, s1; + + s0 = input.substr(peg$currPos, 7); + if (s0.toLowerCase() === peg$c50) { + peg$currPos += 7; + } else { + s0 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e51); } + } + if (s0 === peg$FAILED) { + s0 = peg$currPos; + s1 = input.substr(peg$currPos, 8); + if (s1.toLowerCase() === peg$c51) { + peg$currPos += 8; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e52); } + } + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$f44(); + } + s0 = s1; + } + + return s0; + } + function peg$parseoperator() { var s0, s1; @@ -1772,81 +1806,81 @@ function peg$parse(input, options) { peg$currPos++; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e52); } + if (peg$silentFails === 0) { peg$fail(peg$e54); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f44(); + s1 = peg$f45(); } s0 = s1; if (s0 === peg$FAILED) { s0 = peg$currPos; - if (input.substr(peg$currPos, 2) === peg$c50) { - s1 = peg$c50; + if (input.substr(peg$currPos, 2) === peg$c52) { + s1 = peg$c52; peg$currPos += 2; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e53); } + if (peg$silentFails === 0) { peg$fail(peg$e55); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f45(); + s1 = peg$f46(); } s0 = s1; if (s0 === peg$FAILED) { s0 = peg$currPos; - if (input.substr(peg$currPos, 2) === peg$c51) { - s1 = peg$c51; + if (input.substr(peg$currPos, 2) === peg$c53) { + s1 = peg$c53; peg$currPos += 2; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e54); } + if (peg$silentFails === 0) { peg$fail(peg$e56); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f46(); + s1 = peg$f47(); } s0 = s1; if (s0 === peg$FAILED) { s0 = peg$currPos; if (input.charCodeAt(peg$currPos) === 62) { - s1 = peg$c52; + s1 = peg$c54; peg$currPos++; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e55); } + if (peg$silentFails === 0) { peg$fail(peg$e57); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f47(); + s1 = peg$f48(); } s0 = s1; if (s0 === peg$FAILED) { s0 = peg$currPos; - if (input.substr(peg$currPos, 2) === peg$c53) { - s1 = peg$c53; + if (input.substr(peg$currPos, 2) === peg$c55) { + s1 = peg$c55; peg$currPos += 2; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e56); } + if (peg$silentFails === 0) { peg$fail(peg$e58); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f48(); + s1 = peg$f49(); } s0 = s1; if (s0 === peg$FAILED) { s0 = peg$currPos; if (input.charCodeAt(peg$currPos) === 60) { - s1 = peg$c54; + s1 = peg$c56; peg$currPos++; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e57); } + if (peg$silentFails === 0) { peg$fail(peg$e59); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f49(); + s1 = peg$f50(); } s0 = s1; } @@ -1857,7 +1891,7 @@ function peg$parse(input, options) { peg$silentFails--; if (s0 === peg$FAILED) { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e51); } + if (peg$silentFails === 0) { peg$fail(peg$e53); } } return s0; @@ -1870,7 +1904,7 @@ function peg$parse(input, options) { s1 = peg$parseoperator(); if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f50(s1); + s1 = peg$f51(s1); } s0 = s1; @@ -1888,7 +1922,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e59); } + if (peg$silentFails === 0) { peg$fail(peg$e61); } } if (s2 !== peg$FAILED) { while (s2 !== peg$FAILED) { @@ -1898,7 +1932,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e59); } + if (peg$silentFails === 0) { peg$fail(peg$e61); } } } } else { @@ -1906,13 +1940,13 @@ function peg$parse(input, options) { } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f51(s1); + s1 = peg$f52(s1); } s0 = s1; peg$silentFails--; if (s0 === peg$FAILED) { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e58); } + if (peg$silentFails === 0) { peg$fail(peg$e60); } } return s0; @@ -1924,7 +1958,7 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = peg$parse_(); peg$savedPos = s0; - s1 = peg$f52(); + s1 = peg$f53(); s0 = s1; return s0; @@ -1940,7 +1974,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e61); } + if (peg$silentFails === 0) { peg$fail(peg$e63); } } while (s1 !== peg$FAILED) { s0.push(s1); @@ -1949,12 +1983,12 @@ function peg$parse(input, options) { peg$currPos++; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e61); } + if (peg$silentFails === 0) { peg$fail(peg$e63); } } } peg$silentFails--; s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e60); } + if (peg$silentFails === 0) { peg$fail(peg$e62); } return s0; } @@ -1964,7 +1998,7 @@ function peg$parse(input, options) { s0 = peg$currPos; peg$savedPos = peg$currPos; - s1 = peg$f53(); + s1 = peg$f54(); if (s1) { s1 = undefined; } else { @@ -2001,7 +2035,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e63); } + if (peg$silentFails === 0) { peg$fail(peg$e65); } } while (s2 !== peg$FAILED) { s1.push(s2); @@ -2010,7 +2044,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e63); } + if (peg$silentFails === 0) { peg$fail(peg$e65); } } } s2 = input.charAt(peg$currPos); @@ -2018,7 +2052,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e64); } + if (peg$silentFails === 0) { peg$fail(peg$e66); } } if (s2 !== peg$FAILED) { s3 = []; @@ -2027,7 +2061,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s4 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e65); } + if (peg$silentFails === 0) { peg$fail(peg$e67); } } while (s4 !== peg$FAILED) { s3.push(s4); @@ -2036,7 +2070,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s4 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e65); } + if (peg$silentFails === 0) { peg$fail(peg$e67); } } } s4 = input.charAt(peg$currPos); @@ -2044,7 +2078,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s4 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e64); } + if (peg$silentFails === 0) { peg$fail(peg$e66); } } if (s4 !== peg$FAILED) { s5 = []; @@ -2053,7 +2087,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s6 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e59); } + if (peg$silentFails === 0) { peg$fail(peg$e61); } } while (s6 !== peg$FAILED) { s5.push(s6); @@ -2062,11 +2096,11 @@ function peg$parse(input, options) { peg$currPos++; } else { s6 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e59); } + if (peg$silentFails === 0) { peg$fail(peg$e61); } } } peg$savedPos = s0; - s0 = peg$f54(s1, s3, s5); + s0 = peg$f55(s1, s3, s5); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -2078,7 +2112,7 @@ function peg$parse(input, options) { peg$silentFails--; if (s0 === peg$FAILED) { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e62); } + if (peg$silentFails === 0) { peg$fail(peg$e64); } } return s0; @@ -2095,7 +2129,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e63); } + if (peg$silentFails === 0) { peg$fail(peg$e65); } } while (s2 !== peg$FAILED) { s1.push(s2); @@ -2104,7 +2138,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e63); } + if (peg$silentFails === 0) { peg$fail(peg$e65); } } } s2 = input.charAt(peg$currPos); @@ -2112,7 +2146,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e64); } + if (peg$silentFails === 0) { peg$fail(peg$e66); } } if (s2 !== peg$FAILED) { s3 = []; @@ -2121,7 +2155,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s4 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e65); } + if (peg$silentFails === 0) { peg$fail(peg$e67); } } if (s4 === peg$FAILED) { s4 = peg$currPos; @@ -2137,15 +2171,15 @@ function peg$parse(input, options) { } if (s5 !== peg$FAILED) { if (input.charCodeAt(peg$currPos) === 8220) { - s6 = peg$c55; + s6 = peg$c57; peg$currPos++; } else { s6 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e66); } + if (peg$silentFails === 0) { peg$fail(peg$e68); } } if (s6 !== peg$FAILED) { peg$savedPos = s4; - s4 = peg$f55(s1); + s4 = peg$f56(s1); } else { peg$currPos = s4; s4 = peg$FAILED; @@ -2168,15 +2202,15 @@ function peg$parse(input, options) { } if (s5 !== peg$FAILED) { if (input.charCodeAt(peg$currPos) === 8221) { - s6 = peg$c56; + s6 = peg$c58; peg$currPos++; } else { s6 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e67); } + if (peg$silentFails === 0) { peg$fail(peg$e69); } } if (s6 !== peg$FAILED) { peg$savedPos = s4; - s4 = peg$f56(s1); + s4 = peg$f57(s1); } else { peg$currPos = s4; s4 = peg$FAILED; @@ -2199,15 +2233,15 @@ function peg$parse(input, options) { } if (s5 !== peg$FAILED) { if (input.charCodeAt(peg$currPos) === 34) { - s6 = peg$c57; + s6 = peg$c59; peg$currPos++; } else { s6 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e68); } + if (peg$silentFails === 0) { peg$fail(peg$e70); } } if (s6 !== peg$FAILED) { peg$savedPos = s4; - s4 = peg$f57(s1); + s4 = peg$f58(s1); } else { peg$currPos = s4; s4 = peg$FAILED; @@ -2226,7 +2260,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s4 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e65); } + if (peg$silentFails === 0) { peg$fail(peg$e67); } } if (s4 === peg$FAILED) { s4 = peg$currPos; @@ -2242,15 +2276,15 @@ function peg$parse(input, options) { } if (s5 !== peg$FAILED) { if (input.charCodeAt(peg$currPos) === 8220) { - s6 = peg$c55; + s6 = peg$c57; peg$currPos++; } else { s6 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e66); } + if (peg$silentFails === 0) { peg$fail(peg$e68); } } if (s6 !== peg$FAILED) { peg$savedPos = s4; - s4 = peg$f55(s1); + s4 = peg$f56(s1); } else { peg$currPos = s4; s4 = peg$FAILED; @@ -2273,15 +2307,15 @@ function peg$parse(input, options) { } if (s5 !== peg$FAILED) { if (input.charCodeAt(peg$currPos) === 8221) { - s6 = peg$c56; + s6 = peg$c58; peg$currPos++; } else { s6 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e67); } + if (peg$silentFails === 0) { peg$fail(peg$e69); } } if (s6 !== peg$FAILED) { peg$savedPos = s4; - s4 = peg$f56(s1); + s4 = peg$f57(s1); } else { peg$currPos = s4; s4 = peg$FAILED; @@ -2304,15 +2338,15 @@ function peg$parse(input, options) { } if (s5 !== peg$FAILED) { if (input.charCodeAt(peg$currPos) === 34) { - s6 = peg$c57; + s6 = peg$c59; peg$currPos++; } else { s6 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e68); } + if (peg$silentFails === 0) { peg$fail(peg$e70); } } if (s6 !== peg$FAILED) { peg$savedPos = s4; - s4 = peg$f57(s1); + s4 = peg$f58(s1); } else { peg$currPos = s4; s4 = peg$FAILED; @@ -2328,7 +2362,7 @@ function peg$parse(input, options) { s4 = peg$parseclosingQuote(); if (s4 !== peg$FAILED) { peg$savedPos = s0; - s0 = peg$f58(s1, s3, s4); + s0 = peg$f59(s1, s3, s4); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -2340,7 +2374,7 @@ function peg$parse(input, options) { peg$silentFails--; if (s0 === peg$FAILED) { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e62); } + if (peg$silentFails === 0) { peg$fail(peg$e64); } } return s0; @@ -2355,7 +2389,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e64); } + if (peg$silentFails === 0) { peg$fail(peg$e66); } } if (s1 !== peg$FAILED) { s2 = peg$currPos; @@ -2393,7 +2427,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e69); } + if (peg$silentFails === 0) { peg$fail(peg$e71); } } while (s2 !== peg$FAILED) { s1.push(s2); @@ -2402,7 +2436,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e69); } + if (peg$silentFails === 0) { peg$fail(peg$e71); } } } s2 = []; @@ -2411,7 +2445,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s3 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e70); } + if (peg$silentFails === 0) { peg$fail(peg$e72); } } while (s3 !== peg$FAILED) { s2.push(s3); @@ -2420,7 +2454,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s3 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e70); } + if (peg$silentFails === 0) { peg$fail(peg$e72); } } } s3 = []; @@ -2429,7 +2463,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s4 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e71); } + if (peg$silentFails === 0) { peg$fail(peg$e73); } } while (s4 !== peg$FAILED) { s3.push(s4); @@ -2438,7 +2472,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s4 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e71); } + if (peg$silentFails === 0) { peg$fail(peg$e73); } } } s4 = peg$parseoperator(); @@ -2457,7 +2491,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e72); } + if (peg$silentFails === 0) { peg$fail(peg$e74); } } while (s2 !== peg$FAILED) { s1.push(s2); @@ -2466,7 +2500,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e72); } + if (peg$silentFails === 0) { peg$fail(peg$e74); } } } s2 = peg$currPos; @@ -2487,7 +2521,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s4 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e73); } + if (peg$silentFails === 0) { peg$fail(peg$e75); } } peg$silentFails--; if (s4 === peg$FAILED) { @@ -2513,7 +2547,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s0 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e74); } + if (peg$silentFails === 0) { peg$fail(peg$e76); } } } } diff --git a/src/libs/SearchParser/baseRules.peggy b/src/libs/SearchParser/baseRules.peggy index 5a6a76b92659..f7df2ee6f603 100644 --- a/src/libs/SearchParser/baseRules.peggy +++ b/src/libs/SearchParser/baseRules.peggy @@ -70,6 +70,13 @@ assignee = "assignee"i { return "assignee"; } createdBy = "createdBy"i / "created-by"i { return "createdBy"; } action = "action"i { return "action"; } +// Value transformation rules +values + = perDiem + +perDiem + = "perDiem"i / "per-diem"i { return "perDiem"; } + operator "operator" = (":" / "=") { return "eq"; } / "!=" { return "neq"; } diff --git a/src/libs/SearchParser/searchParser.js b/src/libs/SearchParser/searchParser.js index ac66623b422e..90cb23806039 100644 --- a/src/libs/SearchParser/searchParser.js +++ b/src/libs/SearchParser/searchParser.js @@ -234,14 +234,16 @@ function peg$parse(input, options) { var peg$c47 = "createdby"; var peg$c48 = "created-by"; var peg$c49 = "action"; - var peg$c50 = "!="; - var peg$c51 = ">="; - var peg$c52 = ">"; - var peg$c53 = "<="; - var peg$c54 = "<"; - var peg$c55 = "\u201C"; - var peg$c56 = "\u201D"; - var peg$c57 = "\""; + var peg$c50 = "perdiem"; + var peg$c51 = "per-diem"; + var peg$c52 = "!="; + var peg$c53 = ">="; + var peg$c54 = ">"; + var peg$c55 = "<="; + var peg$c56 = "<"; + var peg$c57 = "\u201C"; + var peg$c58 = "\u201D"; + var peg$c59 = "\""; var peg$r0 = /^[^ \t\r\n\xA0]/; var peg$r1 = /^[:=]/; @@ -309,30 +311,32 @@ function peg$parse(input, options) { var peg$e50 = peg$literalExpectation("createdBy", true); var peg$e51 = peg$literalExpectation("created-by", true); var peg$e52 = peg$literalExpectation("action", true); - var peg$e53 = peg$otherExpectation("operator"); - var peg$e54 = peg$classExpectation([":", "="], false, false); - var peg$e55 = peg$literalExpectation("!=", false); - var peg$e56 = peg$literalExpectation(">=", false); - var peg$e57 = peg$literalExpectation(">", false); - var peg$e58 = peg$literalExpectation("<=", false); - var peg$e59 = peg$literalExpectation("<", false); - var peg$e60 = peg$otherExpectation("word"); - var peg$e61 = peg$classExpectation([" ", ",", "\t", "\n", "\r", "\xA0"], true, false); - var peg$e62 = peg$otherExpectation("whitespace"); - var peg$e63 = peg$classExpectation([" ", "\t", "\r", "\n", "\xA0"], false, false); - var peg$e64 = peg$otherExpectation("quote"); - var peg$e65 = peg$classExpectation([" ", ",", "\"", "\u201D", "\u201C", "\t", "\n", "\r", "\xA0"], true, false); - var peg$e66 = peg$classExpectation(["\"", ["\u201C", "\u201D"]], false, false); - var peg$e67 = peg$classExpectation(["\"", "\u201D", "\u201C", "\r", "\n"], true, false); - var peg$e68 = peg$literalExpectation("\u201C", false); - var peg$e69 = peg$literalExpectation("\u201D", false); - var peg$e70 = peg$literalExpectation("\"", false); - var peg$e71 = peg$classExpectation([" ", "\t", "\n", "\r", "\xA0", ["a", "z"], ["A", "Z"], ["0", "9"]], false, false); - var peg$e72 = peg$classExpectation([["a", "z"], ["A", "Z"], ["0", "9"]], false, false); - var peg$e73 = peg$classExpectation([" ", "\t", "\n", "\r", "\xA0"], false, false); - var peg$e74 = peg$classExpectation([" ", "\t", "\n", "\r", "\xA0", ["a", "z"], ["A", "Z"]], false, false); - var peg$e75 = peg$anyExpectation(); - var peg$e76 = peg$classExpectation([","], false, false); + var peg$e53 = peg$literalExpectation("perDiem", true); + var peg$e54 = peg$literalExpectation("per-diem", true); + var peg$e55 = peg$otherExpectation("operator"); + var peg$e56 = peg$classExpectation([":", "="], false, false); + var peg$e57 = peg$literalExpectation("!=", false); + var peg$e58 = peg$literalExpectation(">=", false); + var peg$e59 = peg$literalExpectation(">", false); + var peg$e60 = peg$literalExpectation("<=", false); + var peg$e61 = peg$literalExpectation("<", false); + var peg$e62 = peg$otherExpectation("word"); + var peg$e63 = peg$classExpectation([" ", ",", "\t", "\n", "\r", "\xA0"], true, false); + var peg$e64 = peg$otherExpectation("whitespace"); + var peg$e65 = peg$classExpectation([" ", "\t", "\r", "\n", "\xA0"], false, false); + var peg$e66 = peg$otherExpectation("quote"); + var peg$e67 = peg$classExpectation([" ", ",", "\"", "\u201D", "\u201C", "\t", "\n", "\r", "\xA0"], true, false); + var peg$e68 = peg$classExpectation(["\"", ["\u201C", "\u201D"]], false, false); + var peg$e69 = peg$classExpectation(["\"", "\u201D", "\u201C", "\r", "\n"], true, false); + var peg$e70 = peg$literalExpectation("\u201C", false); + var peg$e71 = peg$literalExpectation("\u201D", false); + var peg$e72 = peg$literalExpectation("\"", false); + var peg$e73 = peg$classExpectation([" ", "\t", "\n", "\r", "\xA0", ["a", "z"], ["A", "Z"], ["0", "9"]], false, false); + var peg$e74 = peg$classExpectation([["a", "z"], ["A", "Z"], ["0", "9"]], false, false); + var peg$e75 = peg$classExpectation([" ", "\t", "\n", "\r", "\xA0"], false, false); + var peg$e76 = peg$classExpectation([" ", "\t", "\n", "\r", "\xA0", ["a", "z"], ["A", "Z"]], false, false); + var peg$e77 = peg$anyExpectation(); + var peg$e78 = peg$classExpectation([","], false, false); var peg$f0 = function(filters) { return applyDefaults(filters); }; var peg$f1 = function(head, tail) { @@ -437,28 +441,29 @@ function peg$parse(input, options) { var peg$f42 = function() { return "assignee"; }; var peg$f43 = function() { return "createdBy"; }; var peg$f44 = function() { return "action"; }; - var peg$f45 = function() { return "eq"; }; - var peg$f46 = function() { return "neq"; }; - var peg$f47 = function() { return "gte"; }; - var peg$f48 = function() { return "gt"; }; - var peg$f49 = function() { return "lte"; }; - var peg$f50 = function() { return "lt"; }; - var peg$f51 = function(o) { + var peg$f45 = function() { return "perDiem"; }; + var peg$f46 = function() { return "eq"; }; + var peg$f47 = function() { return "neq"; }; + var peg$f48 = function() { return "gte"; }; + var peg$f49 = function() { return "gt"; }; + var peg$f50 = function() { return "lte"; }; + var peg$f51 = function() { return "lt"; }; + var peg$f52 = function(o) { if (nameOperator) { expectingNestedQuote = (o === "eq"); // Use simple parser if no valid operator is found } return o; }; - var peg$f52 = function(chars) { return chars.join("").trim(); }; - var peg$f53 = function() { return "and"; }; - var peg$f54 = function() { return expectingNestedQuote; }; - var peg$f55 = function(start, inner, end) { //handle no-breaking space + var peg$f53 = function(chars) { return chars.join("").trim(); }; + var peg$f54 = function() { return "and"; }; + var peg$f55 = function() { return expectingNestedQuote; }; + var peg$f56 = function(start, inner, end) { //handle no-breaking space return [...start, '"', ...inner, '"', ...end].join(""); }; - var peg$f56 = function(start) {return "“"}; - var peg$f57 = function(start) {return "”"}; - var peg$f58 = function(start) {return "\""}; - var peg$f59 = function(start, inner, end) { + var peg$f57 = function(start) {return "“"}; + var peg$f58 = function(start) {return "”"}; + var peg$f59 = function(start) {return "\""}; + var peg$f60 = function(start, inner, end) { return [...start, '"', ...inner, '"'].join(""); }; var peg$currPos = options.peg$currPos | 0; @@ -999,9 +1004,12 @@ function peg$parse(input, options) { } s2 = peg$currPos; s3 = []; - s4 = peg$parsequotedString(); + s4 = peg$parseperDiem(); if (s4 === peg$FAILED) { - s4 = peg$parsealphanumeric(); + s4 = peg$parsequotedString(); + if (s4 === peg$FAILED) { + s4 = peg$parsealphanumeric(); + } } while (s4 !== peg$FAILED) { s3.push(s4); @@ -1029,9 +1037,12 @@ function peg$parse(input, options) { s5 = peg$FAILED; } if (s5 !== peg$FAILED) { - s5 = peg$parsequotedString(); + s5 = peg$parseperDiem(); if (s5 === peg$FAILED) { - s5 = peg$parsealphanumeric(); + s5 = peg$parsequotedString(); + if (s5 === peg$FAILED) { + s5 = peg$parsealphanumeric(); + } } if (s5 === peg$FAILED) { peg$currPos = s4; @@ -1944,6 +1955,35 @@ function peg$parse(input, options) { return s0; } + function peg$parseperDiem() { + var s0, s1; + + s0 = input.substr(peg$currPos, 7); + if (s0.toLowerCase() === peg$c50) { + peg$currPos += 7; + } else { + s0 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e53); } + } + if (s0 === peg$FAILED) { + s0 = peg$currPos; + s1 = input.substr(peg$currPos, 8); + if (s1.toLowerCase() === peg$c51) { + peg$currPos += 8; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e54); } + } + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$f45(); + } + s0 = s1; + } + + return s0; + } + function peg$parseoperator() { var s0, s1; @@ -1954,81 +1994,81 @@ function peg$parse(input, options) { peg$currPos++; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e54); } + if (peg$silentFails === 0) { peg$fail(peg$e56); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f45(); + s1 = peg$f46(); } s0 = s1; if (s0 === peg$FAILED) { s0 = peg$currPos; - if (input.substr(peg$currPos, 2) === peg$c50) { - s1 = peg$c50; + if (input.substr(peg$currPos, 2) === peg$c52) { + s1 = peg$c52; peg$currPos += 2; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e55); } + if (peg$silentFails === 0) { peg$fail(peg$e57); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f46(); + s1 = peg$f47(); } s0 = s1; if (s0 === peg$FAILED) { s0 = peg$currPos; - if (input.substr(peg$currPos, 2) === peg$c51) { - s1 = peg$c51; + if (input.substr(peg$currPos, 2) === peg$c53) { + s1 = peg$c53; peg$currPos += 2; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e56); } + if (peg$silentFails === 0) { peg$fail(peg$e58); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f47(); + s1 = peg$f48(); } s0 = s1; if (s0 === peg$FAILED) { s0 = peg$currPos; if (input.charCodeAt(peg$currPos) === 62) { - s1 = peg$c52; + s1 = peg$c54; peg$currPos++; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e57); } + if (peg$silentFails === 0) { peg$fail(peg$e59); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f48(); + s1 = peg$f49(); } s0 = s1; if (s0 === peg$FAILED) { s0 = peg$currPos; - if (input.substr(peg$currPos, 2) === peg$c53) { - s1 = peg$c53; + if (input.substr(peg$currPos, 2) === peg$c55) { + s1 = peg$c55; peg$currPos += 2; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e58); } + if (peg$silentFails === 0) { peg$fail(peg$e60); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f49(); + s1 = peg$f50(); } s0 = s1; if (s0 === peg$FAILED) { s0 = peg$currPos; if (input.charCodeAt(peg$currPos) === 60) { - s1 = peg$c54; + s1 = peg$c56; peg$currPos++; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e59); } + if (peg$silentFails === 0) { peg$fail(peg$e61); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f50(); + s1 = peg$f51(); } s0 = s1; } @@ -2039,7 +2079,7 @@ function peg$parse(input, options) { peg$silentFails--; if (s0 === peg$FAILED) { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e53); } + if (peg$silentFails === 0) { peg$fail(peg$e55); } } return s0; @@ -2052,7 +2092,7 @@ function peg$parse(input, options) { s1 = peg$parseoperator(); if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f51(s1); + s1 = peg$f52(s1); } s0 = s1; @@ -2070,7 +2110,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e61); } + if (peg$silentFails === 0) { peg$fail(peg$e63); } } if (s2 !== peg$FAILED) { while (s2 !== peg$FAILED) { @@ -2080,7 +2120,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e61); } + if (peg$silentFails === 0) { peg$fail(peg$e63); } } } } else { @@ -2088,13 +2128,13 @@ function peg$parse(input, options) { } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f52(s1); + s1 = peg$f53(s1); } s0 = s1; peg$silentFails--; if (s0 === peg$FAILED) { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e60); } + if (peg$silentFails === 0) { peg$fail(peg$e62); } } return s0; @@ -2106,7 +2146,7 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = peg$parse_(); peg$savedPos = s0; - s1 = peg$f53(); + s1 = peg$f54(); s0 = s1; return s0; @@ -2122,7 +2162,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e63); } + if (peg$silentFails === 0) { peg$fail(peg$e65); } } while (s1 !== peg$FAILED) { s0.push(s1); @@ -2131,12 +2171,12 @@ function peg$parse(input, options) { peg$currPos++; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e63); } + if (peg$silentFails === 0) { peg$fail(peg$e65); } } } peg$silentFails--; s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e62); } + if (peg$silentFails === 0) { peg$fail(peg$e64); } return s0; } @@ -2146,7 +2186,7 @@ function peg$parse(input, options) { s0 = peg$currPos; peg$savedPos = peg$currPos; - s1 = peg$f54(); + s1 = peg$f55(); if (s1) { s1 = undefined; } else { @@ -2183,7 +2223,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e65); } + if (peg$silentFails === 0) { peg$fail(peg$e67); } } while (s2 !== peg$FAILED) { s1.push(s2); @@ -2192,7 +2232,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e65); } + if (peg$silentFails === 0) { peg$fail(peg$e67); } } } s2 = input.charAt(peg$currPos); @@ -2200,7 +2240,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e66); } + if (peg$silentFails === 0) { peg$fail(peg$e68); } } if (s2 !== peg$FAILED) { s3 = []; @@ -2209,7 +2249,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s4 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e67); } + if (peg$silentFails === 0) { peg$fail(peg$e69); } } while (s4 !== peg$FAILED) { s3.push(s4); @@ -2218,7 +2258,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s4 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e67); } + if (peg$silentFails === 0) { peg$fail(peg$e69); } } } s4 = input.charAt(peg$currPos); @@ -2226,7 +2266,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s4 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e66); } + if (peg$silentFails === 0) { peg$fail(peg$e68); } } if (s4 !== peg$FAILED) { s5 = []; @@ -2235,7 +2275,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s6 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e61); } + if (peg$silentFails === 0) { peg$fail(peg$e63); } } while (s6 !== peg$FAILED) { s5.push(s6); @@ -2244,11 +2284,11 @@ function peg$parse(input, options) { peg$currPos++; } else { s6 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e61); } + if (peg$silentFails === 0) { peg$fail(peg$e63); } } } peg$savedPos = s0; - s0 = peg$f55(s1, s3, s5); + s0 = peg$f56(s1, s3, s5); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -2260,7 +2300,7 @@ function peg$parse(input, options) { peg$silentFails--; if (s0 === peg$FAILED) { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e64); } + if (peg$silentFails === 0) { peg$fail(peg$e66); } } return s0; @@ -2277,7 +2317,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e65); } + if (peg$silentFails === 0) { peg$fail(peg$e67); } } while (s2 !== peg$FAILED) { s1.push(s2); @@ -2286,7 +2326,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e65); } + if (peg$silentFails === 0) { peg$fail(peg$e67); } } } s2 = input.charAt(peg$currPos); @@ -2294,7 +2334,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e66); } + if (peg$silentFails === 0) { peg$fail(peg$e68); } } if (s2 !== peg$FAILED) { s3 = []; @@ -2303,7 +2343,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s4 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e67); } + if (peg$silentFails === 0) { peg$fail(peg$e69); } } if (s4 === peg$FAILED) { s4 = peg$currPos; @@ -2319,15 +2359,15 @@ function peg$parse(input, options) { } if (s5 !== peg$FAILED) { if (input.charCodeAt(peg$currPos) === 8220) { - s6 = peg$c55; + s6 = peg$c57; peg$currPos++; } else { s6 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e68); } + if (peg$silentFails === 0) { peg$fail(peg$e70); } } if (s6 !== peg$FAILED) { peg$savedPos = s4; - s4 = peg$f56(s1); + s4 = peg$f57(s1); } else { peg$currPos = s4; s4 = peg$FAILED; @@ -2350,15 +2390,15 @@ function peg$parse(input, options) { } if (s5 !== peg$FAILED) { if (input.charCodeAt(peg$currPos) === 8221) { - s6 = peg$c56; + s6 = peg$c58; peg$currPos++; } else { s6 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e69); } + if (peg$silentFails === 0) { peg$fail(peg$e71); } } if (s6 !== peg$FAILED) { peg$savedPos = s4; - s4 = peg$f57(s1); + s4 = peg$f58(s1); } else { peg$currPos = s4; s4 = peg$FAILED; @@ -2381,15 +2421,15 @@ function peg$parse(input, options) { } if (s5 !== peg$FAILED) { if (input.charCodeAt(peg$currPos) === 34) { - s6 = peg$c57; + s6 = peg$c59; peg$currPos++; } else { s6 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e70); } + if (peg$silentFails === 0) { peg$fail(peg$e72); } } if (s6 !== peg$FAILED) { peg$savedPos = s4; - s4 = peg$f58(s1); + s4 = peg$f59(s1); } else { peg$currPos = s4; s4 = peg$FAILED; @@ -2408,7 +2448,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s4 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e67); } + if (peg$silentFails === 0) { peg$fail(peg$e69); } } if (s4 === peg$FAILED) { s4 = peg$currPos; @@ -2424,15 +2464,15 @@ function peg$parse(input, options) { } if (s5 !== peg$FAILED) { if (input.charCodeAt(peg$currPos) === 8220) { - s6 = peg$c55; + s6 = peg$c57; peg$currPos++; } else { s6 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e68); } + if (peg$silentFails === 0) { peg$fail(peg$e70); } } if (s6 !== peg$FAILED) { peg$savedPos = s4; - s4 = peg$f56(s1); + s4 = peg$f57(s1); } else { peg$currPos = s4; s4 = peg$FAILED; @@ -2455,15 +2495,15 @@ function peg$parse(input, options) { } if (s5 !== peg$FAILED) { if (input.charCodeAt(peg$currPos) === 8221) { - s6 = peg$c56; + s6 = peg$c58; peg$currPos++; } else { s6 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e69); } + if (peg$silentFails === 0) { peg$fail(peg$e71); } } if (s6 !== peg$FAILED) { peg$savedPos = s4; - s4 = peg$f57(s1); + s4 = peg$f58(s1); } else { peg$currPos = s4; s4 = peg$FAILED; @@ -2486,15 +2526,15 @@ function peg$parse(input, options) { } if (s5 !== peg$FAILED) { if (input.charCodeAt(peg$currPos) === 34) { - s6 = peg$c57; + s6 = peg$c59; peg$currPos++; } else { s6 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e70); } + if (peg$silentFails === 0) { peg$fail(peg$e72); } } if (s6 !== peg$FAILED) { peg$savedPos = s4; - s4 = peg$f58(s1); + s4 = peg$f59(s1); } else { peg$currPos = s4; s4 = peg$FAILED; @@ -2510,7 +2550,7 @@ function peg$parse(input, options) { s4 = peg$parseclosingQuote(); if (s4 !== peg$FAILED) { peg$savedPos = s0; - s0 = peg$f59(s1, s3, s4); + s0 = peg$f60(s1, s3, s4); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -2522,7 +2562,7 @@ function peg$parse(input, options) { peg$silentFails--; if (s0 === peg$FAILED) { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e64); } + if (peg$silentFails === 0) { peg$fail(peg$e66); } } return s0; @@ -2537,7 +2577,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e66); } + if (peg$silentFails === 0) { peg$fail(peg$e68); } } if (s1 !== peg$FAILED) { s2 = peg$currPos; @@ -2575,7 +2615,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e71); } + if (peg$silentFails === 0) { peg$fail(peg$e73); } } while (s2 !== peg$FAILED) { s1.push(s2); @@ -2584,7 +2624,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e71); } + if (peg$silentFails === 0) { peg$fail(peg$e73); } } } s2 = []; @@ -2593,7 +2633,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s3 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e72); } + if (peg$silentFails === 0) { peg$fail(peg$e74); } } while (s3 !== peg$FAILED) { s2.push(s3); @@ -2602,7 +2642,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s3 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e72); } + if (peg$silentFails === 0) { peg$fail(peg$e74); } } } s3 = []; @@ -2611,7 +2651,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s4 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e73); } + if (peg$silentFails === 0) { peg$fail(peg$e75); } } while (s4 !== peg$FAILED) { s3.push(s4); @@ -2620,7 +2660,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s4 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e73); } + if (peg$silentFails === 0) { peg$fail(peg$e75); } } } s4 = peg$parseoperator(); @@ -2639,7 +2679,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e74); } + if (peg$silentFails === 0) { peg$fail(peg$e76); } } while (s2 !== peg$FAILED) { s1.push(s2); @@ -2648,7 +2688,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e74); } + if (peg$silentFails === 0) { peg$fail(peg$e76); } } } s2 = peg$currPos; @@ -2669,7 +2709,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s4 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e75); } + if (peg$silentFails === 0) { peg$fail(peg$e77); } } peg$silentFails--; if (s4 === peg$FAILED) { @@ -2695,7 +2735,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s0 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e76); } + if (peg$silentFails === 0) { peg$fail(peg$e78); } } } } diff --git a/src/libs/SearchParser/searchParser.peggy b/src/libs/SearchParser/searchParser.peggy index 39334f134a4e..1c52fd8cb11d 100644 --- a/src/libs/SearchParser/searchParser.peggy +++ b/src/libs/SearchParser/searchParser.peggy @@ -152,7 +152,7 @@ filterKey defaultKey "default key" = @(type / status / sortBy / sortOrder / policyID / groupBy) identifier - = (","+)? parts:(quotedString / alphanumeric)|1.., ","+| empty:(","+)? { + = (","+)? parts:(values / quotedString / alphanumeric)|1.., ","+| empty:(","+)? { const value = parts.flat().filter(Boolean).map((word) => { if (word.startsWith('"') && word.endsWith('"') && word.length >= 2) { return word.slice(1, -1); diff --git a/src/libs/SearchQueryUtils.ts b/src/libs/SearchQueryUtils.ts index 8cf9d65dcf79..83dc81293caa 100644 --- a/src/libs/SearchQueryUtils.ts +++ b/src/libs/SearchQueryUtils.ts @@ -14,6 +14,7 @@ import type { SearchStatus, SearchWithdrawalType, UserFriendlyKey, + UserFriendlyValue, } from '@components/Search/types'; import CONST from '@src/CONST'; import NAVIGATORS from '@src/NAVIGATORS'; @@ -55,48 +56,52 @@ const operatorToCharMap = { [CONST.SEARCH.SYNTAX_OPERATORS.OR]: ' ' as const, }; +// Create reverse lookup maps for O(1) performance +const createKeyToUserFriendlyMap = () => { + const map = new Map(); + + // Map SYNTAX_FILTER_KEYS values to their user-friendly names + Object.entries(CONST.SEARCH.SYNTAX_FILTER_KEYS).forEach(([keyName, keyValue]) => { + if (!(keyName in CONST.SEARCH.SEARCH_USER_FRIENDLY_KEYS)) { + return; + } + map.set(keyValue, CONST.SEARCH.SEARCH_USER_FRIENDLY_KEYS[keyName as keyof typeof CONST.SEARCH.SEARCH_USER_FRIENDLY_KEYS]); + }); + + // Map SYNTAX_ROOT_KEYS values to their user-friendly names + Object.entries(CONST.SEARCH.SYNTAX_ROOT_KEYS).forEach(([keyName, keyValue]) => { + if (!(keyName in CONST.SEARCH.SEARCH_USER_FRIENDLY_KEYS)) { + return; + } + map.set(keyValue, CONST.SEARCH.SEARCH_USER_FRIENDLY_KEYS[keyName as keyof typeof CONST.SEARCH.SEARCH_USER_FRIENDLY_KEYS]); + }); + + return map; +}; + +// Create the maps once at module initialization for performance +const keyToUserFriendlyMap = createKeyToUserFriendlyMap(); + /** - * A mapping object that maps filter names from the internal codebase format to user-friendly names. + * Lookup a key in the keyToUserFriendlyMap and return the user-friendly key. + * + * @example + * getUserFriendlyKey("taxRate") // returns "tax-rate" */ -const UserFriendlyKeyMap: Record = { - type: 'type', - status: 'status', - sortBy: 'sort-by', - sortOrder: 'sort-order', - policyID: 'workspace', - date: 'date', - amount: 'amount', - expenseType: 'expense-type', - currency: 'currency', - groupCurrency: 'group-currency', - merchant: 'merchant', - description: 'description', - from: 'from', - to: 'to', - payer: 'payer', - exporter: 'exporter', - category: 'category', - tag: 'tag', - taxRate: 'tax-rate', - cardID: 'card', - feed: 'feed', - reportID: 'report-id', - keyword: 'keyword', - in: 'in', - submitted: 'submitted', - approved: 'approved', - paid: 'paid', - exported: 'exported', - posted: 'posted', - withdrawalType: 'withdrawal-type', - withdrawn: 'withdrawn', - groupBy: 'group-by', - title: 'title', - assignee: 'assignee', - billable: 'billable', - reimbursable: 'reimbursable', - action: 'action', -}; +function getUserFriendlyKey(keyName: SearchFilterKey | typeof CONST.SEARCH.SYNTAX_ROOT_KEYS.SORT_BY | typeof CONST.SEARCH.SYNTAX_ROOT_KEYS.SORT_ORDER): UserFriendlyKey { + return (keyToUserFriendlyMap.get(keyName) ?? keyName) as UserFriendlyKey; +} + +/** + * Converts a filter value from backend value to user friendly display text. + * + * @example + * getUserFriendlyValues("perDiem") // returns "per-diem" + */ +function getUserFriendlyValue(value: string): UserFriendlyValue { + return CONST.SEARCH.SEARCH_USER_FRIENDLY_VALUES_MAP[value as keyof typeof CONST.SEARCH.SEARCH_USER_FRIENDLY_VALUES_MAP] ?? value; +} + /** * @private * Returns string value wrapped in quotes "", if the value contains space or   (no-breaking space). @@ -850,7 +855,7 @@ function buildUserReadableQueryString( } else { displayQueryFilters = queryFilter.map((filter) => ({ operator: filter.operator, - value: getFilterDisplayValue(key, filter.value.toString(), PersonalDetails, reports, cardList, cardFeeds, policies), + value: getFilterDisplayValue(key, getUserFriendlyValue(filter.value.toString()), PersonalDetails, reports, cardList, cardFeeds, policies), })); } title += buildFilterValuesString(getUserFriendlyKey(key), displayQueryFilters); @@ -1047,21 +1052,6 @@ function getQueryWithoutFilters(searchQuery: string) { return keywordFilter?.filters.map((filter) => filter.value).join(' ') ?? ''; } -/** - * 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]; -} - function shouldHighlight(referenceText: string, searchText: string) { if (!referenceText || !searchText) { return false; @@ -1091,10 +1081,11 @@ export { getQueryWithUpdatedValues, getCurrentSearchQueryJSON, getQueryWithoutFilters, - getUserFriendlyKey, isDefaultExpensesQuery, sortOptionsWithEmptyValue, shouldHighlight, getAllPolicyValues, getTodoSearchQuery, + getUserFriendlyValue, + getUserFriendlyKey, }; diff --git a/tests/unit/SearchAutocompleteParserTest.ts b/tests/unit/SearchAutocompleteParserTest.ts index 7ce74ee5d619..11fd6d16b212 100644 --- a/tests/unit/SearchAutocompleteParserTest.ts +++ b/tests/unit/SearchAutocompleteParserTest.ts @@ -247,6 +247,18 @@ const tests = [ ], }, }, + { + query: 'expense-type:per-diem', + expected: { + autocomplete: { + key: 'expenseType', + value: 'per-diem', + start: 13, + length: 8, + }, + ranges: [{key: 'expenseType', value: 'per-diem', start: 13, length: 8}], + }, + }, ]; const nameFieldContinuationTests = [ diff --git a/tests/unit/SearchParserTest.ts b/tests/unit/SearchParserTest.ts index da962d816688..34500adee0f7 100644 --- a/tests/unit/SearchParserTest.ts +++ b/tests/unit/SearchParserTest.ts @@ -615,6 +615,20 @@ const keywordTests = [ }, }, }, + { + query: 'expense-type:per-diem', + expected: { + type: 'expense', + status: CONST.SEARCH.STATUS.EXPENSE.ALL, + sortBy: 'date', + sortOrder: 'desc', + filters: { + operator: 'eq', + left: 'expenseType', + right: 'perDiem', + }, + }, + }, ]; describe('search parser', () => {