diff --git a/client/components/main/globalSearch.js b/client/components/main/globalSearch.js index 8ad6aec2f..8795579df 100644 --- a/client/components/main/globalSearch.js +++ b/client/components/main/globalSearch.js @@ -212,6 +212,7 @@ BlazeComponent.extendComponent({ operatorMap[TAPi18n.__('operator-due')] = 'dueAt'; operatorMap[TAPi18n.__('operator-created')] = 'createdAt'; operatorMap[TAPi18n.__('operator-modified')] = 'modifiedAt'; + operatorMap[TAPi18n.__('operator-sort')] = 'sort'; // eslint-disable-next-line no-console console.log('operatorMap:', operatorMap); @@ -256,12 +257,16 @@ BlazeComponent.extendComponent({ } else if ( ['dueAt', 'createdAt', 'modifiedAt'].includes(operatorMap[op]) ) { - const days = parseInt(value, 10); + let days = parseInt(value, 10); + let duration = null; if (isNaN(days)) { if (['day', 'week', 'month', 'quarter', 'year'].includes(value)) { - value = moment() - .subtract(1, value) - .format(); + duration = value; + value = moment(); + } else if (value === 'overdue') { + value = moment(); + duration = 'days'; + days = 0; } else { this.parsingErrors.push({ tag: 'operator-number-expected', @@ -270,9 +275,23 @@ BlazeComponent.extendComponent({ value = null; } } else { - value = moment() - .subtract(days, 'days') - .format(); + value = moment(); + } + if (value) { + if (operatorMap[op] === 'dueAt') { + value = value.add(days, duration ? duration : 'days').format(); + } else { + value = value + .subtract(days, duration ? duration : 'days') + .format(); + } + } + } else if (operatorMap[op] === 'sort') { + if (!['due', 'modified', 'created', 'system'].includes(value)) { + this.parsingErrors.push({ + tag: 'operator-sort-invalid', + value, + }); } } if (Array.isArray(params[operatorMap[op]])) { diff --git a/i18n/en.i18n.json b/i18n/en.i18n.json index 3e020dac7..02bf2ab99 100644 --- a/i18n/en.i18n.json +++ b/i18n/en.i18n.json @@ -898,8 +898,10 @@ "operator-due": "due", "operator-created": "created", "operator-modified": "modified", + "operator-sort": "sort", "operator-unknown-error": "%s is not an operator", "operator-number-expected": "operator __operator__ expected a number, got '__value__'", + "operator-sort-invalid": "sort of '%s' is invalid", "heading-notes": "Notes", "globalSearch-instructions-heading": "Search Instructions", "globalSearch-instructions-description": "Searches can include operators to refine the search. Operators are specified by writing the operator name and value separated by a colon. For example, an operator specification of `list:Blocked` would limit the search to cards that are contained in a list named *Blocked*. If the value contains spaces or special characters it must be enclosed in quotation marks (e.g. `__operator_list__:\"To Review\"`).", diff --git a/models/cards.js b/models/cards.js index dd2b347bc..55ace7c0a 100644 --- a/models/cards.js +++ b/models/cards.js @@ -1955,7 +1955,7 @@ Cards.globalSearch = queryParams => { } if (queryParams.dueAt !== null) { - selector.dueAt = { $gte: new Date(queryParams.dueAt) }; + selector.dueAt = { $lte: new Date(queryParams.dueAt) }; } if (queryParams.createdAt !== null) { @@ -2092,7 +2092,8 @@ Cards.globalSearch = queryParams => { // eslint-disable-next-line no-console console.log('selector:', selector); - const cards = Cards.find(selector, { + + const projection = { fields: { _id: 1, archived: 1, @@ -2111,7 +2112,43 @@ Cards.globalSearch = queryParams => { labelIds: 1, }, limit: 50, - }); + }; + + if (queryParams.sort === 'due') { + projection.sort = { + dueAt: 1, + boardId: 1, + swimlaneId: 1, + listId: 1, + sort: 1, + }; + } else if (queryParams.sort === 'modified') { + projection.sort = { + modifiedAt: -1, + boardId: 1, + swimlaneId: 1, + listId: 1, + sort: 1, + }; + } else if (queryParams.sort === 'created') { + projection.sort = { + createdAt: -1, + boardId: 1, + swimlaneId: 1, + listId: 1, + sort: 1, + }; + } else if (queryParams.sort === 'system') { + projection.sort = { + boardId: 1, + swimlaneId: 1, + listId: 1, + modifiedAt: 1, + sort: 1, + }; + } + + const cards = Cards.find(selector, projection); // eslint-disable-next-line no-console console.log('count:', cards.count());