diff --git a/client/components/main/dueCards.jade b/client/components/main/dueCards.jade index 2570984de..a1970839e 100644 --- a/client/components/main/dueCards.jade +++ b/client/components/main/dueCards.jade @@ -22,13 +22,17 @@ template(name="dueCardsModalTitle") template(name="dueCards") if currentUser - if isPageReady.get - .wrapper - .due-cards-dueat-list-wrapper - each card in dueCardsList - +resultCard(card) - else + if searching.get +spinner + else if hasResults.get + .global-search-results-list-wrapper + if hasQueryErrors.get + div + each msg in errorMessages + span.global-search-error-messages + = msg + else + +resultsPaged(this) template(name="dueCardsViewChangePopup") if currentUser diff --git a/client/components/main/dueCards.js b/client/components/main/dueCards.js index 747c4f457..ac3ab3164 100644 --- a/client/components/main/dueCards.js +++ b/client/components/main/dueCards.js @@ -1,3 +1,5 @@ +import { CardSearchPagedComponent } from '../../lib/cardSearch'; + const subManager = new SubsManager(); BlazeComponent.extendComponent({ @@ -40,102 +42,43 @@ BlazeComponent.extendComponent({ }, }).register('dueCardsViewChangePopup'); -BlazeComponent.extendComponent({ +class DueCardsComponent extends CardSearchPagedComponent { onCreated() { - this.isPageReady = new ReactiveVar(false); + super.onCreated(); - this.autorun(() => { - const handle = subManager.subscribe( - 'dueCards', - Utils.dueCardsView() === 'all', - ); - Tracker.nonreactive(() => { - Tracker.autorun(() => { - this.isPageReady.set(handle.ready()); - }); - }); - }); - Meteor.subscribe('setting'); - }, + const queryParams = { + has: [{ field: 'dueAt', exists: true }], + limit: 5, + skip: 0, + sort: { name: 'dueAt', order: 'des' }, + }; + + if (Utils.dueCardsView() !== 'all') { + queryParams.users = [Meteor.user().username]; + } + + this.autorunGlobalSearch(queryParams); + } dueCardsView() { // eslint-disable-next-line no-console //console.log('sort:', Utils.dueCardsView()); return Utils.dueCardsView(); - }, + } sortByBoard() { return this.dueCardsView() === 'board'; - }, + } dueCardsList() { - const allUsers = Utils.dueCardsView() === 'all'; - - const user = Meteor.user(); - - const archivedBoards = []; - Boards.find({ archived: true }).forEach(board => { - archivedBoards.push(board._id); - }); - - const permiitedBoards = []; - let selector = { - archived: false, - }; - // for every user including admin allow her to see cards only from public boards - // or those where she is a member - //if (!user.isAdmin) { - selector.$or = [ - { permission: 'public' }, - { members: { $elemMatch: { userId: user._id, isActive: true } } }, - ]; - //} - Boards.find(selector).forEach(board => { - permiitedBoards.push(board._id); - }); - - const archivedSwimlanes = []; - Swimlanes.find({ archived: true }).forEach(swimlane => { - archivedSwimlanes.push(swimlane._id); - }); - - const archivedLists = []; - Lists.find({ archived: true }).forEach(list => { - archivedLists.push(list._id); - }); - - selector = { - archived: false, - boardId: { - $nin: archivedBoards, - $in: permiitedBoards, - }, - swimlaneId: { $nin: archivedSwimlanes }, - listId: { $nin: archivedLists }, - dueAt: { $ne: null }, - endAt: null, - }; - - if (!allUsers) { - selector.$or = [{ members: user._id }, { assignees: user._id }]; - } - + const results = this.getResults(); + console.log('results:', results); const cards = []; - - // eslint-disable-next-line no-console - // console.log('cards selector:', selector); - Cards.find(selector).forEach(card => { - cards.push(card); - // eslint-disable-next-line no-console - // console.log( - // 'board:', - // card.board(), - // 'swimlane:', - // card.swimlane(), - // 'list:', - // card.list(), - // ); - }); + if (results) { + results.forEach(card => { + cards.push(card); + }); + } cards.sort((a, b) => { const x = a.dueAt === null ? Date('2100-12-31') : a.dueAt; @@ -148,7 +91,9 @@ BlazeComponent.extendComponent({ }); // eslint-disable-next-line no-console - // console.log('cards:', cards); + console.log('cards:', cards); return cards; - }, -}).register('dueCards'); + } +} + +DueCardsComponent.register('dueCards'); diff --git a/client/components/main/globalSearch.jade b/client/components/main/globalSearch.jade index 989075d02..457461965 100644 --- a/client/components/main/globalSearch.jade +++ b/client/components/main/globalSearch.jade @@ -10,6 +10,23 @@ template(name="globalSearchModalTitle") i.fa.fa-keyboard-o | {{_ 'globalSearch-title'}} +template(name="resultsPaged") + h1 + = resultsHeading.get + a.fa.fa-link(title="{{_ 'link-to-search' }}" href="{{ getSearchHref }}") + each card in results.get + +resultCard(card) + table.global-search-footer + tr + td.global-search-previous-page + if hasPreviousPage.get + button.js-previous-page + | {{_ 'previous-page' }} + td.global-search-next-page(align="right") + if hasNextPage.get + button.js-next-page + | {{_ 'next-page' }} + template(name="globalSearch") if currentUser .wrapper @@ -32,21 +49,7 @@ template(name="globalSearch") span.global-search-error-messages = msg else - h1 - = resultsHeading.get - a.fa.fa-link(title="{{_ 'link-to-search' }}" href="{{ getSearchHref }}") - each card in results.get - +resultCard(card) - table.global-search-footer - tr - td.global-search-previous-page - if hasPreviousPage.get - button.js-previous-page - | {{_ 'previous-page' }} - td.global-search-next-page(align="right") - if hasNextPage.get - button.js-next-page - | {{_ 'next-page' }} + +resultsPaged(this) else .global-search-page .global-search-help diff --git a/client/components/main/globalSearch.js b/client/components/main/globalSearch.js index 7a307b10a..217ff6daa 100644 --- a/client/components/main/globalSearch.js +++ b/client/components/main/globalSearch.js @@ -1,4 +1,6 @@ -const subManager = new SubsManager(); +import { CardSearchPagedComponent } from '../../lib/cardSearch'; + +// const subManager = new SubsManager(); BlazeComponent.extendComponent({ events() { @@ -34,27 +36,15 @@ BlazeComponent.extendComponent({ }, }).register('globalSearchViewChangePopup'); -BlazeComponent.extendComponent({ +class GlobalSearchComponent extends CardSearchPagedComponent { onCreated() { - this.searching = new ReactiveVar(false); - this.hasResults = new ReactiveVar(false); - this.hasQueryErrors = new ReactiveVar(false); - this.query = new ReactiveVar(''); - this.resultsHeading = new ReactiveVar(''); - this.searchLink = new ReactiveVar(null); + super.onCreated(); this.myLists = new ReactiveVar([]); this.myLabelNames = new ReactiveVar([]); this.myBoardNames = new ReactiveVar([]); - this.results = new ReactiveVar([]); - this.hasNextPage = new ReactiveVar(false); - this.hasPreviousPage = new ReactiveVar(false); - this.queryParams = null; this.parsingErrors = []; - this.resultsCount = 0; - this.totalHits = 0; - this.queryErrors = null; this.colorMap = null; - this.resultsPerPage = 25; + this.queryParams = null; Meteor.call('myLists', (err, data) => { if (!err) { @@ -73,7 +63,7 @@ BlazeComponent.extendComponent({ this.myBoardNames.set(data); } }); - }, + } onRendered() { Meteor.subscribe('setting'); @@ -87,67 +77,19 @@ BlazeComponent.extendComponent({ if (Session.get('globalQuery')) { this.searchAllBoards(Session.get('globalQuery')); } - }, + } resetSearch() { - this.searching.set(false); - this.results.set([]); - this.hasResults.set(false); - this.hasQueryErrors.set(false); - this.resultsHeading.set(''); + super.resetSearch(); this.parsingErrors = []; - this.resultsCount = 0; - this.totalHits = 0; - this.queryErrors = null; - }, - - getSessionData() { - return SessionData.findOne({ - userId: Meteor.userId(), - sessionId: SessionData.getSessionId(), - }); - }, - - getResults() { - // eslint-disable-next-line no-console - // console.log('getting results'); - if (this.queryParams) { - const sessionData = this.getSessionData(); - // eslint-disable-next-line no-console - // console.log('selector:', sessionData.getSelector()); - // console.log('session data:', sessionData); - const projection = sessionData.getProjection(); - projection.skip = 0; - const cards = Cards.find({ _id: { $in: sessionData.cards } }, projection); - this.queryErrors = sessionData.errors; - if (this.queryErrors.length) { - this.hasQueryErrors.set(true); - return null; - } - - if (cards) { - this.totalHits = sessionData.totalHits; - this.resultsCount = cards.count(); - this.resultsStart = sessionData.lastHit - this.resultsCount + 1; - this.resultsEnd = sessionData.lastHit; - this.resultsHeading.set(this.getResultsHeading()); - this.results.set(cards); - this.hasNextPage.set(sessionData.lastHit < sessionData.totalHits); - this.hasPreviousPage.set( - sessionData.lastHit - sessionData.resultsCount > 0, - ); - } - } - this.resultsCount = 0; - return null; - }, + } errorMessages() { if (this.parsingErrors.length) { return this.parsingErrorMessages(); } return this.queryErrorMessages(); - }, + } parsingErrorMessages() { const messages = []; @@ -159,21 +101,7 @@ BlazeComponent.extendComponent({ } return messages; - }, - - queryErrorMessages() { - messages = []; - - this.queryErrors.forEach(err => { - let value = err.color ? TAPi18n.__(`color-${err.value}`) : err.value; - if (!value) { - value = err.value; - } - messages.push(TAPi18n.__(err.tag, value)); - }); - - return messages; - }, + } searchAllBoards(query) { query = query.trim(); @@ -300,7 +228,7 @@ BlazeComponent.extendComponent({ let text = ''; while (query) { - m = query.match(reOperator1); + let m = query.match(reOperator1); if (!m) { m = query.match(reOperator2); if (m) { @@ -326,7 +254,7 @@ BlazeComponent.extendComponent({ // console.log('found color:', value); } } else if (['dueAt', 'createdAt', 'modifiedAt'].includes(operator)) { - let days = parseInt(value, 10); + const days = parseInt(value, 10); let duration = null; if (isNaN(days)) { // duration was specified as text @@ -335,7 +263,8 @@ BlazeComponent.extendComponent({ let date = null; switch (duration) { case 'week': - let week = moment().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); @@ -344,7 +273,8 @@ BlazeComponent.extendComponent({ } break; case 'month': - let month = moment().month(); + // eslint-disable-next-line no-case-declarations + const month = moment().month(); // .month() is zero indexed if (month === 11) { date = moment(1, 'M'); @@ -354,7 +284,8 @@ BlazeComponent.extendComponent({ } break; case 'quarter': - let quarter = moment().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); @@ -384,22 +315,20 @@ BlazeComponent.extendComponent({ }); value = null; } + } else if (operator === 'dueAt') { + value = { + operator: '$lt', + value: moment(moment().format('YYYY-MM-DD')) + .add(days + 1, duration ? duration : 'days') + .format(), + }; } else { - if (operator === 'dueAt') { - 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(), - }; - } + value = { + operator: '$gte', + value: moment(moment().format('YYYY-MM-DD')) + .subtract(days, duration ? duration : 'days') + .format(), + }; } } else if (operator === 'sort') { let negated = false; @@ -502,81 +431,11 @@ BlazeComponent.extendComponent({ return; } - this.autorun(() => { - const handle = Meteor.subscribe( - 'globalSearch', - SessionData.getSessionId(), - params, - ); - Tracker.nonreactive(() => { - Tracker.autorun(() => { - if (handle.ready()) { - this.getResults(); - this.searching.set(false); - this.hasResults.set(true); - } - }); - }); - }); - }, - - nextPage() { - const sessionData = this.getSessionData(); - - this.autorun(() => { - const handle = Meteor.subscribe('nextPage', sessionData.sessionId); - Tracker.nonreactive(() => { - Tracker.autorun(() => { - if (handle.ready()) { - this.getResults(); - this.searching.set(false); - this.hasResults.set(true); - } - }); - }); - }); - }, - - previousPage() { - const sessionData = this.getSessionData(); - - this.autorun(() => { - const handle = Meteor.subscribe('previousPage', sessionData.sessionId); - Tracker.nonreactive(() => { - Tracker.autorun(() => { - if (handle.ready()) { - this.getResults(); - this.searching.set(false); - this.hasResults.set(true); - } - }); - }); - }); - }, - - getResultsHeading() { - if (this.resultsCount === 0) { - return TAPi18n.__('no-cards-found'); - } else if (this.resultsCount === 1) { - return TAPi18n.__('one-card-found'); - } else if (this.resultsCount === this.totalHits) { - return TAPi18n.__('n-cards-found', this.resultsCount); - } - - return TAPi18n.__('n-n-of-n-cards-found', { - start: this.resultsStart, - end: this.resultsEnd, - total: this.totalHits, - }); - }, - - getSearchHref() { - const baseUrl = window.location.href.replace(/([?#].*$|\s*$)/, ''); - return `${baseUrl}?q=${encodeURIComponent(this.query.get())}`; - }, + this.autorunGlobalSearch(params); + } searchInstructions() { - tags = { + const tags = { operator_board: TAPi18n.__('operator-board'), operator_list: TAPi18n.__('operator-list'), operator_swimlane: TAPi18n.__('operator-swimlane'), @@ -654,7 +513,7 @@ BlazeComponent.extendComponent({ [ 'globalSearch-instructions-operator-has', 'globalSearch-instructions-operator-sort', - 'globalSearch-instructions-operator-limit' + 'globalSearch-instructions-operator-limit', ].forEach(instruction => { text += `\n* ${TAPi18n.__(instruction, tags)}`; }); @@ -672,7 +531,7 @@ BlazeComponent.extendComponent({ }); return text; - }, + } labelColors() { return Boards.simpleSchema()._schema['labels.$.color'].allowedValues.map( @@ -680,23 +539,16 @@ BlazeComponent.extendComponent({ return { color, name: TAPi18n.__(`color-${color}`) }; }, ); - }, + } events() { return [ { + ...super.events()[0], 'submit .js-search-query-form'(evt) { evt.preventDefault(); this.searchAllBoards(evt.target.searchQuery.value); }, - 'click .js-next-page'(evt) { - evt.preventDefault(); - this.nextPage(); - }, - 'click .js-previous-page'(evt) { - evt.preventDefault(); - this.previousPage(); - }, 'click .js-label-color'(evt) { evt.preventDefault(); const input = document.getElementById('global-search-input'); @@ -739,5 +591,7 @@ BlazeComponent.extendComponent({ }, }, ]; - }, -}).register('globalSearch'); + } +} + +GlobalSearchComponent.register('globalSearch'); diff --git a/client/components/main/myCards.jade b/client/components/main/myCards.jade index 79d28050b..3daae780b 100644 --- a/client/components/main/myCards.jade +++ b/client/components/main/myCards.jade @@ -24,14 +24,16 @@ template(name="myCardsModalTitle") template(name="myCards") if currentUser - if isPageReady.get + if searching.get + +spinner + else .wrapper if $eq myCardsSort 'board' each board in myCardsList .my-cards-board-wrapper .my-cards-board-title(class=board.colorClass, id="header") a(href=board.absoluteUrl) - +viewer + +viewer = board.title each swimlane in board.mySwimlanes .my-cards-swimlane-title(class="{{#if swimlane.colorClass}}{{ swimlane.colorClass }}{{else}}swimlane-default-color{{/if}}") @@ -50,8 +52,6 @@ template(name="myCards") .my-cards-dueat-list-wrapper each card in myDueCardsList +resultCard(card) - else - +spinner template(name="myCardsSortChangePopup") if currentUser diff --git a/client/components/main/myCards.js b/client/components/main/myCards.js index 13eb3e519..54aa8f505 100644 --- a/client/components/main/myCards.js +++ b/client/components/main/myCards.js @@ -1,3 +1,5 @@ +import {CardSearchPagedComponent} from "../../lib/cardSearch"; + const subManager = new SubsManager(); BlazeComponent.extendComponent({ @@ -42,177 +44,139 @@ BlazeComponent.extendComponent({ }, }).register('myCardsSortChangePopup'); -BlazeComponent.extendComponent({ +class MyCardsComponent extends CardSearchPagedComponent { onCreated() { - this.isPageReady = new ReactiveVar(false); + super.onCreated(); - this.autorun(() => { - const handle = subManager.subscribe('myCards'); - Tracker.nonreactive(() => { - Tracker.autorun(() => { - this.isPageReady.set(handle.ready()); - }); - }); - }); + const queryParams = { + users: [Meteor.user().username], + sort: { name: 'dueAt', order: 'des' }, + }; + + this.autorunGlobalSearch(queryParams); Meteor.subscribe('setting'); - }, + } myCardsSort() { // eslint-disable-next-line no-console //console.log('sort:', Utils.myCardsSort()); return Utils.myCardsSort(); - }, + } sortByBoard() { return this.myCardsSort() === 'board'; - }, + } myCardsList() { - const userId = Meteor.userId(); const boards = []; let board = null; let swimlane = null; let list = null; - const cursor = Cards.find( - { - $or: [{ members: userId }, { assignees: userId }], - archived: false, - }, - { - sort: { - boardId: 1, - swimlaneId: 1, - listId: 1, - sort: 1, - }, - }, - ); + const cursor = this.getResults(); - let newBoard = false; - let newSwimlane = false; - let newList = false; + if (cursor) { + let newBoard = false; + let newSwimlane = false; + let newList = false; - cursor.forEach(card => { - // eslint-disable-next-line no-console - // console.log('card:', card.title); - if (list === null || card.listId !== list._id) { + cursor.forEach(card => { // eslint-disable-next-line no-console - // console.log('new list'); - list = card.getList(); - if (list.archived) { - list = null; - return; + // console.log('card:', card.title); + if (list === null || card.listId !== list._id) { + // eslint-disable-next-line no-console + // console.log('new list'); + list = card.getList(); + if (list.archived) { + list = null; + return; + } + list.myCards = [card]; + newList = true; } - list.myCards = [card]; - newList = true; - } - if (swimlane === null || card.swimlaneId !== swimlane._id) { - // eslint-disable-next-line no-console - // console.log('new swimlane'); - swimlane = card.getSwimlane(); - if (swimlane.archived) { - swimlane = null; - return; + if (swimlane === null || card.swimlaneId !== swimlane._id) { + // eslint-disable-next-line no-console + // console.log('new swimlane'); + swimlane = card.getSwimlane(); + if (swimlane.archived) { + swimlane = null; + return; + } + swimlane.myLists = [list]; + newSwimlane = true; } - swimlane.myLists = [list]; - newSwimlane = true; - } - if (board === null || card.boardId !== board._id) { - // eslint-disable-next-line no-console - // console.log('new board'); - board = card.getBoard(); - if (board.archived) { - board = null; - return; + if (board === null || card.boardId !== board._id) { + // eslint-disable-next-line no-console + // console.log('new board'); + board = card.getBoard(); + if (board.archived) { + board = null; + return; + } + // eslint-disable-next-line no-console + // console.log('board:', b, b._id, b.title); + board.mySwimlanes = [swimlane]; + newBoard = true; } - // eslint-disable-next-line no-console - // console.log('board:', b, b._id, b.title); - board.mySwimlanes = [swimlane]; - newBoard = true; - } - if (newBoard) { - boards.push(board); - } else if (newSwimlane) { - board.mySwimlanes.push(swimlane); - } else if (newList) { - swimlane.myLists.push(list); - } else { - list.myCards.push(card); - } + if (newBoard) { + boards.push(board); + } else if (newSwimlane) { + board.mySwimlanes.push(swimlane); + } else if (newList) { + swimlane.myLists.push(list); + } else { + list.myCards.push(card); + } - newBoard = false; - newSwimlane = false; - newList = false; - }); + newBoard = false; + newSwimlane = false; + newList = false; + }); - // sort the data structure - boards.forEach(board => { - board.mySwimlanes.forEach(swimlane => { - swimlane.myLists.forEach(list => { - list.myCards.sort((a, b) => { + // sort the data structure + boards.forEach(board => { + board.mySwimlanes.forEach(swimlane => { + swimlane.myLists.forEach(list => { + list.myCards.sort((a, b) => { + return a.sort - b.sort; + }); + }); + swimlane.myLists.sort((a, b) => { return a.sort - b.sort; }); }); - swimlane.myLists.sort((a, b) => { + board.mySwimlanes.sort((a, b) => { return a.sort - b.sort; }); }); - board.mySwimlanes.sort((a, b) => { - return a.sort - b.sort; + + boards.sort((a, b) => { + let x = a.sort; + let y = b.sort; + + // show the template board last + if (a.type === 'template-container') { + x = 99999999; + } else if (b.type === 'template-container') { + y = 99999999; + } + return x - y; }); - }); - boards.sort((a, b) => { - let x = a.sort; - let y = b.sort; + // eslint-disable-next-line no-console + // console.log('boards:', boards); + return boards; + } - // show the template board last - if (a.type === 'template-container') { - x = 99999999; - } else if (b.type === 'template-container') { - y = 99999999; - } - return x - y; - }); - - // eslint-disable-next-line no-console - // console.log('boards:', boards); - return boards; - }, + return []; + } myDueCardsList() { - const userId = Meteor.userId(); - - const cursor = Cards.find( - { - $or: [{ members: userId }, { assignees: userId }], - archived: false, - }, - { - sort: { - dueAt: -1, - boardId: 1, - swimlaneId: 1, - listId: 1, - sort: 1, - }, - }, - ); - - // eslint-disable-next-line no-console - // console.log('cursor:', cursor); - + const cursor = this.getResults(); const cards = []; cursor.forEach(card => { - if ( - !card.getBoard().archived && - !card.getSwimlane().archived && - !card.getList().archived - ) { - cards.push(card); - } + cards.push(card); }); cards.sort((a, b) => { @@ -228,23 +192,6 @@ BlazeComponent.extendComponent({ // eslint-disable-next-line no-console // console.log('cursor:', cards); return cards; - }, - - events() { - return [ - { - // 'click .js-my-card'(evt) { - // const card = this.currentData().card; - // // eslint-disable-next-line no-console - // console.log('currentData():', this.currentData()); - // // eslint-disable-next-line no-console - // console.log('card:', card); - // if (card) { - // Utils.goCardId(card._id); - // } - // evt.preventDefault(); - // }, - }, - ]; - }, -}).register('myCards'); + } +} +MyCardsComponent.register('myCards'); diff --git a/server/publications/cards.js b/server/publications/cards.js index 4197fd826..a7b3f699c 100644 --- a/server/publications/cards.js +++ b/server/publications/cards.js @@ -5,175 +5,38 @@ Meteor.publish('card', cardId => { return Cards.find({ _id: cardId }); }); -Meteor.publish('myCards', function() { - const userId = Meteor.userId(); +Meteor.publish('myCards', function(sessionId) { - const archivedBoards = []; - Boards.find({ archived: true }).forEach(board => { - archivedBoards.push(board._id); - }); - - const archivedSwimlanes = []; - Swimlanes.find({ archived: true }).forEach(swimlane => { - archivedSwimlanes.push(swimlane._id); - }); - - const archivedLists = []; - Lists.find({ archived: true }).forEach(list => { - archivedLists.push(list._id); - }); - - selector = { - archived: false, - boardId: { $nin: archivedBoards }, - swimlaneId: { $nin: archivedSwimlanes }, - listId: { $nin: archivedLists }, - $or: [{ members: userId }, { assignees: userId }], + const queryParams = { + users: [Meteor.user().username], + // limit: 25, + skip: 0, + // sort: { name: 'dueAt', order: 'des' }, }; - 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 buildQuery(sessionId, queryParams); }); -Meteor.publish('dueCards', function(allUsers = false) { - check(allUsers, Boolean); - - // eslint-disable-next-line no-console - // console.log('all users:', allUsers); - - const user = Users.findOne({ _id: this.userId }); - - const archivedBoards = []; - Boards.find({ archived: true }).forEach(board => { - archivedBoards.push(board._id); - }); - - const permiitedBoards = []; - let selector = { - archived: false, - }; - - selector.$or = [ - { permission: 'public' }, - { members: { $elemMatch: { userId: user._id, isActive: true } } }, - ]; - - Boards.find(selector).forEach(board => { - permiitedBoards.push(board._id); - }); - - const archivedSwimlanes = []; - Swimlanes.find({ archived: true }).forEach(swimlane => { - archivedSwimlanes.push(swimlane._id); - }); - - const archivedLists = []; - Lists.find({ archived: true }).forEach(list => { - archivedLists.push(list._id); - }); - - selector = { - archived: false, - boardId: { $nin: archivedBoards, $in: permiitedBoards }, - swimlaneId: { $nin: archivedSwimlanes }, - listId: { $nin: archivedLists }, - dueAt: { $ne: null }, - endAt: null, - }; - - if (!allUsers) { - selector.$or = [{ members: user._id }, { assignees: user._id }]; - } - - 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('dueCards', function(sessionId, allUsers = false) { +// check(sessionId, String); +// check(allUsers, Boolean); +// +// // eslint-disable-next-line no-console +// // console.log('all users:', allUsers); +// +// const queryParams = { +// has: [{ field: 'dueAt', exists: true }], +// limit: 25, +// skip: 0, +// sort: { name: 'dueAt', order: 'des' }, +// }; +// +// if (!allUsers) { +// queryParams.users = [Meteor.user().username]; +// } +// +// return buildQuery(sessionId, queryParams); +// }); Meteor.publish('globalSearch', function(sessionId, queryParams) { check(sessionId, String); @@ -182,9 +45,11 @@ Meteor.publish('globalSearch', function(sessionId, queryParams) { // eslint-disable-next-line no-console // console.log('queryParams:', queryParams); + return buildQuery(sessionId, queryParams); +}); + +function buildQuery(sessionId, queryParams) { const userId = Meteor.userId(); - // eslint-disable-next-line no-console - // console.log('userId:', userId); const errors = new (class { constructor() { @@ -267,7 +132,7 @@ Meteor.publish('globalSearch', function(sessionId, queryParams) { let archived = false; let endAt = null; - if (queryParams.status.length) { + if (queryParams.status && queryParams.status.length) { queryParams.status.forEach(status => { if (status === 'archived') { archived = true; @@ -320,7 +185,7 @@ Meteor.publish('globalSearch', function(sessionId, queryParams) { selector.endAt = endAt; } - if (queryParams.boards.length) { + if (queryParams.boards && queryParams.boards.length) { const queryBoards = []; queryParams.boards.forEach(query => { const boards = Boards.userSearch(userId, { @@ -338,7 +203,7 @@ Meteor.publish('globalSearch', function(sessionId, queryParams) { selector.boardId.$in = queryBoards; } - if (queryParams.swimlanes.length) { + if (queryParams.swimlanes && queryParams.swimlanes.length) { const querySwimlanes = []; queryParams.swimlanes.forEach(query => { const swimlanes = Swimlanes.find({ @@ -360,7 +225,7 @@ Meteor.publish('globalSearch', function(sessionId, queryParams) { selector.swimlaneId.$in = querySwimlanes; } - if (queryParams.lists.length) { + if (queryParams.lists && queryParams.lists.length) { const queryLists = []; queryParams.lists.forEach(query => { const lists = Lists.find({ @@ -382,7 +247,7 @@ Meteor.publish('globalSearch', function(sessionId, queryParams) { selector.listId.$in = queryLists; } - if (queryParams.comments.length) { + if (queryParams.comments && queryParams.comments.length) { const cardIds = CardComments.textSearch(userId, queryParams.comments).map( com => { return com.cardId; @@ -398,15 +263,15 @@ Meteor.publish('globalSearch', function(sessionId, queryParams) { ['dueAt', 'createdAt', 'modifiedAt'].forEach(field => { if (queryParams[field]) { selector[field] = {}; - selector[field][queryParams[field]['operator']] = new Date( - queryParams[field]['value'], + selector[field][queryParams[field].operator] = new Date( + queryParams[field].value, ); } }); const queryMembers = []; const queryAssignees = []; - if (queryParams.users.length) { + if (queryParams.users && queryParams.users.length) { queryParams.users.forEach(query => { const users = Users.find({ username: query, @@ -422,7 +287,7 @@ Meteor.publish('globalSearch', function(sessionId, queryParams) { }); } - if (queryParams.members.length) { + if (queryParams.members && queryParams.members.length) { queryParams.members.forEach(query => { const users = Users.find({ username: query, @@ -437,7 +302,7 @@ Meteor.publish('globalSearch', function(sessionId, queryParams) { }); } - if (queryParams.assignees.length) { + if (queryParams.assignees && queryParams.assignees.length) { queryParams.assignees.forEach(query => { const users = Users.find({ username: query, @@ -465,7 +330,7 @@ Meteor.publish('globalSearch', function(sessionId, queryParams) { selector.assignees = { $in: queryAssignees }; } - if (queryParams.labels.length) { + if (queryParams.labels && queryParams.labels.length) { queryParams.labels.forEach(label => { const queryLabels = []; @@ -516,16 +381,26 @@ Meteor.publish('globalSearch', function(sessionId, queryParams) { }); } - if (queryParams.has.length) { + if (queryParams.has && queryParams.has.length) { queryParams.has.forEach(has => { switch (has.field) { case 'attachment': - const attachments = Attachments.find({}, { fields: { cardId: 1 } }); - selector.$and.push({ _id: { $in: attachments.map(a => a.cardId) } }); + selector.$and.push({ + _id: { + $in: Attachments.find({}, { fields: { cardId: 1 } }).map( + a => a.cardId, + ), + }, + }); break; case 'checklist': - const checklists = Checklists.find({}, { fields: { cardId: 1 } }); - selector.$and.push({ _id: { $in: checklists.map(a => a.cardId) } }); + selector.$and.push({ + _id: { + $in: Checklists.find({}, { fields: { cardId: 1 } }).map( + a => a.cardId, + ), + }, + }); break; case 'description': case 'startAt': @@ -677,7 +552,7 @@ Meteor.publish('globalSearch', function(sessionId, queryParams) { // console.log('projection:', projection); return findCards(sessionId, selector, projection, errors); -}); +} Meteor.publish('brokenCards', function() { const user = Users.findOne({ _id: this.userId }); @@ -773,7 +648,8 @@ function findCards(sessionId, selector, projection, errors = null) { const userId = Meteor.userId(); // eslint-disable-next-line no-console - // console.log('selector:', selector); + console.log('selector:', selector); + console.log('selector.$and:', selector.$and); // eslint-disable-next-line no-console // console.log('projection:', projection); let cards; @@ -879,5 +755,5 @@ function findCards(sessionId, selector, projection, errors = null) { ]; } - return [SessionData.find({ userId: userId, sessionId })]; + return [SessionData.find({ userId, sessionId })]; }