Fix sort operator

* Add server publications for next and previous page
* Add ability to sort ascending or descending
This commit is contained in:
John R. Supplee 2021-02-25 18:38:51 +02:00
parent 250e79f53c
commit 43f40c4085
5 changed files with 239 additions and 174 deletions

View file

@ -552,6 +552,11 @@ Meteor.publish('globalSearch', function(sessionId, queryParams) {
const attachments = Attachments.find({ 'original.name': regex });
// const comments = CardComments.find(
// { text: regex },
// { fields: { cardId: 1 } },
// );
selector.$and.push({
$or: [
{ title: regex },
@ -566,6 +571,7 @@ Meteor.publish('globalSearch', function(sessionId, queryParams) {
},
{ _id: { $in: checklists.map(list => list.cardId) } },
{ _id: { $in: attachments.map(attach => attach.cardId) } },
// { _id: { $in: comments.map(com => com.cardId) } },
],
});
}
@ -580,89 +586,206 @@ Meteor.publish('globalSearch', function(sessionId, queryParams) {
// eslint-disable-next-line no-console
// console.log('selector.$and:', selector.$and);
let cards = null;
const projection = {
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,
customFields: 1,
},
sort: {
boardId: 1,
swimlaneId: 1,
listId: 1,
sort: 1,
},
skip,
limit,
};
if (!errors.hasErrors()) {
const projection = {
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,
customFields: 1,
},
skip,
limit,
};
if (queryParams.sort === 'due') {
projection.sort = {
dueAt: 1,
boardId: 1,
swimlaneId: 1,
listId: 1,
sort: 1,
};
} else if (queryParams.sort === 'modified') {
projection.sort = {
modifiedAt: -1,
boardId: 1,
swimlaneId: 1,
listId: 1,
sort: 1,
};
} else if (queryParams.sort === 'created') {
projection.sort = {
createdAt: -1,
boardId: 1,
swimlaneId: 1,
listId: 1,
sort: 1,
};
} else if (queryParams.sort === 'system') {
projection.sort = {
boardId: 1,
swimlaneId: 1,
listId: 1,
modifiedAt: 1,
sort: 1,
};
if (queryParams.sort) {
const order = queryParams.sort.order === 'asc' ? 1 : -1;
switch (queryParams.sort.name) {
case 'dueAt':
projection.sort = {
dueAt: order,
boardId: 1,
swimlaneId: 1,
listId: 1,
sort: 1,
};
break;
case 'modifiedAt':
projection.sort = {
modifiedAt: order,
boardId: 1,
swimlaneId: 1,
listId: 1,
sort: 1,
};
break;
case 'createdAt':
projection.sort = {
createdAt: order,
boardId: 1,
swimlaneId: 1,
listId: 1,
sort: 1,
};
break;
case 'system':
projection.sort = {
boardId: order,
swimlaneId: order,
listId: order,
modifiedAt: order,
sort: order,
};
break;
}
// eslint-disable-next-line no-console
// console.log('projection:', projection);
cards = Cards.find(selector, projection);
// eslint-disable-next-line no-console
// console.log('count:', cards.count());
}
// eslint-disable-next-line no-console
// console.log('projection:', projection);
return findCards(sessionId, selector, projection, errors);
});
Meteor.publish('brokenCards', function() {
const user = Users.findOne({ _id: this.userId });
const permiitedBoards = [null];
let selector = {};
selector.$or = [
{ permission: 'public' },
{ members: { $elemMatch: { userId: user._id, isActive: true } } },
];
Boards.find(selector).forEach(board => {
permiitedBoards.push(board._id);
});
selector = {
boardId: { $in: permiitedBoards },
$or: [
{ boardId: { $in: [null, ''] } },
{ swimlaneId: { $in: [null, ''] } },
{ listId: { $in: [null, ''] } },
],
};
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 boards = [];
const swimlanes = [];
const lists = [];
const users = [];
cards.forEach(card => {
if (card.boardId) boards.push(card.boardId);
if (card.swimlaneId) swimlanes.push(card.swimlaneId);
if (card.listId) lists.push(card.listId);
if (card.members) {
card.members.forEach(userId => {
users.push(userId);
});
}
if (card.assignees) {
card.assignees.forEach(userId => {
users.push(userId);
});
}
});
return [
cards,
Boards.find({ _id: { $in: boards } }),
Swimlanes.find({ _id: { $in: swimlanes } }),
Lists.find({ _id: { $in: lists } }),
Users.find({ _id: { $in: users } }, { fields: Users.safeFields }),
];
});
Meteor.publish('nextPage', function(sessionId) {
check(sessionId, String);
const session = SessionData.findOne({ sessionId });
const projection = session.getProjection();
projection.skip = session.lastHit;
return findCards(sessionId, session.getSelector(), projection);
});
Meteor.publish('previousPage', function(sessionId) {
check(sessionId, String);
const session = SessionData.findOne({ sessionId });
const projection = session.getProjection();
projection.skip = session.lastHit - session.resultsCount - projection.limit;
return findCards(sessionId, session.getSelector(), projection);
});
function findCards(sessionId, selector, projection, errors = null) {
// check(selector, Object);
// check(projection, Object);
const userId = Meteor.userId();
let cards;
if (!errors || !errors.hasErrors()) {
cards = Cards.find(selector, projection);
}
console.log('selector:', selector);
console.log('projection:', projection);
console.log('count:', cards.count());
const update = {
$set: {
totalHits: 0,
lastHit: 0,
resultsCount: 0,
cards: [],
errors: errors.errorMessages(),
selector: SessionData.pickle(selector),
projection: SessionData.pickle(projection),
},
};
if (errors) {
update.$set.errors = errors.errorMessages();
}
if (cards) {
update.$set.totalHits = cards.count();
update.$set.lastHit =
skip + limit < cards.count() ? skip + limit : cards.count();
projection.skip + projection.limit < cards.count()
? projection.skip + projection.limit
: cards.count();
update.$set.cards = cards.map(card => {
return card._id;
});
@ -735,79 +858,9 @@ Meteor.publish('globalSearch', function(sessionId, queryParams) {
Checklists.find({ cardId: { $in: cards.map(c => c._id) } }),
Attachments.find({ cardId: { $in: cards.map(c => c._id) } }),
CardComments.find({ cardId: { $in: cards.map(c => c._id) } }),
SessionData.find({ userId: this.userId, sessionId }),
SessionData.find({ userId, sessionId }),
];
}
return [SessionData.find({ userId: this.userId, sessionId })];
});
Meteor.publish('brokenCards', function() {
const user = Users.findOne({ _id: this.userId });
const permiitedBoards = [null];
let selector = {};
selector.$or = [
{ permission: 'public' },
{ members: { $elemMatch: { userId: user._id, isActive: true } } },
];
Boards.find(selector).forEach(board => {
permiitedBoards.push(board._id);
});
selector = {
boardId: { $in: permiitedBoards },
$or: [
{ boardId: { $in: [null, ''] } },
{ swimlaneId: { $in: [null, ''] } },
{ listId: { $in: [null, ''] } },
],
};
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 boards = [];
const swimlanes = [];
const lists = [];
const users = [];
cards.forEach(card => {
if (card.boardId) boards.push(card.boardId);
if (card.swimlaneId) swimlanes.push(card.swimlaneId);
if (card.listId) lists.push(card.listId);
if (card.members) {
card.members.forEach(userId => {
users.push(userId);
});
}
if (card.assignees) {
card.assignees.forEach(userId => {
users.push(userId);
});
}
});
return [
cards,
Boards.find({ _id: { $in: boards } }),
Swimlanes.find({ _id: { $in: swimlanes } }),
Lists.find({ _id: { $in: lists } }),
Users.find({ _id: { $in: users } }, { fields: Users.safeFields }),
];
});
return [SessionData.find({ userId: userId, sessionId })];
}