Przeglądaj źródła

Move global search to cards model

* add some explanation of the operators
John R. Supplee 4 lat temu
rodzic
commit
34000ad159

+ 36 - 27
client/components/main/globalSearch.jade

@@ -12,33 +12,42 @@ template(name="globalSearch")
   .wrapper
     form.js-search-query-form
       input(type="text" name="searchQuery" placeholder="{{_ 'search-example'}}" autofocus dir="auto")
-  if searching.get
-    +spinner
-  else if hasResults.get
-    .global-search-dueat-list-wrapper
-      h1 Results
-      each card in results
-        .global-search-card-wrapper
-          a.minicard-wrapper.card-title(href=card.absoluteUrl)
-            +minicard(card)
-          ul.global-search-context-list
-            li.global-search-context(title="{{_ 'board'}}")
-              +viewer
-                = card.getBoard.title
-            li.global-search-context.global-search-context-separator
-              = ' '
-              | {{_ 'context-separator'}}
-              = ' '
-            li.global-search-context(title="{{_ 'swimlane'}}")
-              +viewer
-                = card.getSwimlane.title
-            li.global-search-context
-              = ' '
-              | {{_ 'context-separator'}}
-              = ' '
-            li.global-search-context(title="{{_ 'list'}}")
-              +viewer
-                = card.getList.title
+    if searching.get
+      +spinner
+    else if hasResults.get
+      .global-search-dueat-list-wrapper
+        h1 Results
+        each card in results
+          .global-search-card-wrapper
+            a.minicard-wrapper.card-title(href=card.absoluteUrl)
+              +minicard(card)
+              //= card.title
+            ul.global-search-context-list
+              li.global-search-context(title="{{_ 'board'}}")
+                +viewer
+                  = card.getBoard.title
+              li.global-search-context.global-search-context-separator
+                = ' '
+                | {{_ 'context-separator'}}
+                = ' '
+              li.global-search-context(title="{{_ 'swimlane'}}")
+                +viewer
+                  = card.getSwimlane.title
+              li.global-search-context
+                = ' '
+                | {{_ 'context-separator'}}
+                = ' '
+              li.global-search-context(title="{{_ 'list'}}")
+                +viewer
+                  = card.getList.title
+    else
+      h2 Search Operators
+      +viewer
+        = '*  `@`username\n'
+        = '*  `#`label\n'
+        = '*  `board:`<name> or `board:`"<name>"\n'
+        = '*  `swimlane:`<name> or `swimlane:`"<name>"\n'
+        = '*  `list:`<name> or `list:`"<name>"\n'
 
 template(name="globalSearchViewChangePopup")
   ul.pop-over-list

+ 24 - 6
client/components/main/globalSearch.js

@@ -40,6 +40,7 @@ BlazeComponent.extendComponent({
     this.searching = new ReactiveVar(false);
     this.hasResults = new ReactiveVar(false);
     this.query = new ReactiveVar('');
+    this.queryParams = null;
 
     // this.autorun(() => {
     //   const handle = subManager.subscribe('globalSearch');
@@ -53,7 +54,10 @@ BlazeComponent.extendComponent({
   },
 
   results() {
-    return Cards.find();
+    if (this.queryParams) {
+      return Cards.globalSearch(this.queryParams);
+    }
+    return [];
   },
 
   events() {
@@ -63,6 +67,12 @@ BlazeComponent.extendComponent({
           evt.preventDefault();
           this.query.set(evt.target.searchQuery.value);
 
+          if (!this.query.get()) {
+            this.searching.set(false);
+            this.hasResults.set(false);
+            return;
+          }
+
           this.searching.set(true);
           this.hasResults.set(false);
 
@@ -70,8 +80,8 @@ BlazeComponent.extendComponent({
           // eslint-disable-next-line no-console
           console.log('query:', query);
 
-          const reUser = /^@(?<user>\w+)(\s+|$)/;
-          const reLabel = /^#(?<label>\w+)(\s+|$)/;
+          const reUser = /^@(?<user>[\w.:]+)(\s+|$)/;
+          const reLabel = /^#(?<label>[\w:-]+)(\s+|$)/;
           const reOperator1 = /^(?<operator>\w+):(?<value>\w+)(\s+|$)/;
           const reOperator2 = /^(?<operator>\w+):(?<quote>["']*)(?<value>.*?)\k<quote>(\s+|$)/;
           const reText = /^(?<text>[^:@#\s]+)(\s+|$)/;
@@ -148,7 +158,7 @@ BlazeComponent.extendComponent({
           }
 
           // eslint-disable-next-line no-console
-          console.log('selector:', selector);
+          // console.log('selector:', selector);
           // eslint-disable-next-line no-console
           console.log('text:', text);
 
@@ -193,13 +203,21 @@ BlazeComponent.extendComponent({
           }
 
           selector.text = text;
+          // eslint-disable-next-line no-console
+          console.log('selector:', selector);
+
+          this.queryParams = selector;
 
           this.autorun(() => {
             const handle = subManager.subscribe('globalSearch', selector);
             Tracker.nonreactive(() => {
               Tracker.autorun(() => {
-                this.searching.set(!handle.ready());
-                this.hasResults.set(handle.ready());
+                // eslint-disable-next-line no-console
+                console.log('ready:', handle.ready());
+                if (handle.ready()) {
+                  this.searching.set(false);
+                  this.hasResults.set(true);
+                }
               });
             });
           });

+ 88 - 0
models/cards.js

@@ -1730,6 +1730,94 @@ Cards.mutations({
   },
 });
 
+Cards.globalSearch = queryParams => {
+  const userId = Meteor.userId;
+  // eslint-disable-next-line no-console
+  console.log('userId:', this.userId);
+
+  let selector = {
+    archived: false,
+  };
+
+  const searchLists = [];
+  // eslint-disable-next-line no-console
+  // console.log('listsSelector:', queryParams.keys());
+  if ('listsSelector' in queryParams) {
+    // eslint-disable-next-line no-console
+    // console.log('listsSelector:', queryParams.listsSelector.keys());
+    for (const key in queryParams.listsSelector) {
+      selector[key] = queryParams.listsSelector[key];
+    }
+
+    // eslint-disable-next-line no-console
+    console.log('search list selector:', selector);
+    Lists.find(selector).forEach(list => {
+      searchLists.push(list._id);
+    });
+    // eslint-disable-next-line no-console
+    console.log('search lists:', searchLists);
+  }
+
+  const searchSwimlanes = [];
+  if ('swimlanesSelector' in queryParams) {
+    for (const key in queryParams.swimlanesSelector) {
+      selector[key] = queryParams.swimlanesSelector[key];
+    }
+
+    Lists.find(selector).forEach(swim => {
+      searchSwimlanes.push(swim._id);
+    });
+  }
+
+  selector = {
+    archived: false,
+    type: 'cardType-card',
+    boardId: { $in: Boards.userBoardIds(userId) },
+    swimlaneId: { $nin: Swimlanes.archivedSwimlaneIds() },
+    listId: { $nin: Lists.archivedListIds() },
+  };
+
+  if (searchSwimlanes.length) {
+    selector.swimlaneId.$in = searchSwimlanes;
+  }
+
+  if (searchLists.length) {
+    selector.listId.$in = searchLists;
+  }
+
+  if (queryParams.users.length) {
+    const users = [];
+    Users.find({ username: { $in: queryParams.users } }).forEach(user => {
+      users.push(user._id);
+    });
+    if (users.length) {
+      selector.$or = [
+        { members: { $in: users } },
+        { assignees: { $in: users } },
+      ];
+    }
+  }
+
+  // eslint-disable-next-line no-console
+  console.log('selector:', selector);
+  return Cards.find(selector, {
+    fields: {
+      _id: 1,
+      archived: 1,
+      boardId: 1,
+      swimlaneId: 1,
+      listId: 1,
+      title: 1,
+      type: 1,
+      sort: 1,
+      members: 1,
+      assignees: 1,
+      colors: 1,
+      dueAt: 1,
+    },
+  });
+};
+
 //FUNCTIONS FOR creation of Activities
 
 function updateActivities(doc, fieldNames, modifier) {

+ 1 - 72
server/publications/cards.js

@@ -181,78 +181,7 @@ Meteor.publish('globalSearch', function(queryParams) {
   // eslint-disable-next-line no-console
   console.log('queryParams:', queryParams);
 
-  const user = Users.findOne(this.userId);
-
-  // const archivedSwimlanes = Swimlanes.archivedSwimlaneIds();
-
-  // const permiitedBoards = Boards.userBoardIds(user._id);
-
-  let selector = {
-    archived: false,
-  };
-  const searchLists = [];
-  // eslint-disable-next-line no-console
-  // console.log('listsSelector:', queryParams.keys());
-  if ('listsSelector' in queryParams) {
-    // eslint-disable-next-line no-console
-    // console.log('listsSelector:', queryParams.listsSelector.keys());
-    for (const key in queryParams.listsSelector) {
-      selector[key] = queryParams.listsSelector[key];
-    }
-
-    // eslint-disable-next-line no-console
-    console.log('search list selector:', selector);
-    Lists.find(selector).forEach(list => {
-      searchLists.push(list._id);
-    });
-    // eslint-disable-next-line no-console
-    console.log('search lists:', searchLists);
-  }
-
-  const searchSwimlanes = [];
-  if ('swimlanesSelector' in queryParams) {
-    for (const key in queryParams.swimlanesSelector) {
-      selector[key] = queryParams.swimlanesSelector[key];
-    }
-
-    Lists.find(selector).forEach(swim => {
-      searchSwimlanes.push(swim._id);
-    });
-  }
-
-  selector = {
-    archived: false,
-    boardId: { $in: Boards.userBoardIds(user._id) },
-    swimlaneId: { $nin: Swimlanes.archivedSwimlaneIds() },
-    listId: { $nin: Lists.archivedListIds() },
-  };
-
-  if (searchSwimlanes.length) {
-    selector.swimlaneId.$in = searchSwimlanes;
-  }
-
-  if (searchLists.length) {
-    selector.listId.$in = searchLists;
-  }
-
-  // eslint-disable-next-line no-console
-  console.log('selector:', selector);
-  const cards = Cards.find(selector, {
-    fields: {
-      _id: 1,
-      archived: 1,
-      boardId: 1,
-      swimlaneId: 1,
-      listId: 1,
-      title: 1,
-      type: 1,
-      sort: 1,
-      members: 1,
-      assignees: 1,
-      colors: 1,
-      dueAt: 1,
-    },
-  });
+  const cards = Cards.globalSearch(queryParams);
 
   const boards = [];
   const swimlanes = [];