Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/components/Search/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,8 @@ type SearchQueryAST = {
type SearchQueryJSON = {
inputQuery: SearchQueryString;
hash: number;
/** Hash used for putting queries in recent searches list. It ignores sortOrder and sortBy, because we want to treat queries differing only in sort params as the same query */
recentSearchHash: number;
flatFilters: QueryFilters;
} & SearchQueryAST;

Expand Down
22 changes: 14 additions & 8 deletions src/libs/SearchQueryUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -216,15 +216,10 @@ function findIDFromDisplayValue(filterName: ValueOf<typeof CONST.SEARCH.SYNTAX_F
* Computes and returns a numerical hash for a given queryJSON.
* Sorts the query keys and values to ensure that hashes stay consistent.
*/
function getQueryHash(query: SearchQueryJSON): number {
function getQueryHashes(query: SearchQueryJSON): {primaryHash: number; recentSearchHash: number} {
let orderedQuery = '';
if (query.policyID) {
orderedQuery += `${CONST.SEARCH.SYNTAX_ROOT_KEYS.POLICY_ID}:${query.policyID} `;
}
orderedQuery += `${CONST.SEARCH.SYNTAX_ROOT_KEYS.TYPE}:${query.type}`;
orderedQuery += ` ${CONST.SEARCH.SYNTAX_ROOT_KEYS.STATUS}:${query.status}`;
orderedQuery += ` ${CONST.SEARCH.SYNTAX_ROOT_KEYS.SORT_BY}:${query.sortBy}`;
orderedQuery += ` ${CONST.SEARCH.SYNTAX_ROOT_KEYS.SORT_ORDER}:${query.sortOrder}`;

query.flatFilters.forEach((filter) => {
filter.filters.sort((a, b) => localeCompare(a.value.toString(), b.value.toString()));
Expand All @@ -235,7 +230,16 @@ function getQueryHash(query: SearchQueryJSON): number {
.sort()
.forEach((filterString) => (orderedQuery += ` ${filterString}`));

return UserUtils.hashText(orderedQuery, 2 ** 32);
const recentSearchHash = UserUtils.hashText(orderedQuery, 2 ** 32);

@luacmartins luacmartins Oct 25, 2024

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thinking more about it. What if a user explicitly types policyID:X sortOrder:asc? Should we instead just be hashing the input string instead of parts of the AST? That'd ensure anything the user types differently would be a new recent search

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We cannot hash string input. My argument: when user types policyID:X sortOrder:asc and sortOrder:asc policyID:X, we will get different hashes even though the query results will be the same.

I think we should exclude policyID like @rayane-djouah said. It may create some confusion when user types policy:X into query, but:

  1. We have a policy switcher, which is dedicated way of changing policyID, so typing policyID into SearchRouter query is the worst way to change your policyID
  2. We don't even autocomplete policyID key, so how will a user know that such option exists.
  3. It's unlikely that a real user will type something like policyID:31294891892741873, without the help of autocomplete.

What's more if user selects recentSearch with not the policyID he wanted, he can easily switch it on SearchResults page with policy switcher and it's not such a big problem(just like he switches sortOrder or sortBy). WDYT @rayane-djouah @luacmartins

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can go with your current solution for now, but:

when user types policyID:X sortOrder:asc and sortOrder:asc policyID:X

TBH I'd be ok to show both of these as different recent searches, even though they are the same search at the end of the day. My argument is that the user explicitly typed both of those, so they'd probably expect to see both in the recent search area.

We don't even autocomplete policyID key, so how will a user know that such option exists.

I think we should introduce policyID autocomplete. Maybe we need a new workspace: filter for that though, so the autocomplete shows the policy name instead of ID.

cc @JmillsExpensify @trjExpensify for your thoughts.


orderedQuery += ` ${CONST.SEARCH.SYNTAX_ROOT_KEYS.SORT_BY}:${query.sortBy}`;
orderedQuery += ` ${CONST.SEARCH.SYNTAX_ROOT_KEYS.SORT_ORDER}:${query.sortOrder}`;
if (query.policyID) {
orderedQuery += ` ${CONST.SEARCH.SYNTAX_ROOT_KEYS.POLICY_ID}:${query.policyID} `;
}
const primaryHash = UserUtils.hashText(orderedQuery, 2 ** 32);

return {primaryHash, recentSearchHash};
}

/**
Expand All @@ -252,7 +256,9 @@ function buildSearchQueryJSON(query: SearchQueryString) {
// Add the full input and hash to the results
result.inputQuery = query;
result.flatFilters = flatFilters;
result.hash = getQueryHash(result);
const {primaryHash, recentSearchHash} = getQueryHashes(result);
result.hash = primaryHash;
result.recentSearchHash = recentSearchHash;

return result;
} catch (e) {
Expand Down