Browse Source

Global search - add error messages for terms that are not found

John R. Supplee 4 years ago
parent
commit
80b23e5cc1

+ 5 - 0
client/components/main/globalSearch.jade

@@ -19,6 +19,11 @@ template(name="globalSearch")
         h1
           = resultsCount.get
           | Results
+        if queryErrors.get
+          div
+            each msg in errorMessages
+              span.global-search-error-messages
+                | {{_ msg.tag msg.value }}
         each card in results
           .global-search-card-wrapper
             a.minicard-wrapper.card-title(href=card.absoluteUrl)

+ 29 - 12
client/components/main/globalSearch.js

@@ -42,33 +42,50 @@ BlazeComponent.extendComponent({
     this.query = new ReactiveVar('');
     this.queryParams = null;
     this.resultsCount = new ReactiveVar(0);
-
-    // this.autorun(() => {
-    //   const handle = subManager.subscribe('globalSearch');
-    //   Tracker.nonreactive(() => {
-    //     Tracker.autorun(() => {
-    //       this.isPageReady.set(handle.ready());
-    //     });
-    //   });
-    // });
+    this.queryErrors = new ReactiveVar(null);
     Meteor.subscribe('setting');
   },
 
   results() {
     if (this.queryParams) {
-      const cards = Cards.globalSearch(this.queryParams);
-      this.resultsCount.set(cards.count());
-      return cards;
+      const results = Cards.globalSearch(this.queryParams);
+      // eslint-disable-next-line no-console
+      console.log('errors:', results.errors);
+      this.resultsCount.set(results.cards.count());
+      this.queryErrors.set(results.errors);
+      return results.cards;
     }
+    this.resultsCount.set(0);
     return [];
   },
 
+  errorMessages() {
+    const errors = this.queryErrors.get();
+    const messages = [];
+
+    errors.notFound.boards.forEach(board => {
+      messages.push({ tag: 'board-title-not-found', value: board });
+    });
+    errors.notFound.swimlanes.forEach(swim => {
+      messages.push({ tag: 'swimlane-title-not-found', value: swim });
+    });
+    errors.notFound.lists.forEach(list => {
+      messages.push({ tag: 'list-title-not-found', value: list });
+    });
+    errors.notFound.users.forEach(user => {
+      messages.push({ tag: 'user-username-not-found', value: user });
+    });
+
+    return messages;
+  },
+
   events() {
     return [
       {
         'submit .js-search-query-form'(evt) {
           evt.preventDefault();
           this.query.set(evt.target.searchQuery.value);
+          this.queryErrors.set(null);
 
           if (!this.query.get()) {
             this.searching.set(false);

+ 3 - 0
client/components/main/globalSearch.styl

@@ -67,3 +67,6 @@
 
 .global-search-context-list
   margin-bottom: 0.7rem
+
+.global-search-error-messages
+  color: darkred

+ 5 - 1
i18n/en.i18n.json

@@ -861,5 +861,9 @@
   "dueCardsViewChange-title": "Due Cards View",
   "dueCardsViewChange-choice-me": "Me",
   "dueCardsViewChange-choice-all": "All Users",
-  "dueCardsViewChange-choice-all-description": "Shows all incomplete cards with a *Due* date from boards for which the user has permission."
+  "dueCardsViewChange-choice-all-description": "Shows all incomplete cards with a *Due* date from boards for which the user has permission.",
+  "board-title-not-found": "Board '%s' not found.",
+  "swimlane-title-not-found": "Swimlane '%s' not found.",
+  "list-title-not-found": "List '%s' not found.",
+  "user-username-not-found": "Username '%s' not found."
 }

+ 14 - 0
models/boards.js

@@ -1208,6 +1208,20 @@ function boardRemover(userId, doc) {
   );
 }
 
+Boards.userSearch = (userId, includeArchived = false, selector = {}) => {
+  if (!includeArchived) {
+    selector = {
+      archived: false,
+    };
+  }
+  selector.$or = [
+    { permission: 'public' },
+    { members: { $elemMatch: { userId, isActive: true } } },
+  ];
+
+  return Boards.find(selector);
+};
+
 Boards.userBoards = (userId, includeArchived = false, selector = {}) => {
   if (!includeArchived) {
     selector = {

+ 70 - 41
models/cards.js

@@ -1735,6 +1735,15 @@ Cards.globalSearch = queryParams => {
   // eslint-disable-next-line no-console
   console.log('userId:', this.userId);
 
+  const errors = {
+    notFound: {
+      boards: [],
+      swimlanes: [],
+      lists: [],
+      users: [],
+    },
+  };
+
   const selector = {
     archived: false,
     type: 'cardType-card',
@@ -1743,58 +1752,78 @@ Cards.globalSearch = queryParams => {
     listId: { $nin: Lists.archivedListIds() },
   };
 
-  if ('swimlanesSelector' in queryParams) {
-    const swimSelector = {
-      archived: false,
-    };
-
-    for (const key in queryParams.swimlanesSelector) {
-      swimSelector[key] = queryParams.swimlanesSelector[key];
-    }
-
-    selector.swimlaneId.$in = Swimlanes.find(swimSelector).map(swim => {
-      return swim._id;
+  if (queryParams.boards.length) {
+    const queryBoards = [];
+    queryParams.boards.forEach(query => {
+      const boards = Boards.userSearch(userId, {
+        title: query,
+      });
+      if (boards.count()) {
+        boards.forEach(board => {
+          queryBoards.push(board._id);
+        });
+      } else {
+        errors.notFound.boards.push(query);
+      }
     });
+
+    selector.boardId.$in = queryBoards;
   }
 
-  if ('listsSelector' in queryParams) {
-    const listsSelector = {
-      archived: false,
-    };
+  if (queryParams.swimlanes.length) {
+    const querySwimlanes = [];
+    queryParams.swimlanes.forEach(query => {
+      const swimlanes = Swimlanes.find({
+        title: query,
+      });
+      if (swimlanes.count()) {
+        swimlanes.forEach(swim => {
+          querySwimlanes.push(swim._id);
+        });
+      } else {
+        errors.notFound.swimlanes.push(query);
+      }
+    });
 
-    // eslint-disable-next-line no-console
-    // console.log('listsSelector:', queryParams.listsSelector.keys());
-    for (const key in queryParams.listsSelector) {
-      listsSelector[key] = queryParams.listsSelector[key];
-    }
+    selector.swimlaneId.$in = querySwimlanes;
+  }
 
-    // eslint-disable-next-line no-console
-    console.log('search list selector:', selector);
-    selector.listId.$in = Lists.find(listsSelector).map(list => {
-      return list._id;
+  if (queryParams.lists.length) {
+    const queryLists = [];
+    queryParams.lists.forEach(query => {
+      const lists = Lists.find({
+        title: query,
+      });
+      if (lists.count()) {
+        lists.forEach(list => {
+          queryLists.push(list._id);
+        });
+      } else {
+        errors.notFound.lists.push(query);
+      }
     });
+
+    selector.listId.$in = queryLists;
   }
 
   if (queryParams.users.length) {
-    const users = [];
-    Users.find({ username: { $in: queryParams.users } }).forEach(user => {
-      users.push(user._id);
+    const queryUsers = [];
+    queryParams.users.forEach(query => {
+      const users = Users.find({
+        username: query,
+      });
+      if (users.count()) {
+        users.forEach(user => {
+          queryUsers.push(user._id);
+        });
+      } else {
+        errors.notFound.users.push(query);
+      }
     });
-    if (users.length) {
-      selector.$or = [
-        { members: { $in: users } },
-        { assignees: { $in: users } },
-      ];
-    }
-  }
-
-  if (queryParams.text) {
-    const regex = new RegExp(queryParams.text, 'i');
 
     selector.$or = [
-      { title: regex },
-      { description: regex },
-      { customFields: { $elemMatch: { value: regex } } },
+      { members: { $in: queryUsers } },
+      { assignees: { $in: queryUsers } },
     ];
   }
 
@@ -1820,7 +1849,7 @@ Cards.globalSearch = queryParams => {
 
   // eslint-disable-next-line no-console
   console.log('count:', cards.count());
-  return cards;
+  return { cards, errors };
 };
 
 //FUNCTIONS FOR creation of Activities

+ 1 - 1
server/publications/cards.js

@@ -181,7 +181,7 @@ Meteor.publish('globalSearch', function(queryParams) {
   // eslint-disable-next-line no-console
   console.log('queryParams:', queryParams);
 
-  const cards = Cards.globalSearch(queryParams);
+  const cards = Cards.globalSearch(queryParams).cards;
 
   const boards = [];
   const swimlanes = [];