diff --git a/.eslintrc.json b/.eslintrc.json index e7e85ec763..163e308f7e 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -107,6 +107,7 @@ "admin_sections": false, "admin": false, "stream_data": false, + "topic_data": false, "list_util": false, "muting": false, "Dict": false, diff --git a/frontend_tests/node_tests/message_store.js b/frontend_tests/node_tests/message_store.js index 07097900ff..34260f32f6 100644 --- a/frontend_tests/node_tests/message_store.js +++ b/frontend_tests/node_tests/message_store.js @@ -1,7 +1,8 @@ add_dependencies({ people: 'js/people.js', - util: 'js/util.js', pm_conversations: 'js/pm_conversations.js', + topic_data: 'js/topic_data.js', + util: 'js/util.js', }); var noop = function () {}; @@ -15,8 +16,8 @@ set_global('alert_words', { process_message: noop, }); -set_global('stream_data' , { - process_message_for_recent_topics: noop, +set_global('topic_data' , { + process_message: noop, }); set_global('recent_senders', { diff --git a/frontend_tests/node_tests/search_suggestion.js b/frontend_tests/node_tests/search_suggestion.js index 0a027dde11..83eb717d34 100644 --- a/frontend_tests/node_tests/search_suggestion.js +++ b/frontend_tests/node_tests/search_suggestion.js @@ -12,6 +12,7 @@ add_dependencies({ typeahead_helper: 'js/typeahead_helper.js', people: 'js/people.js', stream_data: 'js/stream_data.js', + topic_data: 'js/topic_data.js', narrow_state: 'js/narrow_state.js', }); @@ -35,7 +36,7 @@ init(); set_global('narrow', {}); -global.stream_data.populate_stream_topics_for_tests({}); +topic_data.populate_for_tests({}); (function test_basic_get_suggestions() { var query = 'fred'; @@ -575,7 +576,7 @@ init(); }; var recent_data = {}; - global.stream_data.populate_stream_topics_for_tests(recent_data); + topic_data.populate_for_tests(recent_data); suggestions = search.get_suggestions('te'); expected = [ "te", @@ -592,7 +593,7 @@ init(); {name: 'test'}, ]; - global.stream_data.populate_stream_topics_for_tests(recent_data); + topic_data.populate_for_tests(recent_data); suggestions = search.get_suggestions('te'); expected = [ @@ -677,7 +678,7 @@ init(); return; }; - global.stream_data.populate_stream_topics_for_tests({}); + topic_data.populate_for_tests({}); var suggestions = search.get_suggestions(query); @@ -697,7 +698,7 @@ init(); return; }; - global.stream_data.populate_stream_topics_for_tests({}); + topic_data.populate_for_tests({}); var query = 'stream:of'; var suggestions = search.get_suggestions(query); @@ -749,7 +750,7 @@ init(); people.add(alice); - global.stream_data.populate_stream_topics_for_tests({ + topic_data.populate_for_tests({ office: [ {name: 'team'}, {name: 'ignore'}, @@ -881,7 +882,7 @@ init(); return; }; - global.stream_data.populate_stream_topics_for_tests({}); + topic_data.populate_for_tests({}); // test allowing spaces with quotes surrounding operand var query = 'stream:"dev he"'; diff --git a/frontend_tests/node_tests/stream_data.js b/frontend_tests/node_tests/stream_data.js index 937652cb13..ddbf382f15 100644 --- a/frontend_tests/node_tests/stream_data.js +++ b/frontend_tests/node_tests/stream_data.js @@ -13,12 +13,14 @@ add_dependencies({ narrow: 'js/narrow.js', hash_util: 'js/hash_util.js', hashchange: 'js/hashchange.js', + topic_data: 'js/topic_data.js', util: 'js/util.js', }); set_global('blueslip', {}); var stream_data = require('js/stream_data.js'); + var people = global.people; (function test_basics() { @@ -240,7 +242,7 @@ var people = global.people; assert(!ok); }()); -(function test_process_message_for_recent_topics() { +(function test_process_message() { var stream_id = 55; var rome = { @@ -255,9 +257,9 @@ var people = global.people; timestamp: 101, subject: 'toPic1', }; - stream_data.process_message_for_recent_topics(message); + topic_data.process_message(message); - var history = stream_data.get_recent_topic_names(rome.stream_id); + var history = topic_data.get_recent_names(rome.stream_id); assert.deepEqual(history, ['toPic1']); message = { @@ -265,8 +267,8 @@ var people = global.people; timestamp: 102, subject: 'Topic1', }; - stream_data.process_message_for_recent_topics(message); - history = stream_data.get_recent_topic_names(rome.stream_id); + topic_data.process_message(message); + history = topic_data.get_recent_names(rome.stream_id); assert.deepEqual(history, ['Topic1']); message = { @@ -274,12 +276,12 @@ var people = global.people; timestamp: 103, subject: 'topic2', }; - stream_data.process_message_for_recent_topics(message); - history = stream_data.get_recent_topic_names(rome.stream_id); + topic_data.process_message(message); + history = topic_data.get_recent_names(rome.stream_id); assert.deepEqual(history, ['topic2', 'Topic1']); - stream_data.process_message_for_recent_topics(message, true); - history = stream_data.get_recent_topic_names(rome.stream_id); + topic_data.process_message(message, true); + history = topic_data.get_recent_names(rome.stream_id); assert.deepEqual(history, ['Topic1']); }()); @@ -307,7 +309,7 @@ var people = global.people; timestamp: 108, subject: 'topic2', }; - stream_data.process_message_for_recent_topics(message); + topic_data.process_message(message); assert(stream_data.is_active(sub)); }()); diff --git a/frontend_tests/node_tests/stream_list.js b/frontend_tests/node_tests/stream_list.js index ce1940710b..ac9afcf3d2 100644 --- a/frontend_tests/node_tests/stream_list.js +++ b/frontend_tests/node_tests/stream_list.js @@ -10,6 +10,7 @@ add_dependencies({ stream_color: 'js/stream_color', stream_data: 'js/stream_data', stream_sort: 'js/stream_sort', + topic_data: 'js/topic_data', unread: 'js/unread', unread_ui: 'js/unread_ui', util: 'js/util', diff --git a/frontend_tests/node_tests/topic_generator.js b/frontend_tests/node_tests/topic_generator.js index 284c463c7a..13955ed9e4 100644 --- a/frontend_tests/node_tests/topic_generator.js +++ b/frontend_tests/node_tests/topic_generator.js @@ -2,6 +2,7 @@ add_dependencies({ muting: 'js/muting', stream_data: 'js/stream_data', stream_sort: 'js/stream_sort', + topic_data: 'js/topic_data', unread: 'js/unread', }); @@ -182,7 +183,7 @@ function is_odd(i) { return i % 2 === 1; } devel: devel_stream_id, }; - global.stream_data.get_recent_topic_names = function (stream_id) { + topic_data.get_recent_names = function (stream_id) { switch (stream_id) { case muted_stream_id: return ['red herring']; diff --git a/frontend_tests/node_tests/topic_list.js b/frontend_tests/node_tests/topic_list.js index d9bc58f89b..84ef81139c 100644 --- a/frontend_tests/node_tests/topic_list.js +++ b/frontend_tests/node_tests/topic_list.js @@ -5,6 +5,7 @@ add_dependencies({ muting: 'js/muting', narrow: 'js/narrow', stream_data: 'js/stream_data', + topic_data: 'js/topic_data', templates: 'js/templates', }); @@ -27,7 +28,7 @@ global.compile_template('topic_list_item'); recent_topics[stream_id] = [ {name: "coding"}, ]; - global.stream_data.populate_stream_topics_for_tests(recent_topics); + topic_data.populate_for_tests(recent_topics); global.unread.num_unread_for_subject = function () { return 1; }; diff --git a/static/js/echo.js b/static/js/echo.js index a04227b19e..b1267e2985 100644 --- a/static/js/echo.js +++ b/static/js/echo.js @@ -152,9 +152,9 @@ exports.try_deliver_locally = function try_deliver_locally(message_request) { exports.edit_locally = function edit_locally(message, raw_content, new_topic) { message.raw_content = raw_content; if (new_topic !== undefined) { - stream_data.process_message_for_recent_topics(message, true); + topic_data.process_message(message, true); message.subject = new_topic; - stream_data.process_message_for_recent_topics(message); + topic_data.process_message(message); } markdown.apply_markdown(message); diff --git a/static/js/message_events.js b/static/js/message_events.js index b8d8706769..7fbc099601 100644 --- a/static/js/message_events.js +++ b/static/js/message_events.js @@ -186,7 +186,7 @@ exports.update_messages = function update_messages(events) { // Remove the recent topics entry for the old topics; // must be called before we update msg.subject - stream_data.process_message_for_recent_topics(msg, true); + topic_data.process_message(msg, true); // Update the unread counts; again, this must be called // before we update msg.subject unread.update_unread_topics(msg, event); @@ -196,7 +196,7 @@ exports.update_messages = function update_messages(events) { message_store.set_topic_edit_properties(msg); // Add the recent topics entry for the new topics; must // be called after we update msg.subject - stream_data.process_message_for_recent_topics(msg); + topic_data.process_message(msg); }); } diff --git a/static/js/message_store.js b/static/js/message_store.js index 95478f7332..4951d0c788 100644 --- a/static/js/message_store.js +++ b/static/js/message_store.js @@ -150,7 +150,7 @@ exports.add_message_metadata = function (message) { composebox_typeahead.add_topic(message.stream, message.subject); message.reply_to = message.sender_email; - stream_data.process_message_for_recent_topics(message); + topic_data.process_message(message); exports.set_topic_edit_properties(message); recent_senders.process_message_for_senders(message); diff --git a/static/js/search_suggestion.js b/static/js/search_suggestion.js index 12225dbd39..7d4107d102 100644 --- a/static/js/search_suggestion.js +++ b/static/js/search_suggestion.js @@ -317,7 +317,7 @@ function get_topic_suggestions(last, operators) { return []; } - var topics = stream_data.get_recent_topic_names(stream_id); + var topics = topic_data.get_recent_names(stream_id); if (!topics || !topics.length) { return []; diff --git a/static/js/stream_data.js b/static/js/stream_data.js index efd568ff1c..c93cb9fb86 100644 --- a/static/js/stream_data.js +++ b/static/js/stream_data.js @@ -7,7 +7,6 @@ var exports = {}; // Call clear_subscriptions() to initialize it. var stream_info; var subs_by_stream_id; -var recent_topics = new Dict(); // stream_id -> array of objects var stream_ids_by_name = new Dict({fold_case: true}); @@ -21,7 +20,7 @@ exports.clear_subscriptions = function () { exports.clear_subscriptions(); exports.is_active = function (sub) { - return recent_topics.has(sub.stream_id) || sub.newly_subscribed; + return topic_data.stream_has_topics(sub.stream_id) || sub.newly_subscribed; }; exports.rename_sub = function (sub, new_name) { @@ -380,44 +379,6 @@ exports.receives_audible_notifications = function (stream_name) { return sub.audible_notifications; }; -exports.process_message_for_recent_topics = function process_message_for_recent_topics( - message, remove_message) { - var current_timestamp = 0; - var count = 0; - var stream_id = message.stream_id; - var canon_topic = message.subject.toLowerCase(); - - var recents = recent_topics.get(stream_id) || []; - - recents = _.filter(recents, function (item) { - var is_duplicate = ( - item.name.toLowerCase() === canon_topic); - if (is_duplicate) { - current_timestamp = item.timestamp; - count = item.count; - } - return !is_duplicate; - }); - - if (remove_message !== undefined) { - count = count - 1; - } else { - count = count + 1; - } - - if (count !== 0) { - recents.push({name: message.subject, - count: count, - timestamp: Math.max(message.timestamp, current_timestamp)}); - } - - recents.sort(function (a, b) { - return b.timestamp - a.timestamp; - }); - - recent_topics.set(stream_id, recents); -}; - exports.get_streams_for_settings_page = function () { // Build up our list of subscribed streams from the data we already have. var subscribed_rows = exports.subscribed_subs(); @@ -472,23 +433,6 @@ exports.initialize_from_page_params = function () { delete page_params.never_subscribed; }; -exports.get_recent_topic_names = function (stream_id) { - var topic_objs = recent_topics.get(stream_id); - - if (!topic_objs) { - return []; - } - - return _.map(topic_objs, function (obj) { - return obj.name; - }); -}; - -exports.populate_stream_topics_for_tests = function (stream_map) { - // This is only used by tests. - recent_topics = Dict.from(stream_map); -}; - exports.get_newbie_stream = function () { // This is the stream that we narrow folks to after the tutorial. diff --git a/static/js/topic_data.js b/static/js/topic_data.js new file mode 100644 index 0000000000..5b4e2286d7 --- /dev/null +++ b/static/js/topic_data.js @@ -0,0 +1,70 @@ +var topic_data = (function () { + +var exports = {}; + +var recent_topics = new Dict(); // stream_id -> array of objects + +exports.stream_has_topics = function (stream_id) { + return recent_topics.has(stream_id); +}; + +exports.process_message = function (message, remove_message) { + var current_timestamp = 0; + var count = 0; + var stream_id = message.stream_id; + var canon_topic = message.subject.toLowerCase(); + + var recents = recent_topics.get(stream_id) || []; + + recents = _.filter(recents, function (item) { + var is_duplicate = ( + item.name.toLowerCase() === canon_topic); + if (is_duplicate) { + current_timestamp = item.timestamp; + count = item.count; + } + return !is_duplicate; + }); + + if (remove_message !== undefined) { + count = count - 1; + } else { + count = count + 1; + } + + if (count !== 0) { + recents.push({name: message.subject, + count: count, + timestamp: Math.max(message.timestamp, current_timestamp)}); + } + + recents.sort(function (a, b) { + return b.timestamp - a.timestamp; + }); + + recent_topics.set(stream_id, recents); +}; + +exports.get_recent_names = function (stream_id) { + var topic_objs = recent_topics.get(stream_id); + + if (!topic_objs) { + return []; + } + + return _.map(topic_objs, function (obj) { + return obj.name; + }); +}; + +exports.populate_for_tests = function (stream_map) { + // This is only used by tests. + recent_topics = Dict.from(stream_map); +}; + +return exports; + +}()); +if (typeof module !== 'undefined') { + module.exports = topic_data; +} diff --git a/static/js/topic_generator.js b/static/js/topic_generator.js index e01748f0b4..fd099c3b66 100644 --- a/static/js/topic_generator.js +++ b/static/js/topic_generator.js @@ -164,7 +164,7 @@ exports.get_next_topic = function (curr_stream, curr_topic) { function get_unmuted_topics(stream_name) { var stream_id = stream_data.get_stream_id(stream_name); - var topics = stream_data.get_recent_topic_names(stream_id); + var topics = topic_data.get_recent_names(stream_id); topics = _.reject(topics, function (topic) { return muting.is_topic_muted(stream_name, topic); }); diff --git a/static/js/topic_list.js b/static/js/topic_list.js index 332c4240d8..d721e91794 100644 --- a/static/js/topic_list.js +++ b/static/js/topic_list.js @@ -52,7 +52,7 @@ exports.build_widget = function (parent_elem, my_stream_id, active_topic, max_to var my_stream_name = stream_data.get_sub_by_id(my_stream_id).name; function build_list(active_topic, max_topics) { - var topic_names = stream_data.get_recent_topic_names(my_stream_id); + var topic_names = topic_data.get_recent_names(my_stream_id); if (active_topic) { active_topic = active_topic.toLowerCase(); diff --git a/tools/test-js-with-node b/tools/test-js-with-node index 45a52406ec..546f058742 100755 --- a/tools/test-js-with-node +++ b/tools/test-js-with-node @@ -49,6 +49,7 @@ enforce_fully_covered = { 'static/js/search_suggestion.js', 'static/js/stream_events.js', 'static/js/stream_sort.js', + 'static/js/topic_data.js', 'static/js/topic_generator.js', 'static/js/typeahead_helper.js', 'static/js/typing_data.js', diff --git a/zproject/settings.py b/zproject/settings.py index 52ad6c2b9f..2e58cebb70 100644 --- a/zproject/settings.py +++ b/zproject/settings.py @@ -875,6 +875,7 @@ JS_SPECS = { 'js/compose.js', 'js/stream_color.js', 'js/stream_data.js', + 'js/topic_data.js', 'js/stream_muting.js', 'js/stream_events.js', 'js/stream_create.js',