Merge pull request #3492 from jrsupplee/new-search

Global Search Update
This commit is contained in:
Lauri Ojansivu 2021-01-27 19:11:21 +02:00 committed by GitHub
commit c10f32cc30
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 1384 additions and 811 deletions

View file

@ -1278,37 +1278,33 @@ Boards.userSearch = (
userId,
selector = {},
projection = {},
includeArchived = false,
// includeArchived = false,
) => {
if (!includeArchived) {
selector.archived = false;
}
selector.$or = [
{ permission: 'public' },
{ members: { $elemMatch: { userId, isActive: true } } },
];
// if (!includeArchived) {
// selector.archived = false;
// }
selector.$or = [{ permission: 'public' }];
if (userId) {
selector.$or.push({ members: { $elemMatch: { userId, isActive: true } } });
}
return Boards.find(selector, projection);
};
Boards.userBoards = (userId, includeArchived = false, selector = {}) => {
check(userId, String);
if (!includeArchived) {
selector = {
archived: false,
};
Boards.userBoards = (userId, archived = false, selector = {}) => {
if (typeof archived === 'boolean') {
selector.archived = archived;
}
selector.$or = [
{ permission: 'public' },
{ members: { $elemMatch: { userId, isActive: true } } },
];
selector.$or = [{ permission: 'public' }];
if (userId) {
selector.$or.push({ members: { $elemMatch: { userId, isActive: true } } });
}
return Boards.find(selector);
};
Boards.userBoardIds = (userId, includeArchived = false, selector = {}) => {
return Boards.userBoards(userId, includeArchived, selector).map(board => {
Boards.userBoardIds = (userId, archived = false, selector = {}) => {
return Boards.userBoards(userId, archived, selector).map(board => {
return board._id;
});
};

View file

@ -1,3 +1,4 @@
const escapeForRegex = require('escape-string-regexp');
CardComments = new Mongo.Collection('card_comments');
/**
@ -109,6 +110,28 @@ function commentCreation(userId, doc) {
});
}
CardComments.textSearch = (userId, textArray) => {
const selector = {
boardId: { $in: Boards.userBoardIds(userId) },
$and: [],
};
for (const text of textArray) {
selector.$and.push({ text: new RegExp(escapeForRegex(text)) });
}
// eslint-disable-next-line no-console
// console.log('cardComments selector:', selector);
const comments = CardComments.find(selector);
// eslint-disable-next-line no-console
// console.log('count:', comments.count());
// eslint-disable-next-line no-console
// console.log('cards with comments:', comments.map(com => { return com.cardId }));
return comments;
};
if (Meteor.isServer) {
// Comments are often fetched within a card, so we create an index to make these
// queries more efficient.

View file

@ -1863,262 +1863,6 @@ Cards.mutations({
},
});
Cards.globalSearch = queryParams => {
const userId = Meteor.userId();
// eslint-disable-next-line no-console
// console.log('userId:', userId);
const errors = new (class {
constructor() {
this.notFound = {
boards: [],
swimlanes: [],
lists: [],
labels: [],
users: [],
members: [],
assignees: [],
is: [],
};
}
hasErrors() {
for (const prop in this.notFound) {
if (this.notFound[prop].length) {
return true;
}
}
return false;
}
})();
const selector = {
archived: false,
type: 'cardType-card',
boardId: { $in: Boards.userBoardIds(userId) },
swimlaneId: { $nin: Swimlanes.archivedSwimlaneIds() },
listId: { $nin: Lists.archivedListIds() },
};
if (queryParams.boards.length) {
const queryBoards = [];
queryParams.boards.forEach(query => {
const boards = Boards.userSearch(userId, {
title: new RegExp(query, 'i'),
});
if (boards.count()) {
boards.forEach(board => {
queryBoards.push(board._id);
});
} else {
errors.notFound.boards.push(query);
}
});
selector.boardId.$in = queryBoards;
}
if (queryParams.swimlanes.length) {
const querySwimlanes = [];
queryParams.swimlanes.forEach(query => {
const swimlanes = Swimlanes.find({
title: new RegExp(query, 'i'),
});
if (swimlanes.count()) {
swimlanes.forEach(swim => {
querySwimlanes.push(swim._id);
});
} else {
errors.notFound.swimlanes.push(query);
}
});
selector.swimlaneId.$in = querySwimlanes;
}
if (queryParams.lists.length) {
const queryLists = [];
queryParams.lists.forEach(query => {
const lists = Lists.find({
title: new RegExp(query, 'i'),
});
if (lists.count()) {
lists.forEach(list => {
queryLists.push(list._id);
});
} else {
errors.notFound.lists.push(query);
}
});
selector.listId.$in = queryLists;
}
if (queryParams.dueAt !== null) {
selector.dueAt = { $gte: new Date(queryParams.dueAt) };
}
if (queryParams.createdAt !== null) {
selector.createdAt = { $gte: new Date(queryParams.createdAt) };
}
if (queryParams.modifiedAt !== null) {
selector.modifiedAt = { $gte: new Date(queryParams.modifiedAt) };
}
const queryMembers = [];
const queryAssignees = [];
if (queryParams.users.length) {
queryParams.users.forEach(query => {
const users = Users.find({
username: query,
});
if (users.count()) {
users.forEach(user => {
queryMembers.push(user._id);
queryAssignees.push(user._id);
});
} else {
errors.notFound.users.push(query);
}
});
}
if (queryParams.members.length) {
queryParams.members.forEach(query => {
const users = Users.find({
username: query,
});
if (users.count()) {
users.forEach(user => {
queryMembers.push(user._id);
});
} else {
errors.notFound.members.push(query);
}
});
}
if (queryParams.assignees.length) {
queryParams.assignees.forEach(query => {
const users = Users.find({
username: query,
});
if (users.count()) {
users.forEach(user => {
queryAssignees.push(user._id);
});
} else {
errors.notFound.assignees.push(query);
}
});
}
if (queryMembers.length && queryAssignees.length) {
selector.$or = [
{ members: { $in: queryMembers } },
{ assignees: { $in: queryAssignees } },
];
} else if (queryMembers.length) {
selector.members = { $in: queryMembers };
} else if (queryAssignees.length) {
selector.assignees = { $in: queryAssignees };
}
if (queryParams.labels.length) {
queryParams.labels.forEach(label => {
const queryLabels = [];
let boards = Boards.userSearch(userId, {
labels: { $elemMatch: { color: label.toLowerCase() } },
});
if (boards.count()) {
boards.forEach(board => {
// eslint-disable-next-line no-console
// console.log('board:', board);
// eslint-disable-next-line no-console
// console.log('board.labels:', board.labels);
board.labels
.filter(boardLabel => {
return boardLabel.color === label.toLowerCase();
})
.forEach(boardLabel => {
queryLabels.push(boardLabel._id);
});
});
} else {
// eslint-disable-next-line no-console
// console.log('label:', label);
const reLabel = new RegExp(label, 'i');
// eslint-disable-next-line no-console
// console.log('reLabel:', reLabel);
boards = Boards.userSearch(userId, {
labels: { $elemMatch: { name: reLabel } },
});
if (boards.count()) {
boards.forEach(board => {
board.labels
.filter(boardLabel => {
return boardLabel.name.match(reLabel);
})
.forEach(boardLabel => {
queryLabels.push(boardLabel._id);
});
});
} else {
errors.notFound.labels.push(label);
}
}
selector.labelIds = { $in: queryLabels };
});
}
if (errors.hasErrors()) {
return { cards: null, errors };
}
if (queryParams.text) {
const regex = new RegExp(queryParams.text, 'i');
selector.$or = [
{ title: regex },
{ description: regex },
{ customFields: { $elemMatch: { value: regex } } },
];
}
// 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,
createdAt: 1,
modifiedAt: 1,
labelIds: 1,
},
limit: 50,
});
// eslint-disable-next-line no-console
//console.log('count:', cards.count());
return { cards, errors };
};
//FUNCTIONS FOR creation of Activities
function updateActivities(doc, fieldNames, modifier) {

View file

@ -25,6 +25,13 @@ SessionData.attachSchema(
type: String,
optional: false,
},
sessionId: {
/**
* unique session ID
*/
type: String,
optional: false,
},
totalHits: {
/**
* total number of hits in the last report query
@ -32,6 +39,13 @@ SessionData.attachSchema(
type: Number,
optional: true,
},
resultsCount: {
/**
* number of results returned
*/
type: Number,
optional: true,
},
lastHit: {
/**
* the last hit returned from a report query
@ -39,6 +53,48 @@ SessionData.attachSchema(
type: Number,
optional: true,
},
cards: {
type: [String],
optional: true,
},
selector: {
type: String,
optional: true,
blackbox: true,
},
errorMessages: {
type: [String],
optional: true,
},
errors: {
type: [Object],
optional: true,
defaultValue: [],
},
'errors.$': {
type: new SimpleSchema({
tag: {
/**
* i18n tag
*/
type: String,
optional: false,
},
value: {
/**
* value for the tag
*/
type: String,
optional: true,
defaultValue: null,
},
color: {
type: Boolean,
optional: true,
defaultValue: false,
},
}),
},
createdAt: {
/**
* creation date of the team
@ -70,4 +126,50 @@ SessionData.attachSchema(
}),
);
SessionData.helpers({
getSelector() {
return SessionData.unpickle(this.selector);
},
});
SessionData.unpickle = pickle => {
return JSON.parse(pickle, (key, value) => {
if (typeof value === 'object') {
if (value.hasOwnProperty('$$class')) {
if (value.$$class === 'RegExp') {
return new RegExp(value.source, value.flags);
}
}
}
return value;
});
};
SessionData.pickle = value => {
return JSON.stringify(value, (key, value) => {
if (typeof value === 'object') {
if (value.constructor.name === 'RegExp') {
return {
$$class: 'RegExp',
source: value.source,
flags: value.flags,
};
}
}
return value;
});
};
if (!Meteor.isServer) {
SessionData.getSessionId = () => {
let sessionId = Session.get('sessionId');
if (!sessionId) {
sessionId = `${String(Meteor.userId())}-${String(Math.random())}`;
Session.set('sessionId', sessionId);
}
return sessionId;
};
}
export default SessionData;