From 970988e2a0994530c1c53542b7b8eb81d1c24145 Mon Sep 17 00:00:00 2001 From: Samran Ahmed Date: Sat, 31 Jan 2026 05:39:19 +0500 Subject: [PATCH 01/11] Update search parsers to support exportedTo filter --- src/libs/SearchParser/autocompleteParser.js | 409 +++++++++--------- .../SearchParser/autocompleteParser.peggy | 1 + src/libs/SearchParser/baseRules.peggy | 6 +- src/libs/SearchParser/searchParser.js | 407 +++++++++-------- src/libs/SearchParser/searchParser.peggy | 1 + 5 files changed, 411 insertions(+), 413 deletions(-) diff --git a/src/libs/SearchParser/autocompleteParser.js b/src/libs/SearchParser/autocompleteParser.js index 4f8f6d7b4fb99..f094632b8447f 100644 --- a/src/libs/SearchParser/autocompleteParser.js +++ b/src/libs/SearchParser/autocompleteParser.js @@ -257,33 +257,34 @@ function peg$parse(input, options) { var peg$c71 = "policy-name"; var peg$c72 = "bank-account"; var peg$c73 = "long-report-id"; - var peg$c74 = "exported-to"; - var peg$c75 = "exchange-rate"; - var peg$c76 = "reimbursable-total"; - var peg$c77 = "non-reimbursable-total"; - var peg$c78 = "group-from"; - var peg$c79 = "group-expenses"; - var peg$c80 = "group-total"; - var peg$c81 = "group-card"; - var peg$c82 = "group-feed"; - var peg$c83 = "group-bank-account"; - var peg$c84 = "group-withdrawn"; - var peg$c85 = "group-withdrawal-id"; - var peg$c86 = "group-category"; - var peg$c87 = "group-tag"; - var peg$c88 = "group-merchant"; - var peg$c89 = "group-month"; - var peg$c90 = "group-week"; - var peg$c91 = "group-year"; - var peg$c92 = "group-quarter"; - var peg$c93 = "!="; - var peg$c94 = ">="; - var peg$c95 = ">"; - var peg$c96 = "<="; - var peg$c97 = "<"; - var peg$c98 = "\u201C"; - var peg$c99 = "\u201D"; - var peg$c100 = "\""; + var peg$c74 = "exportedto"; + var peg$c75 = "exported-to"; + var peg$c76 = "exchange-rate"; + var peg$c77 = "reimbursable-total"; + var peg$c78 = "non-reimbursable-total"; + var peg$c79 = "group-from"; + var peg$c80 = "group-expenses"; + var peg$c81 = "group-total"; + var peg$c82 = "group-card"; + var peg$c83 = "group-feed"; + var peg$c84 = "group-bank-account"; + var peg$c85 = "group-withdrawn"; + var peg$c86 = "group-withdrawal-id"; + var peg$c87 = "group-category"; + var peg$c88 = "group-tag"; + var peg$c89 = "group-merchant"; + var peg$c90 = "group-month"; + var peg$c91 = "group-week"; + var peg$c92 = "group-year"; + var peg$c93 = "group-quarter"; + var peg$c94 = "!="; + var peg$c95 = ">="; + var peg$c96 = ">"; + var peg$c97 = "<="; + var peg$c98 = "<"; + var peg$c99 = "\u201C"; + var peg$c100 = "\u201D"; + var peg$c101 = "\""; var peg$r0 = /^[ \t\r\n\xA0,:=<>!]/; var peg$r1 = /^[:=]/; @@ -297,7 +298,7 @@ function peg$parse(input, options) { var peg$r9 = /^[ \t\n\r\xA0]/; var peg$r10 = /^[ \t\n\r\xA0a-zA-Z]/; var peg$r11 = /^[,]/; - var peg$r12 = /^[ \t\n\r\xA0,]/; + var peg$r12 = /^[ \t\n\r\xA0,:=<>!]/; var peg$e0 = peg$literalExpectation("-", false); var peg$e1 = peg$literalExpectation("report-field", true); @@ -376,49 +377,50 @@ function peg$parse(input, options) { var peg$e74 = peg$literalExpectation("policy-name", true); var peg$e75 = peg$literalExpectation("bank-account", true); var peg$e76 = peg$literalExpectation("long-report-id", true); - var peg$e77 = peg$literalExpectation("exported-to", true); - var peg$e78 = peg$literalExpectation("exchange-rate", true); - var peg$e79 = peg$literalExpectation("reimbursable-total", true); - var peg$e80 = peg$literalExpectation("non-reimbursable-total", true); - var peg$e81 = peg$literalExpectation("group-from", true); - var peg$e82 = peg$literalExpectation("group-expenses", true); - var peg$e83 = peg$literalExpectation("group-total", true); - var peg$e84 = peg$literalExpectation("group-card", true); - var peg$e85 = peg$literalExpectation("group-feed", true); - var peg$e86 = peg$literalExpectation("group-bank-account", true); - var peg$e87 = peg$literalExpectation("group-withdrawn", true); - var peg$e88 = peg$literalExpectation("group-withdrawal-id", true); - var peg$e89 = peg$literalExpectation("group-category", true); - var peg$e90 = peg$literalExpectation("group-tag", true); - var peg$e91 = peg$literalExpectation("group-merchant", true); - var peg$e92 = peg$literalExpectation("group-month", true); - var peg$e93 = peg$literalExpectation("group-week", true); - var peg$e94 = peg$literalExpectation("group-year", true); - var peg$e95 = peg$literalExpectation("group-quarter", true); - var peg$e96 = peg$otherExpectation("operator"); - var peg$e97 = peg$classExpectation([":", "="], false, false); - var peg$e98 = peg$literalExpectation("!=", false); - var peg$e99 = peg$literalExpectation(">=", false); - var peg$e100 = peg$literalExpectation(">", false); - var peg$e101 = peg$literalExpectation("<=", false); - var peg$e102 = peg$literalExpectation("<", false); - var peg$e103 = peg$otherExpectation("word"); - var peg$e104 = peg$classExpectation([" ", ",", "\t", "\n", "\r", "\xA0"], true, false); - var peg$e105 = peg$otherExpectation("whitespace"); - var peg$e106 = peg$classExpectation([" ", "\t", "\r", "\n", "\xA0"], false, false); - var peg$e107 = peg$otherExpectation("quote"); - var peg$e108 = peg$classExpectation([" ", ",", "\"", "\u201D", "\u201C", "\t", "\n", "\r", "\xA0"], true, false); - var peg$e109 = peg$classExpectation(["\"", ["\u201C", "\u201D"]], false, false); - var peg$e110 = peg$classExpectation(["\"", "\u201D", "\u201C", "\r", "\n"], true, false); - var peg$e111 = peg$literalExpectation("\u201C", false); - var peg$e112 = peg$literalExpectation("\u201D", false); - var peg$e113 = peg$literalExpectation("\"", false); - var peg$e114 = peg$classExpectation([" ", "\t", "\n", "\r", "\xA0", ["a", "z"], ["A", "Z"], ["0", "9"]], false, false); - var peg$e115 = peg$classExpectation([["a", "z"], ["A", "Z"], ["0", "9"]], false, false); - var peg$e116 = peg$classExpectation([" ", "\t", "\n", "\r", "\xA0"], false, false); - var peg$e117 = peg$classExpectation([" ", "\t", "\n", "\r", "\xA0", ["a", "z"], ["A", "Z"]], false, false); - var peg$e118 = peg$classExpectation([","], false, false); - var peg$e119 = peg$classExpectation([" ", "\t", "\n", "\r", "\xA0", ","], false, false); + var peg$e77 = peg$literalExpectation("exportedTo", true); + var peg$e78 = peg$literalExpectation("exported-to", true); + var peg$e79 = peg$literalExpectation("exchange-rate", true); + var peg$e80 = peg$literalExpectation("reimbursable-total", true); + var peg$e81 = peg$literalExpectation("non-reimbursable-total", true); + var peg$e82 = peg$literalExpectation("group-from", true); + var peg$e83 = peg$literalExpectation("group-expenses", true); + var peg$e84 = peg$literalExpectation("group-total", true); + var peg$e85 = peg$literalExpectation("group-card", true); + var peg$e86 = peg$literalExpectation("group-feed", true); + var peg$e87 = peg$literalExpectation("group-bank-account", true); + var peg$e88 = peg$literalExpectation("group-withdrawn", true); + var peg$e89 = peg$literalExpectation("group-withdrawal-id", true); + var peg$e90 = peg$literalExpectation("group-category", true); + var peg$e91 = peg$literalExpectation("group-tag", true); + var peg$e92 = peg$literalExpectation("group-merchant", true); + var peg$e93 = peg$literalExpectation("group-month", true); + var peg$e94 = peg$literalExpectation("group-week", true); + var peg$e95 = peg$literalExpectation("group-year", true); + var peg$e96 = peg$literalExpectation("group-quarter", true); + var peg$e97 = peg$otherExpectation("operator"); + var peg$e98 = peg$classExpectation([":", "="], false, false); + var peg$e99 = peg$literalExpectation("!=", false); + var peg$e100 = peg$literalExpectation(">=", false); + var peg$e101 = peg$literalExpectation(">", false); + var peg$e102 = peg$literalExpectation("<=", false); + var peg$e103 = peg$literalExpectation("<", false); + var peg$e104 = peg$otherExpectation("word"); + var peg$e105 = peg$classExpectation([" ", ",", "\t", "\n", "\r", "\xA0"], true, false); + var peg$e106 = peg$otherExpectation("whitespace"); + var peg$e107 = peg$classExpectation([" ", "\t", "\r", "\n", "\xA0"], false, false); + var peg$e108 = peg$otherExpectation("quote"); + var peg$e109 = peg$classExpectation([" ", ",", "\"", "\u201D", "\u201C", "\t", "\n", "\r", "\xA0"], true, false); + var peg$e110 = peg$classExpectation(["\"", ["\u201C", "\u201D"]], false, false); + var peg$e111 = peg$classExpectation(["\"", "\u201D", "\u201C", "\r", "\n"], true, false); + var peg$e112 = peg$literalExpectation("\u201C", false); + var peg$e113 = peg$literalExpectation("\u201D", false); + var peg$e114 = peg$literalExpectation("\"", false); + var peg$e115 = peg$classExpectation([" ", "\t", "\n", "\r", "\xA0", ["a", "z"], ["A", "Z"], ["0", "9"]], false, false); + var peg$e116 = peg$classExpectation([["a", "z"], ["A", "Z"], ["0", "9"]], false, false); + var peg$e117 = peg$classExpectation([" ", "\t", "\n", "\r", "\xA0"], false, false); + var peg$e118 = peg$classExpectation([" ", "\t", "\n", "\r", "\xA0", ["a", "z"], ["A", "Z"]], false, false); + var peg$e119 = peg$classExpectation([","], false, false); + var peg$e120 = peg$classExpectation([" ", "\t", "\n", "\r", "\xA0", ",", ":", "=", "<", ">", "!"], false, false); var peg$f0 = function(ranges) { return { autocomplete, ranges }; }; var peg$f1 = function(filters) { return filters.filter(Boolean).flat(); }; @@ -544,7 +546,7 @@ function peg$parse(input, options) { var peg$f63 = function() { return "bankAccount"; }; var peg$f64 = function() { return "reportID"; }; var peg$f65 = function() { return "base62ReportID"; }; - var peg$f66 = function() { return "exportedto"; }; + var peg$f66 = function() { return "exportedTo"; }; var peg$f67 = function() { return "exchangeRate"; }; var peg$f68 = function() { return "reimbursableTotal"; }; var peg$f69 = function() { return "nonReimbursableTotal"; }; @@ -1061,37 +1063,40 @@ function peg$parse(input, options) { if (s1 === peg$FAILED) { s1 = peg$parsepaid(); if (s1 === peg$FAILED) { - s1 = peg$parseexported(); + s1 = peg$parseexportedTo(); if (s1 === peg$FAILED) { - s1 = peg$parsewithdrawn(); + s1 = peg$parseexported(); if (s1 === peg$FAILED) { - s1 = peg$parseposted(); + s1 = peg$parsewithdrawn(); if (s1 === peg$FAILED) { - s1 = peg$parsehas(); + s1 = peg$parseposted(); if (s1 === peg$FAILED) { - s1 = peg$parseis(); + s1 = peg$parsehas(); if (s1 === peg$FAILED) { - s1 = peg$parsepurchaseCurrency(); + s1 = peg$parseis(); if (s1 === peg$FAILED) { - s1 = peg$parsepurchaseAmount(); + s1 = peg$parsepurchaseCurrency(); if (s1 === peg$FAILED) { - s1 = peg$parseamount(); + s1 = peg$parsepurchaseAmount(); if (s1 === peg$FAILED) { - s1 = peg$parsemerchant(); + s1 = peg$parseamount(); if (s1 === peg$FAILED) { - s1 = peg$parsedescription(); + s1 = peg$parsemerchant(); if (s1 === peg$FAILED) { - s1 = peg$parsereportID(); + s1 = peg$parsedescription(); if (s1 === peg$FAILED) { - s1 = peg$parsewithdrawalID(); + s1 = peg$parsereportID(); if (s1 === peg$FAILED) { - s1 = peg$parsetitle(); + s1 = peg$parsewithdrawalID(); if (s1 === peg$FAILED) { - s1 = peg$parsereportFieldDynamic(); + s1 = peg$parsetitle(); if (s1 === peg$FAILED) { - s1 = peg$parsecolumns(); + s1 = peg$parsereportFieldDynamic(); if (s1 === peg$FAILED) { - s1 = peg$parselimit(); + s1 = peg$parsecolumns(); + if (s1 === peg$FAILED) { + s1 = peg$parselimit(); + } } } } @@ -2814,37 +2819,29 @@ function peg$parse(input, options) { } function peg$parseexportedTo() { - var s0, s1, s2, s3; + var s0, s1; - s0 = peg$currPos; - s1 = input.substr(peg$currPos, 11); - if (s1.toLowerCase() === peg$c74) { - peg$currPos += 11; + s0 = input.substr(peg$currPos, 10); + if (s0.toLowerCase() === peg$c74) { + peg$currPos += 10; } else { - s1 = peg$FAILED; + s0 = peg$FAILED; if (peg$silentFails === 0) { peg$fail(peg$e77); } } - if (s1 !== peg$FAILED) { - s2 = peg$currPos; - peg$silentFails++; - s3 = peg$parsewordBoundary(); - peg$silentFails--; - if (s3 !== peg$FAILED) { - peg$currPos = s2; - s2 = undefined; + if (s0 === peg$FAILED) { + s0 = peg$currPos; + s1 = input.substr(peg$currPos, 11); + if (s1.toLowerCase() === peg$c75) { + peg$currPos += 11; } else { - s2 = peg$FAILED; + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e78); } } - if (s2 !== peg$FAILED) { + if (s1 !== peg$FAILED) { peg$savedPos = s0; - s0 = peg$f66(); - } else { - peg$currPos = s0; - s0 = peg$FAILED; + s1 = peg$f66(); } - } else { - peg$currPos = s0; - s0 = peg$FAILED; + s0 = s1; } return s0; @@ -2855,11 +2852,11 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 13); - if (s1.toLowerCase() === peg$c75) { + if (s1.toLowerCase() === peg$c76) { peg$currPos += 13; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e78); } + if (peg$silentFails === 0) { peg$fail(peg$e79); } } if (s1 !== peg$FAILED) { s2 = peg$currPos; @@ -2892,11 +2889,11 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 18); - if (s1.toLowerCase() === peg$c76) { + if (s1.toLowerCase() === peg$c77) { peg$currPos += 18; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e79); } + if (peg$silentFails === 0) { peg$fail(peg$e80); } } if (s1 !== peg$FAILED) { s2 = peg$currPos; @@ -2929,11 +2926,11 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 22); - if (s1.toLowerCase() === peg$c77) { + if (s1.toLowerCase() === peg$c78) { peg$currPos += 22; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e80); } + if (peg$silentFails === 0) { peg$fail(peg$e81); } } if (s1 !== peg$FAILED) { s2 = peg$currPos; @@ -2966,11 +2963,11 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 10); - if (s1.toLowerCase() === peg$c78) { + if (s1.toLowerCase() === peg$c79) { peg$currPos += 10; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e81); } + if (peg$silentFails === 0) { peg$fail(peg$e82); } } if (s1 !== peg$FAILED) { s2 = peg$currPos; @@ -3003,11 +3000,11 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 14); - if (s1.toLowerCase() === peg$c79) { + if (s1.toLowerCase() === peg$c80) { peg$currPos += 14; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e82); } + if (peg$silentFails === 0) { peg$fail(peg$e83); } } if (s1 !== peg$FAILED) { s2 = peg$currPos; @@ -3040,11 +3037,11 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 11); - if (s1.toLowerCase() === peg$c80) { + if (s1.toLowerCase() === peg$c81) { peg$currPos += 11; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e83); } + if (peg$silentFails === 0) { peg$fail(peg$e84); } } if (s1 !== peg$FAILED) { s2 = peg$currPos; @@ -3077,11 +3074,11 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 10); - if (s1.toLowerCase() === peg$c81) { + if (s1.toLowerCase() === peg$c82) { peg$currPos += 10; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e84); } + if (peg$silentFails === 0) { peg$fail(peg$e85); } } if (s1 !== peg$FAILED) { s2 = peg$currPos; @@ -3114,11 +3111,11 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 10); - if (s1.toLowerCase() === peg$c82) { + if (s1.toLowerCase() === peg$c83) { peg$currPos += 10; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e85); } + if (peg$silentFails === 0) { peg$fail(peg$e86); } } if (s1 !== peg$FAILED) { s2 = peg$currPos; @@ -3151,11 +3148,11 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 18); - if (s1.toLowerCase() === peg$c83) { + if (s1.toLowerCase() === peg$c84) { peg$currPos += 18; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e86); } + if (peg$silentFails === 0) { peg$fail(peg$e87); } } if (s1 !== peg$FAILED) { s2 = peg$currPos; @@ -3188,11 +3185,11 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 15); - if (s1.toLowerCase() === peg$c84) { + if (s1.toLowerCase() === peg$c85) { peg$currPos += 15; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e87); } + if (peg$silentFails === 0) { peg$fail(peg$e88); } } if (s1 !== peg$FAILED) { s2 = peg$currPos; @@ -3225,11 +3222,11 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 19); - if (s1.toLowerCase() === peg$c85) { + if (s1.toLowerCase() === peg$c86) { peg$currPos += 19; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e88); } + if (peg$silentFails === 0) { peg$fail(peg$e89); } } if (s1 !== peg$FAILED) { s2 = peg$currPos; @@ -3262,11 +3259,11 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 14); - if (s1.toLowerCase() === peg$c86) { + if (s1.toLowerCase() === peg$c87) { peg$currPos += 14; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e89); } + if (peg$silentFails === 0) { peg$fail(peg$e90); } } if (s1 !== peg$FAILED) { s2 = peg$currPos; @@ -3299,11 +3296,11 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 9); - if (s1.toLowerCase() === peg$c87) { + if (s1.toLowerCase() === peg$c88) { peg$currPos += 9; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e90); } + if (peg$silentFails === 0) { peg$fail(peg$e91); } } if (s1 !== peg$FAILED) { s2 = peg$currPos; @@ -3336,11 +3333,11 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 14); - if (s1.toLowerCase() === peg$c88) { + if (s1.toLowerCase() === peg$c89) { peg$currPos += 14; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e91); } + if (peg$silentFails === 0) { peg$fail(peg$e92); } } if (s1 !== peg$FAILED) { s2 = peg$currPos; @@ -3373,11 +3370,11 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 11); - if (s1.toLowerCase() === peg$c89) { + if (s1.toLowerCase() === peg$c90) { peg$currPos += 11; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e92); } + if (peg$silentFails === 0) { peg$fail(peg$e93); } } if (s1 !== peg$FAILED) { s2 = peg$currPos; @@ -3410,11 +3407,11 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 10); - if (s1.toLowerCase() === peg$c90) { + if (s1.toLowerCase() === peg$c91) { peg$currPos += 10; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e93); } + if (peg$silentFails === 0) { peg$fail(peg$e94); } } if (s1 !== peg$FAILED) { s2 = peg$currPos; @@ -3447,11 +3444,11 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 10); - if (s1.toLowerCase() === peg$c91) { + if (s1.toLowerCase() === peg$c92) { peg$currPos += 10; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e94); } + if (peg$silentFails === 0) { peg$fail(peg$e95); } } if (s1 !== peg$FAILED) { s2 = peg$currPos; @@ -3484,11 +3481,11 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 13); - if (s1.toLowerCase() === peg$c92) { + if (s1.toLowerCase() === peg$c93) { peg$currPos += 13; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e95); } + if (peg$silentFails === 0) { peg$fail(peg$e96); } } if (s1 !== peg$FAILED) { s2 = peg$currPos; @@ -3526,7 +3523,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e97); } + if (peg$silentFails === 0) { peg$fail(peg$e98); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; @@ -3535,12 +3532,12 @@ function peg$parse(input, options) { s0 = s1; if (s0 === peg$FAILED) { s0 = peg$currPos; - if (input.substr(peg$currPos, 2) === peg$c93) { - s1 = peg$c93; + if (input.substr(peg$currPos, 2) === peg$c94) { + s1 = peg$c94; peg$currPos += 2; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e98); } + if (peg$silentFails === 0) { peg$fail(peg$e99); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; @@ -3549,12 +3546,12 @@ function peg$parse(input, options) { s0 = s1; if (s0 === peg$FAILED) { s0 = peg$currPos; - if (input.substr(peg$currPos, 2) === peg$c94) { - s1 = peg$c94; + if (input.substr(peg$currPos, 2) === peg$c95) { + s1 = peg$c95; peg$currPos += 2; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e99); } + if (peg$silentFails === 0) { peg$fail(peg$e100); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; @@ -3564,11 +3561,11 @@ function peg$parse(input, options) { if (s0 === peg$FAILED) { s0 = peg$currPos; if (input.charCodeAt(peg$currPos) === 62) { - s1 = peg$c95; + s1 = peg$c96; peg$currPos++; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e100); } + if (peg$silentFails === 0) { peg$fail(peg$e101); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; @@ -3577,12 +3574,12 @@ function peg$parse(input, options) { s0 = s1; if (s0 === peg$FAILED) { s0 = peg$currPos; - if (input.substr(peg$currPos, 2) === peg$c96) { - s1 = peg$c96; + if (input.substr(peg$currPos, 2) === peg$c97) { + s1 = peg$c97; peg$currPos += 2; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e101); } + if (peg$silentFails === 0) { peg$fail(peg$e102); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; @@ -3592,11 +3589,11 @@ function peg$parse(input, options) { if (s0 === peg$FAILED) { s0 = peg$currPos; if (input.charCodeAt(peg$currPos) === 60) { - s1 = peg$c97; + s1 = peg$c98; peg$currPos++; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e102); } + if (peg$silentFails === 0) { peg$fail(peg$e103); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; @@ -3611,7 +3608,7 @@ function peg$parse(input, options) { peg$silentFails--; if (s0 === peg$FAILED) { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e96); } + if (peg$silentFails === 0) { peg$fail(peg$e97); } } return s0; @@ -3642,7 +3639,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e104); } + if (peg$silentFails === 0) { peg$fail(peg$e105); } } if (s2 !== peg$FAILED) { while (s2 !== peg$FAILED) { @@ -3652,7 +3649,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e104); } + if (peg$silentFails === 0) { peg$fail(peg$e105); } } } } else { @@ -3666,7 +3663,7 @@ function peg$parse(input, options) { peg$silentFails--; if (s0 === peg$FAILED) { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e103); } + if (peg$silentFails === 0) { peg$fail(peg$e104); } } return s0; @@ -3694,7 +3691,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e106); } + if (peg$silentFails === 0) { peg$fail(peg$e107); } } while (s1 !== peg$FAILED) { s0.push(s1); @@ -3703,12 +3700,12 @@ function peg$parse(input, options) { peg$currPos++; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e106); } + if (peg$silentFails === 0) { peg$fail(peg$e107); } } } peg$silentFails--; s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e105); } + if (peg$silentFails === 0) { peg$fail(peg$e106); } return s0; } @@ -3755,7 +3752,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e108); } + if (peg$silentFails === 0) { peg$fail(peg$e109); } } while (s2 !== peg$FAILED) { s1.push(s2); @@ -3764,7 +3761,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e108); } + if (peg$silentFails === 0) { peg$fail(peg$e109); } } } s2 = input.charAt(peg$currPos); @@ -3772,7 +3769,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e109); } + if (peg$silentFails === 0) { peg$fail(peg$e110); } } if (s2 !== peg$FAILED) { s3 = []; @@ -3781,7 +3778,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s4 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e110); } + if (peg$silentFails === 0) { peg$fail(peg$e111); } } while (s4 !== peg$FAILED) { s3.push(s4); @@ -3790,7 +3787,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s4 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e110); } + if (peg$silentFails === 0) { peg$fail(peg$e111); } } } s4 = input.charAt(peg$currPos); @@ -3798,7 +3795,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s4 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e109); } + if (peg$silentFails === 0) { peg$fail(peg$e110); } } if (s4 !== peg$FAILED) { s5 = []; @@ -3807,7 +3804,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s6 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e104); } + if (peg$silentFails === 0) { peg$fail(peg$e105); } } while (s6 !== peg$FAILED) { s5.push(s6); @@ -3816,7 +3813,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s6 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e104); } + if (peg$silentFails === 0) { peg$fail(peg$e105); } } } peg$savedPos = s0; @@ -3832,7 +3829,7 @@ function peg$parse(input, options) { peg$silentFails--; if (s0 === peg$FAILED) { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e107); } + if (peg$silentFails === 0) { peg$fail(peg$e108); } } return s0; @@ -3849,7 +3846,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e108); } + if (peg$silentFails === 0) { peg$fail(peg$e109); } } while (s2 !== peg$FAILED) { s1.push(s2); @@ -3858,7 +3855,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e108); } + if (peg$silentFails === 0) { peg$fail(peg$e109); } } } s2 = input.charAt(peg$currPos); @@ -3866,7 +3863,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e109); } + if (peg$silentFails === 0) { peg$fail(peg$e110); } } if (s2 !== peg$FAILED) { s3 = []; @@ -3875,7 +3872,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s4 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e110); } + if (peg$silentFails === 0) { peg$fail(peg$e111); } } if (s4 === peg$FAILED) { s4 = peg$currPos; @@ -3891,11 +3888,11 @@ function peg$parse(input, options) { } if (s5 !== peg$FAILED) { if (input.charCodeAt(peg$currPos) === 8220) { - s6 = peg$c98; + s6 = peg$c99; peg$currPos++; } else { s6 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e111); } + if (peg$silentFails === 0) { peg$fail(peg$e112); } } if (s6 !== peg$FAILED) { peg$savedPos = s4; @@ -3922,11 +3919,11 @@ function peg$parse(input, options) { } if (s5 !== peg$FAILED) { if (input.charCodeAt(peg$currPos) === 8221) { - s6 = peg$c99; + s6 = peg$c100; peg$currPos++; } else { s6 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e112); } + if (peg$silentFails === 0) { peg$fail(peg$e113); } } if (s6 !== peg$FAILED) { peg$savedPos = s4; @@ -3953,11 +3950,11 @@ function peg$parse(input, options) { } if (s5 !== peg$FAILED) { if (input.charCodeAt(peg$currPos) === 34) { - s6 = peg$c100; + s6 = peg$c101; peg$currPos++; } else { s6 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e113); } + if (peg$silentFails === 0) { peg$fail(peg$e114); } } if (s6 !== peg$FAILED) { peg$savedPos = s4; @@ -3980,7 +3977,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s4 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e110); } + if (peg$silentFails === 0) { peg$fail(peg$e111); } } if (s4 === peg$FAILED) { s4 = peg$currPos; @@ -3996,11 +3993,11 @@ function peg$parse(input, options) { } if (s5 !== peg$FAILED) { if (input.charCodeAt(peg$currPos) === 8220) { - s6 = peg$c98; + s6 = peg$c99; peg$currPos++; } else { s6 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e111); } + if (peg$silentFails === 0) { peg$fail(peg$e112); } } if (s6 !== peg$FAILED) { peg$savedPos = s4; @@ -4027,11 +4024,11 @@ function peg$parse(input, options) { } if (s5 !== peg$FAILED) { if (input.charCodeAt(peg$currPos) === 8221) { - s6 = peg$c99; + s6 = peg$c100; peg$currPos++; } else { s6 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e112); } + if (peg$silentFails === 0) { peg$fail(peg$e113); } } if (s6 !== peg$FAILED) { peg$savedPos = s4; @@ -4058,11 +4055,11 @@ function peg$parse(input, options) { } if (s5 !== peg$FAILED) { if (input.charCodeAt(peg$currPos) === 34) { - s6 = peg$c100; + s6 = peg$c101; peg$currPos++; } else { s6 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e113); } + if (peg$silentFails === 0) { peg$fail(peg$e114); } } if (s6 !== peg$FAILED) { peg$savedPos = s4; @@ -4094,7 +4091,7 @@ function peg$parse(input, options) { peg$silentFails--; if (s0 === peg$FAILED) { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e107); } + if (peg$silentFails === 0) { peg$fail(peg$e108); } } return s0; @@ -4109,7 +4106,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e109); } + if (peg$silentFails === 0) { peg$fail(peg$e110); } } if (s1 !== peg$FAILED) { s2 = peg$currPos; @@ -4147,7 +4144,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e114); } + if (peg$silentFails === 0) { peg$fail(peg$e115); } } while (s2 !== peg$FAILED) { s1.push(s2); @@ -4156,7 +4153,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e114); } + if (peg$silentFails === 0) { peg$fail(peg$e115); } } } s2 = []; @@ -4165,7 +4162,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s3 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e115); } + if (peg$silentFails === 0) { peg$fail(peg$e116); } } while (s3 !== peg$FAILED) { s2.push(s3); @@ -4174,7 +4171,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s3 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e115); } + if (peg$silentFails === 0) { peg$fail(peg$e116); } } } s3 = []; @@ -4183,7 +4180,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s4 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e116); } + if (peg$silentFails === 0) { peg$fail(peg$e117); } } while (s4 !== peg$FAILED) { s3.push(s4); @@ -4192,7 +4189,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s4 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e116); } + if (peg$silentFails === 0) { peg$fail(peg$e117); } } } s4 = peg$parseoperator(); @@ -4211,7 +4208,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e117); } + if (peg$silentFails === 0) { peg$fail(peg$e118); } } while (s2 !== peg$FAILED) { s1.push(s2); @@ -4220,7 +4217,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e117); } + if (peg$silentFails === 0) { peg$fail(peg$e118); } } } s2 = peg$currPos; @@ -4267,7 +4264,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s0 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e118); } + if (peg$silentFails === 0) { peg$fail(peg$e119); } } } } @@ -4283,7 +4280,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s0 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e119); } + if (peg$silentFails === 0) { peg$fail(peg$e120); } } if (s0 === peg$FAILED) { s0 = peg$currPos; diff --git a/src/libs/SearchParser/autocompleteParser.peggy b/src/libs/SearchParser/autocompleteParser.peggy index 2299252b119d2..25207e4acba27 100644 --- a/src/libs/SearchParser/autocompleteParser.peggy +++ b/src/libs/SearchParser/autocompleteParser.peggy @@ -105,6 +105,7 @@ autocompleteKey "key" / submitted / approved / paid + / exportedTo / exported / withdrawn / posted diff --git a/src/libs/SearchParser/baseRules.peggy b/src/libs/SearchParser/baseRules.peggy index 884aab360f4fc..5089313d52de1 100644 --- a/src/libs/SearchParser/baseRules.peggy +++ b/src/libs/SearchParser/baseRules.peggy @@ -131,7 +131,9 @@ withdrawalId = "withdrawal-id"i &wordBoundary { return "wi bankAccount = "bank-account"i &wordBoundary { return "bankAccount"; } reportId = "long-report-id"i &wordBoundary { return "reportID"; } base62ReportId = "report-id"i &wordBoundary { return "base62ReportID"; } -exportedTo = "exported-to"i &wordBoundary { return "exportedto"; } +exportedTo + = "exportedTo"i + / "exported-to"i { return "exportedTo"; } exchangeRate = "exchange-rate"i &wordBoundary { return "exchangeRate"; } reimbursableTotal = "reimbursable-total"i &wordBoundary { return "reimbursableTotal"; } nonReimbursableTotal = "non-reimbursable-total"i &wordBoundary { return "nonReimbursableTotal"; } @@ -207,5 +209,5 @@ validClosingCondition / [,] // Case 3: Followed by a comma wordBoundary - = [ \t\n\r\xA0,] // whitespace or comma + = [ \t\n\r\xA0,:=<>!] // whitespace, comma, or operator (so "exported-to:" is recognized) / !. // or end of input diff --git a/src/libs/SearchParser/searchParser.js b/src/libs/SearchParser/searchParser.js index 69589aabb68da..17c98f5a78c96 100644 --- a/src/libs/SearchParser/searchParser.js +++ b/src/libs/SearchParser/searchParser.js @@ -258,33 +258,34 @@ function peg$parse(input, options) { var peg$c71 = "policy-name"; var peg$c72 = "bank-account"; var peg$c73 = "long-report-id"; - var peg$c74 = "exported-to"; - var peg$c75 = "exchange-rate"; - var peg$c76 = "reimbursable-total"; - var peg$c77 = "non-reimbursable-total"; - var peg$c78 = "group-from"; - var peg$c79 = "group-expenses"; - var peg$c80 = "group-total"; - var peg$c81 = "group-card"; - var peg$c82 = "group-feed"; - var peg$c83 = "group-bank-account"; - var peg$c84 = "group-withdrawn"; - var peg$c85 = "group-withdrawal-id"; - var peg$c86 = "group-category"; - var peg$c87 = "group-tag"; - var peg$c88 = "group-merchant"; - var peg$c89 = "group-month"; - var peg$c90 = "group-week"; - var peg$c91 = "group-year"; - var peg$c92 = "group-quarter"; - var peg$c93 = "!="; - var peg$c94 = ">="; - var peg$c95 = ">"; - var peg$c96 = "<="; - var peg$c97 = "<"; - var peg$c98 = "\u201C"; - var peg$c99 = "\u201D"; - var peg$c100 = "\""; + var peg$c74 = "exportedto"; + var peg$c75 = "exported-to"; + var peg$c76 = "exchange-rate"; + var peg$c77 = "reimbursable-total"; + var peg$c78 = "non-reimbursable-total"; + var peg$c79 = "group-from"; + var peg$c80 = "group-expenses"; + var peg$c81 = "group-total"; + var peg$c82 = "group-card"; + var peg$c83 = "group-feed"; + var peg$c84 = "group-bank-account"; + var peg$c85 = "group-withdrawn"; + var peg$c86 = "group-withdrawal-id"; + var peg$c87 = "group-category"; + var peg$c88 = "group-tag"; + var peg$c89 = "group-merchant"; + var peg$c90 = "group-month"; + var peg$c91 = "group-week"; + var peg$c92 = "group-year"; + var peg$c93 = "group-quarter"; + var peg$c94 = "!="; + var peg$c95 = ">="; + var peg$c96 = ">"; + var peg$c97 = "<="; + var peg$c98 = "<"; + var peg$c99 = "\u201C"; + var peg$c100 = "\u201D"; + var peg$c101 = "\""; var peg$r0 = /^[^ \t\r\n\xA0]/; var peg$r1 = /^[ \t\r\n\xA0,:=<>!]/; @@ -299,7 +300,7 @@ function peg$parse(input, options) { var peg$r10 = /^[ \t\n\r\xA0]/; var peg$r11 = /^[ \t\n\r\xA0a-zA-Z]/; var peg$r12 = /^[,]/; - var peg$r13 = /^[ \t\n\r\xA0,]/; + var peg$r13 = /^[ \t\n\r\xA0,:=<>!]/; var peg$e0 = peg$classExpectation([" ", "\t", "\r", "\n", "\xA0"], true, false); var peg$e1 = peg$literalExpectation("-", false); @@ -380,49 +381,50 @@ function peg$parse(input, options) { var peg$e76 = peg$literalExpectation("policy-name", true); var peg$e77 = peg$literalExpectation("bank-account", true); var peg$e78 = peg$literalExpectation("long-report-id", true); - var peg$e79 = peg$literalExpectation("exported-to", true); - var peg$e80 = peg$literalExpectation("exchange-rate", true); - var peg$e81 = peg$literalExpectation("reimbursable-total", true); - var peg$e82 = peg$literalExpectation("non-reimbursable-total", true); - var peg$e83 = peg$literalExpectation("group-from", true); - var peg$e84 = peg$literalExpectation("group-expenses", true); - var peg$e85 = peg$literalExpectation("group-total", true); - var peg$e86 = peg$literalExpectation("group-card", true); - var peg$e87 = peg$literalExpectation("group-feed", true); - var peg$e88 = peg$literalExpectation("group-bank-account", true); - var peg$e89 = peg$literalExpectation("group-withdrawn", true); - var peg$e90 = peg$literalExpectation("group-withdrawal-id", true); - var peg$e91 = peg$literalExpectation("group-category", true); - var peg$e92 = peg$literalExpectation("group-tag", true); - var peg$e93 = peg$literalExpectation("group-merchant", true); - var peg$e94 = peg$literalExpectation("group-month", true); - var peg$e95 = peg$literalExpectation("group-week", true); - var peg$e96 = peg$literalExpectation("group-year", true); - var peg$e97 = peg$literalExpectation("group-quarter", true); - var peg$e98 = peg$otherExpectation("operator"); - var peg$e99 = peg$classExpectation([":", "="], false, false); - var peg$e100 = peg$literalExpectation("!=", false); - var peg$e101 = peg$literalExpectation(">=", false); - var peg$e102 = peg$literalExpectation(">", false); - var peg$e103 = peg$literalExpectation("<=", false); - var peg$e104 = peg$literalExpectation("<", false); - var peg$e105 = peg$otherExpectation("word"); - var peg$e106 = peg$classExpectation([" ", ",", "\t", "\n", "\r", "\xA0"], true, false); - var peg$e107 = peg$otherExpectation("whitespace"); - var peg$e108 = peg$classExpectation([" ", "\t", "\r", "\n", "\xA0"], false, false); - var peg$e109 = peg$otherExpectation("quote"); - var peg$e110 = peg$classExpectation([" ", ",", "\"", "\u201D", "\u201C", "\t", "\n", "\r", "\xA0"], true, false); - var peg$e111 = peg$classExpectation(["\"", ["\u201C", "\u201D"]], false, false); - var peg$e112 = peg$classExpectation(["\"", "\u201D", "\u201C", "\r", "\n"], true, false); - var peg$e113 = peg$literalExpectation("\u201C", false); - var peg$e114 = peg$literalExpectation("\u201D", false); - var peg$e115 = peg$literalExpectation("\"", false); - var peg$e116 = peg$classExpectation([" ", "\t", "\n", "\r", "\xA0", ["a", "z"], ["A", "Z"], ["0", "9"]], false, false); - var peg$e117 = peg$classExpectation([["a", "z"], ["A", "Z"], ["0", "9"]], false, false); - var peg$e118 = peg$classExpectation([" ", "\t", "\n", "\r", "\xA0"], false, false); - var peg$e119 = peg$classExpectation([" ", "\t", "\n", "\r", "\xA0", ["a", "z"], ["A", "Z"]], false, false); - var peg$e120 = peg$classExpectation([","], false, false); - var peg$e121 = peg$classExpectation([" ", "\t", "\n", "\r", "\xA0", ","], false, false); + var peg$e79 = peg$literalExpectation("exportedTo", true); + var peg$e80 = peg$literalExpectation("exported-to", true); + var peg$e81 = peg$literalExpectation("exchange-rate", true); + var peg$e82 = peg$literalExpectation("reimbursable-total", true); + var peg$e83 = peg$literalExpectation("non-reimbursable-total", true); + var peg$e84 = peg$literalExpectation("group-from", true); + var peg$e85 = peg$literalExpectation("group-expenses", true); + var peg$e86 = peg$literalExpectation("group-total", true); + var peg$e87 = peg$literalExpectation("group-card", true); + var peg$e88 = peg$literalExpectation("group-feed", true); + var peg$e89 = peg$literalExpectation("group-bank-account", true); + var peg$e90 = peg$literalExpectation("group-withdrawn", true); + var peg$e91 = peg$literalExpectation("group-withdrawal-id", true); + var peg$e92 = peg$literalExpectation("group-category", true); + var peg$e93 = peg$literalExpectation("group-tag", true); + var peg$e94 = peg$literalExpectation("group-merchant", true); + var peg$e95 = peg$literalExpectation("group-month", true); + var peg$e96 = peg$literalExpectation("group-week", true); + var peg$e97 = peg$literalExpectation("group-year", true); + var peg$e98 = peg$literalExpectation("group-quarter", true); + var peg$e99 = peg$otherExpectation("operator"); + var peg$e100 = peg$classExpectation([":", "="], false, false); + var peg$e101 = peg$literalExpectation("!=", false); + var peg$e102 = peg$literalExpectation(">=", false); + var peg$e103 = peg$literalExpectation(">", false); + var peg$e104 = peg$literalExpectation("<=", false); + var peg$e105 = peg$literalExpectation("<", false); + var peg$e106 = peg$otherExpectation("word"); + var peg$e107 = peg$classExpectation([" ", ",", "\t", "\n", "\r", "\xA0"], true, false); + var peg$e108 = peg$otherExpectation("whitespace"); + var peg$e109 = peg$classExpectation([" ", "\t", "\r", "\n", "\xA0"], false, false); + var peg$e110 = peg$otherExpectation("quote"); + var peg$e111 = peg$classExpectation([" ", ",", "\"", "\u201D", "\u201C", "\t", "\n", "\r", "\xA0"], true, false); + var peg$e112 = peg$classExpectation(["\"", ["\u201C", "\u201D"]], false, false); + var peg$e113 = peg$classExpectation(["\"", "\u201D", "\u201C", "\r", "\n"], true, false); + var peg$e114 = peg$literalExpectation("\u201C", false); + var peg$e115 = peg$literalExpectation("\u201D", false); + var peg$e116 = peg$literalExpectation("\"", false); + var peg$e117 = peg$classExpectation([" ", "\t", "\n", "\r", "\xA0", ["a", "z"], ["A", "Z"], ["0", "9"]], false, false); + var peg$e118 = peg$classExpectation([["a", "z"], ["A", "Z"], ["0", "9"]], false, false); + var peg$e119 = peg$classExpectation([" ", "\t", "\n", "\r", "\xA0"], false, false); + var peg$e120 = peg$classExpectation([" ", "\t", "\n", "\r", "\xA0", ["a", "z"], ["A", "Z"]], false, false); + var peg$e121 = peg$classExpectation([","], false, false); + var peg$e122 = peg$classExpectation([" ", "\t", "\n", "\r", "\xA0", ",", ":", "=", "<", ">", "!"], false, false); var peg$f0 = function(filters) { return applyDefaults(filters); }; var peg$f1 = function(head, tail) { @@ -571,7 +573,7 @@ function peg$parse(input, options) { var peg$f64 = function() { return "bankAccount"; }; var peg$f65 = function() { return "reportID"; }; var peg$f66 = function() { return "base62ReportID"; }; - var peg$f67 = function() { return "exportedto"; }; + var peg$f67 = function() { return "exportedTo"; }; var peg$f68 = function() { return "exchangeRate"; }; var peg$f69 = function() { return "reimbursableTotal"; }; var peg$f70 = function() { return "nonReimbursableTotal"; }; @@ -1147,35 +1149,38 @@ function peg$parse(input, options) { if (s1 === peg$FAILED) { s1 = peg$parsepaid(); if (s1 === peg$FAILED) { - s1 = peg$parseexported(); + s1 = peg$parseexportedTo(); if (s1 === peg$FAILED) { - s1 = peg$parseposted(); + s1 = peg$parseexported(); if (s1 === peg$FAILED) { - s1 = peg$parsewithdrawn(); + s1 = peg$parseposted(); if (s1 === peg$FAILED) { - s1 = peg$parsefeed(); + s1 = peg$parsewithdrawn(); if (s1 === peg$FAILED) { - s1 = peg$parsetitle(); + s1 = peg$parsefeed(); if (s1 === peg$FAILED) { - s1 = peg$parseassignee(); + s1 = peg$parsetitle(); if (s1 === peg$FAILED) { - s1 = peg$parsecreatedBy(); + s1 = peg$parseassignee(); if (s1 === peg$FAILED) { - s1 = peg$parsereimbursable(); + s1 = peg$parsecreatedBy(); if (s1 === peg$FAILED) { - s1 = peg$parsebillable(); + s1 = peg$parsereimbursable(); if (s1 === peg$FAILED) { - s1 = peg$parseaction(); + s1 = peg$parsebillable(); if (s1 === peg$FAILED) { - s1 = peg$parsehas(); + s1 = peg$parseaction(); if (s1 === peg$FAILED) { - s1 = peg$parseis(); + s1 = peg$parsehas(); if (s1 === peg$FAILED) { - s1 = peg$parsepurchaseCurrency(); + s1 = peg$parseis(); if (s1 === peg$FAILED) { - s1 = peg$parsepurchaseAmount(); + s1 = peg$parsepurchaseCurrency(); if (s1 === peg$FAILED) { - s1 = peg$parsereportFieldDynamic(); + s1 = peg$parsepurchaseAmount(); + if (s1 === peg$FAILED) { + s1 = peg$parsereportFieldDynamic(); + } } } } @@ -2998,37 +3003,29 @@ function peg$parse(input, options) { } function peg$parseexportedTo() { - var s0, s1, s2, s3; + var s0, s1; - s0 = peg$currPos; - s1 = input.substr(peg$currPos, 11); - if (s1.toLowerCase() === peg$c74) { - peg$currPos += 11; + s0 = input.substr(peg$currPos, 10); + if (s0.toLowerCase() === peg$c74) { + peg$currPos += 10; } else { - s1 = peg$FAILED; + s0 = peg$FAILED; if (peg$silentFails === 0) { peg$fail(peg$e79); } } - if (s1 !== peg$FAILED) { - s2 = peg$currPos; - peg$silentFails++; - s3 = peg$parsewordBoundary(); - peg$silentFails--; - if (s3 !== peg$FAILED) { - peg$currPos = s2; - s2 = undefined; + if (s0 === peg$FAILED) { + s0 = peg$currPos; + s1 = input.substr(peg$currPos, 11); + if (s1.toLowerCase() === peg$c75) { + peg$currPos += 11; } else { - s2 = peg$FAILED; + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e80); } } - if (s2 !== peg$FAILED) { + if (s1 !== peg$FAILED) { peg$savedPos = s0; - s0 = peg$f67(); - } else { - peg$currPos = s0; - s0 = peg$FAILED; + s1 = peg$f67(); } - } else { - peg$currPos = s0; - s0 = peg$FAILED; + s0 = s1; } return s0; @@ -3039,11 +3036,11 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 13); - if (s1.toLowerCase() === peg$c75) { + if (s1.toLowerCase() === peg$c76) { peg$currPos += 13; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e80); } + if (peg$silentFails === 0) { peg$fail(peg$e81); } } if (s1 !== peg$FAILED) { s2 = peg$currPos; @@ -3076,11 +3073,11 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 18); - if (s1.toLowerCase() === peg$c76) { + if (s1.toLowerCase() === peg$c77) { peg$currPos += 18; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e81); } + if (peg$silentFails === 0) { peg$fail(peg$e82); } } if (s1 !== peg$FAILED) { s2 = peg$currPos; @@ -3113,11 +3110,11 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 22); - if (s1.toLowerCase() === peg$c77) { + if (s1.toLowerCase() === peg$c78) { peg$currPos += 22; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e82); } + if (peg$silentFails === 0) { peg$fail(peg$e83); } } if (s1 !== peg$FAILED) { s2 = peg$currPos; @@ -3150,11 +3147,11 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 10); - if (s1.toLowerCase() === peg$c78) { + if (s1.toLowerCase() === peg$c79) { peg$currPos += 10; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e83); } + if (peg$silentFails === 0) { peg$fail(peg$e84); } } if (s1 !== peg$FAILED) { s2 = peg$currPos; @@ -3187,11 +3184,11 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 14); - if (s1.toLowerCase() === peg$c79) { + if (s1.toLowerCase() === peg$c80) { peg$currPos += 14; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e84); } + if (peg$silentFails === 0) { peg$fail(peg$e85); } } if (s1 !== peg$FAILED) { s2 = peg$currPos; @@ -3224,11 +3221,11 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 11); - if (s1.toLowerCase() === peg$c80) { + if (s1.toLowerCase() === peg$c81) { peg$currPos += 11; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e85); } + if (peg$silentFails === 0) { peg$fail(peg$e86); } } if (s1 !== peg$FAILED) { s2 = peg$currPos; @@ -3261,11 +3258,11 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 10); - if (s1.toLowerCase() === peg$c81) { + if (s1.toLowerCase() === peg$c82) { peg$currPos += 10; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e86); } + if (peg$silentFails === 0) { peg$fail(peg$e87); } } if (s1 !== peg$FAILED) { s2 = peg$currPos; @@ -3298,11 +3295,11 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 10); - if (s1.toLowerCase() === peg$c82) { + if (s1.toLowerCase() === peg$c83) { peg$currPos += 10; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e87); } + if (peg$silentFails === 0) { peg$fail(peg$e88); } } if (s1 !== peg$FAILED) { s2 = peg$currPos; @@ -3335,11 +3332,11 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 18); - if (s1.toLowerCase() === peg$c83) { + if (s1.toLowerCase() === peg$c84) { peg$currPos += 18; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e88); } + if (peg$silentFails === 0) { peg$fail(peg$e89); } } if (s1 !== peg$FAILED) { s2 = peg$currPos; @@ -3372,11 +3369,11 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 15); - if (s1.toLowerCase() === peg$c84) { + if (s1.toLowerCase() === peg$c85) { peg$currPos += 15; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e89); } + if (peg$silentFails === 0) { peg$fail(peg$e90); } } if (s1 !== peg$FAILED) { s2 = peg$currPos; @@ -3409,11 +3406,11 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 19); - if (s1.toLowerCase() === peg$c85) { + if (s1.toLowerCase() === peg$c86) { peg$currPos += 19; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e90); } + if (peg$silentFails === 0) { peg$fail(peg$e91); } } if (s1 !== peg$FAILED) { s2 = peg$currPos; @@ -3446,11 +3443,11 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 14); - if (s1.toLowerCase() === peg$c86) { + if (s1.toLowerCase() === peg$c87) { peg$currPos += 14; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e91); } + if (peg$silentFails === 0) { peg$fail(peg$e92); } } if (s1 !== peg$FAILED) { s2 = peg$currPos; @@ -3483,11 +3480,11 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 9); - if (s1.toLowerCase() === peg$c87) { + if (s1.toLowerCase() === peg$c88) { peg$currPos += 9; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e92); } + if (peg$silentFails === 0) { peg$fail(peg$e93); } } if (s1 !== peg$FAILED) { s2 = peg$currPos; @@ -3520,11 +3517,11 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 14); - if (s1.toLowerCase() === peg$c88) { + if (s1.toLowerCase() === peg$c89) { peg$currPos += 14; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e93); } + if (peg$silentFails === 0) { peg$fail(peg$e94); } } if (s1 !== peg$FAILED) { s2 = peg$currPos; @@ -3557,11 +3554,11 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 11); - if (s1.toLowerCase() === peg$c89) { + if (s1.toLowerCase() === peg$c90) { peg$currPos += 11; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e94); } + if (peg$silentFails === 0) { peg$fail(peg$e95); } } if (s1 !== peg$FAILED) { s2 = peg$currPos; @@ -3594,11 +3591,11 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 10); - if (s1.toLowerCase() === peg$c90) { + if (s1.toLowerCase() === peg$c91) { peg$currPos += 10; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e95); } + if (peg$silentFails === 0) { peg$fail(peg$e96); } } if (s1 !== peg$FAILED) { s2 = peg$currPos; @@ -3631,11 +3628,11 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 10); - if (s1.toLowerCase() === peg$c91) { + if (s1.toLowerCase() === peg$c92) { peg$currPos += 10; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e96); } + if (peg$silentFails === 0) { peg$fail(peg$e97); } } if (s1 !== peg$FAILED) { s2 = peg$currPos; @@ -3668,11 +3665,11 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 13); - if (s1.toLowerCase() === peg$c92) { + if (s1.toLowerCase() === peg$c93) { peg$currPos += 13; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e97); } + if (peg$silentFails === 0) { peg$fail(peg$e98); } } if (s1 !== peg$FAILED) { s2 = peg$currPos; @@ -3710,7 +3707,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e99); } + if (peg$silentFails === 0) { peg$fail(peg$e100); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; @@ -3719,12 +3716,12 @@ function peg$parse(input, options) { s0 = s1; if (s0 === peg$FAILED) { s0 = peg$currPos; - if (input.substr(peg$currPos, 2) === peg$c93) { - s1 = peg$c93; + if (input.substr(peg$currPos, 2) === peg$c94) { + s1 = peg$c94; peg$currPos += 2; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e100); } + if (peg$silentFails === 0) { peg$fail(peg$e101); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; @@ -3733,12 +3730,12 @@ function peg$parse(input, options) { s0 = s1; if (s0 === peg$FAILED) { s0 = peg$currPos; - if (input.substr(peg$currPos, 2) === peg$c94) { - s1 = peg$c94; + if (input.substr(peg$currPos, 2) === peg$c95) { + s1 = peg$c95; peg$currPos += 2; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e101); } + if (peg$silentFails === 0) { peg$fail(peg$e102); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; @@ -3748,11 +3745,11 @@ function peg$parse(input, options) { if (s0 === peg$FAILED) { s0 = peg$currPos; if (input.charCodeAt(peg$currPos) === 62) { - s1 = peg$c95; + s1 = peg$c96; peg$currPos++; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e102); } + if (peg$silentFails === 0) { peg$fail(peg$e103); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; @@ -3761,12 +3758,12 @@ function peg$parse(input, options) { s0 = s1; if (s0 === peg$FAILED) { s0 = peg$currPos; - if (input.substr(peg$currPos, 2) === peg$c96) { - s1 = peg$c96; + if (input.substr(peg$currPos, 2) === peg$c97) { + s1 = peg$c97; peg$currPos += 2; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e103); } + if (peg$silentFails === 0) { peg$fail(peg$e104); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; @@ -3776,11 +3773,11 @@ function peg$parse(input, options) { if (s0 === peg$FAILED) { s0 = peg$currPos; if (input.charCodeAt(peg$currPos) === 60) { - s1 = peg$c97; + s1 = peg$c98; peg$currPos++; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e104); } + if (peg$silentFails === 0) { peg$fail(peg$e105); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; @@ -3795,7 +3792,7 @@ function peg$parse(input, options) { peg$silentFails--; if (s0 === peg$FAILED) { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e98); } + if (peg$silentFails === 0) { peg$fail(peg$e99); } } return s0; @@ -3826,7 +3823,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e106); } + if (peg$silentFails === 0) { peg$fail(peg$e107); } } if (s2 !== peg$FAILED) { while (s2 !== peg$FAILED) { @@ -3836,7 +3833,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e106); } + if (peg$silentFails === 0) { peg$fail(peg$e107); } } } } else { @@ -3850,7 +3847,7 @@ function peg$parse(input, options) { peg$silentFails--; if (s0 === peg$FAILED) { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e105); } + if (peg$silentFails === 0) { peg$fail(peg$e106); } } return s0; @@ -3878,7 +3875,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e108); } + if (peg$silentFails === 0) { peg$fail(peg$e109); } } while (s1 !== peg$FAILED) { s0.push(s1); @@ -3887,12 +3884,12 @@ function peg$parse(input, options) { peg$currPos++; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e108); } + if (peg$silentFails === 0) { peg$fail(peg$e109); } } } peg$silentFails--; s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e107); } + if (peg$silentFails === 0) { peg$fail(peg$e108); } return s0; } @@ -3939,7 +3936,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e110); } + if (peg$silentFails === 0) { peg$fail(peg$e111); } } while (s2 !== peg$FAILED) { s1.push(s2); @@ -3948,7 +3945,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e110); } + if (peg$silentFails === 0) { peg$fail(peg$e111); } } } s2 = input.charAt(peg$currPos); @@ -3956,7 +3953,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e111); } + if (peg$silentFails === 0) { peg$fail(peg$e112); } } if (s2 !== peg$FAILED) { s3 = []; @@ -3965,7 +3962,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s4 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e112); } + if (peg$silentFails === 0) { peg$fail(peg$e113); } } while (s4 !== peg$FAILED) { s3.push(s4); @@ -3974,7 +3971,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s4 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e112); } + if (peg$silentFails === 0) { peg$fail(peg$e113); } } } s4 = input.charAt(peg$currPos); @@ -3982,7 +3979,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s4 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e111); } + if (peg$silentFails === 0) { peg$fail(peg$e112); } } if (s4 !== peg$FAILED) { s5 = []; @@ -3991,7 +3988,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s6 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e106); } + if (peg$silentFails === 0) { peg$fail(peg$e107); } } while (s6 !== peg$FAILED) { s5.push(s6); @@ -4000,7 +3997,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s6 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e106); } + if (peg$silentFails === 0) { peg$fail(peg$e107); } } } peg$savedPos = s0; @@ -4016,7 +4013,7 @@ function peg$parse(input, options) { peg$silentFails--; if (s0 === peg$FAILED) { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e109); } + if (peg$silentFails === 0) { peg$fail(peg$e110); } } return s0; @@ -4033,7 +4030,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e110); } + if (peg$silentFails === 0) { peg$fail(peg$e111); } } while (s2 !== peg$FAILED) { s1.push(s2); @@ -4042,7 +4039,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e110); } + if (peg$silentFails === 0) { peg$fail(peg$e111); } } } s2 = input.charAt(peg$currPos); @@ -4050,7 +4047,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e111); } + if (peg$silentFails === 0) { peg$fail(peg$e112); } } if (s2 !== peg$FAILED) { s3 = []; @@ -4059,7 +4056,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s4 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e112); } + if (peg$silentFails === 0) { peg$fail(peg$e113); } } if (s4 === peg$FAILED) { s4 = peg$currPos; @@ -4075,11 +4072,11 @@ function peg$parse(input, options) { } if (s5 !== peg$FAILED) { if (input.charCodeAt(peg$currPos) === 8220) { - s6 = peg$c98; + s6 = peg$c99; peg$currPos++; } else { s6 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e113); } + if (peg$silentFails === 0) { peg$fail(peg$e114); } } if (s6 !== peg$FAILED) { peg$savedPos = s4; @@ -4106,11 +4103,11 @@ function peg$parse(input, options) { } if (s5 !== peg$FAILED) { if (input.charCodeAt(peg$currPos) === 8221) { - s6 = peg$c99; + s6 = peg$c100; peg$currPos++; } else { s6 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e114); } + if (peg$silentFails === 0) { peg$fail(peg$e115); } } if (s6 !== peg$FAILED) { peg$savedPos = s4; @@ -4137,11 +4134,11 @@ function peg$parse(input, options) { } if (s5 !== peg$FAILED) { if (input.charCodeAt(peg$currPos) === 34) { - s6 = peg$c100; + s6 = peg$c101; peg$currPos++; } else { s6 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e115); } + if (peg$silentFails === 0) { peg$fail(peg$e116); } } if (s6 !== peg$FAILED) { peg$savedPos = s4; @@ -4164,7 +4161,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s4 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e112); } + if (peg$silentFails === 0) { peg$fail(peg$e113); } } if (s4 === peg$FAILED) { s4 = peg$currPos; @@ -4180,11 +4177,11 @@ function peg$parse(input, options) { } if (s5 !== peg$FAILED) { if (input.charCodeAt(peg$currPos) === 8220) { - s6 = peg$c98; + s6 = peg$c99; peg$currPos++; } else { s6 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e113); } + if (peg$silentFails === 0) { peg$fail(peg$e114); } } if (s6 !== peg$FAILED) { peg$savedPos = s4; @@ -4211,11 +4208,11 @@ function peg$parse(input, options) { } if (s5 !== peg$FAILED) { if (input.charCodeAt(peg$currPos) === 8221) { - s6 = peg$c99; + s6 = peg$c100; peg$currPos++; } else { s6 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e114); } + if (peg$silentFails === 0) { peg$fail(peg$e115); } } if (s6 !== peg$FAILED) { peg$savedPos = s4; @@ -4242,11 +4239,11 @@ function peg$parse(input, options) { } if (s5 !== peg$FAILED) { if (input.charCodeAt(peg$currPos) === 34) { - s6 = peg$c100; + s6 = peg$c101; peg$currPos++; } else { s6 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e115); } + if (peg$silentFails === 0) { peg$fail(peg$e116); } } if (s6 !== peg$FAILED) { peg$savedPos = s4; @@ -4278,7 +4275,7 @@ function peg$parse(input, options) { peg$silentFails--; if (s0 === peg$FAILED) { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e109); } + if (peg$silentFails === 0) { peg$fail(peg$e110); } } return s0; @@ -4293,7 +4290,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e111); } + if (peg$silentFails === 0) { peg$fail(peg$e112); } } if (s1 !== peg$FAILED) { s2 = peg$currPos; @@ -4331,7 +4328,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e116); } + if (peg$silentFails === 0) { peg$fail(peg$e117); } } while (s2 !== peg$FAILED) { s1.push(s2); @@ -4340,7 +4337,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e116); } + if (peg$silentFails === 0) { peg$fail(peg$e117); } } } s2 = []; @@ -4349,7 +4346,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s3 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e117); } + if (peg$silentFails === 0) { peg$fail(peg$e118); } } while (s3 !== peg$FAILED) { s2.push(s3); @@ -4358,7 +4355,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s3 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e117); } + if (peg$silentFails === 0) { peg$fail(peg$e118); } } } s3 = []; @@ -4367,7 +4364,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s4 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e118); } + if (peg$silentFails === 0) { peg$fail(peg$e119); } } while (s4 !== peg$FAILED) { s3.push(s4); @@ -4376,7 +4373,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s4 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e118); } + if (peg$silentFails === 0) { peg$fail(peg$e119); } } } s4 = peg$parseoperator(); @@ -4395,7 +4392,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e119); } + if (peg$silentFails === 0) { peg$fail(peg$e120); } } while (s2 !== peg$FAILED) { s1.push(s2); @@ -4404,7 +4401,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e119); } + if (peg$silentFails === 0) { peg$fail(peg$e120); } } } s2 = peg$currPos; @@ -4451,7 +4448,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s0 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e120); } + if (peg$silentFails === 0) { peg$fail(peg$e121); } } } } @@ -4467,7 +4464,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s0 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e121); } + if (peg$silentFails === 0) { peg$fail(peg$e122); } } if (s0 === peg$FAILED) { s0 = peg$currPos; diff --git a/src/libs/SearchParser/searchParser.peggy b/src/libs/SearchParser/searchParser.peggy index 3a8c8a1c4d2db..9fc895b8ca731 100644 --- a/src/libs/SearchParser/searchParser.peggy +++ b/src/libs/SearchParser/searchParser.peggy @@ -252,6 +252,7 @@ key "key" / submitted / approved / paid + / exportedTo / exported / posted / withdrawn From 595dfcf03d872045eb631d54519d9da082c752b0 Mon Sep 17 00:00:00 2001 From: Samran Ahmed Date: Sat, 31 Jan 2026 05:39:50 +0500 Subject: [PATCH 02/11] Add exportedTo to advanced search filters hook --- src/hooks/useAdvancedSearchFilters.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/hooks/useAdvancedSearchFilters.ts b/src/hooks/useAdvancedSearchFilters.ts index 107a7b90c6c68..48a0445a751fb 100644 --- a/src/hooks/useAdvancedSearchFilters.ts +++ b/src/hooks/useAdvancedSearchFilters.ts @@ -55,6 +55,7 @@ const typeFiltersKeys = { CONST.SEARCH.SYNTAX_FILTER_KEYS.APPROVED, CONST.SEARCH.SYNTAX_FILTER_KEYS.PAID, CONST.SEARCH.SYNTAX_FILTER_KEYS.EXPORTED, + CONST.SEARCH.SYNTAX_FILTER_KEYS.EXPORTED_TO, CONST.SEARCH.SYNTAX_FILTER_KEYS.WITHDRAWAL_TYPE, CONST.SEARCH.SYNTAX_FILTER_KEYS.WITHDRAWAL_ID, CONST.SEARCH.SYNTAX_FILTER_KEYS.WITHDRAWN, @@ -79,6 +80,7 @@ const typeFiltersKeys = { CONST.SEARCH.SYNTAX_FILTER_KEYS.APPROVED, CONST.SEARCH.SYNTAX_FILTER_KEYS.PAID, CONST.SEARCH.SYNTAX_FILTER_KEYS.EXPORTED, + CONST.SEARCH.SYNTAX_FILTER_KEYS.EXPORTED_TO, CONST.SEARCH.SYNTAX_FILTER_KEYS.WITHDRAWAL_TYPE, CONST.SEARCH.SYNTAX_FILTER_KEYS.WITHDRAWAL_ID, CONST.SEARCH.SYNTAX_FILTER_KEYS.WITHDRAWN, @@ -154,6 +156,7 @@ const typeFiltersKeys = { CONST.SEARCH.SYNTAX_FILTER_KEYS.APPROVED, CONST.SEARCH.SYNTAX_FILTER_KEYS.PAID, CONST.SEARCH.SYNTAX_FILTER_KEYS.EXPORTED, + CONST.SEARCH.SYNTAX_FILTER_KEYS.EXPORTED_TO, CONST.SEARCH.SYNTAX_FILTER_KEYS.TITLE, ], ], From fa6b1d27acb89cfafd0e5249c27f7a3c24c56763 Mon Sep 17 00:00:00 2001 From: Samran Ahmed Date: Sat, 31 Jan 2026 05:40:16 +0500 Subject: [PATCH 03/11] Update navigation and routing for exportedTo filter --- .../ModalStackNavigators/index.tsx | 7 +----- .../linkingConfig/RELATIONS/SEARCH_TO_RHP.ts | 1 + src/libs/Navigation/linkingConfig/config.ts | 24 +------------------ 3 files changed, 3 insertions(+), 29 deletions(-) diff --git a/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx b/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx index 9ed54065bb215..6ef810d51202e 100644 --- a/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx +++ b/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx @@ -396,11 +396,6 @@ const SettingsModalStackNavigator = createModalStackNavigator require('../../../../pages/settings/Wallet/ActivatePhysicalCardPage').default, [SCREENS.SETTINGS.WALLET.TRANSFER_BALANCE]: () => require('../../../../pages/settings/Wallet/TransferBalancePage').default, [SCREENS.SETTINGS.WALLET.CHOOSE_TRANSFER_ACCOUNT]: () => require('../../../../pages/settings/Wallet/ChooseTransferAccountPage').default, - [SCREENS.SETTINGS.WALLET.IMPORT_TRANSACTIONS]: () => require('../../../../pages/settings/Wallet/ImportTransactionsPage').default, - [SCREENS.SETTINGS.WALLET.IMPORT_TRANSACTIONS_CARD_NAME]: () => require('../../../../pages/settings/Wallet/ImportTransactionsCardNamePage').default, - [SCREENS.SETTINGS.WALLET.IMPORT_TRANSACTIONS_CURRENCY]: () => require('../../../../pages/settings/Wallet/ImportTransactionsCurrencyPage').default, - [SCREENS.SETTINGS.WALLET.IMPORT_TRANSACTIONS_SPREADSHEET]: () => require('../../../../pages/settings/Wallet/ImportTransactionsSpreadsheetPage').default, - [SCREENS.SETTINGS.WALLET.TRANSACTIONS_IMPORTED]: () => require('../../../../pages/settings/Wallet/TransactionsImportedPage').default, [SCREENS.SETTINGS.WALLET.ENABLE_PAYMENTS]: () => require('../../../../pages/EnablePayments/EnablePayments').default, [SCREENS.SETTINGS.WALLET.UNSHARE_BANK_ACCOUNT]: () => require('../../../../pages/settings/Wallet/UnshareBankAccount/UnshareBankAccount').default, [SCREENS.SETTINGS.WALLET.ENABLE_GLOBAL_REIMBURSEMENTS]: () => require('../../../../pages/settings/Wallet/EnableGlobalReimbursements').default, @@ -767,7 +762,6 @@ const SettingsModalStackNavigator = createModalStackNavigator require('../../../../pages/workspace/expensifyCard/WorkspaceCardSettingsPage').default, [SCREENS.WORKSPACE.EXPENSIFY_CARD_SETTINGS_ACCOUNT]: () => require('../../../../pages/workspace/expensifyCard/WorkspaceSettlementAccountPage').default, [SCREENS.WORKSPACE.EXPENSIFY_CARD_SETTINGS_FREQUENCY]: () => require('../../../../pages/workspace/expensifyCard/WorkspaceSettlementFrequencyPage').default, - [SCREENS.WORKSPACE.TRAVEL_SETTINGS_ACCOUNT]: () => require('../../../../pages/workspace/travel/WorkspaceTravelInvoicingSettlementAccountPage').default, [SCREENS.WORKSPACE.EXPENSIFY_CARD_SELECT_FEED]: () => require('../../../../pages/workspace/expensifyCard/WorkspaceExpensifyCardSelectorPage').default, [SCREENS.WORKSPACE.EXPENSIFY_CARD_BANK_ACCOUNT]: () => require('../../../../pages/workspace/expensifyCard/WorkspaceExpensifyCardBankAccounts').default, [SCREENS.WORKSPACE.EXPENSIFY_CARD_DETAILS]: () => require('../../../../pages/workspace/expensifyCard/WorkspaceExpensifyCardDetailsPage').default, @@ -952,6 +946,7 @@ const SearchAdvancedFiltersModalStackNavigator = createModalStackNavigator require('../../../../pages/Search/SearchAdvancedFiltersPage/SearchFiltersApprovedPage').default, [SCREENS.SEARCH.ADVANCED_FILTERS_PAID_RHP]: () => require('../../../../pages/Search/SearchAdvancedFiltersPage/SearchFiltersPaidPage').default, [SCREENS.SEARCH.ADVANCED_FILTERS_EXPORTED_RHP]: () => require('../../../../pages/Search/SearchAdvancedFiltersPage/SearchFiltersExportedPage').default, + [SCREENS.SEARCH.ADVANCED_FILTERS_EXPORTED_TO_RHP]: () => require('../../../../pages/Search/SearchAdvancedFiltersPage/SearchFiltersExportedToPage').default, [SCREENS.SEARCH.ADVANCED_FILTERS_POSTED_RHP]: () => require('../../../../pages/Search/SearchAdvancedFiltersPage/SearchFiltersPostedPage').default, [SCREENS.SEARCH.ADVANCED_FILTERS_WITHDRAWN_RHP]: () => require('../../../../pages/Search/SearchAdvancedFiltersPage/SearchFiltersWithdrawnPage').default, [SCREENS.SEARCH.ADVANCED_FILTERS_CURRENCY_RHP]: () => require('../../../../pages/Search/SearchAdvancedFiltersPage/SearchFiltersCurrencyPage').default, diff --git a/src/libs/Navigation/linkingConfig/RELATIONS/SEARCH_TO_RHP.ts b/src/libs/Navigation/linkingConfig/RELATIONS/SEARCH_TO_RHP.ts index fb3964849ea89..40391e4cb926d 100644 --- a/src/libs/Navigation/linkingConfig/RELATIONS/SEARCH_TO_RHP.ts +++ b/src/libs/Navigation/linkingConfig/RELATIONS/SEARCH_TO_RHP.ts @@ -22,6 +22,7 @@ const SEARCH_TO_RHP: Partial['config'] = { path: ROUTES.SETTINGS_WALLET_CHOOSE_TRANSFER_ACCOUNT, exact: true, }, - [SCREENS.SETTINGS.WALLET.IMPORT_TRANSACTIONS]: { - path: ROUTES.SETTINGS_WALLET_IMPORT_TRANSACTIONS, - exact: true, - }, - [SCREENS.SETTINGS.WALLET.IMPORT_TRANSACTIONS_CARD_NAME]: { - path: ROUTES.SETTINGS_WALLET_IMPORT_TRANSACTIONS_CARD_NAME, - exact: true, - }, - [SCREENS.SETTINGS.WALLET.IMPORT_TRANSACTIONS_CURRENCY]: { - path: ROUTES.SETTINGS_WALLET_IMPORT_TRANSACTIONS_CURRENCY, - exact: true, - }, - [SCREENS.SETTINGS.WALLET.IMPORT_TRANSACTIONS_SPREADSHEET]: { - path: ROUTES.SETTINGS_WALLET_IMPORT_TRANSACTIONS_SPREADSHEET.route, - exact: true, - }, - [SCREENS.SETTINGS.WALLET.TRANSACTIONS_IMPORTED]: { - path: ROUTES.SETTINGS_WALLET_TRANSACTIONS_IMPORTED.route, - exact: true, - }, [SCREENS.SETTINGS.REPORT_CARD_LOST_OR_DAMAGED]: { path: ROUTES.SETTINGS_WALLET_REPORT_CARD_LOST_OR_DAMAGED.route, exact: true, @@ -821,9 +801,6 @@ const config: LinkingOptions['config'] = { [SCREENS.WORKSPACE.EXPENSIFY_CARD_SELECT_FEED]: { path: ROUTES.WORKSPACE_EXPENSIFY_CARD_SELECT_FEED.route, }, - [SCREENS.WORKSPACE.TRAVEL_SETTINGS_ACCOUNT]: { - path: ROUTES.WORKSPACE_TRAVEL_SETTINGS_ACCOUNT.route, - }, [SCREENS.WORKSPACE.COMPANY_CARDS_SETTINGS]: { path: ROUTES.WORKSPACE_COMPANY_CARDS_SETTINGS.route, }, @@ -1836,6 +1813,7 @@ const config: LinkingOptions['config'] = { [SCREENS.SEARCH.ADVANCED_FILTERS_APPROVED_RHP]: ROUTES.SEARCH_ADVANCED_FILTERS.getRoute(CONST.SEARCH.SYNTAX_FILTER_KEYS.APPROVED), [SCREENS.SEARCH.ADVANCED_FILTERS_PAID_RHP]: ROUTES.SEARCH_ADVANCED_FILTERS.getRoute(CONST.SEARCH.SYNTAX_FILTER_KEYS.PAID), [SCREENS.SEARCH.ADVANCED_FILTERS_EXPORTED_RHP]: ROUTES.SEARCH_ADVANCED_FILTERS.getRoute(CONST.SEARCH.SYNTAX_FILTER_KEYS.EXPORTED), + [SCREENS.SEARCH.ADVANCED_FILTERS_EXPORTED_TO_RHP]: ROUTES.SEARCH_ADVANCED_FILTERS.getRoute(CONST.SEARCH.SYNTAX_FILTER_KEYS.EXPORTED_TO), [SCREENS.SEARCH.ADVANCED_FILTERS_POSTED_RHP]: ROUTES.SEARCH_ADVANCED_FILTERS.getRoute(CONST.SEARCH.SYNTAX_FILTER_KEYS.POSTED), [SCREENS.SEARCH.ADVANCED_FILTERS_WITHDRAWN_RHP]: ROUTES.SEARCH_ADVANCED_FILTERS.getRoute(CONST.SEARCH.SYNTAX_FILTER_KEYS.WITHDRAWN), [SCREENS.SEARCH.ADVANCED_FILTERS_CURRENCY_RHP]: ROUTES.SEARCH_ADVANCED_FILTERS.getRoute(CONST.SEARCH.SYNTAX_FILTER_KEYS.CURRENCY), From 0a3ea182527ce3d4838d973d0824a263ddd04051 Mon Sep 17 00:00:00 2001 From: Samran Ahmed Date: Sat, 31 Jan 2026 05:40:28 +0500 Subject: [PATCH 04/11] Add exportedTo filter types and form definitions --- src/types/form/SearchAdvancedFiltersForm.ts | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/types/form/SearchAdvancedFiltersForm.ts b/src/types/form/SearchAdvancedFiltersForm.ts index 54c33c46ab913..839f878f637bd 100644 --- a/src/types/form/SearchAdvancedFiltersForm.ts +++ b/src/types/form/SearchAdvancedFiltersForm.ts @@ -128,6 +128,9 @@ const FILTER_KEYS = { EXPORTER_NOT: 'exporterNot', EXPORTER: 'exporter', + EXPORTED_TO_NOT: 'exportedToNot', + EXPORTED_TO: 'exportedTo', + IN_NOT: 'inNot', IN: 'in', @@ -249,6 +252,8 @@ const ALLOWED_TYPE_FILTERS = { FILTER_KEYS.EXPORTED_BEFORE, FILTER_KEYS.EXPORTER, FILTER_KEYS.EXPORTER_NOT, + FILTER_KEYS.EXPORTED_TO, + FILTER_KEYS.EXPORTED_TO_NOT, FILTER_KEYS.GROUP_BY, FILTER_KEYS.VIEW, FILTER_KEYS.ACTION, @@ -318,6 +323,8 @@ const ALLOWED_TYPE_FILTERS = { FILTER_KEYS.EXPORTED_ON, FILTER_KEYS.EXPORTED_NOT, FILTER_KEYS.EXPORTER, + FILTER_KEYS.EXPORTED_TO, + FILTER_KEYS.EXPORTED_TO_NOT, FILTER_KEYS.ACTION, FILTER_KEYS.ACTION_NOT, FILTER_KEYS.WITHDRAWAL_ID, @@ -476,6 +483,8 @@ const ALLOWED_TYPE_FILTERS = { FILTER_KEYS.EXPORTED_BEFORE, FILTER_KEYS.EXPORTER, FILTER_KEYS.EXPORTER_NOT, + FILTER_KEYS.EXPORTED_TO, + FILTER_KEYS.EXPORTED_TO_NOT, FILTER_KEYS.ACTION, FILTER_KEYS.ACTION_NOT, FILTER_KEYS.PURCHASE_AMOUNT_EQUAL_TO, @@ -636,6 +645,9 @@ type SearchAdvancedFiltersForm = Form< [FILTER_KEYS.EXPORTER]: string[]; [FILTER_KEYS.EXPORTER_NOT]: string[]; + [FILTER_KEYS.EXPORTED_TO]: string[]; + [FILTER_KEYS.EXPORTED_TO_NOT]: string[]; + [FILTER_KEYS.TO]: string[]; [FILTER_KEYS.TO_NOT]: string[]; From eaa85d22e54430a4cc717e8f84fd84f51264e245 Mon Sep 17 00:00:00 2001 From: Samran Ahmed Date: Sat, 31 Jan 2026 05:40:37 +0500 Subject: [PATCH 05/11] Implement exportedTo filter utilities and logic --- src/libs/ReportUtils.ts | 76 ++++++++++++++++++----------- src/libs/SearchAutocompleteUtils.ts | 4 ++ src/libs/SearchQueryUtils.ts | 45 +++++++++++++++++ 3 files changed, 97 insertions(+), 28 deletions(-) diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index a108a3773df06..9c820061e5bf7 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -59,7 +59,6 @@ import type { Transaction, TransactionViolation, TransactionViolations, - VisibleReportActionsDerivedValue, } from '@src/types/onyx'; import type {ReportTransactionsAndViolations} from '@src/types/onyx/DerivedValues'; import type {Attendee, Participant} from '@src/types/onyx/IOU'; @@ -267,7 +266,6 @@ import { isRenamedAction, isReopenedAction, isReportActionAttachment, - isReportActionVisible, isReportPreviewAction, isRetractedAction, isReversedTransaction, @@ -282,6 +280,7 @@ import { isTripPreview, isUnapprovedAction, isWhisperAction, + shouldReportActionBeVisible, wasActionTakenByCurrentUser, } from './ReportActionsUtils'; import type {LastVisibleMessage} from './ReportActionsUtils'; @@ -7034,7 +7033,7 @@ function getMovedTransactionMessage(translate: LocalizedTranslate, action: Repor // This will be fixed as follow up https://github.com/Expensify/App/pull/75357 // eslint-disable-next-line @typescript-eslint/no-deprecated - const reportName = Parser.htmlToText(getReportName(report) ?? report?.reportName ?? ''); + const reportName = getReportName(report) ?? report?.reportName ?? ''; const reportUrl = getReportURLForCurrentContext(report?.reportID); if (typeof fromReportID === 'undefined') { return translate('iou.movedTransactionTo', { @@ -7056,7 +7055,7 @@ function getUnreportedTransactionMessage(translate: LocalizedTranslate, action: // This will be fixed as follow up https://github.com/Expensify/App/pull/75357 // eslint-disable-next-line @typescript-eslint/no-deprecated - const reportName = Parser.htmlToText(getReportName(fromReport) ?? fromReport?.reportName ?? ''); + const reportName = getReportName(fromReport) ?? fromReport?.reportName ?? ''; let reportUrl = getReportURLForCurrentContext(fromReportID); @@ -9157,23 +9156,14 @@ function isReportNotFound(report: OnyxEntry): boolean { /** * Check if the report is the parent report of the currently viewed report or at least one child report has report action */ -function shouldHideReport( - report: OnyxEntry, - currentReportId: string | undefined, - isReportArchived: boolean | undefined, - visibleReportActionsData?: VisibleReportActionsDerivedValue, -): boolean { +function shouldHideReport(report: OnyxEntry, currentReportId: string | undefined, isReportArchived: boolean | undefined): boolean { const currentReport = getReportOrDraftReport(currentReportId); const parentReport = getParentReport(!isEmptyObject(currentReport) ? currentReport : undefined); const reportActions = allReportActions?.[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${report?.reportID}`] ?? {}; - const reportID = report?.reportID; - const isChildReportHasComment = - !!reportID && - Object.values(reportActions ?? {})?.some( - (reportAction) => - (reportAction?.childVisibleActionCount ?? 0) > 0 && - isReportActionVisible(reportAction, reportID, canUserPerformWriteAction(report, isReportArchived), visibleReportActionsData), - ); + const isChildReportHasComment = Object.values(reportActions ?? {})?.some( + (reportAction) => + (reportAction?.childVisibleActionCount ?? 0) > 0 && shouldReportActionBeVisible(reportAction, reportAction.reportActionID, canUserPerformWriteAction(report, isReportArchived)), + ); return parentReport?.reportID !== report?.reportID && !isChildReportHasComment; } @@ -10201,13 +10191,7 @@ function isMoneyRequestReportPendingDeletion(reportOrID: OnyxEntry | str return parentReportAction?.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE; } -function navigateToLinkedReportAction( - ancestor: Ancestor, - isInNarrowPaneModal: boolean, - canUserPerformWrite: boolean | undefined, - isOffline: boolean, - visibleReportActionsData?: VisibleReportActionsDerivedValue, -) { +function navigateToLinkedReportAction(ancestor: Ancestor, isInNarrowPaneModal: boolean, canUserPerformWrite: boolean | undefined, isOffline: boolean) { if (isInNarrowPaneModal) { Navigation.navigate( ROUTES.SEARCH_REPORT.getRoute({ @@ -10222,8 +10206,7 @@ function navigateToLinkedReportAction( // Pop the thread report screen before navigating to the chat report. Navigation.goBack(ROUTES.REPORT_WITH_ID.getRoute(ancestor.report.reportID)); - const reportID = ancestor.report.reportID; - const isVisibleAction = !!reportID && isReportActionVisible(ancestor.reportAction, reportID, canUserPerformWrite, visibleReportActionsData); + const isVisibleAction = shouldReportActionBeVisible(ancestor.reportAction, ancestor.reportAction.reportActionID, canUserPerformWrite); if (isVisibleAction && !isOffline) { // Pop the chat report screen before navigating to the linked report action. @@ -12355,7 +12338,10 @@ function getSourceIDFromReportAction(reportAction: OnyxEntry): str return sourceID; } -function getIntegrationIcon(connectionName?: ConnectionName, expensifyIcons?: Record<'XeroSquare' | 'QBOSquare' | 'NetSuiteSquare' | 'IntacctSquare' | 'QBDSquare', IconAsset> | undefined) { +function getIntegrationIcon( + connectionName?: ConnectionName, + expensifyIcons?: Record<'XeroSquare' | 'QBOSquare' | 'NetSuiteSquare' | 'IntacctSquare' | 'QBDSquare' | 'CertiniaSquare', IconAsset> | undefined, +) { if (connectionName === CONST.POLICY.CONNECTIONS.NAME.XERO) { return expensifyIcons?.XeroSquare; } @@ -12371,6 +12357,38 @@ function getIntegrationIcon(connectionName?: ConnectionName, expensifyIcons?: Re if (connectionName === CONST.POLICY.CONNECTIONS.NAME.QBD) { return expensifyIcons?.QBDSquare; } + if (connectionName === CONST.POLICY.CONNECTIONS.NAME.CERTINIA) { + return expensifyIcons?.CertiniaSquare; + } + + return undefined; +} + +function getConnectionNameForExportedToFilter(value: string): ConnectionName | undefined { + const map: Record = { + xero: CONST.POLICY.CONNECTIONS.NAME.XERO, + qbo: CONST.POLICY.CONNECTIONS.NAME.QBO, + qbd: CONST.POLICY.CONNECTIONS.NAME.QBD, + netsuite: CONST.POLICY.CONNECTIONS.NAME.NETSUITE, + intacct: CONST.POLICY.CONNECTIONS.NAME.SAGE_INTACCT, + certinia: CONST.POLICY.CONNECTIONS.NAME.CERTINIA, + }; + return map[value.toLowerCase()]; +} + +function getIntegrationExportIcon(connectionName?: ConnectionName): 'XeroExport' | 'QBOExport' | 'NetSuiteExport' | 'SageIntacctExport' | undefined { + if (connectionName === CONST.POLICY.CONNECTIONS.NAME.XERO) { + return 'XeroExport'; + } + if (connectionName === CONST.POLICY.CONNECTIONS.NAME.QBO || connectionName === CONST.POLICY.CONNECTIONS.NAME.QBD) { + return 'QBOExport'; + } + if (connectionName === CONST.POLICY.CONNECTIONS.NAME.NETSUITE) { + return 'NetSuiteExport'; + } + if (connectionName === CONST.POLICY.CONNECTIONS.NAME.SAGE_INTACCT) { + return 'SageIntacctExport'; + } return undefined; } @@ -13358,7 +13376,9 @@ export { getFieldViolation, getReportViolations, findPolicyExpenseChatByPolicyID, + getConnectionNameForExportedToFilter, getIntegrationIcon, + getIntegrationExportIcon, canBeExported, isExported, hasExportError, diff --git a/src/libs/SearchAutocompleteUtils.ts b/src/libs/SearchAutocompleteUtils.ts index e6e0aa7387ed6..1dbfdf96c76d7 100644 --- a/src/libs/SearchAutocompleteUtils.ts +++ b/src/libs/SearchAutocompleteUtils.ts @@ -141,6 +141,8 @@ const userFriendlyColumnList = new Set( .map(([, value]) => value), ); +const exportedToFilterList = ['xero', 'qbo', 'qbd', 'netsuite', 'intacct', 'certinia']; + /** * @private * Determines if a specific value in the search syntax can/should be highlighted as valid or not @@ -229,6 +231,8 @@ function filterOutRangesWithCorrectValue( case CONST.SEARCH.SYNTAX_FILTER_KEYS.DESCRIPTION: case CONST.SEARCH.SYNTAX_FILTER_KEYS.TITLE: return range.value.length > 0; + case CONST.SEARCH.SYNTAX_FILTER_KEYS.EXPORTED_TO: + return exportedToFilterList.includes(range.value.toLowerCase()); case CONST.SEARCH.SYNTAX_FILTER_KEYS.WITHDRAWAL_ID: case CONST.SEARCH.SYNTAX_FILTER_KEYS.REPORT_ID: return !['', 'null', 'undefined', '0', '-1'].includes(range.value); diff --git a/src/libs/SearchQueryUtils.ts b/src/libs/SearchQueryUtils.ts index 6d3688c3e5baf..981705658550c 100644 --- a/src/libs/SearchQueryUtils.ts +++ b/src/libs/SearchQueryUtils.ts @@ -118,6 +118,22 @@ function getUserFriendlyValue(value: string | undefined): UserFriendlyValue { return CONST.SEARCH.SEARCH_USER_FRIENDLY_VALUES_MAP[value as keyof typeof CONST.SEARCH.SEARCH_USER_FRIENDLY_VALUES_MAP] ?? value; } +/** + * @private + * Converts exportedTo internal ID to the display label expected by the search API in the query string. + * When building the URL from form values, we must send the display label (e.g. "All Data - Expense Level Export") + * not the internal template name (e.g. detailed_export), so that the backend returns results. + */ +function getExportedToQueryValue(value: string): string { + if (value === CONST.REPORT.EXPORT_OPTIONS.REPORT_LEVEL_EXPORT) { + return CONST.REPORT.EXPORT_OPTION_LABELS.REPORT_LEVEL_EXPORT; + } + if (value === CONST.REPORT.EXPORT_OPTIONS.EXPENSE_LEVEL_EXPORT) { + return CONST.REPORT.EXPORT_OPTION_LABELS.EXPENSE_LEVEL_EXPORT; + } + return value; +} + /** * @private * Returns string value wrapped in quotes "", if the value contains space or   (no-breaking space). @@ -600,6 +616,12 @@ function buildQueryStringFromFilterFormValues(filterValues: Partial 0) { + otherFilters.exportedTo = otherFilters.exportedTo.map(getExportedToQueryValue); + } + const filtersString: string[] = []; filtersString.push(`${CONST.SEARCH.SYNTAX_ROOT_KEYS.SORT_BY}:${options?.sortBy ?? CONST.SEARCH.TABLE_COLUMNS.DATE}`); @@ -728,6 +750,7 @@ function buildQueryStringFromFilterFormValues(filterValues: Partial personalDetails?.[id]); } + if (filterKey === CONST.SEARCH.SYNTAX_FILTER_KEYS.EXPORTED_TO) { + // Normalize display labels from URL back to internal IDs so the Export to picker can match selected items + const formValues = filterValues.map((val) => { + if (val === CONST.REPORT.EXPORT_OPTION_LABELS.REPORT_LEVEL_EXPORT) { + return CONST.REPORT.EXPORT_OPTIONS.REPORT_LEVEL_EXPORT; + } + if (val === CONST.REPORT.EXPORT_OPTION_LABELS.EXPENSE_LEVEL_EXPORT) { + return CONST.REPORT.EXPORT_OPTIONS.EXPENSE_LEVEL_EXPORT; + } + return val; + }); + filtersForm[key as typeof filterKey] = formValues; + } if (filterKey === CONST.SEARCH.SYNTAX_FILTER_KEYS.PAYER) { filtersForm[key as typeof filterKey] = filterValues.find((id) => personalDetails?.[id]); @@ -1109,6 +1145,15 @@ function getFilterDisplayValue( if (filterName === CONST.SEARCH.SYNTAX_FILTER_KEYS.POLICY_ID) { return getPolicyNameWithFallback(filterValue, policies, reports); } + if (filterName === CONST.SEARCH.SYNTAX_FILTER_KEYS.EXPORTED_TO) { + if (filterValue === CONST.REPORT.EXPORT_OPTIONS.REPORT_LEVEL_EXPORT) { + return CONST.REPORT.EXPORT_OPTION_LABELS.REPORT_LEVEL_EXPORT; + } + if (filterValue === CONST.REPORT.EXPORT_OPTIONS.EXPENSE_LEVEL_EXPORT) { + return CONST.REPORT.EXPORT_OPTION_LABELS.EXPENSE_LEVEL_EXPORT; + } + return filterValue; + } return filterValue; } From 24e11231a4f77a5564623c1db22a3bccd4abeb72 Mon Sep 17 00:00:00 2001 From: Samran Ahmed Date: Sat, 31 Jan 2026 05:40:50 +0500 Subject: [PATCH 06/11] Add exportedTo filter UI components --- src/CONST/index.ts | 22 ++- .../Search/SearchAutocompleteList.tsx | 41 +++--- src/pages/Search/AdvancedSearchFilters.tsx | 23 +++ .../SearchFiltersExportedToPage.tsx | 133 ++++++++++++++++++ 4 files changed, 189 insertions(+), 30 deletions(-) create mode 100644 src/pages/Search/SearchAdvancedFiltersPage/SearchFiltersExportedToPage.tsx diff --git a/src/CONST/index.ts b/src/CONST/index.ts index 7c7b810bf5a27..c648f52f56c5b 100755 --- a/src/CONST/index.ts +++ b/src/CONST/index.ts @@ -744,6 +744,7 @@ const CONST = { ZERO_EXPENSES: 'zeroExpenses', NEW_DOT_DEW: 'newDotDEW', GPS_MILEAGE: 'gpsMileage', + NEW_DOT_HOME: 'newDotHome', PERSONAL_CARD_IMPORT: 'personalCardImport', }, BUTTON_STATES: { @@ -1075,14 +1076,14 @@ const CONST = { // Use Environment.getEnvironmentURL to get the complete URL with port number DEV_NEW_EXPENSIFY_URL: 'https://dev.new.expensify.com:', STORYLANE: { - ADMIN_TOUR: 'https://expensify.storylane.io/share/nfrgmfpppolt', - ADMIN_TOUR_MOBILE: 'https://expensify.storylane.io/share/7t9urrrcqk5k', + ADMIN_TOUR: 'https://app.storylane.io/demo/bbcreg8vccag?embed=inline', + ADMIN_TOUR_MOBILE: 'https://app.storylane.io/demo/b6faqcdsxgww?embed=inline', ADMIN_MIGRATED: 'https://app.storylane.io/share/qlgnexxbsdtp', ADMIN_MIGRATED_MOBILE: 'https://app.storylane.io/share/fgireksbt2oh', TRACK_WORKSPACE_TOUR: 'https://app.storylane.io/share/mqzy3huvtrhx?embed=inline', TRACK_WORKSPACE_TOUR_MOBILE: 'https://app.storylane.io/share/wq4hiwsqvoho?embed=inline', - EMPLOYEE_TOUR: 'https://expensify.storylane.io/share/ohsppww6qi71', - EMPLOYEE_TOUR_MOBILE: 'https://expensify.storylane.io/share/v8uwkznocw0g', + EMPLOYEE_TOUR: 'https://app.storylane.io/share/izmryscwurdd?embed=inline', + EMPLOYEE_TOUR_MOBILE: 'https://app.storylane.io/share/wckqdetaacgy?embed=inline', EMPLOYEE_MIGRATED: 'https://app.storylane.io/share/v9dr1rjqsd9y', EMPLOYEE_MIGRATED_MOBILE: 'https://app.storylane.io/share/qbbob6zvapqo', }, @@ -3274,6 +3275,7 @@ const CONST = { XERO: 'xero', NETSUITE: 'netsuite', SAGE_INTACCT: 'intacct', + CERTINIA: 'certinia', }, SUPPORTED_ONLY_ON_OLDDOT: { FINANCIALFORCE: 'financialForce', @@ -3295,6 +3297,7 @@ const CONST = { xero: 'Xero', intacct: 'Sage Intacct', financialForce: 'FinancialForce', + certinia: 'Certinia', billCom: 'Bill.com', zenefits: 'Zenefits', sap: 'SAP', @@ -7225,6 +7228,7 @@ const CONST = { ATTENDEE: 'attendee', IS: 'is', REPORT_FIELD: 'reportField', + EXPORTED_TO: 'exportedTo', }, REPORT_FIELD: { // All report fields start with this, so use this to check if a search key is a report field @@ -7291,6 +7295,7 @@ const CONST = { ATTENDEE: 'attendee', IS: 'is', REPORT_FIELD: 'report-field', + EXPORTED_TO: 'exported-to', COLUMNS: 'columns', LIMIT: 'limit', }, @@ -7404,6 +7409,7 @@ const CONST = { }, TODO_BADGE_MAX_COUNT: 50, TOP_SEARCH_LIMIT: 10, + PREDEFINED_INTEGRATION_FILTER_VALUES: ['xero', 'qbo', 'qbd', 'netsuite', 'intacct', 'certinia'], }, SEARCH_SELECTOR: { SELECTION_MODE_SINGLE: 'single', @@ -8018,8 +8024,6 @@ const CONST = { HOME: 'NavigationTabBar-Home', FLOATING_ACTION_BUTTON: 'NavigationTabBar-FloatingActionButton', FLOATING_RECEIPT_BUTTON: 'NavigationTabBar-FloatingReceiptButton', - FLOATING_GPS_BUTTON: 'NavigationTabBar-FloatingGpsButton', - FLOATING_CAMERA_BUTTON: 'NavigationTabBar-FloatingCameraButton', }, FAB_MENU: { CREATE_EXPENSE: 'FABMenu-CreateExpense', @@ -8200,12 +8204,6 @@ const CONST = { VIEW_ASSIGNEE: 'Task-ViewAssignee', HEADER_ACTION_BUTTON: 'Task-HeaderActionButton', }, - DISCOVER_SECTION: { - TEST_DRIVE: 'DiscoverSection-TestDrive', - }, - HOME_PAGE: { - WIDGET_ITEM: 'HomePage-WidgetItem', - }, }, DOMAIN: { diff --git a/src/components/Search/SearchAutocompleteList.tsx b/src/components/Search/SearchAutocompleteList.tsx index e839504b4989a..dee09b3362200 100644 --- a/src/components/Search/SearchAutocompleteList.tsx +++ b/src/components/Search/SearchAutocompleteList.tsx @@ -17,6 +17,7 @@ import useLocalize from '@hooks/useLocalize'; import useOnyx from '@hooks/useOnyx'; import useResponsiveLayout from '@hooks/useResponsiveLayout'; import useThemeStyles from '@hooks/useThemeStyles'; +import {getExportTemplates} from '@libs/actions/Search'; import {getCardFeedsForDisplay} from '@libs/CardFeedUtils'; import {getCardDescription, isCard, isCardHiddenFromSearch} from '@libs/CardUtils'; import {getDecodedCategoryName} from '@libs/CategoryUtils'; @@ -196,7 +197,6 @@ function SearchAutocompleteList({ const [recentSearches] = useOnyx(ONYXKEYS.RECENT_SEARCHES, {canBeMissing: true}); const [countryCode] = useOnyx(ONYXKEYS.COUNTRY_CODE, {canBeMissing: false}); const [loginList] = useOnyx(ONYXKEYS.LOGIN_LIST, {canBeMissing: true}); - const [visibleReportActionsData] = useOnyx(ONYXKEYS.DERIVED.VISIBLE_REPORT_ACTIONS, {canBeMissing: true}); const currentUserPersonalDetails = useCurrentUserPersonalDetails(); const currentUserEmail = currentUserPersonalDetails.email ?? ''; const currentUserAccountID = currentUserPersonalDetails.accountID; @@ -223,23 +223,10 @@ function SearchAutocompleteList({ shouldShowGBR: false, shouldUnreadBeBold: true, loginList, - visibleReportActionsData, currentUserAccountID, currentUserEmail, }); - }, [ - areOptionsInitialized, - options, - draftComments, - nvpDismissedProductTraining, - betas, - autocompleteQueryValue, - countryCode, - loginList, - visibleReportActionsData, - currentUserAccountID, - currentUserEmail, - ]); + }, [areOptionsInitialized, options, draftComments, nvpDismissedProductTraining, betas, autocompleteQueryValue, countryCode, loginList, currentUserAccountID, currentUserEmail]); const [isInitialRender, setIsInitialRender] = useState(true); const parsedQuery = useMemo(() => parseForAutocomplete(autocompleteQueryValue), [autocompleteQueryValue]); @@ -340,6 +327,15 @@ function SearchAutocompleteList({ }, [allPoliciesTags]); const recentTagsAutocompleteList = useMemo(() => getAutocompleteRecentTags(allRecentTags), [allRecentTags]); + const [integrationsExportTemplates] = useOnyx(ONYXKEYS.NVP_INTEGRATION_SERVER_EXPORT_TEMPLATES, {canBeMissing: true}); + const [csvExportLayouts] = useOnyx(ONYXKEYS.NVP_CSV_EXPORT_LAYOUTS, {canBeMissing: true}); + const exportedToAutocompleteList = useMemo(() => { + const predefinedValues = CONST.SEARCH.PREDEFINED_INTEGRATION_FILTER_VALUES; + const exportTemplates = getExportTemplates(integrationsExportTemplates ?? [], csvExportLayouts ?? {}, translate, undefined, true); + const customNames = exportTemplates.map((t) => t.templateName).filter(Boolean); + return [...new Set([...predefinedValues, ...customNames])]; + }, [integrationsExportTemplates, csvExportLayouts, translate]); + const [autocompleteParsedQuery, autocompleteQueryWithoutFilters] = useMemo(() => { const queryWithoutFilters = getQueryWithoutFilters(autocompleteQueryValue); return [parsedQuery, queryWithoutFilters]; @@ -450,7 +446,6 @@ function SearchAutocompleteList({ countryCode, loginList, shouldShowGBR: true, - visibleReportActionsData, currentUserAccountID, currentUserEmail, }).personalDetails.filter((participant) => participant.text && !alreadyAutocompletedKeys.has(participant.text.toLowerCase())); @@ -484,7 +479,6 @@ function SearchAutocompleteList({ countryCode, loginList, shouldShowGBR: true, - visibleReportActionsData, currentUserAccountID, currentUserEmail, }).recentReports.filter((chat) => { @@ -633,6 +627,17 @@ function SearchAutocompleteList({ case CONST.SEARCH.SYNTAX_FILTER_KEYS.SUBMITTED: case CONST.SEARCH.SYNTAX_FILTER_KEYS.APPROVED: case CONST.SEARCH.SYNTAX_FILTER_KEYS.PAID: + case CONST.SEARCH.SYNTAX_FILTER_KEYS.EXPORTED_TO: { + const filteredExportedTo = exportedToAutocompleteList + .filter((value) => value.toLowerCase().includes(autocompleteValue.toLowerCase()) && !alreadyAutocompletedKeys.has(value.toLowerCase())) + .sort() + .slice(0, 10); + return filteredExportedTo.map((value) => ({ + filterKey: CONST.SEARCH.SEARCH_USER_FRIENDLY_KEYS.EXPORTED_TO, + text: value, + mapKey: CONST.SEARCH.SYNTAX_FILTER_KEYS.EXPORTED_TO, + })); + } case CONST.SEARCH.SYNTAX_FILTER_KEYS.EXPORTED: case CONST.SEARCH.SYNTAX_FILTER_KEYS.WITHDRAWN: case CONST.SEARCH.SYNTAX_FILTER_KEYS.POSTED: { @@ -673,7 +678,7 @@ function SearchAutocompleteList({ workspaceList, hasAutocompleteList, isAutocompleteList, - visibleReportActionsData, + exportedToAutocompleteList, ]); const sortedRecentSearches = useMemo(() => { diff --git a/src/pages/Search/AdvancedSearchFilters.tsx b/src/pages/Search/AdvancedSearchFilters.tsx index 8c77d9f28cb02..75f4657e2f489 100644 --- a/src/pages/Search/AdvancedSearchFilters.tsx +++ b/src/pages/Search/AdvancedSearchFilters.tsx @@ -107,6 +107,11 @@ const baseFilterConfig = { description: 'search.filters.exported' as const, route: ROUTES.SEARCH_ADVANCED_FILTERS.getRoute(CONST.SEARCH.SYNTAX_FILTER_KEYS.EXPORTED), }, + exportedTo: { + getTitle: getFilterDisplayTitle, + description: 'search.exportedTo' as const, + route: ROUTES.SEARCH_ADVANCED_FILTERS.getRoute(CONST.SEARCH.SYNTAX_FILTER_KEYS.EXPORTED_TO), + }, posted: { getTitle: getFilterDisplayTitle, description: 'search.filters.posted' as const, @@ -491,6 +496,24 @@ function getFilterDisplayTitle( return filterValue ? filterValue.map((value) => translate(`common.${value as ValueOf}`)).join(', ') : undefined; } + if (key === CONST.SEARCH.SYNTAX_FILTER_KEYS.EXPORTED_TO) { + const filterValue = filters[key]; + if (!filterValue) { + return undefined; + } + return (Array.isArray(filterValue) ? filterValue : [filterValue]) + .map((value) => { + if (value === CONST.REPORT.EXPORT_OPTIONS.REPORT_LEVEL_EXPORT) { + return CONST.REPORT.EXPORT_OPTION_LABELS.REPORT_LEVEL_EXPORT; + } + if (value === CONST.REPORT.EXPORT_OPTIONS.EXPENSE_LEVEL_EXPORT) { + return CONST.REPORT.EXPORT_OPTION_LABELS.EXPENSE_LEVEL_EXPORT; + } + return value; + }) + .join(', '); + } + const filterValue = filters[key]; return Array.isArray(filterValue) ? filterValue.join(', ') : filterValue; } diff --git a/src/pages/Search/SearchAdvancedFiltersPage/SearchFiltersExportedToPage.tsx b/src/pages/Search/SearchAdvancedFiltersPage/SearchFiltersExportedToPage.tsx new file mode 100644 index 0000000000000..ca8a5e8be12d9 --- /dev/null +++ b/src/pages/Search/SearchAdvancedFiltersPage/SearchFiltersExportedToPage.tsx @@ -0,0 +1,133 @@ +import React, {useMemo} from 'react'; +import {View} from 'react-native'; +import Table from '@assets/images/table.svg'; +import HeaderWithBackButton from '@components/HeaderWithBackButton'; +import Icon from '@components/Icon'; +import ScreenWrapper from '@components/ScreenWrapper'; +import SearchMultipleSelectionPicker from '@components/Search/SearchMultipleSelectionPicker'; +import type {SearchMultipleSelectionPickerItem} from '@components/Search/SearchMultipleSelectionPicker'; +import {useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset'; +import useLocalize from '@hooks/useLocalize'; +import useOnyx from '@hooks/useOnyx'; +import useStyleUtils from '@hooks/useStyleUtils'; +import useThemeStyles from '@hooks/useThemeStyles'; +import {getExportTemplates, updateAdvancedFilters} from '@libs/actions/Search'; +import Navigation from '@libs/Navigation/Navigation'; +import {getConnectionNameForExportedToFilter, getIntegrationIcon} from '@libs/ReportUtils'; +import CONST from '@src/CONST'; +import ONYXKEYS from '@src/ONYXKEYS'; +import ROUTES from '@src/ROUTES'; + +const PREDEFINED_INTEGRATION_VALUES = [ + {value: 'xero', displayKey: 'xero' as const}, + {value: 'qbo', displayKey: 'quickbooksOnline' as const}, + {value: 'qbd', displayKey: 'quickbooksDesktop' as const}, + {value: 'netsuite', displayKey: 'netsuite' as const}, + {value: 'intacct', displayKey: 'intacct' as const}, + {value: 'certinia', displayKey: 'certinia' as const}, +] as const; + +function SearchFiltersExportedToPage() { + const styles = useThemeStyles(); + const {translate} = useLocalize(); + const StyleUtils = useStyleUtils(); + const expensifyIcons = useMemoizedLazyExpensifyIcons(['XeroSquare', 'QBOSquare', 'NetSuiteSquare', 'IntacctSquare', 'QBDSquare', 'CertiniaSquare']); + + const [searchAdvancedFiltersForm] = useOnyx(ONYXKEYS.FORMS.SEARCH_ADVANCED_FILTERS_FORM, {canBeMissing: true}); + const [integrationsExportTemplates] = useOnyx(ONYXKEYS.NVP_INTEGRATION_SERVER_EXPORT_TEMPLATES, {canBeMissing: true}); + const [csvExportLayouts] = useOnyx(ONYXKEYS.NVP_CSV_EXPORT_LAYOUTS, {canBeMissing: true}); + const policyIDs = searchAdvancedFiltersForm?.policyID ?? []; + const [policies] = useOnyx(ONYXKEYS.COLLECTION.POLICY, {canBeMissing: true}); + const policy = policyIDs?.length === 1 ? policies?.[`${ONYXKEYS.COLLECTION.POLICY}${policyIDs[0]}`] : undefined; + + const tableIconElement = useMemo( + () => ( + + + + ), + [styles], + ); + + const items = useMemo((): SearchMultipleSelectionPickerItem[] => { + const integrationItems: SearchMultipleSelectionPickerItem[] = PREDEFINED_INTEGRATION_VALUES.map((item) => { + const connectionName = getConnectionNameForExportedToFilter(item.value); + const icon = connectionName ? getIntegrationIcon(connectionName, expensifyIcons) : undefined; + const leftElement = + icon != null ? ( + + + + ) : ( + tableIconElement + ); + return { + name: CONST.POLICY.CONNECTIONS.NAME_USER_FRIENDLY[item.displayKey], + value: item.value, + leftElement, + }; + }); + const exportTemplates = getExportTemplates(integrationsExportTemplates ?? [], csvExportLayouts ?? {}, translate, policy, true); + + const otherItems: SearchMultipleSelectionPickerItem[] = exportTemplates + .filter((template) => template.templateName && !PREDEFINED_INTEGRATION_VALUES.some((p) => p.value === template.templateName?.toLowerCase())) + .map((template) => ({ + name: template.name ?? template.templateName ?? '', + value: template.templateName, + leftElement: tableIconElement, + })) + .filter((item) => item.name !== '') + .sort((a, b) => (a.name as string).localeCompare(b.name as string)); + + return [...integrationItems, ...otherItems]; + }, [integrationsExportTemplates, csvExportLayouts, policy, expensifyIcons, styles, StyleUtils, translate, tableIconElement]); + + const initiallySelectedItems = useMemo((): SearchMultipleSelectionPickerItem[] | undefined => { + const selectedValues = searchAdvancedFiltersForm?.exportedTo ?? []; + if (selectedValues.length === 0) { + return undefined; + } + const normalizedSet = new Set(selectedValues.map((v) => v.toLowerCase())); + return items.filter((item) => normalizedSet.has(item.value as string)); + }, [searchAdvancedFiltersForm?.exportedTo, items]); + + const onSaveSelection = useMemo( + () => (values: string[]) => { + updateAdvancedFilters({exportedTo: values}); + }, + [], + ); + + return ( + + Navigation.goBack(ROUTES.SEARCH_ADVANCED_FILTERS.getRoute())} + /> + + + + + ); +} + +export default SearchFiltersExportedToPage; From 7296c4970f435b1a965d302d8e89994acc90c5b2 Mon Sep 17 00:00:00 2001 From: Samran Ahmed Date: Sat, 31 Jan 2026 06:22:06 +0500 Subject: [PATCH 07/11] resolve merge conflicts --- src/CONST/index.ts | 17 ++++++--- src/SCREENS.ts | 1 + .../Search/SearchAutocompleteList.tsx | 19 +++++++++- .../Search/SearchMultipleSelectionPicker.tsx | 21 +++++++---- .../ModalStackNavigators/index.tsx | 6 +++ src/libs/Navigation/linkingConfig/config.ts | 23 ++++++++++++ src/libs/ReportUtils.ts | 37 ++++++++++++++----- src/libs/SearchAutocompleteUtils.ts | 4 +- 8 files changed, 102 insertions(+), 26 deletions(-) diff --git a/src/CONST/index.ts b/src/CONST/index.ts index c648f52f56c5b..43b52dbc7042f 100755 --- a/src/CONST/index.ts +++ b/src/CONST/index.ts @@ -744,7 +744,6 @@ const CONST = { ZERO_EXPENSES: 'zeroExpenses', NEW_DOT_DEW: 'newDotDEW', GPS_MILEAGE: 'gpsMileage', - NEW_DOT_HOME: 'newDotHome', PERSONAL_CARD_IMPORT: 'personalCardImport', }, BUTTON_STATES: { @@ -1076,14 +1075,14 @@ const CONST = { // Use Environment.getEnvironmentURL to get the complete URL with port number DEV_NEW_EXPENSIFY_URL: 'https://dev.new.expensify.com:', STORYLANE: { - ADMIN_TOUR: 'https://app.storylane.io/demo/bbcreg8vccag?embed=inline', - ADMIN_TOUR_MOBILE: 'https://app.storylane.io/demo/b6faqcdsxgww?embed=inline', + ADMIN_TOUR: 'https://expensify.storylane.io/share/nfrgmfpppolt', + ADMIN_TOUR_MOBILE: 'https://expensify.storylane.io/share/7t9urrrcqk5k', ADMIN_MIGRATED: 'https://app.storylane.io/share/qlgnexxbsdtp', ADMIN_MIGRATED_MOBILE: 'https://app.storylane.io/share/fgireksbt2oh', TRACK_WORKSPACE_TOUR: 'https://app.storylane.io/share/mqzy3huvtrhx?embed=inline', TRACK_WORKSPACE_TOUR_MOBILE: 'https://app.storylane.io/share/wq4hiwsqvoho?embed=inline', - EMPLOYEE_TOUR: 'https://app.storylane.io/share/izmryscwurdd?embed=inline', - EMPLOYEE_TOUR_MOBILE: 'https://app.storylane.io/share/wckqdetaacgy?embed=inline', + EMPLOYEE_TOUR: 'https://expensify.storylane.io/share/ohsppww6qi71', + EMPLOYEE_TOUR_MOBILE: 'https://expensify.storylane.io/share/v8uwkznocw0g', EMPLOYEE_MIGRATED: 'https://app.storylane.io/share/v9dr1rjqsd9y', EMPLOYEE_MIGRATED_MOBILE: 'https://app.storylane.io/share/qbbob6zvapqo', }, @@ -8024,6 +8023,8 @@ const CONST = { HOME: 'NavigationTabBar-Home', FLOATING_ACTION_BUTTON: 'NavigationTabBar-FloatingActionButton', FLOATING_RECEIPT_BUTTON: 'NavigationTabBar-FloatingReceiptButton', + FLOATING_GPS_BUTTON: 'NavigationTabBar-FloatingGpsButton', + FLOATING_CAMERA_BUTTON: 'NavigationTabBar-FloatingCameraButton', }, FAB_MENU: { CREATE_EXPENSE: 'FABMenu-CreateExpense', @@ -8204,6 +8205,12 @@ const CONST = { VIEW_ASSIGNEE: 'Task-ViewAssignee', HEADER_ACTION_BUTTON: 'Task-HeaderActionButton', }, + DISCOVER_SECTION: { + TEST_DRIVE: 'DiscoverSection-TestDrive', + }, + HOME_PAGE: { + WIDGET_ITEM: 'HomePage-WidgetItem', + }, }, DOMAIN: { diff --git a/src/SCREENS.ts b/src/SCREENS.ts index 1871a47bc9c17..b76da7dd9a48d 100644 --- a/src/SCREENS.ts +++ b/src/SCREENS.ts @@ -60,6 +60,7 @@ const SCREENS = { ADVANCED_FILTERS_APPROVED_RHP: 'Search_Advanced_Filters_Approved_RHP', ADVANCED_FILTERS_PAID_RHP: 'Search_Advanced_Filters_Paid_RHP', ADVANCED_FILTERS_EXPORTED_RHP: 'Search_Advanced_Filters_Exported_RHP', + ADVANCED_FILTERS_EXPORTED_TO_RHP: 'Search_Advanced_Filters_Exported_To_RHP', ADVANCED_FILTERS_POSTED_RHP: 'Search_Advanced_Filters_Posted_RHP', ADVANCED_FILTERS_WITHDRAWN_RHP: 'Search_Advanced_Filters_Withdrawn_RHP', ADVANCED_FILTERS_CURRENCY_RHP: 'Search_Advanced_Filters_Currency_RHP', diff --git a/src/components/Search/SearchAutocompleteList.tsx b/src/components/Search/SearchAutocompleteList.tsx index dee09b3362200..25bd0b4e8ef4d 100644 --- a/src/components/Search/SearchAutocompleteList.tsx +++ b/src/components/Search/SearchAutocompleteList.tsx @@ -197,6 +197,7 @@ function SearchAutocompleteList({ const [recentSearches] = useOnyx(ONYXKEYS.RECENT_SEARCHES, {canBeMissing: true}); const [countryCode] = useOnyx(ONYXKEYS.COUNTRY_CODE, {canBeMissing: false}); const [loginList] = useOnyx(ONYXKEYS.LOGIN_LIST, {canBeMissing: true}); + const [visibleReportActionsData] = useOnyx(ONYXKEYS.DERIVED.VISIBLE_REPORT_ACTIONS, {canBeMissing: true}); const currentUserPersonalDetails = useCurrentUserPersonalDetails(); const currentUserEmail = currentUserPersonalDetails.email ?? ''; const currentUserAccountID = currentUserPersonalDetails.accountID; @@ -223,10 +224,23 @@ function SearchAutocompleteList({ shouldShowGBR: false, shouldUnreadBeBold: true, loginList, + visibleReportActionsData, currentUserAccountID, currentUserEmail, }); - }, [areOptionsInitialized, options, draftComments, nvpDismissedProductTraining, betas, autocompleteQueryValue, countryCode, loginList, currentUserAccountID, currentUserEmail]); + }, [ + areOptionsInitialized, + options, + draftComments, + nvpDismissedProductTraining, + betas, + autocompleteQueryValue, + countryCode, + loginList, + visibleReportActionsData, + currentUserAccountID, + currentUserEmail, + ]); const [isInitialRender, setIsInitialRender] = useState(true); const parsedQuery = useMemo(() => parseForAutocomplete(autocompleteQueryValue), [autocompleteQueryValue]); @@ -446,6 +460,7 @@ function SearchAutocompleteList({ countryCode, loginList, shouldShowGBR: true, + visibleReportActionsData, currentUserAccountID, currentUserEmail, }).personalDetails.filter((participant) => participant.text && !alreadyAutocompletedKeys.has(participant.text.toLowerCase())); @@ -479,6 +494,7 @@ function SearchAutocompleteList({ countryCode, loginList, shouldShowGBR: true, + visibleReportActionsData, currentUserAccountID, currentUserEmail, }).recentReports.filter((chat) => { @@ -678,6 +694,7 @@ function SearchAutocompleteList({ workspaceList, hasAutocompleteList, isAutocompleteList, + visibleReportActionsData, exportedToAutocompleteList, ]); diff --git a/src/components/Search/SearchMultipleSelectionPicker.tsx b/src/components/Search/SearchMultipleSelectionPicker.tsx index 1cae120f349c6..dc81b15ca3cc9 100644 --- a/src/components/Search/SearchMultipleSelectionPicker.tsx +++ b/src/components/Search/SearchMultipleSelectionPicker.tsx @@ -13,6 +13,7 @@ import SearchFilterPageFooterButtons from './SearchFilterPageFooterButtons'; type SearchMultipleSelectionPickerItem = { name: string; value: string | string[]; + leftElement?: React.ReactNode; }; type SearchMultipleSelectionPickerProps = { @@ -37,12 +38,16 @@ function SearchMultipleSelectionPicker({items, initiallySelectedItems, pickerTit const selectedItemsSection = selectedItems .filter((item) => item?.name.toLowerCase().includes(debouncedSearchTerm?.toLowerCase())) .sort((a, b) => sortOptionsWithEmptyValue(a.value.toString(), b.value.toString(), localeCompare)) - .map((item) => ({ - text: item.name, - keyForList: item.name, - isSelected: true, - value: item.value, - })); + .map((item) => { + const fullItem = items.find((i) => i.value.toString() === item.value.toString()); + return { + text: item.name, + keyForList: item.name, + isSelected: true, + value: item.value, + leftElement: fullItem?.leftElement, + }; + }); const remainingItemsSection = items .filter( (item) => @@ -54,6 +59,7 @@ function SearchMultipleSelectionPicker({items, initiallySelectedItems, pickerTit keyForList: item.name, isSelected: false, value: item.value, + leftElement: item.leftElement, })); const isEmpty = !selectedItemsSection.length && !remainingItemsSection.length; return { @@ -83,7 +89,8 @@ function SearchMultipleSelectionPicker({items, initiallySelectedItems, pickerTit if (item.isSelected) { setSelectedItems(selectedItems?.filter((selectedItem) => selectedItem.name !== item.keyForList)); } else { - setSelectedItems([...(selectedItems ?? []), {name: item.text, value: item.value}]); + const fullItem = items.find((i) => i.value.toString() === (item.value ?? '').toString()); + setSelectedItems([...(selectedItems ?? []), {name: item.text, value: item.value, leftElement: fullItem?.leftElement}]); } }, [selectedItems], diff --git a/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx b/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx index 6ef810d51202e..843d6799c9357 100644 --- a/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx +++ b/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx @@ -396,6 +396,11 @@ const SettingsModalStackNavigator = createModalStackNavigator require('../../../../pages/settings/Wallet/ActivatePhysicalCardPage').default, [SCREENS.SETTINGS.WALLET.TRANSFER_BALANCE]: () => require('../../../../pages/settings/Wallet/TransferBalancePage').default, [SCREENS.SETTINGS.WALLET.CHOOSE_TRANSFER_ACCOUNT]: () => require('../../../../pages/settings/Wallet/ChooseTransferAccountPage').default, + [SCREENS.SETTINGS.WALLET.IMPORT_TRANSACTIONS]: () => require('../../../../pages/settings/Wallet/ImportTransactionsPage').default, + [SCREENS.SETTINGS.WALLET.IMPORT_TRANSACTIONS_CARD_NAME]: () => require('../../../../pages/settings/Wallet/ImportTransactionsCardNamePage').default, + [SCREENS.SETTINGS.WALLET.IMPORT_TRANSACTIONS_CURRENCY]: () => require('../../../../pages/settings/Wallet/ImportTransactionsCurrencyPage').default, + [SCREENS.SETTINGS.WALLET.IMPORT_TRANSACTIONS_SPREADSHEET]: () => require('../../../../pages/settings/Wallet/ImportTransactionsSpreadsheetPage').default, + [SCREENS.SETTINGS.WALLET.TRANSACTIONS_IMPORTED]: () => require('../../../../pages/settings/Wallet/TransactionsImportedPage').default, [SCREENS.SETTINGS.WALLET.ENABLE_PAYMENTS]: () => require('../../../../pages/EnablePayments/EnablePayments').default, [SCREENS.SETTINGS.WALLET.UNSHARE_BANK_ACCOUNT]: () => require('../../../../pages/settings/Wallet/UnshareBankAccount/UnshareBankAccount').default, [SCREENS.SETTINGS.WALLET.ENABLE_GLOBAL_REIMBURSEMENTS]: () => require('../../../../pages/settings/Wallet/EnableGlobalReimbursements').default, @@ -762,6 +767,7 @@ const SettingsModalStackNavigator = createModalStackNavigator require('../../../../pages/workspace/expensifyCard/WorkspaceCardSettingsPage').default, [SCREENS.WORKSPACE.EXPENSIFY_CARD_SETTINGS_ACCOUNT]: () => require('../../../../pages/workspace/expensifyCard/WorkspaceSettlementAccountPage').default, [SCREENS.WORKSPACE.EXPENSIFY_CARD_SETTINGS_FREQUENCY]: () => require('../../../../pages/workspace/expensifyCard/WorkspaceSettlementFrequencyPage').default, + [SCREENS.WORKSPACE.TRAVEL_SETTINGS_ACCOUNT]: () => require('../../../../pages/workspace/travel/WorkspaceTravelInvoicingSettlementAccountPage').default, [SCREENS.WORKSPACE.EXPENSIFY_CARD_SELECT_FEED]: () => require('../../../../pages/workspace/expensifyCard/WorkspaceExpensifyCardSelectorPage').default, [SCREENS.WORKSPACE.EXPENSIFY_CARD_BANK_ACCOUNT]: () => require('../../../../pages/workspace/expensifyCard/WorkspaceExpensifyCardBankAccounts').default, [SCREENS.WORKSPACE.EXPENSIFY_CARD_DETAILS]: () => require('../../../../pages/workspace/expensifyCard/WorkspaceExpensifyCardDetailsPage').default, diff --git a/src/libs/Navigation/linkingConfig/config.ts b/src/libs/Navigation/linkingConfig/config.ts index 7afbb707fcff1..4e9063a25539a 100644 --- a/src/libs/Navigation/linkingConfig/config.ts +++ b/src/libs/Navigation/linkingConfig/config.ts @@ -288,6 +288,26 @@ const config: LinkingOptions['config'] = { path: ROUTES.SETTINGS_WALLET_CHOOSE_TRANSFER_ACCOUNT, exact: true, }, + [SCREENS.SETTINGS.WALLET.IMPORT_TRANSACTIONS]: { + path: ROUTES.SETTINGS_WALLET_IMPORT_TRANSACTIONS, + exact: true, + }, + [SCREENS.SETTINGS.WALLET.IMPORT_TRANSACTIONS_CARD_NAME]: { + path: ROUTES.SETTINGS_WALLET_IMPORT_TRANSACTIONS_CARD_NAME, + exact: true, + }, + [SCREENS.SETTINGS.WALLET.IMPORT_TRANSACTIONS_CURRENCY]: { + path: ROUTES.SETTINGS_WALLET_IMPORT_TRANSACTIONS_CURRENCY, + exact: true, + }, + [SCREENS.SETTINGS.WALLET.IMPORT_TRANSACTIONS_SPREADSHEET]: { + path: ROUTES.SETTINGS_WALLET_IMPORT_TRANSACTIONS_SPREADSHEET.route, + exact: true, + }, + [SCREENS.SETTINGS.WALLET.TRANSACTIONS_IMPORTED]: { + path: ROUTES.SETTINGS_WALLET_TRANSACTIONS_IMPORTED.route, + exact: true, + }, [SCREENS.SETTINGS.REPORT_CARD_LOST_OR_DAMAGED]: { path: ROUTES.SETTINGS_WALLET_REPORT_CARD_LOST_OR_DAMAGED.route, exact: true, @@ -801,6 +821,9 @@ const config: LinkingOptions['config'] = { [SCREENS.WORKSPACE.EXPENSIFY_CARD_SELECT_FEED]: { path: ROUTES.WORKSPACE_EXPENSIFY_CARD_SELECT_FEED.route, }, + [SCREENS.WORKSPACE.TRAVEL_SETTINGS_ACCOUNT]: { + path: ROUTES.WORKSPACE_TRAVEL_SETTINGS_ACCOUNT.route, + }, [SCREENS.WORKSPACE.COMPANY_CARDS_SETTINGS]: { path: ROUTES.WORKSPACE_COMPANY_CARDS_SETTINGS.route, }, diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index 9c820061e5bf7..8c95263e7bbb4 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -59,6 +59,7 @@ import type { Transaction, TransactionViolation, TransactionViolations, + VisibleReportActionsDerivedValue, } from '@src/types/onyx'; import type {ReportTransactionsAndViolations} from '@src/types/onyx/DerivedValues'; import type {Attendee, Participant} from '@src/types/onyx/IOU'; @@ -266,6 +267,7 @@ import { isRenamedAction, isReopenedAction, isReportActionAttachment, + isReportActionVisible, isReportPreviewAction, isRetractedAction, isReversedTransaction, @@ -280,7 +282,6 @@ import { isTripPreview, isUnapprovedAction, isWhisperAction, - shouldReportActionBeVisible, wasActionTakenByCurrentUser, } from './ReportActionsUtils'; import type {LastVisibleMessage} from './ReportActionsUtils'; @@ -7033,7 +7034,7 @@ function getMovedTransactionMessage(translate: LocalizedTranslate, action: Repor // This will be fixed as follow up https://github.com/Expensify/App/pull/75357 // eslint-disable-next-line @typescript-eslint/no-deprecated - const reportName = getReportName(report) ?? report?.reportName ?? ''; + const reportName = Parser.htmlToText(getReportName(report) ?? report?.reportName ?? ''); const reportUrl = getReportURLForCurrentContext(report?.reportID); if (typeof fromReportID === 'undefined') { return translate('iou.movedTransactionTo', { @@ -7055,7 +7056,7 @@ function getUnreportedTransactionMessage(translate: LocalizedTranslate, action: // This will be fixed as follow up https://github.com/Expensify/App/pull/75357 // eslint-disable-next-line @typescript-eslint/no-deprecated - const reportName = getReportName(fromReport) ?? fromReport?.reportName ?? ''; + const reportName = Parser.htmlToText(getReportName(fromReport) ?? fromReport?.reportName ?? ''); let reportUrl = getReportURLForCurrentContext(fromReportID); @@ -9156,14 +9157,23 @@ function isReportNotFound(report: OnyxEntry): boolean { /** * Check if the report is the parent report of the currently viewed report or at least one child report has report action */ -function shouldHideReport(report: OnyxEntry, currentReportId: string | undefined, isReportArchived: boolean | undefined): boolean { +function shouldHideReport( + report: OnyxEntry, + currentReportId: string | undefined, + isReportArchived: boolean | undefined, + visibleReportActionsData?: VisibleReportActionsDerivedValue, +): boolean { const currentReport = getReportOrDraftReport(currentReportId); const parentReport = getParentReport(!isEmptyObject(currentReport) ? currentReport : undefined); const reportActions = allReportActions?.[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${report?.reportID}`] ?? {}; - const isChildReportHasComment = Object.values(reportActions ?? {})?.some( - (reportAction) => - (reportAction?.childVisibleActionCount ?? 0) > 0 && shouldReportActionBeVisible(reportAction, reportAction.reportActionID, canUserPerformWriteAction(report, isReportArchived)), - ); + const reportID = report?.reportID; + const isChildReportHasComment = + !!reportID && + Object.values(reportActions ?? {})?.some( + (reportAction) => + (reportAction?.childVisibleActionCount ?? 0) > 0 && + isReportActionVisible(reportAction, reportID, canUserPerformWriteAction(report, isReportArchived), visibleReportActionsData), + ); return parentReport?.reportID !== report?.reportID && !isChildReportHasComment; } @@ -10191,7 +10201,13 @@ function isMoneyRequestReportPendingDeletion(reportOrID: OnyxEntry | str return parentReportAction?.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE; } -function navigateToLinkedReportAction(ancestor: Ancestor, isInNarrowPaneModal: boolean, canUserPerformWrite: boolean | undefined, isOffline: boolean) { +function navigateToLinkedReportAction( + ancestor: Ancestor, + isInNarrowPaneModal: boolean, + canUserPerformWrite: boolean | undefined, + isOffline: boolean, + visibleReportActionsData?: VisibleReportActionsDerivedValue, +) { if (isInNarrowPaneModal) { Navigation.navigate( ROUTES.SEARCH_REPORT.getRoute({ @@ -10206,7 +10222,8 @@ function navigateToLinkedReportAction(ancestor: Ancestor, isInNarrowPaneModal: b // Pop the thread report screen before navigating to the chat report. Navigation.goBack(ROUTES.REPORT_WITH_ID.getRoute(ancestor.report.reportID)); - const isVisibleAction = shouldReportActionBeVisible(ancestor.reportAction, ancestor.reportAction.reportActionID, canUserPerformWrite); + const reportID = ancestor.report.reportID; + const isVisibleAction = !!reportID && isReportActionVisible(ancestor.reportAction, reportID, canUserPerformWrite, visibleReportActionsData); if (isVisibleAction && !isOffline) { // Pop the chat report screen before navigating to the linked report action. diff --git a/src/libs/SearchAutocompleteUtils.ts b/src/libs/SearchAutocompleteUtils.ts index 1dbfdf96c76d7..e67e5b6440c03 100644 --- a/src/libs/SearchAutocompleteUtils.ts +++ b/src/libs/SearchAutocompleteUtils.ts @@ -141,8 +141,6 @@ const userFriendlyColumnList = new Set( .map(([, value]) => value), ); -const exportedToFilterList = ['xero', 'qbo', 'qbd', 'netsuite', 'intacct', 'certinia']; - /** * @private * Determines if a specific value in the search syntax can/should be highlighted as valid or not @@ -232,7 +230,7 @@ function filterOutRangesWithCorrectValue( case CONST.SEARCH.SYNTAX_FILTER_KEYS.TITLE: return range.value.length > 0; case CONST.SEARCH.SYNTAX_FILTER_KEYS.EXPORTED_TO: - return exportedToFilterList.includes(range.value.toLowerCase()); + return CONST.SEARCH.PREDEFINED_INTEGRATION_FILTER_VALUES.includes(range.value.toLowerCase()); case CONST.SEARCH.SYNTAX_FILTER_KEYS.WITHDRAWAL_ID: case CONST.SEARCH.SYNTAX_FILTER_KEYS.REPORT_ID: return !['', 'null', 'undefined', '0', '-1'].includes(range.value); From f9b6cb53c98aee3259f53481463427aa1e15342b Mon Sep 17 00:00:00 2001 From: Samran Ahmed Date: Sun, 1 Feb 2026 16:15:10 +0500 Subject: [PATCH 08/11] refector SearchFiltersExportedToPage --- .../SearchFiltersExportedToPage.tsx | 88 +++++++++---------- 1 file changed, 44 insertions(+), 44 deletions(-) diff --git a/src/pages/Search/SearchAdvancedFiltersPage/SearchFiltersExportedToPage.tsx b/src/pages/Search/SearchAdvancedFiltersPage/SearchFiltersExportedToPage.tsx index ca8a5e8be12d9..93a71974fe07d 100644 --- a/src/pages/Search/SearchAdvancedFiltersPage/SearchFiltersExportedToPage.tsx +++ b/src/pages/Search/SearchAdvancedFiltersPage/SearchFiltersExportedToPage.tsx @@ -1,6 +1,5 @@ -import React, {useMemo} from 'react'; +import React, {useCallback, useMemo} from 'react'; import {View} from 'react-native'; -import Table from '@assets/images/table.svg'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; import Icon from '@components/Icon'; import ScreenWrapper from '@components/ScreenWrapper'; @@ -10,28 +9,22 @@ import {useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset'; import useLocalize from '@hooks/useLocalize'; import useOnyx from '@hooks/useOnyx'; import useStyleUtils from '@hooks/useStyleUtils'; +import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; import {getExportTemplates, updateAdvancedFilters} from '@libs/actions/Search'; import Navigation from '@libs/Navigation/Navigation'; -import {getConnectionNameForExportedToFilter, getIntegrationIcon} from '@libs/ReportUtils'; +import {getIntegrationIcon} from '@libs/ReportUtils'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; - -const PREDEFINED_INTEGRATION_VALUES = [ - {value: 'xero', displayKey: 'xero' as const}, - {value: 'qbo', displayKey: 'quickbooksOnline' as const}, - {value: 'qbd', displayKey: 'quickbooksDesktop' as const}, - {value: 'netsuite', displayKey: 'netsuite' as const}, - {value: 'intacct', displayKey: 'intacct' as const}, - {value: 'certinia', displayKey: 'certinia' as const}, -] as const; +import type {ConnectionName} from '@src/types/onyx/Policy'; function SearchFiltersExportedToPage() { const styles = useThemeStyles(); const {translate} = useLocalize(); const StyleUtils = useStyleUtils(); - const expensifyIcons = useMemoizedLazyExpensifyIcons(['XeroSquare', 'QBOSquare', 'NetSuiteSquare', 'IntacctSquare', 'QBDSquare', 'CertiniaSquare']); + const theme = useTheme(); + const expensifyIcons = useMemoizedLazyExpensifyIcons(['XeroSquare', 'QBOSquare', 'NetSuiteSquare', 'IntacctSquare', 'QBDSquare', 'CertiniaSquare', 'Table']); const [searchAdvancedFiltersForm] = useOnyx(ONYXKEYS.FORMS.SEARCH_ADVANCED_FILTERS_FORM, {canBeMissing: true}); const [integrationsExportTemplates] = useOnyx(ONYXKEYS.NVP_INTEGRATION_SERVER_EXPORT_TEMPLATES, {canBeMissing: true}); @@ -42,9 +35,10 @@ function SearchFiltersExportedToPage() { const tableIconElement = useMemo( () => ( - + @@ -54,39 +48,47 @@ function SearchFiltersExportedToPage() { ); const items = useMemo((): SearchMultipleSelectionPickerItem[] => { - const integrationItems: SearchMultipleSelectionPickerItem[] = PREDEFINED_INTEGRATION_VALUES.map((item) => { - const connectionName = getConnectionNameForExportedToFilter(item.value); - const icon = connectionName ? getIntegrationIcon(connectionName, expensifyIcons) : undefined; - const leftElement = - icon != null ? ( - - - - ) : ( - tableIconElement - ); + const predefinedConnectionNamesList: ConnectionName[] = [ + CONST.POLICY.CONNECTIONS.NAME.XERO, + CONST.POLICY.CONNECTIONS.NAME.QBO, + CONST.POLICY.CONNECTIONS.NAME.QBD, + CONST.POLICY.CONNECTIONS.NAME.NETSUITE, + CONST.POLICY.CONNECTIONS.NAME.SAGE_INTACCT, + CONST.POLICY.CONNECTIONS.NAME.CERTINIA, + ]; + const predefinedConnectionNamesSet = new Set(predefinedConnectionNamesList); + + const integrationItems: SearchMultipleSelectionPickerItem[] = predefinedConnectionNamesList.map((value) => { + const icon = getIntegrationIcon(value, expensifyIcons); + const leftElement = icon ? ( + + + + ) : ( + tableIconElement + ); return { - name: CONST.POLICY.CONNECTIONS.NAME_USER_FRIENDLY[item.displayKey], - value: item.value, + name: CONST.POLICY.CONNECTIONS.NAME_USER_FRIENDLY[value], + value, leftElement, }; }); const exportTemplates = getExportTemplates(integrationsExportTemplates ?? [], csvExportLayouts ?? {}, translate, policy, true); const otherItems: SearchMultipleSelectionPickerItem[] = exportTemplates - .filter((template) => template.templateName && !PREDEFINED_INTEGRATION_VALUES.some((p) => p.value === template.templateName?.toLowerCase())) + .filter((template) => template.templateName && !predefinedConnectionNamesSet.has(template.templateName)) .map((template) => ({ name: template.name ?? template.templateName ?? '', value: template.templateName, leftElement: tableIconElement, })) - .filter((item) => item.name !== '') - .sort((a, b) => (a.name as string).localeCompare(b.name as string)); + .sort((a, b) => a.name.localeCompare(b.name)); return [...integrationItems, ...otherItems]; }, [integrationsExportTemplates, csvExportLayouts, policy, expensifyIcons, styles, StyleUtils, translate, tableIconElement]); @@ -96,16 +98,14 @@ function SearchFiltersExportedToPage() { if (selectedValues.length === 0) { return undefined; } - const normalizedSet = new Set(selectedValues.map((v) => v.toLowerCase())); - return items.filter((item) => normalizedSet.has(item.value as string)); + const normalizedSet = new Set(selectedValues.map((selectedValue) => selectedValue.toLowerCase())); + return items.filter((item) => { + const value = typeof item.value === 'string' ? item.value : (item.value[0] ?? ''); + return normalizedSet.has(value.toLowerCase()); + }); }, [searchAdvancedFiltersForm?.exportedTo, items]); - const onSaveSelection = useMemo( - () => (values: string[]) => { - updateAdvancedFilters({exportedTo: values}); - }, - [], - ); + const onSaveSelection = useCallback((values: string[]) => updateAdvancedFilters({exportedTo: values}), []); return ( Date: Sun, 1 Feb 2026 16:18:57 +0500 Subject: [PATCH 09/11] add CertiniaSquare icon at missing locations --- src/components/ImportedFromAccountingSoftware.tsx | 2 +- src/components/MoneyReportHeader.tsx | 1 + src/components/ReportActionItem/ExportWithDropdownMenu.tsx | 2 +- src/pages/inbox/report/ReportDetailsExportPage.tsx | 2 +- 4 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/components/ImportedFromAccountingSoftware.tsx b/src/components/ImportedFromAccountingSoftware.tsx index b82186f0129ba..6a95106f23128 100644 --- a/src/components/ImportedFromAccountingSoftware.tsx +++ b/src/components/ImportedFromAccountingSoftware.tsx @@ -34,7 +34,7 @@ function ImportedFromAccountingSoftware({policyID, currentConnectionName, transl const StyleUtils = useStyleUtils(); const {translate} = useLocalize(); const {environmentURL} = useEnvironment(); - const expensifyIcons = useMemoizedLazyExpensifyIcons(['XeroSquare', 'QBOSquare', 'NetSuiteSquare', 'IntacctSquare', 'QBDSquare']); + const expensifyIcons = useMemoizedLazyExpensifyIcons(['XeroSquare', 'QBOSquare', 'NetSuiteSquare', 'IntacctSquare', 'QBDSquare', 'CertiniaSquare']); const icon = getIntegrationIcon(connectedIntegration, expensifyIcons); return ( diff --git a/src/components/MoneyReportHeader.tsx b/src/components/MoneyReportHeader.tsx index e0f7270c6dfbd..b5a95123774d2 100644 --- a/src/components/MoneyReportHeader.tsx +++ b/src/components/MoneyReportHeader.tsx @@ -249,6 +249,7 @@ function MoneyReportHeader({ 'NetSuiteSquare', 'IntacctSquare', 'QBDSquare', + 'CertiniaSquare', 'Feed', 'Close', 'Location', diff --git a/src/components/ReportActionItem/ExportWithDropdownMenu.tsx b/src/components/ReportActionItem/ExportWithDropdownMenu.tsx index 0ddf931bb40b2..7433d6d3d9139 100644 --- a/src/components/ReportActionItem/ExportWithDropdownMenu.tsx +++ b/src/components/ReportActionItem/ExportWithDropdownMenu.tsx @@ -53,7 +53,7 @@ function ExportWithDropdownMenu({ const {shouldUseNarrowLayout} = useResponsiveLayout(); const [modalStatus, setModalStatus] = useState(null); const [exportMethods] = useOnyx(ONYXKEYS.LAST_EXPORT_METHOD, {canBeMissing: true}); - const expensifyIcons = useMemoizedLazyExpensifyIcons(['XeroSquare', 'QBOSquare', 'NetSuiteSquare', 'IntacctSquare', 'QBDSquare']); + const expensifyIcons = useMemoizedLazyExpensifyIcons(['XeroSquare', 'QBOSquare', 'NetSuiteSquare', 'IntacctSquare', 'QBDSquare', 'CertiniaSquare']); const iconToDisplay = getIntegrationIcon(connectionName, expensifyIcons); const canBeExported = canBeExportedUtils(report); diff --git a/src/pages/inbox/report/ReportDetailsExportPage.tsx b/src/pages/inbox/report/ReportDetailsExportPage.tsx index efd0e362040a0..e4e5f1edbf6c4 100644 --- a/src/pages/inbox/report/ReportDetailsExportPage.tsx +++ b/src/pages/inbox/report/ReportDetailsExportPage.tsx @@ -40,7 +40,7 @@ function ReportDetailsExportPage({route}: ReportDetailsExportPageProps) { const {showConfirmModal} = useConfirmModal(); const styles = useThemeStyles(); const lazyIllustrations = useMemoizedLazyIllustrations(['LaptopWithSecondScreenAndHourglass']); - const expensifyIcons = useMemoizedLazyExpensifyIcons(['XeroSquare', 'QBOSquare', 'NetSuiteSquare', 'IntacctSquare', 'QBDSquare']); + const expensifyIcons = useMemoizedLazyExpensifyIcons(['XeroSquare', 'QBOSquare', 'NetSuiteSquare', 'IntacctSquare', 'QBDSquare', 'CertiniaSquare']); const iconToDisplay = getIntegrationIcon(connectionName, expensifyIcons); const canBeExported = canBeExportedUtil(report); From 1de881471c86ba0f786633aaa936aeda7997dd2b Mon Sep 17 00:00:00 2001 From: Samran Ahmed Date: Sun, 1 Feb 2026 16:19:55 +0500 Subject: [PATCH 10/11] add certinia in type Connections --- .../Search/SearchAutocompleteList.tsx | 8 ++--- src/libs/ReportUtils.ts | 31 ------------------- src/types/onyx/Policy.ts | 3 ++ 3 files changed, 7 insertions(+), 35 deletions(-) diff --git a/src/components/Search/SearchAutocompleteList.tsx b/src/components/Search/SearchAutocompleteList.tsx index 25bd0b4e8ef4d..9556764c51e58 100644 --- a/src/components/Search/SearchAutocompleteList.tsx +++ b/src/components/Search/SearchAutocompleteList.tsx @@ -639,10 +639,6 @@ function SearchAutocompleteList({ return filteredIsValues.map((isValue) => ({filterKey: CONST.SEARCH.SEARCH_USER_FRIENDLY_KEYS.IS, text: isValue})); } - case CONST.SEARCH.SYNTAX_FILTER_KEYS.DATE: - case CONST.SEARCH.SYNTAX_FILTER_KEYS.SUBMITTED: - case CONST.SEARCH.SYNTAX_FILTER_KEYS.APPROVED: - case CONST.SEARCH.SYNTAX_FILTER_KEYS.PAID: case CONST.SEARCH.SYNTAX_FILTER_KEYS.EXPORTED_TO: { const filteredExportedTo = exportedToAutocompleteList .filter((value) => value.toLowerCase().includes(autocompleteValue.toLowerCase()) && !alreadyAutocompletedKeys.has(value.toLowerCase())) @@ -654,6 +650,10 @@ function SearchAutocompleteList({ mapKey: CONST.SEARCH.SYNTAX_FILTER_KEYS.EXPORTED_TO, })); } + case CONST.SEARCH.SYNTAX_FILTER_KEYS.DATE: + case CONST.SEARCH.SYNTAX_FILTER_KEYS.SUBMITTED: + case CONST.SEARCH.SYNTAX_FILTER_KEYS.APPROVED: + case CONST.SEARCH.SYNTAX_FILTER_KEYS.PAID: case CONST.SEARCH.SYNTAX_FILTER_KEYS.EXPORTED: case CONST.SEARCH.SYNTAX_FILTER_KEYS.WITHDRAWN: case CONST.SEARCH.SYNTAX_FILTER_KEYS.POSTED: { diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index 8c95263e7bbb4..965a1cada2e99 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -12381,35 +12381,6 @@ function getIntegrationIcon( return undefined; } -function getConnectionNameForExportedToFilter(value: string): ConnectionName | undefined { - const map: Record = { - xero: CONST.POLICY.CONNECTIONS.NAME.XERO, - qbo: CONST.POLICY.CONNECTIONS.NAME.QBO, - qbd: CONST.POLICY.CONNECTIONS.NAME.QBD, - netsuite: CONST.POLICY.CONNECTIONS.NAME.NETSUITE, - intacct: CONST.POLICY.CONNECTIONS.NAME.SAGE_INTACCT, - certinia: CONST.POLICY.CONNECTIONS.NAME.CERTINIA, - }; - return map[value.toLowerCase()]; -} - -function getIntegrationExportIcon(connectionName?: ConnectionName): 'XeroExport' | 'QBOExport' | 'NetSuiteExport' | 'SageIntacctExport' | undefined { - if (connectionName === CONST.POLICY.CONNECTIONS.NAME.XERO) { - return 'XeroExport'; - } - if (connectionName === CONST.POLICY.CONNECTIONS.NAME.QBO || connectionName === CONST.POLICY.CONNECTIONS.NAME.QBD) { - return 'QBOExport'; - } - if (connectionName === CONST.POLICY.CONNECTIONS.NAME.NETSUITE) { - return 'NetSuiteExport'; - } - if (connectionName === CONST.POLICY.CONNECTIONS.NAME.SAGE_INTACCT) { - return 'SageIntacctExport'; - } - - return undefined; -} - function canBeExported(report: OnyxEntry) { if (!report?.statusNum) { return false; @@ -13393,9 +13364,7 @@ export { getFieldViolation, getReportViolations, findPolicyExpenseChatByPolicyID, - getConnectionNameForExportedToFilter, getIntegrationIcon, - getIntegrationExportIcon, canBeExported, isExported, hasExportError, diff --git a/src/types/onyx/Policy.ts b/src/types/onyx/Policy.ts index a70079302a1c1..feffbb8a9e8ce 100644 --- a/src/types/onyx/Policy.ts +++ b/src/types/onyx/Policy.ts @@ -1463,6 +1463,9 @@ type Connections = { /** QuickBooks Desktop integration connection */ [CONST.POLICY.CONNECTIONS.NAME.QBD]: Connection; + + /** Certinia integration connection */ + [CONST.POLICY.CONNECTIONS.NAME.CERTINIA]: Connection, Record>; }; /** All integration connections, including unsupported ones */ From f08cb119a453a096a5b76b229243875c0b462795 Mon Sep 17 00:00:00 2001 From: Samran Ahmed Date: Sun, 1 Feb 2026 18:43:15 +0500 Subject: [PATCH 11/11] refactor exported-to filter to use map keys for consistent value mapping --- .../SearchFiltersExportedToPage.tsx | 45 ++++++++++++------- 1 file changed, 28 insertions(+), 17 deletions(-) diff --git a/src/pages/Search/SearchAdvancedFiltersPage/SearchFiltersExportedToPage.tsx b/src/pages/Search/SearchAdvancedFiltersPage/SearchFiltersExportedToPage.tsx index 93a71974fe07d..5502df6468ccf 100644 --- a/src/pages/Search/SearchAdvancedFiltersPage/SearchFiltersExportedToPage.tsx +++ b/src/pages/Search/SearchAdvancedFiltersPage/SearchFiltersExportedToPage.tsx @@ -19,6 +19,20 @@ import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; import type {ConnectionName} from '@src/types/onyx/Policy'; +const CONNECTION_NAME_TO_EXPORTED_TO_SEARCH_VALUE: Record = { + [CONST.POLICY.CONNECTIONS.NAME.XERO]: 'xero', + [CONST.POLICY.CONNECTIONS.NAME.QBO]: 'qbo', + [CONST.POLICY.CONNECTIONS.NAME.QBD]: 'qbd', + [CONST.POLICY.CONNECTIONS.NAME.NETSUITE]: 'netsuite', + [CONST.POLICY.CONNECTIONS.NAME.SAGE_INTACCT]: 'intacct', + [CONST.POLICY.CONNECTIONS.NAME.CERTINIA]: 'certinia', +}; + +const EXPORT_OPTION_TO_QUERY_LABEL: Record = { + [CONST.REPORT.EXPORT_OPTIONS.REPORT_LEVEL_EXPORT]: CONST.REPORT.EXPORT_OPTION_LABELS.REPORT_LEVEL_EXPORT, + [CONST.REPORT.EXPORT_OPTIONS.EXPENSE_LEVEL_EXPORT]: CONST.REPORT.EXPORT_OPTION_LABELS.EXPENSE_LEVEL_EXPORT, +}; + function SearchFiltersExportedToPage() { const styles = useThemeStyles(); const {translate} = useLocalize(); @@ -48,18 +62,11 @@ function SearchFiltersExportedToPage() { ); const items = useMemo((): SearchMultipleSelectionPickerItem[] => { - const predefinedConnectionNamesList: ConnectionName[] = [ - CONST.POLICY.CONNECTIONS.NAME.XERO, - CONST.POLICY.CONNECTIONS.NAME.QBO, - CONST.POLICY.CONNECTIONS.NAME.QBD, - CONST.POLICY.CONNECTIONS.NAME.NETSUITE, - CONST.POLICY.CONNECTIONS.NAME.SAGE_INTACCT, - CONST.POLICY.CONNECTIONS.NAME.CERTINIA, - ]; + const predefinedConnectionNamesList = Object.keys(CONNECTION_NAME_TO_EXPORTED_TO_SEARCH_VALUE) as ConnectionName[]; const predefinedConnectionNamesSet = new Set(predefinedConnectionNamesList); - const integrationItems: SearchMultipleSelectionPickerItem[] = predefinedConnectionNamesList.map((value) => { - const icon = getIntegrationIcon(value, expensifyIcons); + const integrationItems: SearchMultipleSelectionPickerItem[] = predefinedConnectionNamesList.map((connectionName) => { + const icon = getIntegrationIcon(connectionName, expensifyIcons); const leftElement = icon ? ( template.templateName && !predefinedConnectionNamesSet.has(template.templateName)) - .map((template) => ({ - name: template.name ?? template.templateName ?? '', - value: template.templateName, - leftElement: tableIconElement, - })) + .map((template) => { + const name = template.name ?? template.templateName ?? ''; + const value = EXPORT_OPTION_TO_QUERY_LABEL[template.templateName] ?? template.templateName; + return { + name, + value, + leftElement: tableIconElement, + }; + }) .sort((a, b) => a.name.localeCompare(b.name)); return [...integrationItems, ...otherItems];