| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251 |
- import { ReactiveCache } from '/imports/reactiveCache';
- import { BlazeComponent } from 'meteor/peerlibrary:blaze-components';
- import { TAPi18n } from '/imports/i18n';
- // const subManager = new SubsManager();
- BlazeComponent.extendComponent({
- dueCardsView() {
- // eslint-disable-next-line no-console
- // console.log('sort:', Utils.dueCardsView());
- return Utils && Utils.dueCardsView ? Utils.dueCardsView() : 'me';
- },
- events() {
- return [
- {
- 'click .js-due-cards-view-change': Popup.open('dueCardsViewChange'),
- },
- ];
- },
- }).register('dueCardsHeaderBar');
- Template.dueCards.helpers({
- userId() {
- return Meteor.userId();
- },
- dueCardsList() {
- const component = BlazeComponent.getComponentForElement(this.firstNode);
- if (component && component.dueCardsList) {
- return component.dueCardsList();
- }
- return [];
- },
- hasResults() {
- const component = BlazeComponent.getComponentForElement(this.firstNode);
- if (component && component.hasResults) {
- return component.hasResults.get();
- }
- return false;
- },
- searching() {
- const component = BlazeComponent.getComponentForElement(this.firstNode);
- if (component && component.isLoading) {
- return component.isLoading.get();
- }
- return true; // Show loading by default
- },
- hasQueryErrors() {
- return false; // No longer using search, so always false
- },
- errorMessages() {
- return []; // No longer using search, so always empty
- },
- cardsCount() {
- const component = BlazeComponent.getComponentForElement(this.firstNode);
- if (component && component.cardsCount) {
- return component.cardsCount();
- }
- return 0;
- },
- resultsText() {
- const component = BlazeComponent.getComponentForElement(this.firstNode);
- if (component && component.resultsText) {
- return component.resultsText();
- }
- return '';
- },
- });
- BlazeComponent.extendComponent({
- events() {
- return [
- {
- 'click .js-due-cards-view-me'() {
- if (Utils && Utils.setDueCardsView) {
- Utils.setDueCardsView('me');
- }
- Popup.back();
- },
- 'click .js-due-cards-view-all'() {
- if (Utils && Utils.setDueCardsView) {
- Utils.setDueCardsView('all');
- }
- Popup.back();
- },
- },
- ];
- },
- }).register('dueCardsViewChangePopup');
- class DueCardsComponent extends BlazeComponent {
- onCreated() {
- super.onCreated();
-
- this._cachedCards = null;
- this._cachedTimestamp = null;
- this.subscriptionHandle = null;
- this.isLoading = new ReactiveVar(true);
- this.hasResults = new ReactiveVar(false);
- this.searching = new ReactiveVar(false);
-
- // Subscribe to the optimized due cards publication
- this.autorun(() => {
- const allUsers = this.dueCardsView() === 'all';
- if (this.subscriptionHandle) {
- this.subscriptionHandle.stop();
- }
- this.subscriptionHandle = Meteor.subscribe('dueCards', allUsers);
-
- // Update loading state based on subscription
- this.autorun(() => {
- if (this.subscriptionHandle && this.subscriptionHandle.ready()) {
- if (process.env.DEBUG === 'true') {
- console.log('dueCards: subscription ready, loading data...');
- }
- this.isLoading.set(false);
- const cards = this.dueCardsList();
- this.hasResults.set(cards && cards.length > 0);
- } else {
- if (process.env.DEBUG === 'true') {
- console.log('dueCards: subscription not ready, showing loading...');
- }
- this.isLoading.set(true);
- this.hasResults.set(false);
- }
- });
- });
- }
- onDestroyed() {
- super.onDestroyed();
- if (this.subscriptionHandle) {
- this.subscriptionHandle.stop();
- }
- }
- dueCardsView() {
- // eslint-disable-next-line no-console
- //console.log('sort:', Utils.dueCardsView());
- return Utils && Utils.dueCardsView ? Utils.dueCardsView() : 'me';
- }
- sortByBoard() {
- return this.dueCardsView() === 'board';
- }
- hasResults() {
- return this.hasResults.get();
- }
- cardsCount() {
- const cards = this.dueCardsList();
- return cards ? cards.length : 0;
- }
- resultsText() {
- const count = this.cardsCount();
- if (count === 1) {
- return TAPi18n.__('one-card-found');
- } else {
- // Get the translated text and manually replace %s with the count
- const baseText = TAPi18n.__('n-cards-found');
- const result = baseText.replace('%s', count);
-
- if (process.env.DEBUG === 'true') {
- console.log('dueCards: base text:', baseText, 'count:', count, 'result:', result);
- }
- return result;
- }
- }
- dueCardsList() {
- // Check if subscription is ready
- if (!this.subscriptionHandle || !this.subscriptionHandle.ready()) {
- if (process.env.DEBUG === 'true') {
- console.log('dueCards client: subscription not ready');
- }
- return [];
- }
- // Use cached results if available to avoid expensive re-sorting
- if (this._cachedCards && this._cachedTimestamp && (Date.now() - this._cachedTimestamp < 5000)) {
- if (process.env.DEBUG === 'true') {
- console.log('dueCards client: using cached results,', this._cachedCards.length, 'cards');
- }
- return this._cachedCards;
- }
- // Get cards directly from the subscription (already sorted by the publication)
- const cards = ReactiveCache.getCards({
- type: 'cardType-card',
- archived: false,
- dueAt: { $exists: true, $nin: [null, ''] }
- });
- if (process.env.DEBUG === 'true') {
- console.log('dueCards client: found', cards.length, 'cards with due dates');
- console.log('dueCards client: cards details:', cards.map(c => ({
- id: c._id,
- title: c.title,
- dueAt: c.dueAt,
- boardId: c.boardId,
- members: c.members,
- assignees: c.assignees,
- userId: c.userId
- })));
- }
- // Filter cards based on user view preference
- const allUsers = this.dueCardsView() === 'all';
- const currentUser = ReactiveCache.getCurrentUser();
- let filteredCards = cards;
- if (process.env.DEBUG === 'true') {
- console.log('dueCards client: current user:', currentUser ? currentUser._id : 'none');
- console.log('dueCards client: showing all users:', allUsers);
- }
- if (!allUsers && currentUser) {
- filteredCards = cards.filter(card => {
- const isMember = card.members && card.members.includes(currentUser._id);
- const isAssignee = card.assignees && card.assignees.includes(currentUser._id);
- const isAuthor = card.userId === currentUser._id;
- const matches = isMember || isAssignee || isAuthor;
-
- if (process.env.DEBUG === 'true' && matches) {
- console.log('dueCards client: card matches user:', card.title, { isMember, isAssignee, isAuthor });
- }
-
- return matches;
- });
- }
- if (process.env.DEBUG === 'true') {
- console.log('dueCards client: filtered to', filteredCards.length, 'cards');
- }
- // Cache the results for 5 seconds to avoid re-filtering on every render
- this._cachedCards = filteredCards;
- this._cachedTimestamp = Date.now();
- // Update reactive variables
- this.hasResults.set(filteredCards && filteredCards.length > 0);
- this.isLoading.set(false);
- return filteredCards;
- }
- }
- DueCardsComponent.register('dueCards');
|