瀏覽代碼

Bug fix for #3864 searching archived cards and add new operators for organizations and teams

John Supplee 3 年之前
父節點
當前提交
aa0dee1fba
共有 8 個文件被更改,包括 89 次插入6 次删除
  1. 6 0
      config/query-classes.js
  2. 2 0
      config/search-const.js
  3. 4 0
      i18n/en.i18n.json
  4. 2 2
      models/boards.js
  5. 11 0
      models/lists.js
  6. 11 0
      models/swimlanes.js
  7. 2 0
      models/users.js
  8. 51 4
      server/publications/cards.js

+ 6 - 0
config/query-classes.js

@@ -12,9 +12,11 @@ import {
   OPERATOR_LIST,
   OPERATOR_MEMBER,
   OPERATOR_MODIFIED_AT,
+  OPERATOR_ORG,
   OPERATOR_SORT,
   OPERATOR_STATUS,
   OPERATOR_SWIMLANE,
+  OPERATOR_TEAM,
   OPERATOR_UNKNOWN,
   OPERATOR_USER,
   ORDER_ASCENDING,
@@ -161,6 +163,8 @@ export class QueryErrors {
     [OPERATOR_ASSIGNEE, 'user-username-not-found'],
     [OPERATOR_MEMBER, 'user-username-not-found'],
     [OPERATOR_CREATOR, 'user-username-not-found'],
+    [OPERATOR_ORG, 'org-name-not-found'],
+    [OPERATOR_TEAM, 'team-name-not-found'],
   ];
 
   constructor() {
@@ -313,6 +317,8 @@ export class Query {
       'operator-sort': OPERATOR_SORT,
       'operator-limit': OPERATOR_LIMIT,
       'operator-debug': OPERATOR_DEBUG,
+      'operator-org': OPERATOR_ORG,
+      'operator-team': OPERATOR_TEAM,
     };
 
     const predicates = {

+ 2 - 0
config/search-const.js

@@ -12,9 +12,11 @@ export const OPERATOR_LIMIT = 'limit';
 export const OPERATOR_LIST = 'list';
 export const OPERATOR_MEMBER = 'members';
 export const OPERATOR_MODIFIED_AT = 'modifiedAt';
+export const OPERATOR_ORG = 'org';
 export const OPERATOR_SORT = 'sort';
 export const OPERATOR_STATUS = 'status';
 export const OPERATOR_SWIMLANE = 'swimlane';
+export const OPERATOR_TEAM = 'team';
 export const OPERATOR_UNKNOWN = 'unknown';
 export const OPERATOR_USER = 'user';
 export const ORDER_ASCENDING = 'asc';

+ 4 - 0
i18n/en.i18n.json

@@ -943,6 +943,8 @@
   "label-color-not-found": "Label color %s not found.",
   "user-username-not-found": "Username '%s' not found.",
   "comment-not-found": "Card with comment containing text '%s' not found.",
+  "org-name-not-found": "Organization '%s' not found.",
+  "team-name-not-found": "Team '%s' not found.",
   "globalSearch-title": "Search All Boards",
   "no-cards-found": "No Cards Found",
   "one-card-found": "One Card Found",
@@ -972,6 +974,8 @@
   "operator-has": "has",
   "operator-limit": "limit",
   "operator-debug": "debug",
+  "operator-org": "org",
+  "operator-team": "team",
   "predicate-archived": "archived",
   "predicate-open": "open",
   "predicate-ended": "ended",

+ 2 - 2
models/boards.js

@@ -1501,8 +1501,8 @@ Boards.userBoards = (
   selector.$or = [
     { permission: 'public' },
     { members: { $elemMatch: { userId, isActive: true } } },
-    { 'orgs.orgId': { $in: user.orgIds() } },
-    { 'teams.teamId': { $in : user.teamIds() } },
+    { orgs: { $elemMatch: { orgId: { $in: user.orgIds() }, isActive: true } } },
+    { teams: { $elemMatch: { teamId: { $in: user.teamIds() }, isActive: true } } },
   ];
 
   return Boards.find(selector, projection);

+ 11 - 0
models/lists.js

@@ -345,6 +345,17 @@ Lists.mutations({
   },
 });
 
+Lists.userArchivedLists = userId => {
+  return Lists.find({
+    boardId: { $in: Boards.userBoardIds(userId, null) },
+    archived: true,
+  })
+};
+
+Lists.userArchivedListIds = () => {
+  return Lists.userArchivedLists().map(list => { return list._id; });
+};
+
 Lists.archivedLists = () => {
   return Lists.find({ archived: true });
 };

+ 11 - 0
models/swimlanes.js

@@ -306,6 +306,17 @@ Swimlanes.mutations({
   },
 });
 
+Swimlanes.userArchivedSwimlanes = userId => {
+  return Swimlanes.find({
+    boardId: { $in: Boards.userBoardIds(userId, null) },
+    archived: true,
+  })
+};
+
+Swimlanes.userArchivedSwimlaneIds = () => {
+  return Swimlanes.userArchivedSwimlanes().map(swim => { return swim._id; });
+};
+
 Swimlanes.archivedSwimlanes = () => {
   return Swimlanes.find({ archived: true });
 };

+ 2 - 0
models/users.js

@@ -521,12 +521,14 @@ Users.helpers({
   },
   teamIds() {
     if (this.teams) {
+      // TODO: Should the Team collection be queried to determine if the team isActive?
       return this.teams.map(team => { return team.teamId });
     }
     return [];
   },
   orgIds() {
     if (this.orgs) {
+      // TODO: Should the Org collection be queried to determine if the organization isActive?
       return this.orgs.map(org => { return org.orgId });
     }
     return [];

+ 51 - 4
server/publications/cards.js

@@ -24,10 +24,10 @@ import {
   OPERATOR_LIMIT,
   OPERATOR_LIST,
   OPERATOR_MEMBER,
-  OPERATOR_MODIFIED_AT,
+  OPERATOR_MODIFIED_AT, OPERATOR_ORG,
   OPERATOR_SORT,
   OPERATOR_STATUS,
-  OPERATOR_SWIMLANE,
+  OPERATOR_SWIMLANE, OPERATOR_TEAM,
   OPERATOR_USER,
   ORDER_ASCENDING,
   PREDICATE_ALL,
@@ -49,6 +49,8 @@ import {
 } from '/config/search-const';
 import { QueryErrors, QueryParams, Query } from '/config/query-classes';
 import { CARD_TYPES } from '../../config/const';
+import Org from "../../models/org";
+import Team from "../../models/team";
 
 const escapeForRegex = require('escape-string-regexp');
 
@@ -151,6 +153,51 @@ function buildSelector(queryParams) {
         }
       });
     }
+
+    if (queryParams.hasOperator(OPERATOR_ORG)) {
+      const orgs = [];
+      queryParams.getPredicates(OPERATOR_ORG).forEach(name => {
+        const org = Org.findOne({
+          $or: [
+            { orgDisplayName: name },
+            { orgShortName: name }
+          ]
+        });
+        if (org) {
+          orgs.push(org._id);
+        } else {
+          errors.addNotFound(OPERATOR_ORG, name);
+        }
+      });
+      if (orgs.length) {
+        boardsSelector.orgs = {
+          $elemMatch: { orgId: { $in: orgs }, isActive: true }
+        };
+      }
+    }
+
+    if (queryParams.hasOperator(OPERATOR_TEAM)) {
+      const teams = [];
+      queryParams.getPredicates(OPERATOR_TEAM).forEach(name => {
+        const team = Team.findOne({
+          $or: [
+            { teamDisplayName: name },
+            { teamShortName: name }
+          ]
+        });
+        if (team) {
+          teams.push(team._id);
+        } else {
+          errors.addNotFound(OPERATOR_TEAM, name);
+        }
+      });
+      if (teams.length) {
+        boardsSelector.teams = {
+          $elemMatch: { teamId: { $in: teams }, isActive: true }
+        };
+      }
+    }
+
     selector = {
       type: 'cardType-card',
       // boardId: { $in: Boards.userBoardIds(userId) },
@@ -169,8 +216,8 @@ function buildSelector(queryParams) {
                 $in: Boards.userBoardIds(userId, archived, boardsSelector),
               },
             },
-            { swimlaneId: { $in: Swimlanes.archivedSwimlaneIds() } },
-            { listId: { $in: Lists.archivedListIds() } },
+            { swimlaneId: { $in: Swimlanes.userArchivedSwimlaneIds(userId) } },
+            { listId: { $in: Lists.userArchivedListIds(userId) } },
             { archived: true },
           ],
         });