From f74c21d2e7eac951ae00f0278da6b021e027f281 Mon Sep 17 00:00:00 2001 From: Sam Date: Mon, 21 Sep 2015 10:36:20 +1000 Subject: [PATCH] FIX: tracking of new/unread/latest in category/subcategory was broken --- .../models/topic-tracking-state.js.es6 | 45 +++++++++++++++++-- app/models/topic_tracking_state.rb | 1 + .../models/topic-tracking-state-test.js.es6 | 31 +++++++++++++ 3 files changed, 74 insertions(+), 3 deletions(-) diff --git a/app/assets/javascripts/discourse/models/topic-tracking-state.js.es6 b/app/assets/javascripts/discourse/models/topic-tracking-state.js.es6 index f77f242715f..f72d6988135 100644 --- a/app/assets/javascripts/discourse/models/topic-tracking-state.js.es6 +++ b/app/assets/javascripts/discourse/models/topic-tracking-state.js.es6 @@ -40,6 +40,15 @@ const TopicTrackingState = Discourse.Model.extend({ } } + // fill parent_category_id we need it for counting new/unread + if (data.payload && data.payload.category_id) { + var category = Discourse.Category.findById(data.payload.category_id); + + if (category && category.parent_category_id) { + data.payload.parent_category_id = category.parent_category_id; + } + } + if (data.message_type === "latest"){ tracker.notify(data); } @@ -75,6 +84,15 @@ const TopicTrackingState = Discourse.Model.extend({ if (!this.newIncoming) { return; } const filter = this.get("filter"); + const filterCategory = this.get("filterCategory"); + const categoryId = data.payload && data.payload.category_id; + + if (filterCategory && filterCategory.get("id") !== categoryId) { + const category = categoryId && Discourse.Category.findById(categoryId); + if (!category || category.get("parentCategory.id") !== filterCategory.get('id')) { + return; + } + } if (filter === Discourse.Utilities.defaultHomepage()) { const suppressed_from_homepage_category_ids = Discourse.Site.currentProp("suppressed_from_homepage_category_ids"); @@ -115,6 +133,17 @@ const TopicTrackingState = Discourse.Model.extend({ // track how many new topics came for this filter trackIncoming(filter) { this.newIncoming = []; + const split = filter.split('/'); + + if (split.length >= 4) { + filter = split[split.length-1]; + // c/cat/subcat/l/latest + var category = Discourse.Category.findSingleBySlug(split.splice(1,split.length - 3).join('/')); + this.set("filterCategory", category); + } else { + this.set("filterCategory", null); + } + this.set("filter", filter); this.set("incomingCount", 0); }, @@ -238,7 +267,7 @@ const TopicTrackingState = Discourse.Model.extend({ countNew(category_id) { return _.chain(this.states) .where(isNew) - .where(topic => topic.category_id === category_id || !category_id) + .where(topic => topic.category_id === category_id || topic.parent_category_id === category_id || !category_id) .value() .length; }, @@ -254,7 +283,7 @@ const TopicTrackingState = Discourse.Model.extend({ countUnread(category_id) { return _.chain(this.states) .where(isUnread) - .where(topic => topic.category_id === category_id || !category_id) + .where(topic => topic.category_id === category_id || topic.parent_category_id === category_id || !category_id) .value() .length; }, @@ -293,8 +322,18 @@ const TopicTrackingState = Discourse.Model.extend({ loadStates(data) { const states = this.states; + const idMap = Discourse.Category.idMap(); + + // I am taking some shortcuts here to avoid 500 gets for + // a large list if (data) { - _.each(data,topic => states["t" + topic.topic_id] = topic); + _.each(data,topic => { + var category = idMap[topic.category_id]; + if (category && category.parent_category_id) { + topic.parent_category_id = category.parent_category_id; + } + states["t" + topic.topic_id] = topic; + }); } } }); diff --git a/app/models/topic_tracking_state.rb b/app/models/topic_tracking_state.rb index 0da784219c9..a38b6ec6d8b 100644 --- a/app/models/topic_tracking_state.rb +++ b/app/models/topic_tracking_state.rb @@ -73,6 +73,7 @@ class TopicTrackingState highest_post_number: post.post_number, created_at: post.created_at, topic_id: post.topic_id, + category_id: post.topic.category_id, notification_level: tu.notification_level } } diff --git a/test/javascripts/models/topic-tracking-state-test.js.es6 b/test/javascripts/models/topic-tracking-state-test.js.es6 index f135584ee2f..0814487950c 100644 --- a/test/javascripts/models/topic-tracking-state-test.js.es6 +++ b/test/javascripts/models/topic-tracking-state-test.js.es6 @@ -1,4 +1,5 @@ import TopicTrackingState from 'discourse/models/topic-tracking-state'; +import createStore from 'helpers/create-store'; module("model:topic-tracking-state"); @@ -17,3 +18,33 @@ test("sync", function (assert) { state.sync(list, "new"); assert.equal(list.topics.length, 0, "expect new topic to be removed as it was seen"); }); + +test("subscribe to category", function(assert){ + + const store = createStore(); + const darth = store.createRecord('category', {id: 1, slug: 'darth'}), + luke = store.createRecord('category', {id: 2, slug: 'luke', parentCategory: darth}), + categoryList = [darth, luke]; + + sandbox.stub(Discourse.Category, 'list').returns(categoryList); + + + const state = TopicTrackingState.create(); + + state.trackIncoming('c/darth/l/latest'); + + state.notify({message_type: 'new_topic', topic_id: 1, payload: {category_id: 2, topic_id: 1}}); + state.notify({message_type: 'new_topic', topic_id: 2, payload: {category_id: 3, topic_id: 2}}); + state.notify({message_type: 'new_topic', topic_id: 3, payload: {category_id: 1, topic_id: 3}}); + + assert.equal(state.get("incomingCount"), 2, "expect to properly track incoming for category"); + + state.resetTracking(); + state.trackIncoming('c/darth/luke/l/latest'); + + state.notify({message_type: 'new_topic', topic_id: 1, payload: {category_id: 2, topic_id: 1}}); + state.notify({message_type: 'new_topic', topic_id: 2, payload: {category_id: 3, topic_id: 2}}); + state.notify({message_type: 'new_topic', topic_id: 3, payload: {category_id: 1, topic_id: 3}}); + + assert.equal(state.get("incomingCount"), 1, "expect to properly track incoming for subcategory"); +});