| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596 | 
							- import {
 
-   OPERATOR_ASSIGNEE,
 
-   OPERATOR_BOARD,
 
-   OPERATOR_COMMENT,
 
-   OPERATOR_CREATED_AT,
 
-   OPERATOR_CREATOR,
 
-   OPERATOR_DEBUG,
 
-   OPERATOR_DUE,
 
-   OPERATOR_HAS,
 
-   OPERATOR_LABEL,
 
-   OPERATOR_LIMIT,
 
-   OPERATOR_LIST,
 
-   OPERATOR_MEMBER,
 
-   OPERATOR_MODIFIED_AT,
 
-   OPERATOR_ORG,
 
-   OPERATOR_SORT,
 
-   OPERATOR_STATUS,
 
-   OPERATOR_SWIMLANE,
 
-   OPERATOR_TEAM,
 
-   OPERATOR_UNKNOWN,
 
-   OPERATOR_USER,
 
-   ORDER_ASCENDING,
 
-   ORDER_DESCENDING,
 
-   PREDICATE_ALL,
 
-   PREDICATE_ARCHIVED,
 
-   PREDICATE_ASSIGNEES,
 
-   PREDICATE_ATTACHMENT,
 
-   PREDICATE_CHECKLIST,
 
-   PREDICATE_CREATED_AT,
 
-   PREDICATE_DESCRIPTION,
 
-   PREDICATE_DUE_AT,
 
-   PREDICATE_END_AT,
 
-   PREDICATE_ENDED,
 
-   PREDICATE_MEMBERS,
 
-   PREDICATE_MODIFIED_AT,
 
-   PREDICATE_MONTH,
 
-   PREDICATE_OPEN,
 
-   PREDICATE_OVERDUE,
 
-   PREDICATE_PRIVATE,
 
-   PREDICATE_PROJECTION,
 
-   PREDICATE_PUBLIC,
 
-   PREDICATE_QUARTER,
 
-   PREDICATE_SELECTOR,
 
-   PREDICATE_START_AT,
 
-   PREDICATE_WEEK,
 
-   PREDICATE_YEAR,
 
- } from './search-const';
 
- 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 = '';
 
-   constructor(params = {}, text = '') {
 
-     this.params = params;
 
-     this.text = text;
 
-   }
 
-   hasOperator(operator) {
 
-     return (
 
-       this.params[operator] !== undefined &&
 
-       (this.params[operator].length === undefined ||
 
-         this.params[operator].length > 0)
 
-     );
 
-   }
 
-   addPredicate(operator, predicate) {
 
-     if (!this.hasOperator(operator)) {
 
-       this.params[operator] = [];
 
-     }
 
-     this.params[operator].push(predicate);
 
-   }
 
-   setPredicate(operator, predicate) {
 
-     this.params[operator] = predicate;
 
-   }
 
-   getPredicate(operator) {
 
-     if (this.hasOperator(operator)){
 
-       if (typeof this.params[operator] === 'object') {
 
-         return this.params[operator][0];
 
-       } else {
 
-         return this.params[operator];
 
-       }
 
-     }
 
-     return null;
 
-   }
 
-   getPredicates(operator) {
 
-     return this.params[operator];
 
-   }
 
-   getParams() {
 
-     return this.params;
 
-   }
 
- }
 
- export class QueryErrors {
 
-   operatorTagMap = [
 
-     [OPERATOR_BOARD, 'board-title-not-found'],
 
-     [OPERATOR_SWIMLANE, 'swimlane-title-not-found'],
 
-     [
 
-       OPERATOR_LABEL,
 
-       label => {
 
-         if (Boards.labelColors().includes(label)) {
 
-           return {
 
-             tag: 'label-color-not-found',
 
-             value: label,
 
-             color: true,
 
-           };
 
-         } else {
 
-           return {
 
-             tag: 'label-not-found',
 
-             value: label,
 
-             color: false,
 
-           };
 
-         }
 
-       },
 
-     ],
 
-     [OPERATOR_LIST, 'list-title-not-found'],
 
-     [OPERATOR_COMMENT, 'comment-not-found'],
 
-     [OPERATOR_USER, 'user-username-not-found'],
 
-     [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() {
 
-     this._errors = {};
 
-     this.operatorTags = {};
 
-     this.operatorTagMap.forEach(([operator, tag]) => {
 
-       this.operatorTags[operator] = tag;
 
-     });
 
-     this.colorMap = Boards.colorMap();
 
-   }
 
-   addError(operator, error) {
 
-     if (!this._errors[operator]) {
 
-       this._errors[operator] = [];
 
-     }
 
-     this._errors[operator].push(error);
 
-   }
 
-   addNotFound(operator, value) {
 
-     if (typeof this.operatorTags[operator] === 'function') {
 
-       this.addError(operator, this.operatorTags[operator](value));
 
-     } else {
 
-       this.addError(operator, { tag: this.operatorTags[operator], value });
 
-     }
 
-   }
 
-   hasErrors() {
 
-     return Object.entries(this._errors).length > 0;
 
-   }
 
-   errors() {
 
-     const errs = [];
 
-     // eslint-disable-next-line no-unused-vars
 
-     Object.entries(this._errors).forEach(([, errors]) => {
 
-       errors.forEach(err => {
 
-         errs.push(err);
 
-       });
 
-     });
 
-     return errs;
 
-   }
 
-   errorMessages() {
 
-     const messages = [];
 
-     // eslint-disable-next-line no-unused-vars
 
-     Object.entries(this._errors).forEach(([, errors]) => {
 
-       errors.forEach(err => {
 
-         messages.push(TAPi18n.__(err.tag, err.value));
 
-       });
 
-     });
 
-     return messages;
 
-   }
 
- }
 
- export class Query {
 
-   selector = {};
 
-   projection = {};
 
-   constructor(selector, projection) {
 
-     this._errors = new QueryErrors();
 
-     this.queryParams = new QueryParams();
 
-     this.colorMap = Boards.colorMap();
 
-     if (selector) {
 
-       this.selector = selector;
 
-     }
 
-     if (projection) {
 
-       this.projection = projection;
 
-     }
 
-   }
 
-   hasErrors() {
 
-     return this._errors.hasErrors();
 
-   }
 
-   errors() {
 
-     return this._errors.errors();
 
-   }
 
-   addError(operator, error) {
 
-     this._errors.addError(operator, error)
 
-   }
 
-   errorMessages() {
 
-     return this._errors.errorMessages();
 
-   }
 
-   getQueryParams() {
 
-     return this.queryParams;
 
-   }
 
-   setQueryParams(queryParams) {
 
-     this.queryParams = queryParams;
 
-   }
 
-   addPredicate(operator, predicate) {
 
-     this.queryParams.addPredicate(operator, predicate);
 
-   }
 
-   buildParams(queryText) {
 
-     this.queryParams = new QueryParams();
 
-     queryText = queryText.trim();
 
-     // eslint-disable-next-line no-console
 
-     //console.log('query:', query);
 
-     if (!queryText) {
 
-       return;
 
-     }
 
-     const reOperator1 = new RegExp(
 
-       '^((?<operator>[\\p{Letter}\\p{Mark}]+):|(?<abbrev>[#@]))(?<value>[\\p{Letter}\\p{Mark}]+)(\\s+|$)',
 
-       'iu',
 
-     );
 
-     const reOperator2 = new RegExp(
 
-       '^((?<operator>[\\p{Letter}\\p{Mark}]+):|(?<abbrev>[#@]))(?<quote>["\']*)(?<value>.*?)\\k<quote>(\\s+|$)',
 
-       'iu',
 
-     );
 
-     const reText = new RegExp('^(?<text>\\S+)(\\s+|$)', 'u');
 
-     const reQuotedText = new RegExp(
 
-       '^(?<quote>["\'])(?<text>.*?)\\k<quote>(\\s+|$)',
 
-       'u',
 
-     );
 
-     const reNegatedOperator = new RegExp('^-(?<operator>.*)$');
 
-     const operators = {
 
-       'operator-board': OPERATOR_BOARD,
 
-       'operator-board-abbrev': OPERATOR_BOARD,
 
-       'operator-swimlane': OPERATOR_SWIMLANE,
 
-       'operator-swimlane-abbrev': OPERATOR_SWIMLANE,
 
-       'operator-list': OPERATOR_LIST,
 
-       'operator-list-abbrev': OPERATOR_LIST,
 
-       'operator-label': OPERATOR_LABEL,
 
-       'operator-label-abbrev': OPERATOR_LABEL,
 
-       'operator-user': OPERATOR_USER,
 
-       'operator-user-abbrev': OPERATOR_USER,
 
-       'operator-member': OPERATOR_MEMBER,
 
-       'operator-member-abbrev': OPERATOR_MEMBER,
 
-       'operator-assignee': OPERATOR_ASSIGNEE,
 
-       'operator-creator': OPERATOR_CREATOR,
 
-       'operator-assignee-abbrev': OPERATOR_ASSIGNEE,
 
-       'operator-status': OPERATOR_STATUS,
 
-       'operator-due': OPERATOR_DUE,
 
-       'operator-created': OPERATOR_CREATED_AT,
 
-       'operator-modified': OPERATOR_MODIFIED_AT,
 
-       'operator-comment': OPERATOR_COMMENT,
 
-       'operator-has': OPERATOR_HAS,
 
-       'operator-sort': OPERATOR_SORT,
 
-       'operator-limit': OPERATOR_LIMIT,
 
-       'operator-debug': OPERATOR_DEBUG,
 
-       'operator-org': OPERATOR_ORG,
 
-       'operator-team': OPERATOR_TEAM,
 
-     };
 
-     const predicates = {
 
-       durations: {
 
-         'predicate-week': PREDICATE_WEEK,
 
-         'predicate-month': PREDICATE_MONTH,
 
-         'predicate-quarter': PREDICATE_QUARTER,
 
-         'predicate-year': PREDICATE_YEAR,
 
-       },
 
-     };
 
-     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] = {};
 
-       Object.entries(catPreds).forEach(([tag, value]) => {
 
-         predicateTranslations[category][TAPi18n.__(tag)] = value;
 
-       });
 
-     });
 
-     // eslint-disable-next-line no-console
 
-     // console.log('predicateTranslations:', predicateTranslations);
 
-     const operatorMap = {};
 
-     Object.entries(operators).forEach(([key, value]) => {
 
-       operatorMap[TAPi18n.__(key).toLowerCase()] = value;
 
-     });
 
-     // eslint-disable-next-line no-console
 
-     // console.log('operatorMap:', operatorMap);
 
-     let text = '';
 
-     while (queryText) {
 
-       let m = queryText.match(reOperator1);
 
-       if (!m) {
 
-         m = queryText.match(reOperator2);
 
-         if (m) {
 
-           queryText = queryText.replace(reOperator2, '');
 
-         }
 
-       } else {
 
-         queryText = queryText.replace(reOperator1, '');
 
-       }
 
-       if (m) {
 
-         let op;
 
-         if (m.groups.operator) {
 
-           op = m.groups.operator.toLowerCase();
 
-         } else {
 
-           op = m.groups.abbrev.toLowerCase();
 
-         }
 
-         // eslint-disable-next-line no-prototype-builtins
 
-         if (operatorMap.hasOwnProperty(op)) {
 
-           const operator = operatorMap[op];
 
-           let value = m.groups.value;
 
-           if (operator === OPERATOR_LABEL) {
 
-             if (value in this.colorMap) {
 
-               value = this.colorMap[value];
 
-               // console.log('found color:', value);
 
-             }
 
-           } else if (
 
-             [OPERATOR_DUE, OPERATOR_CREATED_AT, OPERATOR_MODIFIED_AT].includes(
 
-               operator,
 
-             )
 
-           ) {
 
-             const days = parseInt(value, 10);
 
-             let duration = null;
 
-             if (isNaN(days)) {
 
-               // duration was specified as text
 
-               if (predicateTranslations.durations[value]) {
 
-                 duration = predicateTranslations.durations[value];
 
-                 let date = null;
 
-                 switch (duration) {
 
-                   case PREDICATE_WEEK:
 
-                     // eslint-disable-next-line no-case-declarations
 
-                     const week = moment().week();
 
-                     if (week === 52) {
 
-                       date = moment(1, 'W');
 
-                       date.set('year', date.year() + 1);
 
-                     } else {
 
-                       date = moment(week + 1, 'W');
 
-                     }
 
-                     break;
 
-                   case PREDICATE_MONTH:
 
-                     // eslint-disable-next-line no-case-declarations
 
-                     const month = moment().month();
 
-                     // .month() is zero indexed
 
-                     if (month === 11) {
 
-                       date = moment(1, 'M');
 
-                       date.set('year', date.year() + 1);
 
-                     } else {
 
-                       date = moment(month + 2, 'M');
 
-                     }
 
-                     break;
 
-                   case PREDICATE_QUARTER:
 
-                     // eslint-disable-next-line no-case-declarations
 
-                     const quarter = moment().quarter();
 
-                     if (quarter === 4) {
 
-                       date = moment(1, 'Q');
 
-                       date.set('year', date.year() + 1);
 
-                     } else {
 
-                       date = moment(quarter + 1, 'Q');
 
-                     }
 
-                     break;
 
-                   case PREDICATE_YEAR:
 
-                     date = moment(moment().year() + 1, 'YYYY');
 
-                     break;
 
-                 }
 
-                 if (date) {
 
-                   value = {
 
-                     operator: '$lt',
 
-                     value: date.format('YYYY-MM-DD'),
 
-                   };
 
-                 }
 
-               } else if (
 
-                 operator === OPERATOR_DUE &&
 
-                 value === PREDICATE_OVERDUE
 
-               ) {
 
-                 value = {
 
-                   operator: '$lt',
 
-                   value: moment().format('YYYY-MM-DD'),
 
-                 };
 
-               } else {
 
-                 this.addError(OPERATOR_DUE, {
 
-                   tag: 'operator-number-expected',
 
-                   value: { operator: op, value },
 
-                 });
 
-                 continue;
 
-               }
 
-             } else if (operator === OPERATOR_DUE) {
 
-               value = {
 
-                 operator: '$lt',
 
-                 value: moment(moment().format('YYYY-MM-DD'))
 
-                   .add(days + 1, duration ? duration : 'days')
 
-                   .format(),
 
-               };
 
-             } else {
 
-               value = {
 
-                 operator: '$gte',
 
-                 value: moment(moment().format('YYYY-MM-DD'))
 
-                   .subtract(days, duration ? duration : 'days')
 
-                   .format(),
 
-               };
 
-             }
 
-           } else if (operator === OPERATOR_SORT) {
 
-             let negated = false;
 
-             const m = value.match(reNegatedOperator);
 
-             if (m) {
 
-               value = m.groups.operator;
 
-               negated = true;
 
-             }
 
-             if (!predicateTranslations[OPERATOR_SORT][value]) {
 
-               this.addError(OPERATOR_SORT, {
 
-                 tag: 'operator-sort-invalid',
 
-                 value,
 
-               });
 
-               continue;
 
-             } else {
 
-               value = {
 
-                 name: predicateTranslations[OPERATOR_SORT][value],
 
-                 order: negated ? ORDER_DESCENDING : ORDER_ASCENDING,
 
-               };
 
-             }
 
-           } else if (operator === OPERATOR_STATUS) {
 
-             if (!predicateTranslations[OPERATOR_STATUS][value]) {
 
-               this.addError(OPERATOR_STATUS, {
 
-                 tag: 'operator-status-invalid',
 
-                 value,
 
-               });
 
-               continue;
 
-             } else {
 
-               value = predicateTranslations[OPERATOR_STATUS][value];
 
-             }
 
-           } else if (operator === OPERATOR_HAS) {
 
-             let negated = false;
 
-             const m = value.match(reNegatedOperator);
 
-             if (m) {
 
-               value = m.groups.operator;
 
-               negated = true;
 
-             }
 
-             if (!predicateTranslations[OPERATOR_HAS][value]) {
 
-               this.addError(OPERATOR_HAS, {
 
-                 tag: 'operator-has-invalid',
 
-                 value,
 
-               });
 
-               continue;
 
-             } else {
 
-               value = {
 
-                 field: predicateTranslations[OPERATOR_HAS][value],
 
-                 exists: !negated,
 
-               };
 
-             }
 
-           } else if (operator === OPERATOR_LIMIT) {
 
-             const limit = parseInt(value, 10);
 
-             if (isNaN(limit) || limit < 1) {
 
-               this.addError(OPERATOR_LIMIT, {
 
-                 tag: 'operator-limit-invalid',
 
-                 value,
 
-               });
 
-               continue;
 
-             } 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.addError(OPERATOR_UNKNOWN, {
 
-             tag: 'operator-unknown-error',
 
-             value: op,
 
-           });
 
-         }
 
-         continue;
 
-       }
 
-       m = queryText.match(reQuotedText);
 
-       if (!m) {
 
-         m = queryText.match(reText);
 
-         if (m) {
 
-           queryText = queryText.replace(reText, '');
 
-         }
 
-       } else {
 
-         queryText = queryText.replace(reQuotedText, '');
 
-       }
 
-       if (m) {
 
-         text += (text ? ' ' : '') + m.groups.text;
 
-       }
 
-     }
 
-     this.queryParams.text = text;
 
-     // eslint-disable-next-line no-console
 
-     if (this.queryParams.hasOperator(OPERATOR_DEBUG)) {
 
-       // eslint-disable-next-line no-console
 
-       console.log('text:', this.queryParams.text);
 
-       console.log('queryParams:', this.queryParams);
 
-     }
 
-   }
 
- }
 
 
  |