From a863f93fc39ee445230f0b3f3e488b70755cede1 Mon Sep 17 00:00:00 2001 From: 289Adam289 Date: Wed, 4 Dec 2024 11:20:27 +0100 Subject: [PATCH 01/12] Grammar change names and make case insensitive --- src/libs/SearchParser/autocompleteParser.js | 712 +++++++++++++---- .../SearchParser/autocompleteParser.peggy | 22 +- src/libs/SearchParser/baseRules.peggy | 21 + src/libs/SearchParser/searchParser.js | 728 +++++++++++++----- src/libs/SearchParser/searchParser.peggy | 32 +- 5 files changed, 1104 insertions(+), 411 deletions(-) diff --git a/src/libs/SearchParser/autocompleteParser.js b/src/libs/SearchParser/autocompleteParser.js index bd114b56e099..e3c954b1d994 100644 --- a/src/libs/SearchParser/autocompleteParser.js +++ b/src/libs/SearchParser/autocompleteParser.js @@ -176,23 +176,32 @@ 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 = "tax-rate"; + var peg$c13 = "card"; + var peg$c14 = "from"; + var peg$c15 = "expense-type"; + var peg$c16 = "type"; + var peg$c17 = "status"; + var peg$c18 = "sort-by"; + var peg$c19 = "sort-order"; + var peg$c20 = "workspace"; + var peg$c21 = "!="; + var peg$c22 = ">="; + var peg$c23 = ">"; + var peg$c24 = "<="; + var peg$c25 = "<"; + var peg$c26 = "\""; var peg$r0 = /^[:=]/; var peg$r1 = /^[^ ,"\t\n\r]/; @@ -202,32 +211,41 @@ 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("tax-rate", true); + var peg$e14 = peg$literalExpectation("card", true); + var peg$e15 = peg$literalExpectation("from", true); + var peg$e16 = peg$literalExpectation("expense-type", true); + var peg$e17 = peg$literalExpectation("type", true); + var peg$e18 = peg$literalExpectation("status", true); + var peg$e19 = peg$literalExpectation("sort-by", true); + var peg$e20 = peg$literalExpectation("sort-order", true); + var peg$e21 = peg$literalExpectation("workspace", true); + var peg$e22 = peg$otherExpectation("operator"); + var peg$e23 = peg$classExpectation([":", "="], false, false); + var peg$e24 = peg$literalExpectation("!=", false); + var peg$e25 = peg$literalExpectation(">=", false); + var peg$e26 = peg$literalExpectation(">", false); + var peg$e27 = peg$literalExpectation("<=", false); + var peg$e28 = peg$literalExpectation("<", false); + var peg$e29 = peg$otherExpectation("quote"); + var peg$e30 = peg$classExpectation([" ", ",", "\"", "\t", "\n", "\r"], true, false); + var peg$e31 = peg$literalExpectation("\"", false); + var peg$e32 = peg$classExpectation(["\"", "\r", "\n"], true, false); + var peg$e33 = peg$classExpectation([" ", ",", "\t", "\n", "\r"], true, false); + var peg$e34 = peg$otherExpectation("word"); + var peg$e35 = peg$otherExpectation("whitespace"); + var peg$e36 = 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 +295,37 @@ 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 "eq"; }; + var peg$f26 = function() { return "neq"; }; + var peg$f27 = function() { return "gte"; }; + var peg$f28 = function() { return "gt"; }; + var peg$f29 = function() { return "lte"; }; + var peg$f30 = function() { return "lt"; }; + var peg$f31 = 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$f32 = function(chars) { return chars.join("").trim(); }; + var peg$f33 = function() { return "and"; }; var peg$currPos = options.peg$currPos | 0; var peg$savedPos = peg$currPos; var peg$posDetailsCache = [{ line: 1, column: 1 }]; @@ -567,93 +605,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 +713,406 @@ 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 = peg$currPos; + s1 = input.substr(peg$currPos, 8); + if (s1.toLowerCase() === peg$c12) { + peg$currPos += 8; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e13); } + } + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$f16(); + } + s0 = s1; + + return s0; + } + + function peg$parsecardID() { + var s0, s1; + + s0 = peg$currPos; + s1 = input.substr(peg$currPos, 4); + if (s1.toLowerCase() === peg$c13) { + peg$currPos += 4; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e14); } + } + 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$c14) { + peg$currPos += 4; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e15); } + } + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$f18(); + } + s0 = s1; + + return s0; + } + + function peg$parseexpenseType() { + var s0, s1; + + s0 = peg$currPos; + s1 = input.substr(peg$currPos, 12); + if (s1.toLowerCase() === peg$c15) { + peg$currPos += 12; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e16); } + } + 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$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$f20(); + } + s0 = s1; + + return s0; + } + + function peg$parsestatus() { + var s0, s1; + + s0 = peg$currPos; + s1 = input.substr(peg$currPos, 6); + if (s1.toLowerCase() === peg$c17) { + peg$currPos += 6; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e18); } + } + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$f21(); + } + s0 = s1; + + return s0; + } + + function peg$parsesortBy() { + var s0, s1; + + s0 = peg$currPos; + s1 = input.substr(peg$currPos, 7); + if (s1.toLowerCase() === peg$c18) { + peg$currPos += 7; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e19); } + } + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$f22(); + } + s0 = s1; + + return s0; + } + + function peg$parsesortOrder() { + var s0, s1; + + s0 = peg$currPos; + s1 = input.substr(peg$currPos, 10); + if (s1.toLowerCase() === peg$c19) { + peg$currPos += 10; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e20); } + } + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$f23(); + } + s0 = s1; + + return s0; + } + + function peg$parsepolicyID() { + var s0, s1; + + s0 = peg$currPos; + s1 = input.substr(peg$currPos, 9); + if (s1.toLowerCase() === peg$c20) { + peg$currPos += 9; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e21); } + } + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$f24(); + } + s0 = s1; + + return s0; + } + function peg$parseoperator() { var s0, s1; @@ -751,81 +1123,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$e23); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f5(); + s1 = peg$f25(); } 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$c21) { + s1 = peg$c21; peg$currPos += 2; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e15); } + if (peg$silentFails === 0) { peg$fail(peg$e24); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f6(); + s1 = peg$f26(); } 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$c22) { + s1 = peg$c22; peg$currPos += 2; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e16); } + if (peg$silentFails === 0) { peg$fail(peg$e25); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f7(); + s1 = peg$f27(); } s0 = s1; if (s0 === peg$FAILED) { s0 = peg$currPos; if (input.charCodeAt(peg$currPos) === 62) { - s1 = peg$c14; + s1 = peg$c23; peg$currPos++; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e17); } + if (peg$silentFails === 0) { peg$fail(peg$e26); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f8(); + s1 = peg$f28(); } 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$c24) { + s1 = peg$c24; peg$currPos += 2; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e18); } + if (peg$silentFails === 0) { peg$fail(peg$e27); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f9(); + s1 = peg$f29(); } s0 = s1; if (s0 === peg$FAILED) { s0 = peg$currPos; if (input.charCodeAt(peg$currPos) === 60) { - s1 = peg$c16; + s1 = peg$c25; peg$currPos++; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e19); } + if (peg$silentFails === 0) { peg$fail(peg$e28); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f10(); + s1 = peg$f30(); } s0 = s1; } @@ -836,7 +1208,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$e22); } } return s0; @@ -853,7 +1225,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$e30); } } while (s2 !== peg$FAILED) { s1.push(s2); @@ -862,15 +1234,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$e30); } } } if (input.charCodeAt(peg$currPos) === 34) { - s2 = peg$c17; + s2 = peg$c26; peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e22); } + if (peg$silentFails === 0) { peg$fail(peg$e31); } } if (s2 !== peg$FAILED) { s3 = []; @@ -879,7 +1251,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$e32); } } while (s4 !== peg$FAILED) { s3.push(s4); @@ -888,15 +1260,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$e32); } } } if (input.charCodeAt(peg$currPos) === 34) { - s4 = peg$c17; + s4 = peg$c26; peg$currPos++; } else { s4 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e22); } + if (peg$silentFails === 0) { peg$fail(peg$e31); } } if (s4 !== peg$FAILED) { s5 = []; @@ -905,7 +1277,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$e33); } } while (s6 !== peg$FAILED) { s5.push(s6); @@ -914,11 +1286,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$e33); } } } peg$savedPos = s0; - s0 = peg$f11(s1, s3, s5); + s0 = peg$f31(s1, s3, s5); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -930,7 +1302,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$e29); } } return s0; @@ -947,7 +1319,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$e33); } } if (s2 !== peg$FAILED) { while (s2 !== peg$FAILED) { @@ -957,7 +1329,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$e33); } } } } else { @@ -965,13 +1337,13 @@ function peg$parse(input, options) { } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f12(s1); + s1 = peg$f32(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$e34); } } return s0; @@ -983,7 +1355,7 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = peg$parse_(); peg$savedPos = s0; - s1 = peg$f13(); + s1 = peg$f33(); s0 = s1; return s0; @@ -999,7 +1371,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$e36); } } while (s1 !== peg$FAILED) { s0.push(s1); @@ -1008,12 +1380,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$e36); } } } peg$silentFails--; s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e26); } + if (peg$silentFails === 0) { peg$fail(peg$e35); } 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..e2ca9d4ffb2b 100644 --- a/src/libs/SearchParser/baseRules.peggy +++ b/src/libs/SearchParser/baseRules.peggy @@ -8,6 +8,27 @@ // logicalAnd: rule to match whitespace and return it as a logical 'and' operator. // whitespace: rule to match whitespaces. +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 = "tax-rate"i {return "taxRate"} +cardID = "card"i {return "cardID"} +from = "from"i {return "from"} +expenseType = "expense-type"i {return "expenseType"} +type = "type"i {return "type"} +status = "status"i {return "status"} +sortBy = "sort-by"i {return "sortBy"} +sortOrder = "sort-order"i {return "sortOrder"} +policyID = "workspace"i {return "policyID"} + operator "operator" = (":" / "=") { return "eq"; } / "!=" { return "neq"; } diff --git a/src/libs/SearchParser/searchParser.js b/src/libs/SearchParser/searchParser.js index c94222f3a6e9..08910c7ce108 100644 --- a/src/libs/SearchParser/searchParser.js +++ b/src/libs/SearchParser/searchParser.js @@ -180,27 +180,27 @@ 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 = "type"; - var peg$c16 = "status"; - var peg$c17 = "sortBy"; - var peg$c18 = "sortOrder"; - var peg$c19 = "policyID"; - var peg$c20 = ","; + 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 = "tax-rate"; + var peg$c13 = "card"; + var peg$c14 = "from"; + var peg$c15 = "expense-type"; + var peg$c16 = "type"; + var peg$c17 = "status"; + var peg$c18 = "sort-by"; + var peg$c19 = "sort-order"; + var peg$c20 = "workspace"; var peg$c21 = "!="; var peg$c22 = ">="; var peg$c23 = ">"; @@ -217,28 +217,28 @@ 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$otherExpectation("default key"); - var peg$e18 = peg$literalExpectation("type", false); - var peg$e19 = peg$literalExpectation("status", false); - var peg$e20 = peg$literalExpectation("sortBy", false); - var peg$e21 = peg$literalExpectation("sortOrder", false); - var peg$e22 = peg$literalExpectation("policyID", false); - var peg$e23 = peg$literalExpectation(",", 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("tax-rate", true); + var peg$e16 = peg$literalExpectation("card", true); + var peg$e17 = peg$literalExpectation("from", true); + var peg$e18 = peg$literalExpectation("expense-type", true); + var peg$e19 = peg$literalExpectation("type", true); + var peg$e20 = peg$literalExpectation("status", true); + var peg$e21 = peg$literalExpectation("sort-by", true); + var peg$e22 = peg$literalExpectation("sort-order", true); + var peg$e23 = peg$literalExpectation("workspace", true); var peg$e24 = peg$otherExpectation("operator"); var peg$e25 = peg$classExpectation([":", "="], false, false); var peg$e26 = peg$literalExpectation("!=", false); @@ -309,17 +309,37 @@ 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 "eq"; }; + var peg$f27 = function() { return "neq"; }; + var peg$f28 = function() { return "gte"; }; + var peg$f29 = function() { return "gt"; }; + var peg$f30 = function() { return "lte"; }; + var peg$f31 = function() { return "lt"; }; + var peg$f32 = 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$f33 = function(chars) { return chars.join("").trim(); }; + var peg$f34 = function() { return "and"; }; var peg$currPos = options.peg$currPos | 0; var peg$savedPos = peg$currPos; var peg$posDetailsCache = [{ line: 1, column: 1 }]; @@ -668,125 +688,35 @@ 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(); } } } @@ -821,45 +751,15 @@ function peg$parse(input, options) { peg$silentFails++; s0 = peg$currPos; - if (input.substr(peg$currPos, 4) === peg$c15) { - s1 = peg$c15; - peg$currPos += 4; - } else { - s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e18); } - } + s1 = peg$parsetype(); if (s1 === peg$FAILED) { - if (input.substr(peg$currPos, 6) === peg$c16) { - s1 = peg$c16; - peg$currPos += 6; - } else { - s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e19); } - } + s1 = peg$parsestatus(); if (s1 === peg$FAILED) { - if (input.substr(peg$currPos, 6) === peg$c17) { - s1 = peg$c17; - peg$currPos += 6; - } else { - s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e20); } - } + s1 = peg$parsesortBy(); if (s1 === peg$FAILED) { - if (input.substr(peg$currPos, 9) === peg$c18) { - s1 = peg$c18; - peg$currPos += 9; - } else { - s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e21); } - } + s1 = peg$parsesortOrder(); if (s1 === peg$FAILED) { - if (input.substr(peg$currPos, 8) === peg$c19) { - s1 = peg$c19; - peg$currPos += 8; - } else { - s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e22); } - } + s1 = peg$parsepolicyID(); } } } @@ -873,7 +773,7 @@ function peg$parse(input, options) { peg$silentFails--; if (s0 === peg$FAILED) { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e17); } + if (peg$silentFails === 0) { peg$fail(peg$e2); } } return s0; @@ -885,21 +785,21 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = []; if (input.charCodeAt(peg$currPos) === 44) { - s2 = peg$c20; + s2 = peg$c0; peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e23); } + 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$c20; + s2 = peg$c0; peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e23); } + if (peg$silentFails === 0) { peg$fail(peg$e3); } } } } else { @@ -919,21 +819,21 @@ function peg$parse(input, options) { s4 = peg$currPos; s5 = []; if (input.charCodeAt(peg$currPos) === 44) { - s6 = peg$c20; + s6 = peg$c0; peg$currPos++; } else { s6 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e23); } + 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$c20; + s6 = peg$c0; peg$currPos++; } else { s6 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e23); } + if (peg$silentFails === 0) { peg$fail(peg$e3); } } } } else { @@ -963,21 +863,21 @@ function peg$parse(input, options) { if (s2 !== peg$FAILED) { s3 = []; if (input.charCodeAt(peg$currPos) === 44) { - s4 = peg$c20; + s4 = peg$c0; peg$currPos++; } else { s4 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e23); } + 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$c20; + s4 = peg$c0; peg$currPos++; } else { s4 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e23); } + if (peg$silentFails === 0) { peg$fail(peg$e3); } } } } else { @@ -996,6 +896,406 @@ 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 = peg$currPos; + s1 = input.substr(peg$currPos, 8); + if (s1.toLowerCase() === peg$c12) { + peg$currPos += 8; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e15); } + } + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$f17(); + } + s0 = s1; + + return s0; + } + + function peg$parsecardID() { + var s0, s1; + + s0 = peg$currPos; + s1 = input.substr(peg$currPos, 4); + if (s1.toLowerCase() === peg$c13) { + peg$currPos += 4; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e16); } + } + 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$c14) { + peg$currPos += 4; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e17); } + } + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$f19(); + } + s0 = s1; + + return s0; + } + + function peg$parseexpenseType() { + var s0, s1; + + s0 = peg$currPos; + s1 = input.substr(peg$currPos, 12); + if (s1.toLowerCase() === peg$c15) { + peg$currPos += 12; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e18); } + } + 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$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$f21(); + } + s0 = s1; + + return s0; + } + + function peg$parsestatus() { + var s0, s1; + + s0 = peg$currPos; + s1 = input.substr(peg$currPos, 6); + if (s1.toLowerCase() === peg$c17) { + peg$currPos += 6; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e20); } + } + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$f22(); + } + s0 = s1; + + return s0; + } + + function peg$parsesortBy() { + var s0, s1; + + s0 = peg$currPos; + s1 = input.substr(peg$currPos, 7); + if (s1.toLowerCase() === peg$c18) { + peg$currPos += 7; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e21); } + } + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$f23(); + } + s0 = s1; + + return s0; + } + + function peg$parsesortOrder() { + var s0, s1; + + s0 = peg$currPos; + s1 = input.substr(peg$currPos, 10); + if (s1.toLowerCase() === peg$c19) { + peg$currPos += 10; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e22); } + } + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$f24(); + } + s0 = s1; + + return s0; + } + + function peg$parsepolicyID() { + var s0, s1; + + s0 = peg$currPos; + s1 = input.substr(peg$currPos, 9); + if (s1.toLowerCase() === peg$c20) { + peg$currPos += 9; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e23); } + } + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$f25(); + } + s0 = s1; + + return s0; + } + function peg$parseoperator() { var s0, s1; @@ -1010,7 +1310,7 @@ function peg$parse(input, options) { } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f6(); + s1 = peg$f26(); } s0 = s1; if (s0 === peg$FAILED) { @@ -1024,7 +1324,7 @@ function peg$parse(input, options) { } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f7(); + s1 = peg$f27(); } s0 = s1; if (s0 === peg$FAILED) { @@ -1038,7 +1338,7 @@ function peg$parse(input, options) { } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f8(); + s1 = peg$f28(); } s0 = s1; if (s0 === peg$FAILED) { @@ -1052,7 +1352,7 @@ function peg$parse(input, options) { } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f9(); + s1 = peg$f29(); } s0 = s1; if (s0 === peg$FAILED) { @@ -1066,7 +1366,7 @@ function peg$parse(input, options) { } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f10(); + s1 = peg$f30(); } s0 = s1; if (s0 === peg$FAILED) { @@ -1080,7 +1380,7 @@ function peg$parse(input, options) { } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f11(); + s1 = peg$f31(); } s0 = s1; } @@ -1173,7 +1473,7 @@ function peg$parse(input, options) { } } peg$savedPos = s0; - s0 = peg$f12(s1, s3, s5); + s0 = peg$f32(s1, s3, s5); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -1220,7 +1520,7 @@ function peg$parse(input, options) { } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f13(s1); + s1 = peg$f33(s1); } s0 = s1; peg$silentFails--; @@ -1238,7 +1538,7 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = peg$parse_(); peg$savedPos = s0; - s1 = peg$f14(); + s1 = peg$f34(); s0 = s1; return s0; diff --git a/src/libs/SearchParser/searchParser.peggy b/src/libs/SearchParser/searchParser.peggy index d3aaf5ddf97b..8f6909278977 100644 --- a/src/libs/SearchParser/searchParser.peggy +++ b/src/libs/SearchParser/searchParser.peggy @@ -98,25 +98,25 @@ standardFilter key "key" = @( - "date" - / "amount" - / "merchant" - / "description" - / "reportID" - / "keyword" - / "in" - / "currency" - / "tag" - / "category" - / "to" - / "taxRate" - / "cardID" - / "from" - / "expenseType" + date + / amount + / merchant + / description + / reportID + / keyword + / in + / currency + / tag + / category + / to + / taxRate + / cardID + / from + / expenseType ) defaultKey "default key" - = @("type" / "status" / "sortBy" / "sortOrder" / "policyID") + = @(type / status / sortBy / sortOrder / policyID) identifier = (","+)? parts:(quotedString / alphanumeric)|1.., ","+| empty:(","+)? { From 2ffb521c592973244d58bd2bdf16c9af0e3be41d Mon Sep 17 00:00:00 2001 From: 289Adam289 Date: Wed, 4 Dec 2024 11:21:08 +0100 Subject: [PATCH 02/12] change names in tests --- tests/unit/SearchAutocompleteParserTest.ts | 24 +++++++++++----------- tests/unit/SearchParserTest.ts | 4 ++-- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/tests/unit/SearchAutocompleteParserTest.ts b/tests/unit/SearchAutocompleteParserTest.ts index 2571b03089b1..1ad3a77207bd 100644 --- a/tests/unit/SearchAutocompleteParserTest.ts +++ b/tests/unit/SearchAutocompleteParserTest.ts @@ -3,7 +3,7 @@ import * as autocompleteParser from '@libs/SearchParser/autocompleteParser'; const tests = [ { - query: 'date>2024-01-01 amount>100 merchant:"A B" description:A,B,C ,, reportID:123456789 word', + query: 'date>2024-01-01 amount>100 merchant:"A B" description:A,B,C ,, reportid:123456789 word', expected: { autocomplete: null, ranges: [], @@ -131,12 +131,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 +145,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..774e68f03248 100644 --- a/tests/unit/SearchParserTest.ts +++ b/tests/unit/SearchParserTest.ts @@ -159,7 +159,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', @@ -229,7 +229,7 @@ const tests = [ }, }, { - query: 'amount>200 expenseType:cash,card description:"Las Vegas party" date:2024-06-01 category:travel,hotel,"meal & entertainment"', + query: 'amount>200 expense-type:cash,card description:"Las Vegas party" date:2024-06-01 category:travel,hotel,"meal & entertainment"', expected: { type: 'expense', status: 'all', From 69f7764ca615b4e3d8046b824bd3e19531a1d667 Mon Sep 17 00:00:00 2001 From: 289Adam289 Date: Fri, 6 Dec 2024 10:42:59 +0100 Subject: [PATCH 03/12] Parser old names --- src/libs/SearchParser/autocompleteParser.js | 338 ++++++++++++-------- src/libs/SearchParser/baseRules.peggy | 12 +- src/libs/SearchParser/searchParser.js | 338 ++++++++++++-------- 3 files changed, 410 insertions(+), 278 deletions(-) diff --git a/src/libs/SearchParser/autocompleteParser.js b/src/libs/SearchParser/autocompleteParser.js index e3c954b1d994..9efdf300865d 100644 --- a/src/libs/SearchParser/autocompleteParser.js +++ b/src/libs/SearchParser/autocompleteParser.js @@ -187,21 +187,27 @@ function peg$parse(input, options) { var peg$c9 = "tag"; var peg$c10 = "category"; var peg$c11 = "to"; - var peg$c12 = "tax-rate"; - var peg$c13 = "card"; - var peg$c14 = "from"; - var peg$c15 = "expense-type"; - var peg$c16 = "type"; - var peg$c17 = "status"; - var peg$c18 = "sort-by"; - var peg$c19 = "sort-order"; - var peg$c20 = "workspace"; - var peg$c21 = "!="; - var peg$c22 = ">="; - var peg$c23 = ">"; - var peg$c24 = "<="; - var peg$c25 = "<"; - var peg$c26 = "\""; + 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 = "!="; + var peg$c28 = ">="; + var peg$c29 = ">"; + var peg$c30 = "<="; + var peg$c31 = "<"; + var peg$c32 = "\""; var peg$r0 = /^[:=]/; var peg$r1 = /^[^ ,"\t\n\r]/; @@ -222,30 +228,36 @@ function peg$parse(input, options) { 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("tax-rate", true); - var peg$e14 = peg$literalExpectation("card", true); - var peg$e15 = peg$literalExpectation("from", true); - var peg$e16 = peg$literalExpectation("expense-type", true); - var peg$e17 = peg$literalExpectation("type", true); - var peg$e18 = peg$literalExpectation("status", true); - var peg$e19 = peg$literalExpectation("sort-by", true); - var peg$e20 = peg$literalExpectation("sort-order", true); - var peg$e21 = peg$literalExpectation("workspace", true); - var peg$e22 = peg$otherExpectation("operator"); - var peg$e23 = peg$classExpectation([":", "="], false, false); - var peg$e24 = peg$literalExpectation("!=", false); - var peg$e25 = peg$literalExpectation(">=", false); - var peg$e26 = peg$literalExpectation(">", false); - var peg$e27 = peg$literalExpectation("<=", false); - var peg$e28 = peg$literalExpectation("<", false); - var peg$e29 = peg$otherExpectation("quote"); - var peg$e30 = peg$classExpectation([" ", ",", "\"", "\t", "\n", "\r"], true, false); - var peg$e31 = peg$literalExpectation("\"", false); - var peg$e32 = peg$classExpectation(["\"", "\r", "\n"], true, false); - var peg$e33 = peg$classExpectation([" ", ",", "\t", "\n", "\r"], true, false); - var peg$e34 = peg$otherExpectation("word"); - var peg$e35 = peg$otherExpectation("whitespace"); - var peg$e36 = peg$classExpectation([" ", "\t", "\r", "\n"], false, false); + 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$otherExpectation("operator"); + var peg$e29 = peg$classExpectation([":", "="], false, false); + var peg$e30 = peg$literalExpectation("!=", 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$otherExpectation("quote"); + var peg$e36 = peg$classExpectation([" ", ",", "\"", "\t", "\n", "\r"], true, false); + var peg$e37 = peg$literalExpectation("\"", false); + var peg$e38 = peg$classExpectation(["\"", "\r", "\n"], true, false); + var peg$e39 = peg$classExpectation([" ", ",", "\t", "\n", "\r"], true, false); + var peg$e40 = peg$otherExpectation("word"); + var peg$e41 = peg$otherExpectation("whitespace"); + var peg$e42 = 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(); }; @@ -936,19 +948,28 @@ function peg$parse(input, options) { function peg$parsetaxRate() { var s0, s1; - s0 = peg$currPos; - s1 = input.substr(peg$currPos, 8); - if (s1.toLowerCase() === peg$c12) { - peg$currPos += 8; + s0 = input.substr(peg$currPos, 7); + if (s0.toLowerCase() === peg$c12) { + peg$currPos += 7; } else { - s1 = peg$FAILED; + s0 = peg$FAILED; if (peg$silentFails === 0) { peg$fail(peg$e13); } } - if (s1 !== peg$FAILED) { - peg$savedPos = s0; - s1 = peg$f16(); + 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; } - s0 = s1; return s0; } @@ -956,19 +977,28 @@ function peg$parse(input, options) { function peg$parsecardID() { var s0, s1; - s0 = peg$currPos; - s1 = input.substr(peg$currPos, 4); - if (s1.toLowerCase() === peg$c13) { - peg$currPos += 4; + if (input.substr(peg$currPos, 6) === peg$c14) { + s0 = peg$c14; + peg$currPos += 6; } else { - s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e14); } + s0 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e15); } } - if (s1 !== peg$FAILED) { - peg$savedPos = s0; - s1 = peg$f17(); + 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; } - s0 = s1; return s0; } @@ -978,11 +1008,11 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 4); - if (s1.toLowerCase() === peg$c14) { + if (s1.toLowerCase() === peg$c16) { peg$currPos += 4; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e15); } + if (peg$silentFails === 0) { peg$fail(peg$e17); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; @@ -996,19 +1026,28 @@ function peg$parse(input, options) { function peg$parseexpenseType() { var s0, s1; - s0 = peg$currPos; - s1 = input.substr(peg$currPos, 12); - if (s1.toLowerCase() === peg$c15) { - peg$currPos += 12; + if (input.substr(peg$currPos, 11) === peg$c17) { + s0 = peg$c17; + peg$currPos += 11; } else { - s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e16); } + s0 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e18); } } - if (s1 !== peg$FAILED) { - peg$savedPos = s0; - s1 = peg$f19(); + 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; } - s0 = s1; return s0; } @@ -1018,11 +1057,11 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 4); - if (s1.toLowerCase() === peg$c16) { + if (s1.toLowerCase() === peg$c19) { peg$currPos += 4; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e17); } + if (peg$silentFails === 0) { peg$fail(peg$e20); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; @@ -1038,11 +1077,11 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 6); - if (s1.toLowerCase() === peg$c17) { + if (s1.toLowerCase() === peg$c20) { peg$currPos += 6; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e18); } + if (peg$silentFails === 0) { peg$fail(peg$e21); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; @@ -1056,19 +1095,28 @@ function peg$parse(input, options) { function peg$parsesortBy() { var s0, s1; - s0 = peg$currPos; - s1 = input.substr(peg$currPos, 7); - if (s1.toLowerCase() === peg$c18) { - peg$currPos += 7; + if (input.substr(peg$currPos, 6) === peg$c21) { + s0 = peg$c21; + peg$currPos += 6; } else { - s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e19); } + s0 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e22); } } - if (s1 !== peg$FAILED) { - peg$savedPos = s0; - s1 = peg$f22(); + 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; } - s0 = s1; return s0; } @@ -1076,19 +1124,28 @@ function peg$parse(input, options) { function peg$parsesortOrder() { var s0, s1; - s0 = peg$currPos; - s1 = input.substr(peg$currPos, 10); - if (s1.toLowerCase() === peg$c19) { - peg$currPos += 10; + if (input.substr(peg$currPos, 9) === peg$c23) { + s0 = peg$c23; + peg$currPos += 9; } else { - s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e20); } + s0 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e24); } } - if (s1 !== peg$FAILED) { - peg$savedPos = s0; - s1 = peg$f23(); + 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; } - s0 = s1; return s0; } @@ -1096,19 +1153,28 @@ function peg$parse(input, options) { function peg$parsepolicyID() { var s0, s1; - s0 = peg$currPos; - s1 = input.substr(peg$currPos, 9); - if (s1.toLowerCase() === peg$c20) { - peg$currPos += 9; + if (input.substr(peg$currPos, 8) === peg$c25) { + s0 = peg$c25; + peg$currPos += 8; } else { - s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e21); } + s0 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e26); } } - if (s1 !== peg$FAILED) { - peg$savedPos = s0; - s1 = peg$f24(); + 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; } - s0 = s1; return s0; } @@ -1123,7 +1189,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e23); } + if (peg$silentFails === 0) { peg$fail(peg$e29); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; @@ -1132,12 +1198,12 @@ function peg$parse(input, options) { s0 = s1; if (s0 === peg$FAILED) { s0 = peg$currPos; - if (input.substr(peg$currPos, 2) === peg$c21) { - s1 = peg$c21; + if (input.substr(peg$currPos, 2) === peg$c27) { + s1 = peg$c27; peg$currPos += 2; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e24); } + if (peg$silentFails === 0) { peg$fail(peg$e30); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; @@ -1146,12 +1212,12 @@ function peg$parse(input, options) { s0 = s1; if (s0 === peg$FAILED) { s0 = peg$currPos; - if (input.substr(peg$currPos, 2) === peg$c22) { - s1 = peg$c22; + if (input.substr(peg$currPos, 2) === peg$c28) { + s1 = peg$c28; peg$currPos += 2; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e25); } + if (peg$silentFails === 0) { peg$fail(peg$e31); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; @@ -1161,11 +1227,11 @@ function peg$parse(input, options) { if (s0 === peg$FAILED) { s0 = peg$currPos; if (input.charCodeAt(peg$currPos) === 62) { - s1 = peg$c23; + s1 = peg$c29; peg$currPos++; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e26); } + if (peg$silentFails === 0) { peg$fail(peg$e32); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; @@ -1174,12 +1240,12 @@ function peg$parse(input, options) { s0 = s1; if (s0 === peg$FAILED) { s0 = peg$currPos; - if (input.substr(peg$currPos, 2) === peg$c24) { - s1 = peg$c24; + if (input.substr(peg$currPos, 2) === peg$c30) { + s1 = peg$c30; peg$currPos += 2; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e27); } + if (peg$silentFails === 0) { peg$fail(peg$e33); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; @@ -1189,11 +1255,11 @@ function peg$parse(input, options) { if (s0 === peg$FAILED) { s0 = peg$currPos; if (input.charCodeAt(peg$currPos) === 60) { - s1 = peg$c25; + s1 = peg$c31; peg$currPos++; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e28); } + if (peg$silentFails === 0) { peg$fail(peg$e34); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; @@ -1208,7 +1274,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$e28); } } return s0; @@ -1225,7 +1291,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e30); } + if (peg$silentFails === 0) { peg$fail(peg$e36); } } while (s2 !== peg$FAILED) { s1.push(s2); @@ -1234,15 +1300,15 @@ function peg$parse(input, options) { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e30); } + if (peg$silentFails === 0) { peg$fail(peg$e36); } } } if (input.charCodeAt(peg$currPos) === 34) { - s2 = peg$c26; + s2 = peg$c32; peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e31); } + if (peg$silentFails === 0) { peg$fail(peg$e37); } } if (s2 !== peg$FAILED) { s3 = []; @@ -1251,7 +1317,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s4 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e32); } + if (peg$silentFails === 0) { peg$fail(peg$e38); } } while (s4 !== peg$FAILED) { s3.push(s4); @@ -1260,15 +1326,15 @@ function peg$parse(input, options) { peg$currPos++; } else { s4 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e32); } + if (peg$silentFails === 0) { peg$fail(peg$e38); } } } if (input.charCodeAt(peg$currPos) === 34) { - s4 = peg$c26; + s4 = peg$c32; peg$currPos++; } else { s4 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e31); } + if (peg$silentFails === 0) { peg$fail(peg$e37); } } if (s4 !== peg$FAILED) { s5 = []; @@ -1277,7 +1343,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s6 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e33); } + if (peg$silentFails === 0) { peg$fail(peg$e39); } } while (s6 !== peg$FAILED) { s5.push(s6); @@ -1286,7 +1352,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s6 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e33); } + if (peg$silentFails === 0) { peg$fail(peg$e39); } } } peg$savedPos = s0; @@ -1302,7 +1368,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; @@ -1319,7 +1385,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e33); } + if (peg$silentFails === 0) { peg$fail(peg$e39); } } if (s2 !== peg$FAILED) { while (s2 !== peg$FAILED) { @@ -1329,7 +1395,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e33); } + if (peg$silentFails === 0) { peg$fail(peg$e39); } } } } else { @@ -1343,7 +1409,7 @@ function peg$parse(input, options) { peg$silentFails--; if (s0 === peg$FAILED) { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e34); } + if (peg$silentFails === 0) { peg$fail(peg$e40); } } return s0; @@ -1371,7 +1437,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e36); } + if (peg$silentFails === 0) { peg$fail(peg$e42); } } while (s1 !== peg$FAILED) { s0.push(s1); @@ -1380,12 +1446,12 @@ function peg$parse(input, options) { peg$currPos++; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e36); } + if (peg$silentFails === 0) { peg$fail(peg$e42); } } } peg$silentFails--; s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e35); } + if (peg$silentFails === 0) { peg$fail(peg$e41); } return s0; } diff --git a/src/libs/SearchParser/baseRules.peggy b/src/libs/SearchParser/baseRules.peggy index e2ca9d4ffb2b..388d5a543320 100644 --- a/src/libs/SearchParser/baseRules.peggy +++ b/src/libs/SearchParser/baseRules.peggy @@ -19,15 +19,15 @@ currency = "currency"i {return "currency"} tag = "tag"i {return "tag"} category = "category"i {return "category"} to = "to"i {return "to"} -taxRate = "tax-rate"i {return "taxRate"} -cardID = "card"i {return "cardID"} +taxRate = "taxRate"i/ "tax-rate"i {return "taxRate"} +cardID = "cardID"/"card"i {return "cardID"} from = "from"i {return "from"} -expenseType = "expense-type"i {return "expenseType"} +expenseType = "expenseType" /"expense-type"i {return "expenseType"} type = "type"i {return "type"} status = "status"i {return "status"} -sortBy = "sort-by"i {return "sortBy"} -sortOrder = "sort-order"i {return "sortOrder"} -policyID = "workspace"i {return "policyID"} +sortBy = "sortBy"/"sort-by"i {return "sortBy"} +sortOrder = "sortOrder"/"sort-order"i {return "sortOrder"} +policyID = "policyID"/"workspace"i {return "policyID"} operator "operator" = (":" / "=") { return "eq"; } diff --git a/src/libs/SearchParser/searchParser.js b/src/libs/SearchParser/searchParser.js index 08910c7ce108..0912ce10340e 100644 --- a/src/libs/SearchParser/searchParser.js +++ b/src/libs/SearchParser/searchParser.js @@ -192,21 +192,27 @@ function peg$parse(input, options) { var peg$c9 = "tag"; var peg$c10 = "category"; var peg$c11 = "to"; - var peg$c12 = "tax-rate"; - var peg$c13 = "card"; - var peg$c14 = "from"; - var peg$c15 = "expense-type"; - var peg$c16 = "type"; - var peg$c17 = "status"; - var peg$c18 = "sort-by"; - var peg$c19 = "sort-order"; - var peg$c20 = "workspace"; - var peg$c21 = "!="; - var peg$c22 = ">="; - var peg$c23 = ">"; - var peg$c24 = "<="; - var peg$c25 = "<"; - var peg$c26 = "\""; + 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 = "!="; + var peg$c28 = ">="; + var peg$c29 = ">"; + var peg$c30 = "<="; + var peg$c31 = "<"; + var peg$c32 = "\""; var peg$r0 = /^[^ \t\r\n]/; var peg$r1 = /^[:=]/; @@ -230,30 +236,36 @@ function peg$parse(input, options) { 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("tax-rate", true); - var peg$e16 = peg$literalExpectation("card", true); - var peg$e17 = peg$literalExpectation("from", true); - var peg$e18 = peg$literalExpectation("expense-type", true); - var peg$e19 = peg$literalExpectation("type", true); - var peg$e20 = peg$literalExpectation("status", true); - var peg$e21 = peg$literalExpectation("sort-by", true); - var peg$e22 = peg$literalExpectation("sort-order", true); - var peg$e23 = peg$literalExpectation("workspace", true); - var peg$e24 = peg$otherExpectation("operator"); - var peg$e25 = peg$classExpectation([":", "="], false, false); - var peg$e26 = peg$literalExpectation("!=", false); - var peg$e27 = peg$literalExpectation(">=", false); - var peg$e28 = peg$literalExpectation(">", false); - var peg$e29 = peg$literalExpectation("<=", false); - var peg$e30 = peg$literalExpectation("<", false); - var peg$e31 = peg$otherExpectation("quote"); - var peg$e32 = peg$classExpectation([" ", ",", "\"", "\t", "\n", "\r"], true, false); - var peg$e33 = peg$literalExpectation("\"", false); - var peg$e34 = peg$classExpectation(["\"", "\r", "\n"], true, false); - var peg$e35 = peg$classExpectation([" ", ",", "\t", "\n", "\r"], true, false); - var peg$e36 = peg$otherExpectation("word"); - var peg$e37 = peg$otherExpectation("whitespace"); - var peg$e38 = peg$classExpectation([" ", "\t", "\r", "\n"], false, false); + 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("sort-order", true); + var peg$e28 = peg$literalExpectation("policyID", false); + var peg$e29 = peg$literalExpectation("workspace", true); + var peg$e30 = peg$otherExpectation("operator"); + var peg$e31 = peg$classExpectation([":", "="], false, 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$literalExpectation("<", false); + var peg$e37 = peg$otherExpectation("quote"); + var peg$e38 = peg$classExpectation([" ", ",", "\"", "\t", "\n", "\r"], true, false); + var peg$e39 = peg$literalExpectation("\"", false); + var peg$e40 = peg$classExpectation(["\"", "\r", "\n"], true, false); + var peg$e41 = peg$classExpectation([" ", ",", "\t", "\n", "\r"], true, false); + var peg$e42 = peg$otherExpectation("word"); + var peg$e43 = peg$otherExpectation("whitespace"); + var peg$e44 = peg$classExpectation([" ", "\t", "\r", "\n"], false, false); var peg$f0 = function(filters) { return applyDefaults(filters); }; var peg$f1 = function(head, tail) { @@ -1119,19 +1131,28 @@ function peg$parse(input, options) { function peg$parsetaxRate() { var s0, s1; - s0 = peg$currPos; - s1 = input.substr(peg$currPos, 8); - if (s1.toLowerCase() === peg$c12) { - peg$currPos += 8; + s0 = input.substr(peg$currPos, 7); + if (s0.toLowerCase() === peg$c12) { + peg$currPos += 7; } else { - s1 = peg$FAILED; + s0 = peg$FAILED; if (peg$silentFails === 0) { peg$fail(peg$e15); } } - if (s1 !== peg$FAILED) { - peg$savedPos = s0; - s1 = peg$f17(); + 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; } - s0 = s1; return s0; } @@ -1139,19 +1160,28 @@ function peg$parse(input, options) { function peg$parsecardID() { var s0, s1; - s0 = peg$currPos; - s1 = input.substr(peg$currPos, 4); - if (s1.toLowerCase() === peg$c13) { - peg$currPos += 4; + if (input.substr(peg$currPos, 6) === peg$c14) { + s0 = peg$c14; + peg$currPos += 6; } else { - s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e16); } + s0 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e17); } } - if (s1 !== peg$FAILED) { - peg$savedPos = s0; - s1 = peg$f18(); + 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; } - s0 = s1; return s0; } @@ -1161,11 +1191,11 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 4); - if (s1.toLowerCase() === peg$c14) { + if (s1.toLowerCase() === peg$c16) { peg$currPos += 4; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e17); } + if (peg$silentFails === 0) { peg$fail(peg$e19); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; @@ -1179,19 +1209,28 @@ function peg$parse(input, options) { function peg$parseexpenseType() { var s0, s1; - s0 = peg$currPos; - s1 = input.substr(peg$currPos, 12); - if (s1.toLowerCase() === peg$c15) { - peg$currPos += 12; + if (input.substr(peg$currPos, 11) === peg$c17) { + s0 = peg$c17; + peg$currPos += 11; } else { - s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e18); } + s0 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e20); } } - if (s1 !== peg$FAILED) { - peg$savedPos = s0; - s1 = peg$f20(); + 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; } - s0 = s1; return s0; } @@ -1201,11 +1240,11 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 4); - if (s1.toLowerCase() === peg$c16) { + if (s1.toLowerCase() === peg$c19) { peg$currPos += 4; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e19); } + if (peg$silentFails === 0) { peg$fail(peg$e22); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; @@ -1221,11 +1260,11 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 6); - if (s1.toLowerCase() === peg$c17) { + if (s1.toLowerCase() === peg$c20) { peg$currPos += 6; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e20); } + if (peg$silentFails === 0) { peg$fail(peg$e23); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; @@ -1239,19 +1278,28 @@ function peg$parse(input, options) { function peg$parsesortBy() { var s0, s1; - s0 = peg$currPos; - s1 = input.substr(peg$currPos, 7); - if (s1.toLowerCase() === peg$c18) { - peg$currPos += 7; + if (input.substr(peg$currPos, 6) === peg$c21) { + s0 = peg$c21; + peg$currPos += 6; } else { - s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e21); } + s0 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e24); } } - if (s1 !== peg$FAILED) { - peg$savedPos = s0; - s1 = peg$f23(); + 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; } - s0 = s1; return s0; } @@ -1259,19 +1307,28 @@ function peg$parse(input, options) { function peg$parsesortOrder() { var s0, s1; - s0 = peg$currPos; - s1 = input.substr(peg$currPos, 10); - if (s1.toLowerCase() === peg$c19) { - peg$currPos += 10; + if (input.substr(peg$currPos, 9) === peg$c23) { + s0 = peg$c23; + peg$currPos += 9; } else { - s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e22); } + s0 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e26); } } - if (s1 !== peg$FAILED) { - peg$savedPos = s0; - s1 = peg$f24(); + 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; } - s0 = s1; return s0; } @@ -1279,19 +1336,28 @@ function peg$parse(input, options) { function peg$parsepolicyID() { var s0, s1; - s0 = peg$currPos; - s1 = input.substr(peg$currPos, 9); - if (s1.toLowerCase() === peg$c20) { - peg$currPos += 9; + if (input.substr(peg$currPos, 8) === peg$c25) { + s0 = peg$c25; + peg$currPos += 8; } else { - s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e23); } + s0 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e28); } } - if (s1 !== peg$FAILED) { - peg$savedPos = s0; - s1 = peg$f25(); + 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; } - s0 = s1; return s0; } @@ -1306,7 +1372,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e25); } + if (peg$silentFails === 0) { peg$fail(peg$e31); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; @@ -1315,12 +1381,12 @@ function peg$parse(input, options) { s0 = s1; if (s0 === peg$FAILED) { s0 = peg$currPos; - if (input.substr(peg$currPos, 2) === peg$c21) { - s1 = peg$c21; + if (input.substr(peg$currPos, 2) === peg$c27) { + s1 = peg$c27; peg$currPos += 2; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e26); } + if (peg$silentFails === 0) { peg$fail(peg$e32); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; @@ -1329,12 +1395,12 @@ function peg$parse(input, options) { s0 = s1; if (s0 === peg$FAILED) { s0 = peg$currPos; - if (input.substr(peg$currPos, 2) === peg$c22) { - s1 = peg$c22; + if (input.substr(peg$currPos, 2) === peg$c28) { + s1 = peg$c28; peg$currPos += 2; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e27); } + if (peg$silentFails === 0) { peg$fail(peg$e33); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; @@ -1344,11 +1410,11 @@ function peg$parse(input, options) { if (s0 === peg$FAILED) { s0 = peg$currPos; if (input.charCodeAt(peg$currPos) === 62) { - s1 = peg$c23; + s1 = peg$c29; peg$currPos++; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e28); } + if (peg$silentFails === 0) { peg$fail(peg$e34); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; @@ -1357,12 +1423,12 @@ function peg$parse(input, options) { s0 = s1; if (s0 === peg$FAILED) { s0 = peg$currPos; - if (input.substr(peg$currPos, 2) === peg$c24) { - s1 = peg$c24; + if (input.substr(peg$currPos, 2) === peg$c30) { + s1 = peg$c30; peg$currPos += 2; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e29); } + if (peg$silentFails === 0) { peg$fail(peg$e35); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; @@ -1372,11 +1438,11 @@ function peg$parse(input, options) { if (s0 === peg$FAILED) { s0 = peg$currPos; if (input.charCodeAt(peg$currPos) === 60) { - s1 = peg$c25; + s1 = peg$c31; 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; @@ -1391,7 +1457,7 @@ function peg$parse(input, options) { peg$silentFails--; if (s0 === peg$FAILED) { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e24); } + if (peg$silentFails === 0) { peg$fail(peg$e30); } } return s0; @@ -1408,7 +1474,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e32); } + if (peg$silentFails === 0) { peg$fail(peg$e38); } } while (s2 !== peg$FAILED) { s1.push(s2); @@ -1417,15 +1483,15 @@ function peg$parse(input, options) { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e32); } + if (peg$silentFails === 0) { peg$fail(peg$e38); } } } if (input.charCodeAt(peg$currPos) === 34) { - s2 = peg$c26; + s2 = peg$c32; peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e33); } + if (peg$silentFails === 0) { peg$fail(peg$e39); } } if (s2 !== peg$FAILED) { s3 = []; @@ -1434,7 +1500,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s4 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e34); } + if (peg$silentFails === 0) { peg$fail(peg$e40); } } while (s4 !== peg$FAILED) { s3.push(s4); @@ -1443,15 +1509,15 @@ function peg$parse(input, options) { peg$currPos++; } else { s4 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e34); } + if (peg$silentFails === 0) { peg$fail(peg$e40); } } } if (input.charCodeAt(peg$currPos) === 34) { - s4 = peg$c26; + s4 = peg$c32; peg$currPos++; } else { s4 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e33); } + if (peg$silentFails === 0) { peg$fail(peg$e39); } } if (s4 !== peg$FAILED) { s5 = []; @@ -1460,7 +1526,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s6 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e35); } + if (peg$silentFails === 0) { peg$fail(peg$e41); } } while (s6 !== peg$FAILED) { s5.push(s6); @@ -1469,7 +1535,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s6 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e35); } + if (peg$silentFails === 0) { peg$fail(peg$e41); } } } peg$savedPos = s0; @@ -1485,7 +1551,7 @@ function peg$parse(input, options) { peg$silentFails--; if (s0 === peg$FAILED) { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e31); } + if (peg$silentFails === 0) { peg$fail(peg$e37); } } return s0; @@ -1502,7 +1568,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e35); } + if (peg$silentFails === 0) { peg$fail(peg$e41); } } if (s2 !== peg$FAILED) { while (s2 !== peg$FAILED) { @@ -1512,7 +1578,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e35); } + if (peg$silentFails === 0) { peg$fail(peg$e41); } } } } else { @@ -1526,7 +1592,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; @@ -1554,7 +1620,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e38); } + if (peg$silentFails === 0) { peg$fail(peg$e44); } } while (s1 !== peg$FAILED) { s0.push(s1); @@ -1563,12 +1629,12 @@ function peg$parse(input, options) { peg$currPos++; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e38); } + if (peg$silentFails === 0) { peg$fail(peg$e44); } } } peg$silentFails--; s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e37); } + if (peg$silentFails === 0) { peg$fail(peg$e43); } return s0; } From bbbc665ece2450c1f2e5ce3c03f4f1d23586875e Mon Sep 17 00:00:00 2001 From: 289Adam289 Date: Fri, 6 Dec 2024 10:45:14 +0100 Subject: [PATCH 04/12] translate old keys --- src/CONST.ts | 22 ++++++++++++++++ .../Search/SearchRouter/SearchRouter.tsx | 8 +++--- .../Search/SearchRouter/SearchRouterList.tsx | 26 +++++++++---------- .../SearchRouter/getQueryWithSubstitutions.ts | 4 ++- src/libs/SearchQueryUtils.ts | 2 +- 5 files changed, 43 insertions(+), 19 deletions(-) diff --git a/src/CONST.ts b/src/CONST.ts index ea9955600d9a..eaba0145348b 100755 --- a/src/CONST.ts +++ b/src/CONST.ts @@ -6076,6 +6076,28 @@ const CONST = { AUTOCOMPLETE_SUGGESTION: 'autocompleteSuggestion', SEARCH: 'searchItem', }, + SEARCH_UI_KEYS: { + 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', + }, }, REFERRER: { diff --git a/src/components/Search/SearchRouter/SearchRouter.tsx b/src/components/Search/SearchRouter/SearchRouter.tsx index 14e84aaa80e5..39acc0a45199 100644 --- a/src/components/Search/SearchRouter/SearchRouter.tsx +++ b/src/components/Search/SearchRouter/SearchRouter.tsx @@ -50,20 +50,20 @@ function getContextualSearchAutocompleteKey(item: SearchQueryItem) { } function getContextualSearchQuery(item: SearchQueryItem) { - const baseQuery = `${CONST.SEARCH.SYNTAX_ROOT_KEYS.TYPE}:${item.roomType}`; + const baseQuery = `${CONST.SEARCH.SEARCH_UI_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_UI_KEYS.policyID}:${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_UI_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_UI_KEYS.in}:${SearchQueryUtils.sanitizeSearchValue(item.searchQuery ?? '')}`; break; } return baseQuery + additionalQuery; diff --git a/src/components/Search/SearchRouter/SearchRouterList.tsx b/src/components/Search/SearchRouter/SearchRouterList.tsx index 63dd1e6af229..2d2215e14b0a 100644 --- a/src/components/Search/SearchRouter/SearchRouterList.tsx +++ b/src/components/Search/SearchRouter/SearchRouterList.tsx @@ -2,9 +2,9 @@ import {Str} from 'expensify-common'; import React, {forwardRef, useMemo, useState} from 'react'; import type {ForwardedRef} from 'react'; import {useOnyx} from 'react-native-onyx'; +import type {ValueOf} from 'type-fest'; import * as Expensicons from '@components/Icon/Expensicons'; import {useOptionsList} from '@components/OptionListContextProvider'; -import type {SearchFilterKey} 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'; @@ -36,7 +36,7 @@ import type PersonalDetails from '@src/types/onyx/PersonalDetails'; import {getSubstitutionMapKey} from './getQueryWithSubstitutions'; type AutocompleteItemData = { - filterKey: SearchFilterKey; + filterKey: ValueOf; text: string; autocompleteID?: string; }; @@ -217,7 +217,7 @@ function SearchRouterList( .slice(0, 10); return filteredTags.map((tagName) => ({ - filterKey: CONST.SEARCH.SYNTAX_FILTER_KEYS.TAG, + filterKey: CONST.SEARCH.SEARCH_UI_KEYS.tag, text: tagName, })); } @@ -229,7 +229,7 @@ function SearchRouterList( .slice(0, 10); return filteredCategories.map((categoryName) => ({ - filterKey: CONST.SEARCH.SYNTAX_FILTER_KEYS.CATEGORY, + filterKey: CONST.SEARCH.SEARCH_UI_KEYS.category, text: categoryName, })); } @@ -241,7 +241,7 @@ function SearchRouterList( .slice(0, 10); return filteredCurrencies.map((currencyName) => ({ - filterKey: CONST.SEARCH.SYNTAX_FILTER_KEYS.CURRENCY, + filterKey: CONST.SEARCH.SEARCH_UI_KEYS.currency, text: currencyName, })); } @@ -252,7 +252,7 @@ function SearchRouterList( .slice(0, 10); return filteredTaxRates.map((tax) => ({ - filterKey: CONST.SEARCH.SYNTAX_FILTER_KEYS.TAX_RATE, + filterKey: CONST.SEARCH.SEARCH_UI_KEYS.taxRate, text: tax.taxRateName, autocompleteID: tax.taxRateIds.join(','), })); @@ -263,7 +263,7 @@ function SearchRouterList( .slice(0, 10); return filteredParticipants.map((participant) => ({ - filterKey: CONST.SEARCH.SYNTAX_FILTER_KEYS.FROM, + filterKey: CONST.SEARCH.SEARCH_UI_KEYS.from, text: participant.name, autocompleteID: participant.accountID, })); @@ -274,7 +274,7 @@ function SearchRouterList( .slice(0, 10); return filteredParticipants.map((participant) => ({ - filterKey: CONST.SEARCH.SYNTAX_FILTER_KEYS.TO, + filterKey: CONST.SEARCH.SEARCH_UI_KEYS.to, text: participant.name, autocompleteID: participant.accountID, })); @@ -285,7 +285,7 @@ function SearchRouterList( .slice(0, 10); return filteredChats.map((chat) => ({ - filterKey: CONST.SEARCH.SYNTAX_FILTER_KEYS.IN, + filterKey: CONST.SEARCH.SEARCH_UI_KEYS.in, text: chat.text ?? '', autocompleteID: chat.reportID, })); @@ -295,7 +295,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_UI_KEYS.type, text: type})); } case CONST.SEARCH.SYNTAX_ROOT_KEYS.STATUS: { const filteredStatuses = statusAutocompleteList @@ -303,7 +303,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_UI_KEYS.status, text: status})); } case CONST.SEARCH.SYNTAX_FILTER_KEYS.EXPENSE_TYPE: { const filteredExpenseTypes = expenseTypes @@ -311,7 +311,7 @@ function SearchRouterList( .sort(); return filteredExpenseTypes.map((expenseType) => ({ - filterKey: CONST.SEARCH.SYNTAX_FILTER_KEYS.EXPENSE_TYPE, + filterKey: CONST.SEARCH.SEARCH_UI_KEYS.expenseType, text: expenseType, })); } @@ -325,7 +325,7 @@ function SearchRouterList( .slice(0, 10); return filteredCards.map((card) => ({ - filterKey: CONST.SEARCH.SYNTAX_FILTER_KEYS.CARD_ID, + filterKey: CONST.SEARCH.SEARCH_UI_KEYS.cardID, text: CardUtils.getCardDescription(card.cardID), autocompleteID: card.cardID.toString(), })); diff --git a/src/components/Search/SearchRouter/getQueryWithSubstitutions.ts b/src/components/Search/SearchRouter/getQueryWithSubstitutions.ts index 117745fee480..12d8fe2bb68a 100644 --- a/src/components/Search/SearchRouter/getQueryWithSubstitutions.ts +++ b/src/components/Search/SearchRouter/getQueryWithSubstitutions.ts @@ -1,9 +1,11 @@ +import type {ValueOf} from 'type-fest'; import type {SearchAutocompleteQueryRange, SearchFilterKey} from '@components/Search/types'; import * as parser from '@libs/SearchParser/autocompleteParser'; +import type CONST from '@src/CONST'; type SubstitutionMap = Record; -const getSubstitutionMapKey = (filterKey: SearchFilterKey, value: string) => `${filterKey}:${value}`; +const getSubstitutionMapKey = (filterKey: SearchFilterKey | ValueOf, value: string) => `${filterKey}:${value}`; /** * Given a plaintext query and a SubstitutionMap object, this function will return a transformed query where: diff --git a/src/libs/SearchQueryUtils.ts b/src/libs/SearchQueryUtils.ts index f975c575400d..c28084539fee 100644 --- a/src/libs/SearchQueryUtils.ts +++ b/src/libs/SearchQueryUtils.ts @@ -556,7 +556,7 @@ function buildUserReadableQueryString( value: getFilterDisplayValue(key, filter.value.toString(), PersonalDetails, reports), })); } - title += buildFilterValuesString(key, displayQueryFilters); + title += buildFilterValuesString(CONST.SEARCH.SEARCH_UI_KEYS[key], displayQueryFilters); } return title; From 5b4dd5238d94fa8d1ddf8b832a30645128ad2111 Mon Sep 17 00:00:00 2001 From: 289Adam289 Date: Fri, 6 Dec 2024 11:05:20 +0100 Subject: [PATCH 05/12] fix Search in bug with policyID --- src/components/Search/SearchRouter/SearchRouter.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/components/Search/SearchRouter/SearchRouter.tsx b/src/components/Search/SearchRouter/SearchRouter.tsx index 39acc0a45199..1da812717f46 100644 --- a/src/components/Search/SearchRouter/SearchRouter.tsx +++ b/src/components/Search/SearchRouter/SearchRouter.tsx @@ -255,7 +255,9 @@ function SearchRouter({onRouterClose, shouldHideInputCaret}: SearchRouterProps) if (!queryJSON) { return; } - queryJSON.policyID = activeWorkspaceID; + if (!queryJSON.policyID) { + queryJSON.policyID = activeWorkspaceID; + } onRouterClose(); const standardizedQuery = SearchQueryUtils.traverseAndUpdatedQuery(queryJSON, SearchQueryUtils.getUpdatedAmountValue); From 357c918a4781d4ee67ed018d019654b304587218 Mon Sep 17 00:00:00 2001 From: 289Adam289 Date: Mon, 9 Dec 2024 12:22:53 +0100 Subject: [PATCH 06/12] review suggestions and bug fix --- src/CONST.ts | 42 +++++++++--------- .../Search/SearchRouter/SearchRouter.tsx | 8 ++-- .../Search/SearchRouter/SearchRouterList.tsx | 26 +++++------ .../SearchRouter/getQueryWithSubstitutions.ts | 10 ++--- src/components/Search/types.ts | 3 ++ src/libs/SearchQueryUtils.ts | 43 ++++++++++++++++++- 6 files changed, 87 insertions(+), 45 deletions(-) diff --git a/src/CONST.ts b/src/CONST.ts index 85ada1f30758..4062769072a4 100755 --- a/src/CONST.ts +++ b/src/CONST.ts @@ -6079,27 +6079,27 @@ const CONST = { AUTOCOMPLETE_SUGGESTION: 'autocompleteSuggestion', SEARCH: 'searchItem', }, - SEARCH_UI_KEYS: { - 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', + 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', }, }, diff --git a/src/components/Search/SearchRouter/SearchRouter.tsx b/src/components/Search/SearchRouter/SearchRouter.tsx index c24d9e29a3fc..7d7c81539c4d 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.SEARCH_UI_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.SEARCH_UI_KEYS.policyID}:${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.SEARCH_UI_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.SEARCH_UI_KEYS.in}:${SearchQueryUtils.sanitizeSearchValue(item.searchQuery ?? '')}`; + additionalQuery = ` ${CONST.SEARCH.SEARCH_USER_FRIENDLY_KEYS.IN}:${SearchQueryUtils.sanitizeSearchValue(item.searchQuery ?? '')}`; break; } return baseQuery + additionalQuery; diff --git a/src/components/Search/SearchRouter/SearchRouterList.tsx b/src/components/Search/SearchRouter/SearchRouterList.tsx index 99aceb523802..fa3f25be8704 100644 --- a/src/components/Search/SearchRouter/SearchRouterList.tsx +++ b/src/components/Search/SearchRouter/SearchRouterList.tsx @@ -2,10 +2,10 @@ import {Str} from 'expensify-common'; import React, {forwardRef, useCallback, useEffect, useMemo, useState} from 'react'; import type {ForwardedRef} from 'react'; import {useOnyx} from 'react-native-onyx'; -import type {ValueOf} from 'type-fest'; import * as Expensicons from '@components/Icon/Expensicons'; import {usePersonalDetails} from '@components/OnyxProvider'; import {useOptionsList} from '@components/OptionListContextProvider'; +import type {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,7 +40,7 @@ import type PersonalDetails from '@src/types/onyx/PersonalDetails'; import {getSubstitutionMapKey} from './getQueryWithSubstitutions'; type AutocompleteItemData = { - filterKey: ValueOf; + filterKey: UserFriendlyKey; text: string; autocompleteID?: string; }; @@ -223,7 +223,7 @@ function SearchRouterList( .slice(0, 10); return filteredTags.map((tagName) => ({ - filterKey: CONST.SEARCH.SEARCH_UI_KEYS.tag, + filterKey: CONST.SEARCH.SEARCH_USER_FRIENDLY_KEYS.TAG, text: tagName, })); } @@ -235,7 +235,7 @@ function SearchRouterList( .slice(0, 10); return filteredCategories.map((categoryName) => ({ - filterKey: CONST.SEARCH.SEARCH_UI_KEYS.category, + filterKey: CONST.SEARCH.SEARCH_USER_FRIENDLY_KEYS.CATEGORY, text: categoryName, })); } @@ -247,7 +247,7 @@ function SearchRouterList( .slice(0, 10); return filteredCurrencies.map((currencyName) => ({ - filterKey: CONST.SEARCH.SEARCH_UI_KEYS.currency, + filterKey: CONST.SEARCH.SEARCH_USER_FRIENDLY_KEYS.CURRENCY, text: currencyName, })); } @@ -258,7 +258,7 @@ function SearchRouterList( .slice(0, 10); return filteredTaxRates.map((tax) => ({ - filterKey: CONST.SEARCH.SEARCH_UI_KEYS.taxRate, + filterKey: CONST.SEARCH.SEARCH_USER_FRIENDLY_KEYS.TAX_RATE, text: tax.taxRateName, autocompleteID: tax.taxRateIds.join(','), })); @@ -269,7 +269,7 @@ function SearchRouterList( .slice(0, 10); return filteredParticipants.map((participant) => ({ - filterKey: CONST.SEARCH.SEARCH_UI_KEYS.from, + filterKey: CONST.SEARCH.SEARCH_USER_FRIENDLY_KEYS.FROM, text: participant.name, autocompleteID: participant.accountID, })); @@ -280,7 +280,7 @@ function SearchRouterList( .slice(0, 10); return filteredParticipants.map((participant) => ({ - filterKey: CONST.SEARCH.SEARCH_UI_KEYS.to, + filterKey: CONST.SEARCH.SEARCH_USER_FRIENDLY_KEYS.TO, text: participant.name, autocompleteID: participant.accountID, })); @@ -291,7 +291,7 @@ function SearchRouterList( .slice(0, 10); return filteredChats.map((chat) => ({ - filterKey: CONST.SEARCH.SEARCH_UI_KEYS.in, + filterKey: CONST.SEARCH.SEARCH_USER_FRIENDLY_KEYS.IN, text: chat.text ?? '', autocompleteID: chat.reportID, })); @@ -301,7 +301,7 @@ function SearchRouterList( .filter((type) => type.toLowerCase().includes(autocompleteValue.toLowerCase()) && !alreadyAutocompletedKeys.includes(type.toLowerCase())) .sort(); - return filteredTypes.map((type) => ({filterKey: CONST.SEARCH.SEARCH_UI_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 +309,7 @@ function SearchRouterList( .sort() .slice(0, 10); - return filteredStatuses.map((status) => ({filterKey: CONST.SEARCH.SEARCH_UI_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 +317,7 @@ function SearchRouterList( .sort(); return filteredExpenseTypes.map((expenseType) => ({ - filterKey: CONST.SEARCH.SEARCH_UI_KEYS.expenseType, + filterKey: CONST.SEARCH.SEARCH_USER_FRIENDLY_KEYS.EXPENSE_TYPE, text: expenseType, })); } @@ -331,7 +331,7 @@ function SearchRouterList( .slice(0, 10); return filteredCards.map((card) => ({ - filterKey: CONST.SEARCH.SEARCH_UI_KEYS.cardID, + filterKey: CONST.SEARCH.SEARCH_USER_FRIENDLY_KEYS.CARD_ID, text: CardUtils.getCardDescription(card.cardID), autocompleteID: card.cardID.toString(), })); diff --git a/src/components/Search/SearchRouter/getQueryWithSubstitutions.ts b/src/components/Search/SearchRouter/getQueryWithSubstitutions.ts index 12d8fe2bb68a..5a39159f52ff 100644 --- a/src/components/Search/SearchRouter/getQueryWithSubstitutions.ts +++ b/src/components/Search/SearchRouter/getQueryWithSubstitutions.ts @@ -1,11 +1,10 @@ -import type {ValueOf} from 'type-fest'; -import type {SearchAutocompleteQueryRange, SearchFilterKey} from '@components/Search/types'; +import type {SearchAutocompleteQueryRange, SearchFilterKey, UserFriendlyKey} from '@components/Search/types'; import * as parser from '@libs/SearchParser/autocompleteParser'; -import type CONST from '@src/CONST'; +import {getUserFriendlyKey} from '@libs/SearchQueryUtils'; type SubstitutionMap = Record; -const getSubstitutionMapKey = (filterKey: SearchFilterKey | ValueOf, value: string) => `${filterKey}:${value}`; +const getSubstitutionMapKey = (filterKey: SearchFilterKey | UserFriendlyKey, value: string) => `${filterKey}:${value}`; /** * Given a plaintext query and a SubstitutionMap object, this function will return a transformed query where: @@ -33,7 +32,8 @@ function getQueryWithSubstitutions(changedQuery: string, substitutions: Substitu for (const range of searchAutocompleteQueryRanges) { const itemKey = getSubstitutionMapKey(range.key, range.value); - const substitutionEntry = substitutions[itemKey]; + const alternativeItemKey = getSubstitutionMapKey(getUserFriendlyKey(range.key), range.value); + const substitutionEntry = substitutions[itemKey] ?? substitutions[alternativeItemKey]; if (substitutionEntry) { const substitutionStart = range.start + lengthDiff; diff --git a/src/components/Search/types.ts b/src/components/Search/types.ts index af72b7f6bcc1..29d892bf4db4 100644 --- a/src/components/Search/types.ts +++ b/src/components/Search/types.ts @@ -89,6 +89,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[]; @@ -139,6 +141,7 @@ export type { QueryFilter, QueryFilters, SearchFilterKey, + UserFriendlyKey, ExpenseSearchStatus, InvoiceSearchStatus, TripSearchStatus, diff --git a/src/libs/SearchQueryUtils.ts b/src/libs/SearchQueryUtils.ts index 8702d7f37bf1..b64f8b3da1ea 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, SearchQueryJSON, SearchQueryString, SearchStatus} from '@components/Search/types'; +import type {ASTNode, QueryFilter, QueryFilters, 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'; @@ -569,7 +569,7 @@ function buildUserReadableQueryString( value: getFilterDisplayValue(key, filter.value.toString(), PersonalDetails, reports), })); } - title += buildFilterValuesString(CONST.SEARCH.SEARCH_UI_KEYS[key], displayQueryFilters); + title += buildFilterValuesString(getUserFriendlyKey(key), displayQueryFilters); } return title; @@ -658,6 +658,44 @@ function getQueryWithUpdatedValues(query: string, policyID?: string) { return buildSearchQueryString(standardizedQuery); } +/** + * A mapping object that transforms 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', +}; + +/** + * Converts a filter key from camelCase to user friendly kebab-case. + * + * This function is designed to translate filter names used in the codebase (in camelCase) + * to a user-friendly format (kebab-case). + * @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, @@ -670,4 +708,5 @@ export { isCannedSearchQuery, sanitizeSearchValue, getQueryWithUpdatedValues, + getUserFriendlyKey, }; From 7dbb448a3e3e27a20ddda2920ac43907444bd1ee Mon Sep 17 00:00:00 2001 From: 289Adam289 Date: Mon, 9 Dec 2024 13:10:43 +0100 Subject: [PATCH 07/12] generate autocomplete parser --- src/libs/SearchParser/autocompleteParser.js | 257 ++++++++++++++------ 1 file changed, 186 insertions(+), 71 deletions(-) diff --git a/src/libs/SearchParser/autocompleteParser.js b/src/libs/SearchParser/autocompleteParser.js index 9efdf300865d..8482a18103aa 100644 --- a/src/libs/SearchParser/autocompleteParser.js +++ b/src/libs/SearchParser/autocompleteParser.js @@ -202,12 +202,17 @@ function peg$parse(input, options) { var peg$c24 = "sort-order"; var peg$c25 = "policyID"; var peg$c26 = "workspace"; - var peg$c27 = "!="; - var peg$c28 = ">="; - var peg$c29 = ">"; - var peg$c30 = "<="; - var peg$c31 = "<"; - var peg$c32 = "\""; + 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]/; @@ -243,21 +248,26 @@ function peg$parse(input, options) { 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$otherExpectation("operator"); - var peg$e29 = peg$classExpectation([":", "="], false, false); - var peg$e30 = peg$literalExpectation("!=", 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$otherExpectation("quote"); - var peg$e36 = peg$classExpectation([" ", ",", "\"", "\t", "\n", "\r"], true, false); - var peg$e37 = peg$literalExpectation("\"", false); - var peg$e38 = peg$classExpectation(["\"", "\r", "\n"], true, false); - var peg$e39 = peg$classExpectation([" ", ",", "\t", "\n", "\r"], true, false); - var peg$e40 = peg$otherExpectation("word"); - var peg$e41 = peg$otherExpectation("whitespace"); - var peg$e42 = peg$classExpectation([" ", "\t", "\r", "\n"], false, false); + 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(); }; @@ -327,17 +337,22 @@ function peg$parse(input, options) { var peg$f22 = function() {return "sortBy"}; var peg$f23 = function() {return "sortOrder"}; var peg$f24 = function() {return "policyID"}; - var peg$f25 = function() { return "eq"; }; - var peg$f26 = function() { return "neq"; }; - var peg$f27 = function() { return "gte"; }; - var peg$f28 = function() { return "gt"; }; - var peg$f29 = function() { return "lte"; }; - var peg$f30 = function() { return "lt"; }; - var peg$f31 = function(start, inner, end) { + 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$f32 = function(chars) { return chars.join("").trim(); }; - var peg$f33 = 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 }]; @@ -1179,6 +1194,106 @@ function peg$parse(input, options) { 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; @@ -1189,81 +1304,81 @@ function peg$parse(input, options) { peg$currPos++; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e29); } + if (peg$silentFails === 0) { peg$fail(peg$e34); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f25(); + s1 = peg$f30(); } 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$c32) { + s1 = peg$c32; peg$currPos += 2; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e30); } + if (peg$silentFails === 0) { peg$fail(peg$e35); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f26(); + s1 = peg$f31(); } s0 = s1; if (s0 === peg$FAILED) { s0 = peg$currPos; - if (input.substr(peg$currPos, 2) === peg$c28) { - s1 = peg$c28; + 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$e31); } + if (peg$silentFails === 0) { peg$fail(peg$e36); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f27(); + s1 = peg$f32(); } s0 = s1; if (s0 === peg$FAILED) { s0 = peg$currPos; if (input.charCodeAt(peg$currPos) === 62) { - s1 = peg$c29; + s1 = peg$c34; peg$currPos++; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e32); } + if (peg$silentFails === 0) { peg$fail(peg$e37); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f28(); + s1 = peg$f33(); } s0 = s1; if (s0 === peg$FAILED) { s0 = peg$currPos; - if (input.substr(peg$currPos, 2) === peg$c30) { - s1 = peg$c30; + 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$e33); } + if (peg$silentFails === 0) { peg$fail(peg$e38); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f29(); + s1 = peg$f34(); } s0 = s1; if (s0 === peg$FAILED) { s0 = peg$currPos; if (input.charCodeAt(peg$currPos) === 60) { - s1 = peg$c31; + s1 = peg$c36; peg$currPos++; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e34); } + if (peg$silentFails === 0) { peg$fail(peg$e39); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f30(); + s1 = peg$f35(); } s0 = s1; } @@ -1274,7 +1389,7 @@ function peg$parse(input, options) { peg$silentFails--; if (s0 === peg$FAILED) { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e28); } + if (peg$silentFails === 0) { peg$fail(peg$e33); } } return s0; @@ -1291,7 +1406,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e36); } + if (peg$silentFails === 0) { peg$fail(peg$e41); } } while (s2 !== peg$FAILED) { s1.push(s2); @@ -1300,15 +1415,15 @@ function peg$parse(input, options) { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e36); } + if (peg$silentFails === 0) { peg$fail(peg$e41); } } } if (input.charCodeAt(peg$currPos) === 34) { - s2 = peg$c32; + s2 = peg$c37; peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e37); } + if (peg$silentFails === 0) { peg$fail(peg$e42); } } if (s2 !== peg$FAILED) { s3 = []; @@ -1317,7 +1432,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s4 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e38); } + if (peg$silentFails === 0) { peg$fail(peg$e43); } } while (s4 !== peg$FAILED) { s3.push(s4); @@ -1326,15 +1441,15 @@ function peg$parse(input, options) { peg$currPos++; } else { s4 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e38); } + if (peg$silentFails === 0) { peg$fail(peg$e43); } } } if (input.charCodeAt(peg$currPos) === 34) { - s4 = peg$c32; + s4 = peg$c37; peg$currPos++; } else { s4 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e37); } + if (peg$silentFails === 0) { peg$fail(peg$e42); } } if (s4 !== peg$FAILED) { s5 = []; @@ -1343,7 +1458,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s6 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e39); } + if (peg$silentFails === 0) { peg$fail(peg$e44); } } while (s6 !== peg$FAILED) { s5.push(s6); @@ -1352,11 +1467,11 @@ function peg$parse(input, options) { peg$currPos++; } else { s6 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e39); } + if (peg$silentFails === 0) { peg$fail(peg$e44); } } } peg$savedPos = s0; - s0 = peg$f31(s1, s3, s5); + s0 = peg$f36(s1, s3, s5); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -1368,7 +1483,7 @@ function peg$parse(input, options) { peg$silentFails--; if (s0 === peg$FAILED) { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e35); } + if (peg$silentFails === 0) { peg$fail(peg$e40); } } return s0; @@ -1385,7 +1500,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e39); } + if (peg$silentFails === 0) { peg$fail(peg$e44); } } if (s2 !== peg$FAILED) { while (s2 !== peg$FAILED) { @@ -1395,7 +1510,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e39); } + if (peg$silentFails === 0) { peg$fail(peg$e44); } } } } else { @@ -1403,13 +1518,13 @@ function peg$parse(input, options) { } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f32(s1); + s1 = peg$f37(s1); } s0 = s1; peg$silentFails--; if (s0 === peg$FAILED) { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e40); } + if (peg$silentFails === 0) { peg$fail(peg$e45); } } return s0; @@ -1421,7 +1536,7 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = peg$parse_(); peg$savedPos = s0; - s1 = peg$f33(); + s1 = peg$f38(); s0 = s1; return s0; @@ -1437,7 +1552,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e42); } + if (peg$silentFails === 0) { peg$fail(peg$e47); } } while (s1 !== peg$FAILED) { s0.push(s1); @@ -1446,12 +1561,12 @@ function peg$parse(input, options) { peg$currPos++; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e42); } + if (peg$silentFails === 0) { peg$fail(peg$e47); } } } peg$silentFails--; s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e41); } + if (peg$silentFails === 0) { peg$fail(peg$e46); } return s0; } From eb896c68d2d36fccb0fb7a5ecef5360f62bd000b Mon Sep 17 00:00:00 2001 From: 289Adam289 Date: Mon, 9 Dec 2024 15:55:14 +0100 Subject: [PATCH 08/12] fix substitution map to work on old keys --- src/components/Search/SearchPageHeaderInput.tsx | 8 ++++---- src/components/Search/SearchRouter/SearchRouter.tsx | 8 ++++---- .../Search/SearchRouter/SearchRouterList.tsx | 11 +++++++++-- .../Search/SearchRouter/getQueryWithSubstitutions.ts | 4 +--- .../SelectionList/Search/SearchQueryListItem.tsx | 1 + 5 files changed, 19 insertions(+), 13 deletions(-) diff --git a/src/components/Search/SearchPageHeaderInput.tsx b/src/components/Search/SearchPageHeaderInput.tsx index 9394d491244d..f725d0f56267 100644 --- a/src/components/Search/SearchPageHeaderInput.tsx +++ b/src/components/Search/SearchPageHeaderInput.tsx @@ -156,8 +156,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); } @@ -175,11 +175,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 7d7c81539c4d..4b800b637712 100644 --- a/src/components/Search/SearchRouter/SearchRouter.tsx +++ b/src/components/Search/SearchRouter/SearchRouter.tsx @@ -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 fa3f25be8704..8ace6d3b90ad 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 {UserFriendlyKey} 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'; @@ -43,6 +43,7 @@ type AutocompleteItemData = { filterKey: UserFriendlyKey; text: string; autocompleteID?: string; + substitutionMapKey?: SearchFilterKey; }; type SearchRouterListProps = { @@ -261,6 +262,7 @@ function SearchRouterList( filterKey: CONST.SEARCH.SEARCH_USER_FRIENDLY_KEYS.TAX_RATE, text: tax.taxRateName, autocompleteID: tax.taxRateIds.join(','), + substitutionMapKey: CONST.SEARCH.SYNTAX_FILTER_KEYS.TAX_RATE, })); } case CONST.SEARCH.SYNTAX_FILTER_KEYS.FROM: { @@ -272,6 +274,7 @@ function SearchRouterList( filterKey: CONST.SEARCH.SEARCH_USER_FRIENDLY_KEYS.FROM, text: participant.name, autocompleteID: participant.accountID, + substitutionMapKey: CONST.SEARCH.SYNTAX_FILTER_KEYS.FROM, })); } case CONST.SEARCH.SYNTAX_FILTER_KEYS.TO: { @@ -283,6 +286,7 @@ function SearchRouterList( filterKey: CONST.SEARCH.SEARCH_USER_FRIENDLY_KEYS.TO, text: participant.name, autocompleteID: participant.accountID, + substitutionMapKey: CONST.SEARCH.SYNTAX_FILTER_KEYS.TO, })); } case CONST.SEARCH.SYNTAX_FILTER_KEYS.IN: { @@ -294,6 +298,7 @@ function SearchRouterList( filterKey: CONST.SEARCH.SEARCH_USER_FRIENDLY_KEYS.IN, text: chat.text ?? '', autocompleteID: chat.reportID, + substitutionMapKey: CONST.SEARCH.SYNTAX_FILTER_KEYS.IN, })); } case CONST.SEARCH.SYNTAX_ROOT_KEYS.TYPE: { @@ -334,6 +339,7 @@ function SearchRouterList( filterKey: CONST.SEARCH.SEARCH_USER_FRIENDLY_KEYS.CARD_ID, text: CardUtils.getCardDescription(card.cardID), autocompleteID: card.cardID.toString(), + substitutionMapKey: CONST.SEARCH.SYNTAX_FILTER_KEYS.CARD_ID, })); } default: { @@ -411,9 +417,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, substitutionMapKey}) => { return { text: getSubstitutionMapKey(filterKey, text), + mapKey: substitutionMapKey ? getSubstitutionMapKey(substitutionMapKey, text) : undefined, singleIcon: Expensicons.MagnifyingGlass, searchQuery: text, autocompleteID, diff --git a/src/components/Search/SearchRouter/getQueryWithSubstitutions.ts b/src/components/Search/SearchRouter/getQueryWithSubstitutions.ts index 5a39159f52ff..66e01f5c1ada 100644 --- a/src/components/Search/SearchRouter/getQueryWithSubstitutions.ts +++ b/src/components/Search/SearchRouter/getQueryWithSubstitutions.ts @@ -1,6 +1,5 @@ import type {SearchAutocompleteQueryRange, SearchFilterKey, UserFriendlyKey} from '@components/Search/types'; import * as parser from '@libs/SearchParser/autocompleteParser'; -import {getUserFriendlyKey} from '@libs/SearchQueryUtils'; type SubstitutionMap = Record; @@ -32,8 +31,7 @@ function getQueryWithSubstitutions(changedQuery: string, substitutions: Substitu for (const range of searchAutocompleteQueryRanges) { const itemKey = getSubstitutionMapKey(range.key, range.value); - const alternativeItemKey = getSubstitutionMapKey(getUserFriendlyKey(range.key), range.value); - const substitutionEntry = substitutions[itemKey] ?? substitutions[alternativeItemKey]; + const substitutionEntry = substitutions[itemKey]; if (substitutionEntry) { const substitutionStart = range.start + lengthDiff; 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 = { From 40e4b77df18ff20f3e69daee94f608cd2e6b0f02 Mon Sep 17 00:00:00 2001 From: 289Adam289 Date: Mon, 9 Dec 2024 17:13:53 +0100 Subject: [PATCH 09/12] Add common tests and fix typo --- src/libs/SearchQueryUtils.ts | 2 +- tests/unit/SearchAutocompleteParserTest.ts | 69 +++++-- tests/unit/SearchParserTest.ts | 171 +++++++++++++----- .../fixtures/searchParsersCommonQueries.ts | 11 ++ 4 files changed, 191 insertions(+), 62 deletions(-) create mode 100644 tests/utils/fixtures/searchParsersCommonQueries.ts diff --git a/src/libs/SearchQueryUtils.ts b/src/libs/SearchQueryUtils.ts index 6ef0b604a86d..50c7cb293257 100644 --- a/src/libs/SearchQueryUtils.ts +++ b/src/libs/SearchQueryUtils.ts @@ -662,7 +662,7 @@ function getQueryWithUpdatedValues(query: string, policyID?: string) { } /** - * A mapping object that transforms filter names from the internal codebase format to user-friendly names. + * A mapping object that maps filter names from the internal codebase format to user-friendly names. */ const UserFriendlyKeyMap: Record = { type: 'type', diff --git a/tests/unit/SearchAutocompleteParserTest.ts b/tests/unit/SearchAutocompleteParserTest.ts index 1ad3a77207bd..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: { diff --git a/tests/unit/SearchParserTest.ts b/tests/unit/SearchParserTest.ts index 774e68f03248..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: { @@ -228,52 +351,6 @@ const tests = [ }, }, }, - { - query: 'amount>200 expense-type: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; From b4708c7447b014eace15153741fa7382093503de Mon Sep 17 00:00:00 2001 From: 289Adam289 Date: Wed, 11 Dec 2024 09:37:58 +0100 Subject: [PATCH 10/12] review suggestions --- .../Search/SearchRouter/SearchRouterList.tsx | 16 ++-- src/libs/SearchQueryUtils.ts | 73 ++++++++++--------- 2 files changed, 46 insertions(+), 43 deletions(-) diff --git a/src/components/Search/SearchRouter/SearchRouterList.tsx b/src/components/Search/SearchRouter/SearchRouterList.tsx index 8ace6d3b90ad..0b6c0d7d0655 100644 --- a/src/components/Search/SearchRouter/SearchRouterList.tsx +++ b/src/components/Search/SearchRouter/SearchRouterList.tsx @@ -43,7 +43,7 @@ type AutocompleteItemData = { filterKey: UserFriendlyKey; text: string; autocompleteID?: string; - substitutionMapKey?: SearchFilterKey; + mapKey?: SearchFilterKey; }; type SearchRouterListProps = { @@ -262,7 +262,7 @@ function SearchRouterList( filterKey: CONST.SEARCH.SEARCH_USER_FRIENDLY_KEYS.TAX_RATE, text: tax.taxRateName, autocompleteID: tax.taxRateIds.join(','), - substitutionMapKey: CONST.SEARCH.SYNTAX_FILTER_KEYS.TAX_RATE, + mapKey: CONST.SEARCH.SYNTAX_FILTER_KEYS.TAX_RATE, })); } case CONST.SEARCH.SYNTAX_FILTER_KEYS.FROM: { @@ -274,7 +274,7 @@ function SearchRouterList( filterKey: CONST.SEARCH.SEARCH_USER_FRIENDLY_KEYS.FROM, text: participant.name, autocompleteID: participant.accountID, - substitutionMapKey: CONST.SEARCH.SYNTAX_FILTER_KEYS.FROM, + mapKey: CONST.SEARCH.SYNTAX_FILTER_KEYS.FROM, })); } case CONST.SEARCH.SYNTAX_FILTER_KEYS.TO: { @@ -286,7 +286,7 @@ function SearchRouterList( filterKey: CONST.SEARCH.SEARCH_USER_FRIENDLY_KEYS.TO, text: participant.name, autocompleteID: participant.accountID, - substitutionMapKey: CONST.SEARCH.SYNTAX_FILTER_KEYS.TO, + mapKey: CONST.SEARCH.SYNTAX_FILTER_KEYS.TO, })); } case CONST.SEARCH.SYNTAX_FILTER_KEYS.IN: { @@ -298,7 +298,7 @@ function SearchRouterList( filterKey: CONST.SEARCH.SEARCH_USER_FRIENDLY_KEYS.IN, text: chat.text ?? '', autocompleteID: chat.reportID, - substitutionMapKey: CONST.SEARCH.SYNTAX_FILTER_KEYS.IN, + mapKey: CONST.SEARCH.SYNTAX_FILTER_KEYS.IN, })); } case CONST.SEARCH.SYNTAX_ROOT_KEYS.TYPE: { @@ -339,7 +339,7 @@ function SearchRouterList( filterKey: CONST.SEARCH.SEARCH_USER_FRIENDLY_KEYS.CARD_ID, text: CardUtils.getCardDescription(card.cardID), autocompleteID: card.cardID.toString(), - substitutionMapKey: CONST.SEARCH.SYNTAX_FILTER_KEYS.CARD_ID, + mapKey: CONST.SEARCH.SYNTAX_FILTER_KEYS.CARD_ID, })); } default: { @@ -417,10 +417,10 @@ function SearchRouterList( sections.push({title: translate('search.recentChats'), data: styledRecentReports}); if (autocompleteSuggestions.length > 0) { - const autocompleteData = autocompleteSuggestions.map(({filterKey, text, autocompleteID, substitutionMapKey}) => { + const autocompleteData = autocompleteSuggestions.map(({filterKey, text, autocompleteID, mapKey}) => { return { text: getSubstitutionMapKey(filterKey, text), - mapKey: substitutionMapKey ? getSubstitutionMapKey(substitutionMapKey, text) : undefined, + mapKey: mapKey ? getSubstitutionMapKey(mapKey, text) : undefined, singleIcon: Expensicons.MagnifyingGlass, searchQuery: text, autocompleteID, diff --git a/src/libs/SearchQueryUtils.ts b/src/libs/SearchQueryUtils.ts index 50c7cb293257..2958d7dcc7f7 100644 --- a/src/libs/SearchQueryUtils.ts +++ b/src/libs/SearchQueryUtils.ts @@ -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. @@ -662,43 +693,15 @@ function getQueryWithUpdatedValues(query: string, policyID?: string) { } /** - * 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', -}; - -/** - * Converts a filter key from camelCase to user friendly kebab-case. + * 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. * - * This function is designed to translate filter names used in the codebase (in camelCase) - * to a user-friendly format (kebab-case). * @example - * getUserFriendlyKey("taxRate") //returns "tax-rate" + * 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]; From f2c1eb4ec11e203cb3b972b1c90aa6f11e5c5851 Mon Sep 17 00:00:00 2001 From: 289Adam289 Date: Wed, 11 Dec 2024 11:18:32 +0100 Subject: [PATCH 11/12] create helper function --- src/components/Search/SearchRouter/SearchRouterList.tsx | 6 +++++- .../Search/SearchRouter/getQueryWithSubstitutions.ts | 4 ++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/components/Search/SearchRouter/SearchRouterList.tsx b/src/components/Search/SearchRouter/SearchRouterList.tsx index 0b6c0d7d0655..1228c2e263fe 100644 --- a/src/components/Search/SearchRouter/SearchRouterList.tsx +++ b/src/components/Search/SearchRouter/SearchRouterList.tsx @@ -83,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; @@ -419,7 +423,7 @@ function SearchRouterList( if (autocompleteSuggestions.length > 0) { 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, diff --git a/src/components/Search/SearchRouter/getQueryWithSubstitutions.ts b/src/components/Search/SearchRouter/getQueryWithSubstitutions.ts index 66e01f5c1ada..117745fee480 100644 --- a/src/components/Search/SearchRouter/getQueryWithSubstitutions.ts +++ b/src/components/Search/SearchRouter/getQueryWithSubstitutions.ts @@ -1,9 +1,9 @@ -import type {SearchAutocompleteQueryRange, SearchFilterKey, UserFriendlyKey} from '@components/Search/types'; +import type {SearchAutocompleteQueryRange, SearchFilterKey} from '@components/Search/types'; import * as parser from '@libs/SearchParser/autocompleteParser'; type SubstitutionMap = Record; -const getSubstitutionMapKey = (filterKey: SearchFilterKey | UserFriendlyKey, value: string) => `${filterKey}:${value}`; +const getSubstitutionMapKey = (filterKey: SearchFilterKey, value: string) => `${filterKey}:${value}`; /** * Given a plaintext query and a SubstitutionMap object, this function will return a transformed query where: From 95ac3aa7f4aa9e40f6f3dffc7ff60ccc3f7d167e Mon Sep 17 00:00:00 2001 From: 289Adam289 Date: Thu, 12 Dec 2024 16:19:33 +0100 Subject: [PATCH 12/12] format baseRules --- src/libs/SearchParser/autocompleteParser.js | 50 ++++++++-------- src/libs/SearchParser/baseRules.peggy | 63 +++++++++++++-------- src/libs/SearchParser/searchParser.js | 50 ++++++++-------- 3 files changed, 88 insertions(+), 75 deletions(-) diff --git a/src/libs/SearchParser/autocompleteParser.js b/src/libs/SearchParser/autocompleteParser.js index 8482a18103aa..0b456b5823b1 100644 --- a/src/libs/SearchParser/autocompleteParser.js +++ b/src/libs/SearchParser/autocompleteParser.js @@ -317,31 +317,31 @@ function peg$parse(input, options) { }); return result; }; - 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$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"; }; diff --git a/src/libs/SearchParser/baseRules.peggy b/src/libs/SearchParser/baseRules.peggy index 2b3e16d75ee7..cc1305adc8b3 100644 --- a/src/libs/SearchParser/baseRules.peggy +++ b/src/libs/SearchParser/baseRules.peggy @@ -8,31 +8,44 @@ // logicalAnd: rule to match whitespace and return it as a logical 'and' operator. // whitespace: rule to match whitespaces. -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"} +// 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"; } diff --git a/src/libs/SearchParser/searchParser.js b/src/libs/SearchParser/searchParser.js index 90ffb88f209f..47b534d32cad 100644 --- a/src/libs/SearchParser/searchParser.js +++ b/src/libs/SearchParser/searchParser.js @@ -331,31 +331,31 @@ function peg$parse(input, options) { } return value[0]; }; - 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$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"; };