Jelajahi Sumber

Add a new search operator `creator`

John R. Supplee 4 tahun lalu
induk
melakukan
edd07befe2

+ 2 - 0
client/components/main/globalSearch.js

@@ -123,6 +123,7 @@ class GlobalSearchComponent extends CardSearchPagedComponent {
       operator_member_abbrev: TAPi18n.__('operator-member-abbrev'),
       operator_member_abbrev: TAPi18n.__('operator-member-abbrev'),
       operator_assignee: TAPi18n.__('operator-assignee'),
       operator_assignee: TAPi18n.__('operator-assignee'),
       operator_assignee_abbrev: TAPi18n.__('operator-assignee-abbrev'),
       operator_assignee_abbrev: TAPi18n.__('operator-assignee-abbrev'),
+      operator_creator: TAPi18n.__('operator-creator'),
       operator_due: TAPi18n.__('operator-due'),
       operator_due: TAPi18n.__('operator-due'),
       operator_created: TAPi18n.__('operator-created'),
       operator_created: TAPi18n.__('operator-created'),
       operator_modified: TAPi18n.__('operator-modified'),
       operator_modified: TAPi18n.__('operator-modified'),
@@ -167,6 +168,7 @@ class GlobalSearchComponent extends CardSearchPagedComponent {
       ['\n* ', 'globalSearch-instructions-operator-at'],
       ['\n* ', 'globalSearch-instructions-operator-at'],
       ['\n* ', 'globalSearch-instructions-operator-member'],
       ['\n* ', 'globalSearch-instructions-operator-member'],
       ['\n* ', 'globalSearch-instructions-operator-assignee'],
       ['\n* ', 'globalSearch-instructions-operator-assignee'],
+      ['\n* ', 'globalSearch-instructions-operator-creator'],
       ['\n* ', 'globalSearch-instructions-operator-due'],
       ['\n* ', 'globalSearch-instructions-operator-due'],
       ['\n* ', 'globalSearch-instructions-operator-created'],
       ['\n* ', 'globalSearch-instructions-operator-created'],
       ['\n* ', 'globalSearch-instructions-operator-modified'],
       ['\n* ', 'globalSearch-instructions-operator-modified'],

+ 3 - 1
config/query-classes.js

@@ -2,7 +2,7 @@ import {
   OPERATOR_ASSIGNEE,
   OPERATOR_ASSIGNEE,
   OPERATOR_BOARD,
   OPERATOR_BOARD,
   OPERATOR_COMMENT,
   OPERATOR_COMMENT,
-  OPERATOR_CREATED_AT,
+  OPERATOR_CREATED_AT, OPERATOR_CREATOR,
   OPERATOR_DUE,
   OPERATOR_DUE,
   OPERATOR_HAS,
   OPERATOR_HAS,
   OPERATOR_LABEL,
   OPERATOR_LABEL,
@@ -107,6 +107,7 @@ export class QueryErrors {
     [OPERATOR_USER, 'user-username-not-found'],
     [OPERATOR_USER, 'user-username-not-found'],
     [OPERATOR_ASSIGNEE, 'user-username-not-found'],
     [OPERATOR_ASSIGNEE, 'user-username-not-found'],
     [OPERATOR_MEMBER, 'user-username-not-found'],
     [OPERATOR_MEMBER, 'user-username-not-found'],
+    [OPERATOR_CREATOR, 'user-username-not-found'],
   ];
   ];
 
 
   constructor() {
   constructor() {
@@ -238,6 +239,7 @@ export class Query {
       'operator-member': OPERATOR_MEMBER,
       'operator-member': OPERATOR_MEMBER,
       'operator-member-abbrev': OPERATOR_MEMBER,
       'operator-member-abbrev': OPERATOR_MEMBER,
       'operator-assignee': OPERATOR_ASSIGNEE,
       'operator-assignee': OPERATOR_ASSIGNEE,
+      'operator-creator': OPERATOR_CREATOR,
       'operator-assignee-abbrev': OPERATOR_ASSIGNEE,
       'operator-assignee-abbrev': OPERATOR_ASSIGNEE,
       'operator-status': OPERATOR_STATUS,
       'operator-status': OPERATOR_STATUS,
       'operator-due': OPERATOR_DUE,
       'operator-due': OPERATOR_DUE,

+ 3 - 2
config/search-const.js

@@ -1,14 +1,15 @@
 export const DEFAULT_LIMIT = 25;
 export const DEFAULT_LIMIT = 25;
-export const OPERATOR_ASSIGNEE = 'assignee';
+export const OPERATOR_ASSIGNEE = 'assignees';
 export const OPERATOR_COMMENT = 'comment';
 export const OPERATOR_COMMENT = 'comment';
 export const OPERATOR_CREATED_AT = 'createdAt';
 export const OPERATOR_CREATED_AT = 'createdAt';
+export const OPERATOR_CREATOR = 'userId';
 export const OPERATOR_DUE = 'dueAt';
 export const OPERATOR_DUE = 'dueAt';
 export const OPERATOR_BOARD = 'board';
 export const OPERATOR_BOARD = 'board';
 export const OPERATOR_HAS = 'has';
 export const OPERATOR_HAS = 'has';
 export const OPERATOR_LABEL = 'label';
 export const OPERATOR_LABEL = 'label';
 export const OPERATOR_LIMIT = 'limit';
 export const OPERATOR_LIMIT = 'limit';
 export const OPERATOR_LIST = 'list';
 export const OPERATOR_LIST = 'list';
-export const OPERATOR_MEMBER = 'member';
+export const OPERATOR_MEMBER = 'members';
 export const OPERATOR_MODIFIED_AT = 'modifiedAt';
 export const OPERATOR_MODIFIED_AT = 'modifiedAt';
 export const OPERATOR_SORT = 'sort';
 export const OPERATOR_SORT = 'sort';
 export const OPERATOR_STATUS = 'status';
 export const OPERATOR_STATUS = 'status';

+ 2 - 0
i18n/en.i18n.json

@@ -901,6 +901,7 @@
   "operator-member-abbrev": "m",
   "operator-member-abbrev": "m",
   "operator-assignee": "assignee",
   "operator-assignee": "assignee",
   "operator-assignee-abbrev": "a",
   "operator-assignee-abbrev": "a",
+  "operator-creator": "creator",
   "operator-status": "status",
   "operator-status": "status",
   "operator-due": "due",
   "operator-due": "due",
   "operator-created": "created",
   "operator-created": "created",
@@ -952,6 +953,7 @@
   "globalSearch-instructions-operator-at": "`__operator_user_abbrev__username` - shorthand for `user:<username>`",
   "globalSearch-instructions-operator-at": "`__operator_user_abbrev__username` - shorthand for `user:<username>`",
   "globalSearch-instructions-operator-member": "`__operator_member__:<username>` - cards where *<username>* is a *member*",
   "globalSearch-instructions-operator-member": "`__operator_member__:<username>` - cards where *<username>* is a *member*",
   "globalSearch-instructions-operator-assignee": "`__operator_assignee__:<username>` - cards where *<username>* is an *assignee*",
   "globalSearch-instructions-operator-assignee": "`__operator_assignee__:<username>` - cards where *<username>* is an *assignee*",
+  "globalSearch-instructions-operator-creator": "`__operator_creator__:<username>` - cards where *<username>* is the card's creator",
   "globalSearch-instructions-operator-due": "`__operator_due__:<n>` - cards which are due up to *<n>* days from now.  `__operator_due__:__predicate_overdue__ lists all cards past their due date.",
   "globalSearch-instructions-operator-due": "`__operator_due__:<n>` - cards which are due up to *<n>* days from now.  `__operator_due__:__predicate_overdue__ lists all cards past their due date.",
   "globalSearch-instructions-operator-created": "`__operator_created__:<n>` - cards which were created *<n>* days ago or less",
   "globalSearch-instructions-operator-created": "`__operator_created__:<n>` - cards which were created *<n>* days ago or less",
   "globalSearch-instructions-operator-modified": "`__operator_modified__:<n>` - cards which were modified *<n>* days ago or less",
   "globalSearch-instructions-operator-modified": "`__operator_modified__:<n>` - cards which were modified *<n>* days ago or less",

+ 25 - 32
server/publications/cards.js

@@ -15,12 +15,15 @@ import {
   OPERATOR_ASSIGNEE,
   OPERATOR_ASSIGNEE,
   OPERATOR_BOARD,
   OPERATOR_BOARD,
   OPERATOR_COMMENT,
   OPERATOR_COMMENT,
+  OPERATOR_CREATED_AT,
+  OPERATOR_CREATOR,
   OPERATOR_DUE,
   OPERATOR_DUE,
   OPERATOR_HAS,
   OPERATOR_HAS,
   OPERATOR_LABEL,
   OPERATOR_LABEL,
   OPERATOR_LIMIT,
   OPERATOR_LIMIT,
   OPERATOR_LIST,
   OPERATOR_LIST,
   OPERATOR_MEMBER,
   OPERATOR_MEMBER,
+  OPERATOR_MODIFIED_AT,
   OPERATOR_SORT,
   OPERATOR_SORT,
   OPERATOR_STATUS,
   OPERATOR_STATUS,
   OPERATOR_SWIMLANE,
   OPERATOR_SWIMLANE,
@@ -163,7 +166,7 @@ function buildSelector(queryParams) {
 
 
     if (queryParams.hasOperator(OPERATOR_BOARD)) {
     if (queryParams.hasOperator(OPERATOR_BOARD)) {
       const queryBoards = [];
       const queryBoards = [];
-      queryParams.hasOperator(OPERATOR_BOARD).forEach(query => {
+      queryParams.getPredicates(OPERATOR_BOARD).forEach(query => {
         const boards = Boards.userSearch(userId, {
         const boards = Boards.userSearch(userId, {
           title: new RegExp(escapeForRegex(query), 'i'),
           title: new RegExp(escapeForRegex(query), 'i'),
         });
         });
@@ -240,7 +243,7 @@ function buildSelector(queryParams) {
       }
       }
     }
     }
 
 
-    [OPERATOR_DUE, 'createdAt', 'modifiedAt'].forEach(field => {
+    [OPERATOR_DUE, OPERATOR_CREATED_AT, OPERATOR_MODIFIED_AT].forEach(field => {
       if (queryParams.hasOperator(field)) {
       if (queryParams.hasOperator(field)) {
         selector[field] = {};
         selector[field] = {};
         const predicate = queryParams.getPredicate(field);
         const predicate = queryParams.getPredicate(field);
@@ -251,52 +254,42 @@ function buildSelector(queryParams) {
     const queryUsers = {};
     const queryUsers = {};
     queryUsers[OPERATOR_ASSIGNEE] = [];
     queryUsers[OPERATOR_ASSIGNEE] = [];
     queryUsers[OPERATOR_MEMBER] = [];
     queryUsers[OPERATOR_MEMBER] = [];
+    queryUsers[OPERATOR_CREATOR] = [];
 
 
     if (queryParams.hasOperator(OPERATOR_USER)) {
     if (queryParams.hasOperator(OPERATOR_USER)) {
+      const users = [];
       queryParams.getPredicates(OPERATOR_USER).forEach(username => {
       queryParams.getPredicates(OPERATOR_USER).forEach(username => {
         const user = Users.findOne({ username });
         const user = Users.findOne({ username });
         if (user) {
         if (user) {
-          queryUsers[OPERATOR_MEMBER].push(user._id);
-          queryUsers[OPERATOR_ASSIGNEE].push(user._id);
+          users.push(user._id);
         } else {
         } else {
           errors.addNotFound(OPERATOR_USER, username);
           errors.addNotFound(OPERATOR_USER, username);
         }
         }
       });
       });
+      if (users.length) {
+        selector.$and.push({
+          $or: [{ members: { $in: users } }, { assignees: { $in: users } }],
+        });
+      }
     }
     }
 
 
-    [OPERATOR_MEMBER, OPERATOR_ASSIGNEE].forEach(key => {
+    [OPERATOR_MEMBER, OPERATOR_ASSIGNEE, OPERATOR_CREATOR].forEach(key => {
       if (queryParams.hasOperator(key)) {
       if (queryParams.hasOperator(key)) {
-        queryParams.getPredicates(key).forEach(query => {
-          const users = Users.find({
-            username: query,
-          });
-          if (users.count()) {
-            users.forEach(user => {
-              queryUsers[key].push(user._id);
-            });
+        const users = [];
+        queryParams.getPredicates(key).forEach(username => {
+          const user = Users.findOne({ username });
+          if (user) {
+            users.push(user._id);
           } else {
           } else {
-            errors.addNotFound(key, query);
+            errors.addNotFound(key, username);
           }
           }
         });
         });
+        if (users.length) {
+          selector[key] = { $in: users };
+        }
       }
       }
     });
     });
 
 
-    if (
-      queryUsers[OPERATOR_MEMBER].length &&
-      queryUsers[OPERATOR_ASSIGNEE].length
-    ) {
-      selector.$and.push({
-        $or: [
-          { members: { $in: queryUsers[OPERATOR_MEMBER] } },
-          { assignees: { $in: queryUsers[OPERATOR_ASSIGNEE] } },
-        ],
-      });
-    } else if (queryUsers[OPERATOR_MEMBER].length) {
-      selector.members = { $in: queryUsers[OPERATOR_MEMBER] };
-    } else if (queryUsers[OPERATOR_ASSIGNEE].length) {
-      selector.assignees = { $in: queryUsers[OPERATOR_ASSIGNEE] };
-    }
-
     if (queryParams.hasOperator(OPERATOR_LABEL)) {
     if (queryParams.hasOperator(OPERATOR_LABEL)) {
       queryParams.getPredicates(OPERATOR_LABEL).forEach(label => {
       queryParams.getPredicates(OPERATOR_LABEL).forEach(label => {
         const queryLabels = [];
         const queryLabels = [];
@@ -443,9 +436,9 @@ function buildSelector(queryParams) {
   }
   }
 
 
   // eslint-disable-next-line no-console
   // eslint-disable-next-line no-console
-  // console.log('selector:', selector);
+  console.log('selector:', selector);
   // eslint-disable-next-line no-console
   // eslint-disable-next-line no-console
-  // console.log('selector.$and:', selector.$and);
+  console.log('selector.$and:', selector.$and);
 
 
   const query = new Query();
   const query = new Query();
   query.selector = selector;
   query.selector = selector;