2021-03-01 01:49:56 +02:00
|
|
|
import { CardSearchPagedComponent } from '../../lib/cardSearch';
|
2021-03-07 02:12:31 +02:00
|
|
|
import moment from 'moment';
|
2021-03-08 19:18:01 +02:00
|
|
|
import {
|
2021-03-09 02:21:43 +02:00
|
|
|
OPERATOR_ASSIGNEE,
|
2021-03-08 19:18:01 +02:00
|
|
|
OPERATOR_BOARD,
|
2021-03-09 02:21:43 +02:00
|
|
|
OPERATOR_DUE,
|
|
|
|
|
OPERATOR_HAS,
|
|
|
|
|
OPERATOR_LABEL,
|
|
|
|
|
OPERATOR_LIST,
|
|
|
|
|
OPERATOR_MEMBER,
|
|
|
|
|
OPERATOR_SORT,
|
|
|
|
|
OPERATOR_STATUS,
|
|
|
|
|
OPERATOR_SWIMLANE,
|
|
|
|
|
OPERATOR_USER,
|
2021-03-08 19:18:01 +02:00
|
|
|
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_PUBLIC,
|
|
|
|
|
PREDICATE_QUARTER,
|
|
|
|
|
PREDICATE_START_AT,
|
|
|
|
|
PREDICATE_WEEK,
|
|
|
|
|
PREDICATE_YEAR,
|
|
|
|
|
} from '../../../config/search-const';
|
2021-03-09 02:21:43 +02:00
|
|
|
import { QueryParams } from "../../../config/query-classes";
|
2021-03-01 01:49:56 +02:00
|
|
|
|
|
|
|
|
// const subManager = new SubsManager();
|
2021-01-10 21:52:25 +02:00
|
|
|
|
|
|
|
|
BlazeComponent.extendComponent({
|
|
|
|
|
events() {
|
|
|
|
|
return [
|
|
|
|
|
{
|
|
|
|
|
'click .js-due-cards-view-change': Popup.open('globalSearchViewChange'),
|
|
|
|
|
},
|
|
|
|
|
];
|
|
|
|
|
},
|
|
|
|
|
}).register('globalSearchHeaderBar');
|
|
|
|
|
|
|
|
|
|
Template.globalSearch.helpers({
|
|
|
|
|
userId() {
|
|
|
|
|
return Meteor.userId();
|
|
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
BlazeComponent.extendComponent({
|
|
|
|
|
events() {
|
|
|
|
|
return [
|
|
|
|
|
{
|
|
|
|
|
'click .js-due-cards-view-me'() {
|
|
|
|
|
Utils.setDueCardsView('me');
|
|
|
|
|
Popup.close();
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
'click .js-due-cards-view-all'() {
|
|
|
|
|
Utils.setDueCardsView('all');
|
|
|
|
|
Popup.close();
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
];
|
|
|
|
|
},
|
|
|
|
|
}).register('globalSearchViewChangePopup');
|
|
|
|
|
|
2021-03-01 01:49:56 +02:00
|
|
|
class GlobalSearchComponent extends CardSearchPagedComponent {
|
2021-01-10 21:52:25 +02:00
|
|
|
onCreated() {
|
2021-03-01 01:49:56 +02:00
|
|
|
super.onCreated();
|
2021-01-20 21:52:27 +02:00
|
|
|
this.myLists = new ReactiveVar([]);
|
2021-01-21 01:48:24 +02:00
|
|
|
this.myLabelNames = new ReactiveVar([]);
|
|
|
|
|
this.myBoardNames = new ReactiveVar([]);
|
2021-01-17 16:01:42 +02:00
|
|
|
this.parsingErrors = [];
|
2021-01-20 12:52:49 +02:00
|
|
|
this.colorMap = null;
|
2021-03-01 01:49:56 +02:00
|
|
|
this.queryParams = null;
|
2021-01-20 21:52:27 +02:00
|
|
|
|
|
|
|
|
Meteor.call('myLists', (err, data) => {
|
|
|
|
|
if (!err) {
|
|
|
|
|
this.myLists.set(data);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
2021-01-21 01:48:24 +02:00
|
|
|
Meteor.call('myLabelNames', (err, data) => {
|
|
|
|
|
if (!err) {
|
|
|
|
|
this.myLabelNames.set(data);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
Meteor.call('myBoardNames', (err, data) => {
|
|
|
|
|
if (!err) {
|
|
|
|
|
this.myBoardNames.set(data);
|
|
|
|
|
}
|
|
|
|
|
});
|
2021-03-01 01:49:56 +02:00
|
|
|
}
|
2021-01-21 01:48:24 +02:00
|
|
|
|
2021-01-25 00:07:50 +02:00
|
|
|
onRendered() {
|
2021-01-10 21:52:25 +02:00
|
|
|
Meteor.subscribe('setting');
|
2021-01-25 15:39:36 +02:00
|
|
|
|
2021-02-02 17:56:18 +02:00
|
|
|
// eslint-disable-next-line no-console
|
2021-02-02 18:31:13 +02:00
|
|
|
//console.log('lang:', TAPi18n.getLanguage());
|
2021-02-02 17:56:18 +02:00
|
|
|
this.colorMap = Boards.colorMap();
|
|
|
|
|
// eslint-disable-next-line no-console
|
2021-01-25 15:39:36 +02:00
|
|
|
// console.log('colorMap:', this.colorMap);
|
|
|
|
|
|
2021-01-17 16:01:42 +02:00
|
|
|
if (Session.get('globalQuery')) {
|
|
|
|
|
this.searchAllBoards(Session.get('globalQuery'));
|
|
|
|
|
}
|
2021-03-01 01:49:56 +02:00
|
|
|
}
|
2021-01-17 16:01:42 +02:00
|
|
|
|
|
|
|
|
resetSearch() {
|
2021-03-01 01:49:56 +02:00
|
|
|
super.resetSearch();
|
2021-01-17 16:01:42 +02:00
|
|
|
this.parsingErrors = [];
|
2021-03-01 01:49:56 +02:00
|
|
|
}
|
2021-01-10 22:58:29 +02:00
|
|
|
|
2021-01-13 01:14:49 +02:00
|
|
|
errorMessages() {
|
2021-01-25 15:39:36 +02:00
|
|
|
if (this.parsingErrors.length) {
|
|
|
|
|
return this.parsingErrorMessages();
|
|
|
|
|
}
|
|
|
|
|
return this.queryErrorMessages();
|
2021-03-01 01:49:56 +02:00
|
|
|
}
|
2021-01-25 15:39:36 +02:00
|
|
|
|
|
|
|
|
parsingErrorMessages() {
|
2021-01-13 01:14:49 +02:00
|
|
|
const messages = [];
|
|
|
|
|
|
2021-01-17 16:01:42 +02:00
|
|
|
if (this.parsingErrors.length) {
|
|
|
|
|
this.parsingErrors.forEach(err => {
|
2021-01-24 02:32:37 +02:00
|
|
|
messages.push(TAPi18n.__(err.tag, err.value));
|
2021-01-17 16:01:42 +02:00
|
|
|
});
|
|
|
|
|
}
|
2021-01-13 01:14:49 +02:00
|
|
|
|
|
|
|
|
return messages;
|
2021-03-01 01:49:56 +02:00
|
|
|
}
|
2021-01-25 15:39:36 +02:00
|
|
|
|
2021-01-17 16:01:42 +02:00
|
|
|
searchAllBoards(query) {
|
2021-01-20 12:52:49 +02:00
|
|
|
query = query.trim();
|
2021-01-24 15:38:44 +02:00
|
|
|
// eslint-disable-next-line no-console
|
2021-02-02 18:31:13 +02:00
|
|
|
//console.log('query:', query);
|
2021-01-24 15:38:44 +02:00
|
|
|
|
2021-01-17 16:01:42 +02:00
|
|
|
this.query.set(query);
|
|
|
|
|
|
|
|
|
|
this.resetSearch();
|
|
|
|
|
|
|
|
|
|
if (!query) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2021-01-20 12:52:49 +02:00
|
|
|
this.searching.set(true);
|
|
|
|
|
|
2021-01-29 13:15:53 +02:00
|
|
|
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',
|
|
|
|
|
);
|
2021-02-25 18:38:51 +02:00
|
|
|
const reNegatedOperator = new RegExp('^-(?<operator>.*)$');
|
2021-01-17 16:01:42 +02:00
|
|
|
|
2021-01-22 23:07:38 +02:00
|
|
|
const operators = {
|
2021-03-08 19:18:01 +02:00
|
|
|
'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,
|
2021-03-09 02:21:43 +02:00
|
|
|
'operator-label': OPERATOR_LABEL,
|
|
|
|
|
'operator-label-abbrev': OPERATOR_LABEL,
|
2021-03-08 19:18:01 +02:00
|
|
|
'operator-user': OPERATOR_USER,
|
|
|
|
|
'operator-user-abbrev': OPERATOR_USER,
|
2021-03-09 02:21:43 +02:00
|
|
|
'operator-member': OPERATOR_MEMBER,
|
|
|
|
|
'operator-member-abbrev': OPERATOR_MEMBER,
|
|
|
|
|
'operator-assignee': OPERATOR_ASSIGNEE,
|
|
|
|
|
'operator-assignee-abbrev': OPERATOR_ASSIGNEE,
|
|
|
|
|
'operator-status': OPERATOR_STATUS,
|
2021-03-08 19:18:01 +02:00
|
|
|
'operator-due': OPERATOR_DUE,
|
2021-01-22 23:07:38 +02:00
|
|
|
'operator-created': 'createdAt',
|
|
|
|
|
'operator-modified': 'modifiedAt',
|
2021-01-23 18:04:26 +02:00
|
|
|
'operator-comment': 'comments',
|
2021-03-09 02:21:43 +02:00
|
|
|
'operator-has': OPERATOR_HAS,
|
|
|
|
|
'operator-sort': OPERATOR_SORT,
|
2021-02-26 17:31:44 +02:00
|
|
|
'operator-limit': 'limit',
|
2021-01-22 23:07:38 +02:00
|
|
|
};
|
|
|
|
|
|
2021-01-25 19:01:07 +02:00
|
|
|
const predicates = {
|
|
|
|
|
due: {
|
2021-03-08 19:18:01 +02:00
|
|
|
'predicate-overdue': PREDICATE_OVERDUE,
|
2021-01-25 19:01:07 +02:00
|
|
|
},
|
2021-01-26 18:39:09 +02:00
|
|
|
durations: {
|
2021-03-08 19:18:01 +02:00
|
|
|
'predicate-week': PREDICATE_WEEK,
|
|
|
|
|
'predicate-month': PREDICATE_MONTH,
|
|
|
|
|
'predicate-quarter': PREDICATE_QUARTER,
|
|
|
|
|
'predicate-year': PREDICATE_YEAR,
|
2021-01-25 19:01:07 +02:00
|
|
|
},
|
2021-01-26 18:39:09 +02:00
|
|
|
status: {
|
2021-03-08 19:18:01 +02:00
|
|
|
'predicate-archived': PREDICATE_ARCHIVED,
|
|
|
|
|
'predicate-all': PREDICATE_ALL,
|
|
|
|
|
'predicate-open': PREDICATE_OPEN,
|
|
|
|
|
'predicate-ended': PREDICATE_ENDED,
|
|
|
|
|
'predicate-public': PREDICATE_PUBLIC,
|
|
|
|
|
'predicate-private': PREDICATE_PRIVATE,
|
2021-01-26 18:39:09 +02:00
|
|
|
},
|
|
|
|
|
sorts: {
|
2021-03-08 19:18:01 +02:00
|
|
|
'predicate-due': PREDICATE_DUE_AT,
|
|
|
|
|
'predicate-created': PREDICATE_CREATED_AT,
|
|
|
|
|
'predicate-modified': PREDICATE_MODIFIED_AT,
|
2021-01-25 19:01:07 +02:00
|
|
|
},
|
2021-02-21 01:41:58 +02:00
|
|
|
has: {
|
2021-03-08 19:18:01 +02:00
|
|
|
'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,
|
2021-02-21 01:41:58 +02:00
|
|
|
},
|
2021-01-25 19:01:07 +02:00
|
|
|
};
|
|
|
|
|
const predicateTranslations = {};
|
2021-01-26 18:39:09 +02:00
|
|
|
Object.entries(predicates).forEach(([category, catPreds]) => {
|
2021-01-25 19:01:07 +02:00
|
|
|
predicateTranslations[category] = {};
|
2021-01-26 18:39:09 +02:00
|
|
|
Object.entries(catPreds).forEach(([tag, value]) => {
|
2021-01-25 19:01:07 +02:00
|
|
|
predicateTranslations[category][TAPi18n.__(tag)] = value;
|
|
|
|
|
});
|
|
|
|
|
});
|
2021-01-26 18:39:09 +02:00
|
|
|
// eslint-disable-next-line no-console
|
|
|
|
|
// console.log('predicateTranslations:', predicateTranslations);
|
2021-01-25 19:01:07 +02:00
|
|
|
|
2021-01-17 16:01:42 +02:00
|
|
|
const operatorMap = {};
|
2021-01-23 01:35:28 +02:00
|
|
|
Object.entries(operators).forEach(([key, value]) => {
|
|
|
|
|
operatorMap[TAPi18n.__(key).toLowerCase()] = value;
|
|
|
|
|
});
|
2021-01-17 16:01:42 +02:00
|
|
|
// eslint-disable-next-line no-console
|
2021-01-24 15:38:44 +02:00
|
|
|
// console.log('operatorMap:', operatorMap);
|
2021-01-25 15:39:36 +02:00
|
|
|
|
2021-03-09 02:21:43 +02:00
|
|
|
// const params = {
|
|
|
|
|
// limit: this.resultsPerPage,
|
|
|
|
|
// // boards: [],
|
|
|
|
|
// // swimlanes: [],
|
|
|
|
|
// // lists: [],
|
|
|
|
|
// // users: [],
|
|
|
|
|
// members: [],
|
|
|
|
|
// assignees: [],
|
|
|
|
|
// // labels: [],
|
|
|
|
|
// status: [],
|
|
|
|
|
// // dueAt: null,
|
|
|
|
|
// createdAt: null,
|
|
|
|
|
// modifiedAt: null,
|
|
|
|
|
// comments: [],
|
|
|
|
|
// has: [],
|
|
|
|
|
// };
|
|
|
|
|
// params[OPERATOR_BOARD] = [];
|
|
|
|
|
// params[OPERATOR_DUE] = null;
|
|
|
|
|
// params[OPERATOR_LABEL] = [];
|
|
|
|
|
// params[OPERATOR_LIST] = [];
|
|
|
|
|
// params[OPERATOR_SWIMLANE] = [];
|
|
|
|
|
// params[OPERATOR_USER] = [];
|
|
|
|
|
|
|
|
|
|
const params = new QueryParams();
|
2021-01-17 16:01:42 +02:00
|
|
|
let text = '';
|
|
|
|
|
while (query) {
|
2021-03-01 01:49:56 +02:00
|
|
|
let m = query.match(reOperator1);
|
2021-01-17 16:01:42 +02:00
|
|
|
if (!m) {
|
|
|
|
|
m = query.match(reOperator2);
|
|
|
|
|
if (m) {
|
|
|
|
|
query = query.replace(reOperator2, '');
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
query = query.replace(reOperator1, '');
|
|
|
|
|
}
|
|
|
|
|
if (m) {
|
|
|
|
|
let op;
|
|
|
|
|
if (m.groups.operator) {
|
|
|
|
|
op = m.groups.operator.toLowerCase();
|
|
|
|
|
} else {
|
2021-02-02 17:56:18 +02:00
|
|
|
op = m.groups.abbrev.toLowerCase();
|
2021-01-17 16:01:42 +02:00
|
|
|
}
|
2021-02-21 01:41:58 +02:00
|
|
|
// eslint-disable-next-line no-prototype-builtins
|
2021-01-23 01:35:28 +02:00
|
|
|
if (operatorMap.hasOwnProperty(op)) {
|
2021-02-26 01:13:45 +02:00
|
|
|
const operator = operatorMap[op];
|
2021-01-18 17:17:44 +02:00
|
|
|
let value = m.groups.value;
|
2021-03-09 02:21:43 +02:00
|
|
|
if (operator === OPERATOR_LABEL) {
|
2021-01-20 12:52:49 +02:00
|
|
|
if (value in this.colorMap) {
|
|
|
|
|
value = this.colorMap[value];
|
2021-02-02 17:56:18 +02:00
|
|
|
// console.log('found color:', value);
|
2021-01-18 17:17:44 +02:00
|
|
|
}
|
2021-03-08 19:18:01 +02:00
|
|
|
} else if (
|
|
|
|
|
[OPERATOR_DUE, 'createdAt', 'modifiedAt'].includes(operator)
|
|
|
|
|
) {
|
2021-03-01 01:49:56 +02:00
|
|
|
const days = parseInt(value, 10);
|
2021-01-22 00:37:16 +02:00
|
|
|
let duration = null;
|
2021-01-21 18:11:09 +02:00
|
|
|
if (isNaN(days)) {
|
2021-02-26 01:13:45 +02:00
|
|
|
// duration was specified as text
|
2021-01-26 18:39:09 +02:00
|
|
|
if (predicateTranslations.durations[value]) {
|
|
|
|
|
duration = predicateTranslations.durations[value];
|
2021-02-26 01:13:45 +02:00
|
|
|
let date = null;
|
|
|
|
|
switch (duration) {
|
2021-03-08 19:18:01 +02:00
|
|
|
case PREDICATE_WEEK:
|
2021-03-01 01:49:56 +02:00
|
|
|
// eslint-disable-next-line no-case-declarations
|
|
|
|
|
const week = moment().week();
|
2021-02-26 01:13:45 +02:00
|
|
|
if (week === 52) {
|
|
|
|
|
date = moment(1, 'W');
|
|
|
|
|
date.set('year', date.year() + 1);
|
|
|
|
|
} else {
|
|
|
|
|
date = moment(week + 1, 'W');
|
|
|
|
|
}
|
|
|
|
|
break;
|
2021-03-08 19:18:01 +02:00
|
|
|
case PREDICATE_MONTH:
|
2021-03-01 01:49:56 +02:00
|
|
|
// eslint-disable-next-line no-case-declarations
|
|
|
|
|
const month = moment().month();
|
2021-02-26 01:13:45 +02:00
|
|
|
// .month() is zero indexed
|
|
|
|
|
if (month === 11) {
|
|
|
|
|
date = moment(1, 'M');
|
|
|
|
|
date.set('year', date.year() + 1);
|
|
|
|
|
} else {
|
|
|
|
|
date = moment(month + 2, 'M');
|
|
|
|
|
}
|
|
|
|
|
break;
|
2021-03-08 19:18:01 +02:00
|
|
|
case PREDICATE_QUARTER:
|
2021-03-01 01:49:56 +02:00
|
|
|
// eslint-disable-next-line no-case-declarations
|
|
|
|
|
const quarter = moment().quarter();
|
2021-02-26 01:13:45 +02:00
|
|
|
if (quarter === 4) {
|
|
|
|
|
date = moment(1, 'Q');
|
|
|
|
|
date.set('year', date.year() + 1);
|
|
|
|
|
} else {
|
|
|
|
|
date = moment(quarter + 1, 'Q');
|
|
|
|
|
}
|
|
|
|
|
break;
|
2021-03-08 19:18:01 +02:00
|
|
|
case PREDICATE_YEAR:
|
2021-02-26 01:13:45 +02:00
|
|
|
date = moment(moment().year() + 1, 'YYYY');
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if (date) {
|
|
|
|
|
value = {
|
|
|
|
|
operator: '$lt',
|
2021-02-26 23:19:12 +02:00
|
|
|
value: date.format('YYYY-MM-DD'),
|
2021-02-26 01:13:45 +02:00
|
|
|
};
|
|
|
|
|
}
|
2021-03-08 19:18:01 +02:00
|
|
|
} else if (operator === 'dueAt' && value === PREDICATE_OVERDUE) {
|
2021-02-26 01:13:45 +02:00
|
|
|
value = {
|
|
|
|
|
operator: '$lt',
|
2021-02-26 23:19:12 +02:00
|
|
|
value: moment().format('YYYY-MM-DD'),
|
2021-02-26 01:13:45 +02:00
|
|
|
};
|
2021-01-21 18:11:09 +02:00
|
|
|
} else {
|
|
|
|
|
this.parsingErrors.push({
|
|
|
|
|
tag: 'operator-number-expected',
|
|
|
|
|
value: { operator: op, value },
|
|
|
|
|
});
|
|
|
|
|
value = null;
|
|
|
|
|
}
|
2021-03-01 01:49:56 +02:00
|
|
|
} else if (operator === 'dueAt') {
|
|
|
|
|
value = {
|
|
|
|
|
operator: '$lt',
|
|
|
|
|
value: moment(moment().format('YYYY-MM-DD'))
|
|
|
|
|
.add(days + 1, duration ? duration : 'days')
|
|
|
|
|
.format(),
|
|
|
|
|
};
|
2021-01-21 18:11:09 +02:00
|
|
|
} else {
|
2021-03-01 01:49:56 +02:00
|
|
|
value = {
|
|
|
|
|
operator: '$gte',
|
|
|
|
|
value: moment(moment().format('YYYY-MM-DD'))
|
|
|
|
|
.subtract(days, duration ? duration : 'days')
|
|
|
|
|
.format(),
|
|
|
|
|
};
|
2021-01-22 00:37:16 +02:00
|
|
|
}
|
2021-03-09 02:21:43 +02:00
|
|
|
} else if (operator === OPERATOR_SORT) {
|
2021-02-25 18:38:51 +02:00
|
|
|
let negated = false;
|
|
|
|
|
const m = value.match(reNegatedOperator);
|
|
|
|
|
if (m) {
|
|
|
|
|
value = m.groups.operator;
|
|
|
|
|
negated = true;
|
|
|
|
|
}
|
2021-01-26 18:39:09 +02:00
|
|
|
if (!predicateTranslations.sorts[value]) {
|
2021-01-22 00:37:16 +02:00
|
|
|
this.parsingErrors.push({
|
|
|
|
|
tag: 'operator-sort-invalid',
|
|
|
|
|
value,
|
|
|
|
|
});
|
2021-01-26 18:39:09 +02:00
|
|
|
} else {
|
2021-02-25 18:38:51 +02:00
|
|
|
value = {
|
|
|
|
|
name: predicateTranslations.sorts[value],
|
2021-03-08 19:18:01 +02:00
|
|
|
order: negated ? ORDER_DESCENDING : ORDER_ASCENDING,
|
2021-02-25 18:38:51 +02:00
|
|
|
};
|
2021-01-26 18:39:09 +02:00
|
|
|
}
|
2021-03-09 02:21:43 +02:00
|
|
|
} else if (operator === OPERATOR_STATUS) {
|
2021-01-26 18:39:09 +02:00
|
|
|
if (!predicateTranslations.status[value]) {
|
|
|
|
|
this.parsingErrors.push({
|
|
|
|
|
tag: 'operator-status-invalid',
|
|
|
|
|
value,
|
|
|
|
|
});
|
|
|
|
|
} else {
|
|
|
|
|
value = predicateTranslations.status[value];
|
2021-01-21 18:11:09 +02:00
|
|
|
}
|
2021-03-09 02:21:43 +02:00
|
|
|
} else if (operator === OPERATOR_HAS) {
|
2021-02-27 02:26:58 +02:00
|
|
|
let negated = false;
|
|
|
|
|
const m = value.match(reNegatedOperator);
|
|
|
|
|
if (m) {
|
|
|
|
|
value = m.groups.operator;
|
|
|
|
|
negated = true;
|
|
|
|
|
}
|
2021-02-21 01:41:58 +02:00
|
|
|
if (!predicateTranslations.has[value]) {
|
|
|
|
|
this.parsingErrors.push({
|
|
|
|
|
tag: 'operator-has-invalid',
|
|
|
|
|
value,
|
|
|
|
|
});
|
|
|
|
|
} else {
|
2021-02-27 02:26:58 +02:00
|
|
|
value = {
|
|
|
|
|
field: predicateTranslations.has[value],
|
|
|
|
|
exists: !negated,
|
|
|
|
|
};
|
2021-02-21 01:41:58 +02:00
|
|
|
}
|
2021-02-26 17:31:44 +02:00
|
|
|
} else if (operator === 'limit') {
|
|
|
|
|
const limit = parseInt(value, 10);
|
|
|
|
|
if (isNaN(limit) || limit < 1) {
|
|
|
|
|
this.parsingErrors.push({
|
|
|
|
|
tag: 'operator-limit-invalid',
|
|
|
|
|
value,
|
|
|
|
|
});
|
|
|
|
|
} else {
|
|
|
|
|
value = limit;
|
|
|
|
|
}
|
2021-01-21 18:11:09 +02:00
|
|
|
}
|
2021-03-09 02:21:43 +02:00
|
|
|
|
|
|
|
|
params.addPredicate(operator, value);
|
2021-01-17 16:01:42 +02:00
|
|
|
} else {
|
|
|
|
|
this.parsingErrors.push({
|
|
|
|
|
tag: 'operator-unknown-error',
|
|
|
|
|
value: op,
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
m = query.match(reQuotedText);
|
|
|
|
|
if (!m) {
|
|
|
|
|
m = query.match(reText);
|
|
|
|
|
if (m) {
|
|
|
|
|
query = query.replace(reText, '');
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
query = query.replace(reQuotedText, '');
|
|
|
|
|
}
|
|
|
|
|
if (m) {
|
|
|
|
|
text += (text ? ' ' : '') + m.groups.text;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// eslint-disable-next-line no-console
|
|
|
|
|
// console.log('text:', text);
|
|
|
|
|
params.text = text;
|
|
|
|
|
|
|
|
|
|
// eslint-disable-next-line no-console
|
2021-02-02 17:56:18 +02:00
|
|
|
console.log('params:', params);
|
2021-01-17 16:01:42 +02:00
|
|
|
|
|
|
|
|
this.queryParams = params;
|
|
|
|
|
|
2021-01-24 15:38:44 +02:00
|
|
|
if (this.parsingErrors.length) {
|
|
|
|
|
this.searching.set(false);
|
2021-01-25 15:39:36 +02:00
|
|
|
this.queryErrors = this.parsingErrorMessages();
|
2021-01-26 18:39:09 +02:00
|
|
|
this.hasResults.set(true);
|
2021-01-24 15:38:44 +02:00
|
|
|
this.hasQueryErrors.set(true);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2021-03-09 02:21:43 +02:00
|
|
|
this.runGlobalSearch(params.getParams());
|
2021-03-01 01:49:56 +02:00
|
|
|
}
|
2021-01-28 16:31:49 +02:00
|
|
|
|
2021-01-17 00:05:45 +02:00
|
|
|
searchInstructions() {
|
2021-03-01 01:49:56 +02:00
|
|
|
const tags = {
|
2021-01-17 00:05:45 +02:00
|
|
|
operator_board: TAPi18n.__('operator-board'),
|
|
|
|
|
operator_list: TAPi18n.__('operator-list'),
|
|
|
|
|
operator_swimlane: TAPi18n.__('operator-swimlane'),
|
2021-01-26 18:39:09 +02:00
|
|
|
operator_comment: TAPi18n.__('operator-comment'),
|
2021-01-17 00:05:45 +02:00
|
|
|
operator_label: TAPi18n.__('operator-label'),
|
|
|
|
|
operator_label_abbrev: TAPi18n.__('operator-label-abbrev'),
|
|
|
|
|
operator_user: TAPi18n.__('operator-user'),
|
|
|
|
|
operator_user_abbrev: TAPi18n.__('operator-user-abbrev'),
|
2021-01-17 16:01:42 +02:00
|
|
|
operator_member: TAPi18n.__('operator-member'),
|
|
|
|
|
operator_member_abbrev: TAPi18n.__('operator-member-abbrev'),
|
|
|
|
|
operator_assignee: TAPi18n.__('operator-assignee'),
|
|
|
|
|
operator_assignee_abbrev: TAPi18n.__('operator-assignee-abbrev'),
|
2021-01-26 18:39:09 +02:00
|
|
|
operator_due: TAPi18n.__('operator-due'),
|
|
|
|
|
operator_created: TAPi18n.__('operator-created'),
|
|
|
|
|
operator_modified: TAPi18n.__('operator-modified'),
|
|
|
|
|
operator_status: TAPi18n.__('operator-status'),
|
2021-02-21 19:57:35 +02:00
|
|
|
operator_has: TAPi18n.__('operator-has'),
|
2021-02-26 18:51:54 +02:00
|
|
|
operator_sort: TAPi18n.__('operator-sort'),
|
|
|
|
|
operator_limit: TAPi18n.__('operator-limit'),
|
2021-01-26 18:39:09 +02:00
|
|
|
predicate_overdue: TAPi18n.__('predicate-overdue'),
|
|
|
|
|
predicate_archived: TAPi18n.__('predicate-archived'),
|
|
|
|
|
predicate_all: TAPi18n.__('predicate-all'),
|
|
|
|
|
predicate_ended: TAPi18n.__('predicate-ended'),
|
|
|
|
|
predicate_week: TAPi18n.__('predicate-week'),
|
|
|
|
|
predicate_month: TAPi18n.__('predicate-month'),
|
|
|
|
|
predicate_quarter: TAPi18n.__('predicate-quarter'),
|
|
|
|
|
predicate_year: TAPi18n.__('predicate-year'),
|
2021-02-21 19:57:35 +02:00
|
|
|
predicate_attachment: TAPi18n.__('predicate-attachment'),
|
|
|
|
|
predicate_description: TAPi18n.__('predicate-description'),
|
|
|
|
|
predicate_checklist: TAPi18n.__('predicate-checklist'),
|
2021-02-23 17:56:28 +02:00
|
|
|
predicate_public: TAPi18n.__('predicate-public'),
|
|
|
|
|
predicate_private: TAPi18n.__('predicate-private'),
|
2021-02-26 18:51:54 +02:00
|
|
|
predicate_due: TAPi18n.__('predicate-due'),
|
|
|
|
|
predicate_created: TAPi18n.__('predicate-created'),
|
|
|
|
|
predicate_modified: TAPi18n.__('predicate-modified'),
|
2021-02-27 02:26:58 +02:00
|
|
|
predicate_start: TAPi18n.__('predicate-start'),
|
|
|
|
|
predicate_end: TAPi18n.__('predicate-end'),
|
|
|
|
|
predicate_assignee: TAPi18n.__('predicate-assignee'),
|
|
|
|
|
predicate_member: TAPi18n.__('predicate-member'),
|
2021-01-17 00:05:45 +02:00
|
|
|
};
|
|
|
|
|
|
2021-03-04 02:13:22 +02:00
|
|
|
let text = '';
|
2021-02-27 17:02:42 +02:00
|
|
|
[
|
2021-03-04 02:13:22 +02:00
|
|
|
['# ', 'globalSearch-instructions-heading'],
|
|
|
|
|
['\n', 'globalSearch-instructions-description'],
|
|
|
|
|
['\n\n', 'globalSearch-instructions-operators'],
|
|
|
|
|
['\n* ', 'globalSearch-instructions-operator-board'],
|
|
|
|
|
['\n* ', 'globalSearch-instructions-operator-list'],
|
|
|
|
|
['\n* ', 'globalSearch-instructions-operator-swimlane'],
|
|
|
|
|
['\n* ', 'globalSearch-instructions-operator-comment'],
|
|
|
|
|
['\n* ', 'globalSearch-instructions-operator-label'],
|
|
|
|
|
['\n* ', 'globalSearch-instructions-operator-hash'],
|
|
|
|
|
['\n* ', 'globalSearch-instructions-operator-user'],
|
|
|
|
|
['\n* ', 'globalSearch-instructions-operator-at'],
|
|
|
|
|
['\n* ', 'globalSearch-instructions-operator-member'],
|
|
|
|
|
['\n* ', 'globalSearch-instructions-operator-assignee'],
|
|
|
|
|
['\n* ', 'globalSearch-instructions-operator-due'],
|
|
|
|
|
['\n* ', 'globalSearch-instructions-operator-created'],
|
|
|
|
|
['\n* ', 'globalSearch-instructions-operator-modified'],
|
|
|
|
|
['\n* ', 'globalSearch-instructions-operator-status'],
|
|
|
|
|
['\n * ', 'globalSearch-instructions-status-archived'],
|
|
|
|
|
['\n * ', 'globalSearch-instructions-status-public'],
|
|
|
|
|
['\n * ', 'globalSearch-instructions-status-private'],
|
|
|
|
|
['\n * ', 'globalSearch-instructions-status-all'],
|
|
|
|
|
['\n * ', 'globalSearch-instructions-status-ended'],
|
|
|
|
|
['\n* ', 'globalSearch-instructions-operator-has'],
|
|
|
|
|
['\n* ', 'globalSearch-instructions-operator-sort'],
|
|
|
|
|
['\n* ', 'globalSearch-instructions-operator-limit'],
|
|
|
|
|
['\n## ', 'heading-notes'],
|
|
|
|
|
['\n* ', 'globalSearch-instructions-notes-1'],
|
|
|
|
|
['\n* ', 'globalSearch-instructions-notes-2'],
|
|
|
|
|
['\n* ', 'globalSearch-instructions-notes-3'],
|
|
|
|
|
['\n* ', 'globalSearch-instructions-notes-3-2'],
|
|
|
|
|
['\n* ', 'globalSearch-instructions-notes-4'],
|
|
|
|
|
['\n* ', 'globalSearch-instructions-notes-5'],
|
|
|
|
|
].forEach(([prefix, instruction]) => {
|
|
|
|
|
text += `${prefix}${TAPi18n.__(instruction, tags)}`;
|
2021-02-27 17:02:42 +02:00
|
|
|
});
|
2021-01-17 00:05:45 +02:00
|
|
|
|
|
|
|
|
return text;
|
2021-03-01 01:49:56 +02:00
|
|
|
}
|
2021-01-17 00:05:45 +02:00
|
|
|
|
2021-01-20 13:15:10 +02:00
|
|
|
labelColors() {
|
|
|
|
|
return Boards.simpleSchema()._schema['labels.$.color'].allowedValues.map(
|
|
|
|
|
color => {
|
|
|
|
|
return { color, name: TAPi18n.__(`color-${color}`) };
|
|
|
|
|
},
|
|
|
|
|
);
|
2021-03-01 01:49:56 +02:00
|
|
|
}
|
2021-01-20 13:15:10 +02:00
|
|
|
|
2021-01-10 21:52:25 +02:00
|
|
|
events() {
|
|
|
|
|
return [
|
|
|
|
|
{
|
2021-03-01 01:49:56 +02:00
|
|
|
...super.events()[0],
|
2021-01-10 21:52:25 +02:00
|
|
|
'submit .js-search-query-form'(evt) {
|
|
|
|
|
evt.preventDefault();
|
2021-01-17 16:01:42 +02:00
|
|
|
this.searchAllBoards(evt.target.searchQuery.value);
|
2021-01-10 21:52:25 +02:00
|
|
|
},
|
2021-01-21 01:48:24 +02:00
|
|
|
'click .js-label-color'(evt) {
|
|
|
|
|
evt.preventDefault();
|
2021-01-25 01:35:44 +02:00
|
|
|
const input = document.getElementById('global-search-input');
|
2021-01-21 01:48:24 +02:00
|
|
|
this.query.set(
|
2021-01-25 01:35:44 +02:00
|
|
|
`${input.value} ${TAPi18n.__('operator-label')}:"${
|
2021-01-21 01:48:24 +02:00
|
|
|
evt.currentTarget.textContent
|
|
|
|
|
}"`,
|
|
|
|
|
);
|
2021-01-21 11:55:58 +02:00
|
|
|
document.getElementById('global-search-input').focus();
|
2021-01-21 01:48:24 +02:00
|
|
|
},
|
|
|
|
|
'click .js-board-title'(evt) {
|
|
|
|
|
evt.preventDefault();
|
2021-01-25 01:35:44 +02:00
|
|
|
const input = document.getElementById('global-search-input');
|
2021-01-20 13:15:10 +02:00
|
|
|
this.query.set(
|
2021-01-25 01:35:44 +02:00
|
|
|
`${input.value} ${TAPi18n.__('operator-board')}:"${
|
2021-01-21 01:48:24 +02:00
|
|
|
evt.currentTarget.textContent
|
|
|
|
|
}"`,
|
2021-01-20 13:15:10 +02:00
|
|
|
);
|
2021-01-21 11:55:58 +02:00
|
|
|
document.getElementById('global-search-input').focus();
|
2021-01-20 13:15:10 +02:00
|
|
|
},
|
2021-01-20 21:52:27 +02:00
|
|
|
'click .js-list-title'(evt) {
|
2021-01-21 01:48:24 +02:00
|
|
|
evt.preventDefault();
|
2021-01-25 01:35:44 +02:00
|
|
|
const input = document.getElementById('global-search-input');
|
2021-01-21 01:48:24 +02:00
|
|
|
this.query.set(
|
2021-01-25 01:35:44 +02:00
|
|
|
`${input.value} ${TAPi18n.__('operator-list')}:"${
|
2021-01-21 01:48:24 +02:00
|
|
|
evt.currentTarget.textContent
|
|
|
|
|
}"`,
|
|
|
|
|
);
|
2021-01-21 11:55:58 +02:00
|
|
|
document.getElementById('global-search-input').focus();
|
2021-01-21 01:48:24 +02:00
|
|
|
},
|
|
|
|
|
'click .js-label-name'(evt) {
|
|
|
|
|
evt.preventDefault();
|
2021-01-25 01:35:44 +02:00
|
|
|
const input = document.getElementById('global-search-input');
|
2021-01-20 21:52:27 +02:00
|
|
|
this.query.set(
|
2021-01-25 01:35:44 +02:00
|
|
|
`${input.value} ${TAPi18n.__('operator-label')}:"${
|
2021-01-21 01:48:24 +02:00
|
|
|
evt.currentTarget.textContent
|
|
|
|
|
}"`,
|
2021-01-20 21:52:27 +02:00
|
|
|
);
|
2021-01-21 11:55:58 +02:00
|
|
|
document.getElementById('global-search-input').focus();
|
2021-01-20 21:52:27 +02:00
|
|
|
},
|
2021-01-10 21:52:25 +02:00
|
|
|
},
|
|
|
|
|
];
|
2021-03-01 01:49:56 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
GlobalSearchComponent.register('globalSearch');
|