Преглед изворни кода

Add new debug operator to search and fix some bugs

John Supplee пре 3 година
родитељ
комит
94525a4d3d

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

@@ -42,6 +42,16 @@ template(name="globalSearch")
           autofocus dir="auto"
         )
         a.js-new-search.fa.fa-eraser
+      if debug.get.show
+        h1 Debug
+        if debug.get.showSelector
+          h2 Selector
+          pre
+            = sessionData.selector
+        if debug.get.showProjection
+          h2 Projection
+          pre
+            = sessionData.projection
       if searching.get
         +spinner
       else if hasResults.get

+ 19 - 9
client/lib/cardSearch.js

@@ -1,5 +1,7 @@
 import Cards from '../../models/cards';
 import SessionData from '../../models/usersessiondata';
+import {QueryDebug} from "../../config/query-classes";
+import {OPERATOR_DEBUG} from "../../config/search-const";
 
 export class CardSearchPagedComponent extends BlazeComponent {
   onCreated() {
@@ -19,6 +21,8 @@ export class CardSearchPagedComponent extends BlazeComponent {
     this.sessionId = SessionData.getSessionId();
     this.subscriptionHandle = null;
     this.serverError = new ReactiveVar(false);
+    this.sessionData = null;
+    this.debug = new ReactiveVar(new QueryDebug());
 
     const that = this;
     this.subscriptionCallbacks = {
@@ -52,6 +56,7 @@ export class CardSearchPagedComponent extends BlazeComponent {
     this.resultsCount = 0;
     this.totalHits = 0;
     this.queryErrors = null;
+    this.debug.set(new QueryDebug());
   }
 
   getSessionData(sessionId) {
@@ -63,30 +68,34 @@ export class CardSearchPagedComponent extends BlazeComponent {
   getResults() {
     // eslint-disable-next-line no-console
     // console.log('getting results');
-    const sessionData = this.getSessionData();
+    this.sessionData = this.getSessionData();
     // eslint-disable-next-line no-console
-    console.log('session data:', sessionData);
+    console.log('session data:', this.sessionData);
     const cards = [];
-    sessionData.cards.forEach(cardId => {
+    this.sessionData.cards.forEach(cardId => {
       cards.push(Cards.findOne({ _id: cardId }));
     });
-    this.queryErrors = sessionData.errors;
+    this.queryErrors = this.sessionData.errors;
     if (this.queryErrors.length) {
       // console.log('queryErrors:', this.queryErrorMessages());
       this.hasQueryErrors.set(true);
       // return null;
     }
+    this.debug.set(new QueryDebug(this.sessionData.debug));
+    console.log('debug:', this.debug.get().get());
+    console.log('debug.show():', this.debug.get().show());
+    console.log('debug.showSelector():', this.debug.get().showSelector());
 
     if (cards) {
-      this.totalHits = sessionData.totalHits;
+      this.totalHits = this.sessionData.totalHits;
       this.resultsCount = cards.length;
-      this.resultsStart = sessionData.lastHit - this.resultsCount + 1;
-      this.resultsEnd = sessionData.lastHit;
+      this.resultsStart = this.sessionData.lastHit - this.resultsCount + 1;
+      this.resultsEnd = this.sessionData.lastHit;
       this.resultsHeading.set(this.getResultsHeading());
       this.results.set(cards);
-      this.hasNextPage.set(sessionData.lastHit < sessionData.totalHits);
+      this.hasNextPage.set(this.sessionData.lastHit < this.sessionData.totalHits);
       this.hasPreviousPage.set(
-        sessionData.lastHit - sessionData.resultsCount > 0,
+        this.sessionData.lastHit - this.sessionData.resultsCount > 0,
       );
       return cards;
     }
@@ -113,6 +122,7 @@ export class CardSearchPagedComponent extends BlazeComponent {
 
   runGlobalSearch(queryParams) {
     this.searching.set(true);
+    this.debug.set(new QueryDebug());
     this.stopSubscription();
     this.subscriptionHandle = this.getSubscription(queryParams);
   }

+ 109 - 41
config/query-classes.js

@@ -4,6 +4,7 @@ import {
   OPERATOR_COMMENT,
   OPERATOR_CREATED_AT,
   OPERATOR_CREATOR,
+  OPERATOR_DEBUG,
   OPERATOR_DUE,
   OPERATOR_HAS,
   OPERATOR_LABEL,
@@ -34,8 +35,10 @@ import {
   PREDICATE_OPEN,
   PREDICATE_OVERDUE,
   PREDICATE_PRIVATE,
+  PREDICATE_PROJECTION,
   PREDICATE_PUBLIC,
   PREDICATE_QUARTER,
+  PREDICATE_SELECTOR,
   PREDICATE_START_AT,
   PREDICATE_WEEK,
   PREDICATE_YEAR,
@@ -43,6 +46,46 @@ import {
 import Boards from '../models/boards';
 import moment from 'moment';
 
+export class QueryDebug {
+  predicate = null;
+
+  constructor(predicate) {
+    if (predicate) {
+      this.set(predicate)
+    }
+  }
+
+  get() {
+    return this.predicate;
+  }
+
+  set(predicate) {
+    if ([PREDICATE_ALL, PREDICATE_SELECTOR, PREDICATE_PROJECTION].includes(
+      predicate
+    )) {
+      this.predicate = predicate;
+    } else {
+      this.predicate = null;
+    }
+  }
+
+  show() {
+    return (this.predicate !== null);
+  }
+
+  showAll() {
+    return (this.predicate === PREDICATE_ALL);
+  }
+
+  showSelector() {
+    return (this.predicate === PREDICATE_ALL || this.predicate === PREDICATE_SELECTOR);
+  }
+
+  showProjection() {
+    return (this.predicate === PREDICATE_ALL || this.predicate === PREDICATE_PROJECTION);
+  }
+}
+
 export class QueryParams {
   text = '';
 
@@ -196,6 +239,10 @@ export class Query {
     return this._errors.errors();
   }
 
+  addError(operator, error) {
+    this._errors.addError(operator, error)
+  }
+
   errorMessages() {
     return this._errors.errorMessages();
   }
@@ -213,6 +260,8 @@ export class Query {
   }
 
   buildParams(queryText) {
+    this.queryParams = new QueryParams();
+
     queryText = queryText.trim();
     // eslint-disable-next-line no-console
     //console.log('query:', query);
@@ -260,42 +309,49 @@ export class Query {
       'operator-has': OPERATOR_HAS,
       'operator-sort': OPERATOR_SORT,
       'operator-limit': OPERATOR_LIMIT,
+      'operator-debug': OPERATOR_DEBUG,
     };
 
     const predicates = {
-      due: {
-        'predicate-overdue': PREDICATE_OVERDUE,
-      },
       durations: {
         'predicate-week': PREDICATE_WEEK,
         'predicate-month': PREDICATE_MONTH,
         'predicate-quarter': PREDICATE_QUARTER,
         'predicate-year': PREDICATE_YEAR,
       },
-      status: {
-        'predicate-archived': PREDICATE_ARCHIVED,
-        'predicate-all': PREDICATE_ALL,
-        'predicate-open': PREDICATE_OPEN,
-        'predicate-ended': PREDICATE_ENDED,
-        'predicate-public': PREDICATE_PUBLIC,
-        'predicate-private': PREDICATE_PRIVATE,
-      },
-      sorts: {
-        'predicate-due': PREDICATE_DUE_AT,
-        'predicate-created': PREDICATE_CREATED_AT,
-        'predicate-modified': PREDICATE_MODIFIED_AT,
-      },
-      has: {
-        'predicate-description': PREDICATE_DESCRIPTION,
-        'predicate-checklist': PREDICATE_CHECKLIST,
-        'predicate-attachment': PREDICATE_ATTACHMENT,
-        'predicate-start': PREDICATE_START_AT,
-        'predicate-end': PREDICATE_END_AT,
-        'predicate-due': PREDICATE_DUE_AT,
-        'predicate-assignee': PREDICATE_ASSIGNEES,
-        'predicate-member': PREDICATE_MEMBERS,
-      },
     };
+    predicates[OPERATOR_DUE] = {
+      'predicate-overdue': PREDICATE_OVERDUE,
+    };
+    predicates[OPERATOR_STATUS] = {
+      'predicate-archived': PREDICATE_ARCHIVED,
+      'predicate-all': PREDICATE_ALL,
+      'predicate-open': PREDICATE_OPEN,
+      'predicate-ended': PREDICATE_ENDED,
+      'predicate-public': PREDICATE_PUBLIC,
+      'predicate-private': PREDICATE_PRIVATE,
+    };
+    predicates[OPERATOR_SORT] = {
+      'predicate-due': PREDICATE_DUE_AT,
+      'predicate-created': PREDICATE_CREATED_AT,
+      'predicate-modified': PREDICATE_MODIFIED_AT,
+    };
+    predicates[OPERATOR_HAS] = {
+      'predicate-description': PREDICATE_DESCRIPTION,
+      'predicate-checklist': PREDICATE_CHECKLIST,
+      'predicate-attachment': PREDICATE_ATTACHMENT,
+      'predicate-start': PREDICATE_START_AT,
+      'predicate-end': PREDICATE_END_AT,
+      'predicate-due': PREDICATE_DUE_AT,
+      'predicate-assignee': PREDICATE_ASSIGNEES,
+      'predicate-member': PREDICATE_MEMBERS,
+    };
+    predicates[OPERATOR_DEBUG] = {
+      'predicate-all': PREDICATE_ALL,
+      'predicate-selector': PREDICATE_SELECTOR,
+      'predicate-projection': PREDICATE_PROJECTION,
+    };
+
     const predicateTranslations = {};
     Object.entries(predicates).forEach(([category, catPreds]) => {
       predicateTranslations[category] = {};
@@ -403,7 +459,7 @@ export class Query {
                   value: moment().format('YYYY-MM-DD'),
                 };
               } else {
-                this.errors.addError(OPERATOR_DUE, {
+                this.addError(OPERATOR_DUE, {
                   tag: 'operator-number-expected',
                   value: { operator: op, value },
                 });
@@ -431,27 +487,27 @@ export class Query {
               value = m.groups.operator;
               negated = true;
             }
-            if (!predicateTranslations.sorts[value]) {
-              this.errors.addError(OPERATOR_SORT, {
+            if (!predicateTranslations[OPERATOR_SORT][value]) {
+              this.addError(OPERATOR_SORT, {
                 tag: 'operator-sort-invalid',
                 value,
               });
               continue;
             } else {
               value = {
-                name: predicateTranslations.sorts[value],
+                name: predicateTranslations[OPERATOR_SORT][value],
                 order: negated ? ORDER_DESCENDING : ORDER_ASCENDING,
               };
             }
           } else if (operator === OPERATOR_STATUS) {
-            if (!predicateTranslations.status[value]) {
-              this.errors.addError(OPERATOR_STATUS, {
+            if (!predicateTranslations[OPERATOR_STATUS][value]) {
+              this.addError(OPERATOR_STATUS, {
                 tag: 'operator-status-invalid',
                 value,
               });
               continue;
             } else {
-              value = predicateTranslations.status[value];
+              value = predicateTranslations[OPERATOR_STATUS][value];
             }
           } else if (operator === OPERATOR_HAS) {
             let negated = false;
@@ -460,22 +516,22 @@ export class Query {
               value = m.groups.operator;
               negated = true;
             }
-            if (!predicateTranslations.has[value]) {
-              this.errors.addError(OPERATOR_HAS, {
+            if (!predicateTranslations[OPERATOR_HAS][value]) {
+              this.addError(OPERATOR_HAS, {
                 tag: 'operator-has-invalid',
                 value,
               });
               continue;
             } else {
               value = {
-                field: predicateTranslations.has[value],
+                field: predicateTranslations[OPERATOR_HAS][value],
                 exists: !negated,
               };
             }
           } else if (operator === OPERATOR_LIMIT) {
             const limit = parseInt(value, 10);
             if (isNaN(limit) || limit < 1) {
-              this.errors.addError(OPERATOR_LIMIT, {
+              this.addError(OPERATOR_LIMIT, {
                 tag: 'operator-limit-invalid',
                 value,
               });
@@ -483,11 +539,21 @@ export class Query {
             } else {
               value = limit;
             }
+          } else if (operator === OPERATOR_DEBUG) {
+            if (!predicateTranslations[OPERATOR_DEBUG][value]) {
+              this.addError(OPERATOR_DEBUG, {
+                tag: 'operator-debug-invalid',
+                value,
+              });
+              continue;
+            } else {
+              value = predicateTranslations[OPERATOR_DEBUG][value];
+            }
           }
 
           this.queryParams.addPredicate(operator, value);
         } else {
-          this.errors.addError(OPERATOR_UNKNOWN, {
+          this.addError(OPERATOR_UNKNOWN, {
             tag: 'operator-unknown-error',
             value: op,
           });
@@ -509,11 +575,13 @@ export class Query {
       }
     }
 
-    // eslint-disable-next-line no-console
-    // console.log('text:', text);
     this.queryParams.text = text;
 
     // eslint-disable-next-line no-console
-    //console.log('queryParams:', this.queryParams);
+    if (this.queryParams.hasOperator(OPERATOR_DEBUG)) {
+      // eslint-disable-next-line no-console
+      console.log('text:', this.queryParams.text);
+      console.log('queryParams:', this.queryParams);
+    }
   }
 }

+ 3 - 0
config/search-const.js

@@ -3,6 +3,7 @@ export const OPERATOR_ASSIGNEE = 'assignees';
 export const OPERATOR_COMMENT = 'comment';
 export const OPERATOR_CREATED_AT = 'createdAt';
 export const OPERATOR_CREATOR = 'userId';
+export const OPERATOR_DEBUG = 'debug';
 export const OPERATOR_DUE = 'dueAt';
 export const OPERATOR_BOARD = 'board';
 export const OPERATOR_HAS = 'has';
@@ -33,9 +34,11 @@ export const PREDICATE_MODIFIED_AT = 'modifiedAt';
 export const PREDICATE_MONTH = 'month';
 export const PREDICATE_OPEN = 'open';
 export const PREDICATE_OVERDUE = 'overdue';
+export const PREDICATE_PROJECTION = 'projection';
 export const PREDICATE_PRIVATE = 'private';
 export const PREDICATE_PUBLIC = 'public';
 export const PREDICATE_QUARTER = 'quarter';
+export const PREDICATE_SELECTOR = 'selector';
 export const PREDICATE_START_AT = 'startAt';
 export const PREDICATE_SYSTEM = 'system';
 export const PREDICATE_WEEK = 'week';

+ 4 - 0
i18n/en.i18n.json

@@ -971,6 +971,7 @@
   "operator-comment": "comment",
   "operator-has": "has",
   "operator-limit": "limit",
+  "operator-debug": "debug",
   "predicate-archived": "archived",
   "predicate-open": "open",
   "predicate-ended": "ended",
@@ -992,12 +993,15 @@
   "predicate-member": "member",
   "predicate-public": "public",
   "predicate-private": "private",
+  "predicate-selector": "selector",
+  "predicate-projection": "projection",
   "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",
   "operator-status-invalid": "'%s' is not a valid status",
   "operator-has-invalid": "%s is not a valid existence check",
   "operator-limit-invalid": "%s is not a valid limit.  Limit should be a positive integer.",
+  "operator-debug-invalid": "%s is not a valid debug predicate",
   "next-page": "Next Page",
   "previous-page": "Previous Page",
   "heading-notes": "Notes",

+ 5 - 1
models/usersessiondata.js

@@ -77,6 +77,10 @@ SessionData.attachSchema(
       optional: true,
       defaultValue: [],
     },
+    debug: {
+      type: String,
+      optional: true,
+    },
     'errors.$': {
       type: new SimpleSchema({
         tag: {
@@ -177,7 +181,7 @@ function unpickleObject(obj) {
 SessionData.pickle = value => {
   return JSON.stringify(value, (key, value) => {
     return pickleValue(value);
-  });
+  }, 2);
 };
 
 function pickleValue(value) {

+ 3 - 2
server/publications/cards.js

@@ -16,7 +16,7 @@ import {
   OPERATOR_BOARD,
   OPERATOR_COMMENT,
   OPERATOR_CREATED_AT,
-  OPERATOR_CREATOR,
+  OPERATOR_CREATOR, OPERATOR_DEBUG,
   OPERATOR_DUE,
   OPERATOR_HAS,
   OPERATOR_LABEL,
@@ -458,7 +458,7 @@ function buildSelector(queryParams) {
   }
 
   // eslint-disable-next-line no-console
-  //console.log('cards selector:', JSON.stringify(selector, null, 2));
+  // console.log('cards selector:', JSON.stringify(selector, null, 2));
 
   const query = new Query();
   query.selector = selector;
@@ -634,6 +634,7 @@ function findCards(sessionId, query) {
       selector: SessionData.pickle(query.selector),
       projection: SessionData.pickle(query.projection),
       errors: query.errors(),
+      debug: query.getQueryParams().getPredicate(OPERATOR_DEBUG)
     },
   };