diff --git a/frontend_tests/node_tests/narrow.js b/frontend_tests/node_tests/narrow.js index 530322c2ad..224d8e5824 100644 --- a/frontend_tests/node_tests/narrow.js +++ b/frontend_tests/node_tests/narrow.js @@ -16,6 +16,15 @@ const stream_data = zrequire("stream_data"); const {Filter} = zrequire("../js/filter"); const narrow = zrequire("narrow"); +function empty_narrow_html(title, html, search_data) { + const opts = { + title, + html, + search_data, + }; + return require("../../static/templates/empty_feed_notice.hbs")(opts); +} + function set_filter(operators) { operators = operators.map((op) => ({ operator: op[0], @@ -67,6 +76,95 @@ function hide_all_empty_narrow_messages() { } } +run_test("empty_narrow_html", ({mock_template}) => { + mock_template("empty_feed_notice.hbs", true, (data, html) => html); + + let actual_html = empty_narrow_html("This is a title", "

This is the html

"); + assert.equal( + actual_html, + `
+

This is a title

+

This is the html

+
+`, + ); + + const search_data_with_all_search_types = { + topic_query: "test", + stream_query: "new", + has_stop_word: true, + query_words: [ + {query_word: "search", is_stop_word: false}, + {query_word: "a", is_stop_word: true}, + ], + }; + actual_html = empty_narrow_html( + "This is a title", + undefined, + search_data_with_all_search_types, + ); + assert.equal( + actual_html, + `
+

This is a title

+
+ Some common words were excluded from your search.
You searched for: + stream: new + topic: test + search + a +
+
+`, + ); + + const search_data_with_stream_without_stop_words = { + has_stop_word: false, + stream_query: "hello world", + query_words: [{query_word: "searchA", is_stop_word: false}], + }; + actual_html = empty_narrow_html( + "This is a title", + undefined, + search_data_with_stream_without_stop_words, + ); + assert.equal( + actual_html, + `
+

This is a title

+
+ You searched for: + stream: hello world + searchA +
+
+`, + ); + + const search_data_with_topic_without_stop_words = { + has_stop_word: false, + topic_query: "hello", + query_words: [{query_word: "searchB", is_stop_word: false}], + }; + actual_html = empty_narrow_html( + "This is a title", + undefined, + search_data_with_topic_without_stop_words, + ); + assert.equal( + actual_html, + `
+

This is a title

+
+ You searched for: + topic: hello + searchB +
+
+`, + ); +}); + run_test("uris", () => { people.add_active_user(ray); people.add_active_user(alice); @@ -92,111 +190,171 @@ run_test("uris", () => { assert.equal(emails, "me@example.com"); }); -run_test("show_empty_narrow_message", () => { +run_test("show_empty_narrow_message", ({mock_template}) => { page_params.stop_words = []; + mock_template("empty_feed_notice.hbs", true, (data, html) => html); + narrow_state.reset_current_filter(); hide_all_empty_narrow_messages(); narrow_banner.show_empty_narrow_message(); - assert.equal($(".empty_feed_notice").visible(), false); - assert.ok($("#empty_narrow_message").visible()); + assert.equal( + $(".empty_feed_notice_main").html(), + empty_narrow_html( + "translated: Nothing's been sent here yet!", + 'translated HTML: Why not start the conversation?', + ), + ); // for non-existent or private stream set_filter([["stream", "Foo"]]); hide_all_empty_narrow_messages(); narrow_banner.show_empty_narrow_message(); - assert.ok($("#nonsubbed_private_nonexistent_stream_narrow_message").visible()); + assert.equal( + $(".empty_feed_notice_main").html(), + empty_narrow_html("translated: This stream does not exist or is private."), + ); // for non sub public stream stream_data.add_sub({name: "ROME", stream_id: 99}); set_filter([["stream", "Rome"]]); hide_all_empty_narrow_messages(); narrow_banner.show_empty_narrow_message(); - assert.ok($("#nonsubbed_stream_narrow_message").visible()); + assert.equal( + $(".empty_feed_notice_main").html(), + empty_narrow_html( + "translated: You aren't subscribed to this stream and nobody has talked about that yet!", + 'translated HTML: ', + ), + ); set_filter([["is", "starred"]]); hide_all_empty_narrow_messages(); narrow_banner.show_empty_narrow_message(); - assert.ok($("#empty_star_narrow_message").visible()); + assert.equal( + $(".empty_feed_notice_main").html(), + empty_narrow_html( + "translated: You haven't starred anything yet!", + 'translated HTML: Learn more about starring messages here.', + ), + ); set_filter([["is", "mentioned"]]); hide_all_empty_narrow_messages(); narrow_banner.show_empty_narrow_message(); - assert.ok($("#empty_narrow_all_mentioned").visible()); + assert.equal( + $(".empty_feed_notice_main").html(), + empty_narrow_html( + "translated: You haven't been mentioned yet!", + 'translated HTML: Learn more about mentions here.', + ), + ); set_filter([["is", "private"]]); hide_all_empty_narrow_messages(); narrow_banner.show_empty_narrow_message(); - assert.ok($("#empty_narrow_all_private_message").visible()); + assert.equal( + $(".empty_feed_notice_main").html(), + empty_narrow_html( + "translated: You have no private messages yet!", + 'translated HTML: Why not start the conversation?', + ), + ); set_filter([["is", "unread"]]); hide_all_empty_narrow_messages(); narrow_banner.show_empty_narrow_message(); - assert.ok($("#no_unread_narrow_message").visible()); + assert.equal( + $(".empty_feed_notice_main").html(), + empty_narrow_html("translated: You have no unread messages!"), + ); set_filter([["is", "resolved"]]); hide_all_empty_narrow_messages(); narrow_banner.show_empty_narrow_message(); - assert.ok($("#empty_narrow_resolved_topics").visible()); + assert.equal( + $(".empty_feed_notice_main").html(), + empty_narrow_html("translated: No topics are marked as resolved."), + ); set_filter([["pm-with", ["Yo"]]]); hide_all_empty_narrow_messages(); narrow_banner.show_empty_narrow_message(); - assert.ok($("#non_existing_user").visible()); + assert.equal( + $(".empty_feed_notice_main").html(), + empty_narrow_html("translated: This user does not exist!"), + ); people.add_active_user(alice); set_filter([["pm-with", ["alice@example.com", "Yo"]]]); hide_all_empty_narrow_messages(); narrow_banner.show_empty_narrow_message(); - assert.ok($("#non_existing_users").visible()); + assert.equal( + $(".empty_feed_notice_main").html(), + empty_narrow_html("translated: One or more of these users do not exist!"), + ); set_filter([["pm-with", "alice@example.com"]]); hide_all_empty_narrow_messages(); narrow_banner.show_empty_narrow_message(); - assert.ok($("#empty_narrow_private_message").visible()); + assert.equal( + $(".empty_feed_notice_main").html(), + empty_narrow_html( + "translated: You have no private messages with this person yet!", + 'translated HTML: Why not start the conversation?', + ), + ); people.add_active_user(me); people.initialize_current_user(me.user_id); set_filter([["pm-with", me.email]]); hide_all_empty_narrow_messages(); narrow_banner.show_empty_narrow_message(); - assert.ok($("#empty_narrow_self_private_message").visible()); + assert.equal( + $(".empty_feed_notice_main").html(), + empty_narrow_html( + "translated: You have not sent any private messages to yourself yet!", + 'translated HTML: Why not start a conversation with yourself?', + ), + ); set_filter([["pm-with", me.email + "," + alice.email]]); hide_all_empty_narrow_messages(); narrow_banner.show_empty_narrow_message(); - assert.ok($("#empty_narrow_multi_private_message").visible()); + assert.equal( + $(".empty_feed_notice_main").html(), + empty_narrow_html( + "translated: You have no private messages with these people yet!", + 'translated HTML: Why not start the conversation?', + ), + ); set_filter([["group-pm-with", "alice@example.com"]]); hide_all_empty_narrow_messages(); narrow_banner.show_empty_narrow_message(); - assert.ok($("#empty_narrow_group_private_message").visible()); + assert.equal( + $(".empty_feed_notice_main").html(), + empty_narrow_html( + "translated: You have no group private messages with this person yet!", + 'translated HTML: Why not start the conversation?', + ), + ); set_filter([["sender", "ray@example.com"]]); hide_all_empty_narrow_messages(); narrow_banner.show_empty_narrow_message(); - assert.ok($("#silent_user").visible()); + assert.equal( + $(".empty_feed_notice_main").html(), + empty_narrow_html("translated: You haven't received any messages sent by this user yet!"), + ); set_filter([["sender", "sinwar@example.com"]]); hide_all_empty_narrow_messages(); narrow_banner.show_empty_narrow_message(); - assert.ok($("#non_existing_user").visible()); - - const display = $("#empty_search_stop_words_string"); - - const items = []; - display.append = (html) => { - items.push(html); - }; - - set_filter([["search", "grail"]]); - hide_all_empty_narrow_messages(); - narrow_banner.show_empty_narrow_message(); - assert.ok($("#empty_search_narrow_message").visible()); - - assert.equal(items.length, 2); - assert.equal(items[0], " "); - assert.equal(items[1].text(), "grail"); + assert.equal( + $(".empty_feed_notice_main").html(), + empty_narrow_html("translated: This user does not exist!"), + ); set_filter([ ["sender", "alice@example.com"], @@ -204,12 +362,24 @@ run_test("show_empty_narrow_message", () => { ]); hide_all_empty_narrow_messages(); narrow_banner.show_empty_narrow_message(); - assert.ok($("#empty_narrow_message").visible()); + assert.equal( + $(".empty_feed_notice_main").html(), + empty_narrow_html( + "translated: Nothing's been sent here yet!", + 'translated HTML: Why not start the conversation?', + ), + ); set_filter([["is", "invalid"]]); hide_all_empty_narrow_messages(); narrow_banner.show_empty_narrow_message(); - assert.ok($("#empty_narrow_message").visible()); + assert.equal( + $(".empty_feed_notice_main").html(), + empty_narrow_html( + "translated: Nothing's been sent here yet!", + 'translated HTML: Why not start the conversation?', + ), + ); const my_stream = { name: "my stream", @@ -221,60 +391,93 @@ run_test("show_empty_narrow_message", () => { set_filter([["stream", "my stream"]]); hide_all_empty_narrow_messages(); narrow_banner.show_empty_narrow_message(); - assert.ok($("#empty_narrow_message").visible()); + assert.equal( + $(".empty_feed_notice_main").html(), + empty_narrow_html( + "translated: Nothing's been sent here yet!", + 'translated HTML: Why not start the conversation?', + ), + ); set_filter([["stream", ""]]); hide_all_empty_narrow_messages(); narrow_banner.show_empty_narrow_message(); - assert.ok($("#nonsubbed_private_nonexistent_stream_narrow_message").visible()); + assert.equal( + $(".empty_feed_notice_main").html(), + empty_narrow_html("translated: This stream does not exist or is private."), + ); +}); + +run_test("show_empty_narrow_message_with_search", ({mock_template}) => { + page_params.stop_words = []; + + mock_template("empty_feed_notice.hbs", true, (data, html) => html); + + narrow_state.reset_current_filter(); + set_filter([["search", "grail"]]); + hide_all_empty_narrow_messages(); + narrow_banner.show_empty_narrow_message(); + assert.match($(".empty_feed_notice_main").html(), /grail<\/span>/); }); run_test("hide_empty_narrow_message", () => { - $(".empty_feed_notice").show(); + $(".empty_feed_notice_main").html("
Nothing here
"); narrow_banner.hide_empty_narrow_message(); - assert.ok(!$(".empty_feed_notice").visible()); + assert.equal($(".empty_feed_notice").text(), "never-been-set"); }); -run_test("show_search_stopwords", () => { +run_test("show_search_stopwords", ({mock_template}) => { page_params.stop_words = ["what", "about"]; - narrow_state.reset_current_filter(); - let items = []; + mock_template("empty_feed_notice.hbs", true, (data, html) => html); - const display = $("#empty_search_stop_words_string"); - - display.append = (html) => { - if (html.text) { - items.push(html.selector + html.text()); - } + const expected_search_data = { + has_stop_word: true, + query_words: [ + {query_word: "what", is_stop_word: true}, + {query_word: "about", is_stop_word: true}, + {query_word: "grail", is_stop_word: false}, + ], }; - + narrow_state.reset_current_filter(); set_filter([["search", "what about grail"]]); hide_all_empty_narrow_messages(); narrow_banner.show_empty_narrow_message(); - assert.ok($("#empty_search_narrow_message").visible()); + assert.equal( + $(".empty_feed_notice_main").html(), + empty_narrow_html("translated: No search results", undefined, expected_search_data), + ); - assert.equal(items.length, 3); - assert.equal(items[0], "what"); - assert.equal(items[1], "about"); - assert.equal(items[2], "grail"); - - items = []; + const expected_stream_search_data = { + has_stop_word: true, + stream_query: "streamA", + query_words: [ + {query_word: "what", is_stop_word: true}, + {query_word: "about", is_stop_word: true}, + {query_word: "grail", is_stop_word: false}, + ], + }; set_filter([ ["stream", "streamA"], ["search", "what about grail"], ]); hide_all_empty_narrow_messages(); narrow_banner.show_empty_narrow_message(); - assert.ok($("#empty_search_narrow_message").visible()); + assert.equal( + $(".empty_feed_notice_main").html(), + empty_narrow_html("translated: No search results", undefined, expected_stream_search_data), + ); - assert.equal(items.length, 4); - assert.equal(items[0], "stream: streamA"); - assert.equal(items[1], "what"); - assert.equal(items[2], "about"); - assert.equal(items[3], "grail"); - - items = []; + const expected_stream_topic_search_data = { + has_stop_word: true, + stream_query: "streamA", + topic_query: "topicA", + query_words: [ + {query_word: "what", is_stop_word: true}, + {query_word: "about", is_stop_word: true}, + {query_word: "grail", is_stop_word: false}, + ], + }; set_filter([ ["stream", "streamA"], ["topic", "topicA"], @@ -282,18 +485,19 @@ run_test("show_search_stopwords", () => { ]); hide_all_empty_narrow_messages(); narrow_banner.show_empty_narrow_message(); - assert.ok($("#empty_search_narrow_message").visible()); - - assert.equal(items.length, 4); - assert.equal(items[0], "stream: streamA topic: topicA"); - assert.equal(items[1], "what"); - assert.equal(items[2], "about"); - assert.equal(items[3], "grail"); + assert.equal( + $(".empty_feed_notice_main").html(), + empty_narrow_html( + "translated: No search results", + undefined, + expected_stream_topic_search_data, + ), + ); }); -run_test("show_invalid_narrow_message", () => { +run_test("show_invalid_narrow_message", ({mock_template}) => { narrow_state.reset_current_filter(); - const display = $("#empty_search_stop_words_string"); + mock_template("empty_feed_notice.hbs", true, (data, html) => html); stream_data.add_sub({name: "streamA", stream_id: 88}); stream_data.add_sub({name: "streamB", stream_id: 77}); @@ -304,10 +508,12 @@ run_test("show_invalid_narrow_message", () => { ]); hide_all_empty_narrow_messages(); narrow_banner.show_empty_narrow_message(); - assert.ok($("#empty_search_narrow_message").visible()); assert.equal( - display.text(), - "translated: You are searching for messages that belong to more than one stream, which is not possible.", + $(".empty_feed_notice_main").html(), + empty_narrow_html( + "translated: No search results", + "translated HTML:

You are searching for messages that belong to more than one stream, which is not possible.

", + ), ); set_filter([ @@ -316,10 +522,12 @@ run_test("show_invalid_narrow_message", () => { ]); hide_all_empty_narrow_messages(); narrow_banner.show_empty_narrow_message(); - assert.ok($("#empty_search_narrow_message").visible()); assert.equal( - display.text(), - "translated: You are searching for messages that belong to more than one topic, which is not possible.", + $(".empty_feed_notice_main").html(), + empty_narrow_html( + "translated: No search results", + "translated HTML:

You are searching for messages that belong to more than one topic, which is not possible.

", + ), ); people.add_active_user(ray); @@ -331,10 +539,12 @@ run_test("show_invalid_narrow_message", () => { ]); hide_all_empty_narrow_messages(); narrow_banner.show_empty_narrow_message(); - assert.ok($("#empty_search_narrow_message").visible()); assert.equal( - display.text(), - "translated: You are searching for messages that are sent by more than one person, which is not possible.", + $(".empty_feed_notice_main").html(), + empty_narrow_html( + "translated: No search results", + "translated HTML:

You are searching for messages that are sent by more than one person, which is not possible.

", + ), ); }); diff --git a/frontend_tests/puppeteer_tests/message-basics.ts b/frontend_tests/puppeteer_tests/message-basics.ts index db5d8cf176..875fa7e447 100644 --- a/frontend_tests/puppeteer_tests/message-basics.ts +++ b/frontend_tests/puppeteer_tests/message-basics.ts @@ -154,26 +154,29 @@ async function search_silent_user(page: Page, str: string, item: string): Promis await page.click(".search_icon"); await page.waitForSelector("#search_query", {visible: true}); await common.select_item_via_typeahead(page, "#search_query", str, item); - await page.waitForSelector("#silent_user", {visible: true}); + await page.waitForSelector(".empty_feed_notice", {visible: true}); const expect_message = "You haven't received any messages sent by this user yet!"; - assert.strictEqual(await common.get_text_from_selector(page, "#silent_user"), expect_message); + assert.strictEqual( + await common.get_text_from_selector(page, ".empty_feed_notice"), + expect_message, + ); await un_narrow(page); } async function expect_non_existing_user(page: Page): Promise { - await page.waitForSelector("#non_existing_user", {visible: true}); + await page.waitForSelector(".empty_feed_notice", {visible: true}); const expected_message = "This user does not exist!"; assert.strictEqual( - await common.get_text_from_selector(page, "#non_existing_user"), + await common.get_text_from_selector(page, ".empty_feed_notice"), expected_message, ); } async function expect_non_existing_users(page: Page): Promise { - await page.waitForSelector("#non_existing_users", {visible: true}); + await page.waitForSelector(".empty_feed_notice", {visible: true}); const expected_message = "One or more of these users do not exist!"; assert.strictEqual( - await common.get_text_from_selector(page, "#non_existing_users"), + await common.get_text_from_selector(page, ".empty_feed_notice"), expected_message, ); } diff --git a/static/js/narrow_banner.js b/static/js/narrow_banner.js index a41978118b..5742506a33 100644 --- a/static/js/narrow_banner.js +++ b/static/js/narrow_banner.js @@ -1,67 +1,68 @@ import $ from "jquery"; -import _ from "lodash"; -import {$t} from "./i18n"; +import {$t, $t_html} from "./i18n"; +import {narrow_error} from "./narrow_error"; import * as narrow_state from "./narrow_state"; import {page_params} from "./page_params"; import * as people from "./people"; import * as stream_data from "./stream_data"; -function set_invalid_narrow_message(invalid_narrow_message) { - const search_string_display = $("#empty_search_stop_words_string"); - search_string_display.text(invalid_narrow_message); -} - -function show_search_query() { - // when search bar contains multiple filters, only show search queries +function retrieve_search_query_data() { + // when search bar contains multiple filters, only retrieve search queries const current_filter = narrow_state.filter(); const search_query = current_filter.operands("search")[0]; const query_words = search_query.split(" "); - const search_string_display = $("#empty_search_stop_words_string"); - let query_contains_stop_words = false; - - // Also removes previous search_string if any - search_string_display.text($t({defaultMessage: "You searched for:"})); + const search_string_result = { + query_words: [], + has_stop_word: false, + }; // Add in stream:foo and topic:bar if present if (current_filter.has_operator("stream") || current_filter.has_operator("topic")) { - let stream_topic_string = ""; const stream = current_filter.operands("stream")[0]; const topic = current_filter.operands("topic")[0]; if (stream) { - stream_topic_string = "stream: " + stream; + search_string_result.stream_query = stream; } if (topic) { - stream_topic_string = stream_topic_string + " topic: " + topic; + search_string_result.topic_query = topic; } - - search_string_display.append(" "); - search_string_display.append($("").text(stream_topic_string)); } + // Gather information about each query word for (const query_word of query_words) { - search_string_display.append(" "); - - // if query contains stop words, it is enclosed by a tag if (page_params.stop_words.includes(query_word)) { - // stop_words do not need sanitization so this is unnecessary but it is fail-safe. - search_string_display.append($("").text(query_word)); - query_contains_stop_words = true; + search_string_result.has_stop_word = true; + search_string_result.query_words.push({ + query_word, + is_stop_word: true, + }); } else { - // We use .text("...") to sanitize the user-given query_string. - search_string_display.append($("").text(query_word)); + search_string_result.query_words.push({ + query_word, + is_stop_word: false, + }); } } - if (query_contains_stop_words) { - const preamble = $t({defaultMessage: "Some common words were excluded from your search."}); - search_string_display.html(_.escape(preamble) + "
" + search_string_display.html()); - } + return search_string_result; } function pick_empty_narrow_banner() { - const default_banner = $("#empty_narrow_message"); + const default_banner = { + title: $t({defaultMessage: "Nothing's been sent here yet!"}), + html: $t_html( + { + defaultMessage: "Why not start the conversation?", + }, + { + "z-link": (content_html) => + `${content_html}`, + }, + ), + }; + const empty_search_narrow_title = $t({defaultMessage: "No search results"}); const current_filter = narrow_state.filter(); @@ -78,57 +79,105 @@ function pick_empty_narrow_banner() { // For invalid-multi-operator narrows, we display an invalid narrow message const streams = current_filter.operands("stream"); - let invalid_narrow_message = ""; // No message can have multiple streams if (streams.length > 1) { - invalid_narrow_message = $t({ - defaultMessage: - "You are searching for messages that belong to more than one stream, which is not possible.", - }); + return { + title: empty_search_narrow_title, + html: $t_html({ + defaultMessage: + "

You are searching for messages that belong to more than one stream, which is not possible.

", + }), + }; } // No message can have multiple topics if (current_filter.operands("topic").length > 1) { - invalid_narrow_message = $t({ - defaultMessage: - "You are searching for messages that belong to more than one topic, which is not possible.", - }); + return { + title: empty_search_narrow_title, + html: $t_html({ + defaultMessage: + "

You are searching for messages that belong to more than one topic, which is not possible.

", + }), + }; } // No message can have multiple senders if (current_filter.operands("sender").length > 1) { - invalid_narrow_message = $t({ - defaultMessage: - "You are searching for messages that are sent by more than one person, which is not possible.", - }); - } - if (invalid_narrow_message !== "") { - set_invalid_narrow_message(invalid_narrow_message); - return $("#empty_search_narrow_message"); + return { + title: empty_search_narrow_title, + html: $t_html({ + defaultMessage: + "

You are searching for messages that are sent by more than one person, which is not possible.

", + }), + }; } // For empty stream searches within other narrows, we display the stop words if (current_filter.operands("search").length > 0) { - show_search_query(); - return $("#empty_search_narrow_message"); + return { + title: empty_search_narrow_title, + search_data: retrieve_search_query_data(), + }; } + // For other multi-operator narrows, we just use the default banner return default_banner; } + switch (first_operator) { case "is": switch (first_operand) { case "starred": // You have no starred messages. - return $("#empty_star_narrow_message"); + return { + title: $t({defaultMessage: "You haven't starred anything yet!"}), + html: $t_html( + { + defaultMessage: + "Learn more about starring messages here.", + }, + { + "z-link": (content_html) => + `${content_html}`, + }, + ), + }; case "mentioned": - return $("#empty_narrow_all_mentioned"); + return { + title: $t({defaultMessage: "You haven't been mentioned yet!"}), + html: $t_html( + { + defaultMessage: "Learn more about mentions here.", + }, + { + "z-link": (content_html) => + `${content_html}`, + }, + ), + }; case "private": // You have no private messages. - return $("#empty_narrow_all_private_message"); + return { + title: $t({defaultMessage: "You have no private messages yet!"}), + html: $t_html( + { + defaultMessage: "Why not start the conversation?", + }, + { + // TODO: The href here is a bit weird; we probably want to migrate + // this to a button element down the line. + "z-link": (content_html) => + `${content_html}`, + }, + ), + }; case "unread": // You have no unread messages. - return $("#no_unread_narrow_message"); + return { + title: $t({defaultMessage: "You have no unread messages!"}), + }; case "resolved": - return $("#empty_narrow_resolved_topics"); + return { + title: $t({defaultMessage: "No topics are marked as resolved."}), + }; } // fallthrough to default case if no match is found break; @@ -149,48 +198,131 @@ function pick_empty_narrow_banner() { } if (can_toggle_narrowed_stream()) { - return $("#nonsubbed_stream_narrow_message"); + return { + title: $t({ + defaultMessage: + "You aren't subscribed to this stream and nobody has talked about that yet!", + }), + // TODO: Consider moving the button to be its own option in the template. + html: $t_html( + { + defaultMessage: "Subscribe", + }, + { + "z-button": (content_html) => + ``, + }, + ), + }; } - return $("#nonsubbed_private_nonexistent_stream_narrow_message"); + return { + title: $t({defaultMessage: "This stream does not exist or is private."}), + }; } // else fallthrough to default case break; - case "search": + case "search": { // You are narrowed to empty search results. - show_search_query(); - return $("#empty_search_narrow_message"); + return { + title: empty_search_narrow_title, + search_data: retrieve_search_query_data(), + }; + } case "pm-with": if (!people.is_valid_bulk_emails_for_compose(first_operand.split(","))) { if (!first_operand.includes(",")) { - return $("#non_existing_user"); + return { + title: $t({defaultMessage: "This user does not exist!"}), + }; } - return $("#non_existing_users"); + return { + title: $t({defaultMessage: "One or more of these users do not exist!"}), + }; } if (!first_operand.includes(",")) { // You have no private messages with this person if (people.is_current_user(first_operand)) { - return $("#empty_narrow_self_private_message"); + return { + title: $t({ + defaultMessage: + "You have not sent any private messages to yourself yet!", + }), + html: $t_html( + { + defaultMessage: + "Why not start a conversation with yourself?", + }, + { + "z-link": (content_html) => + `${content_html}`, + }, + ), + }; } - return $("#empty_narrow_private_message"); + return { + title: $t({ + defaultMessage: "You have no private messages with this person yet!", + }), + html: $t_html( + { + defaultMessage: "Why not start the conversation?", + }, + { + "z-link": (content_html) => + `${content_html}`, + }, + ), + }; } - return $("#empty_narrow_multi_private_message"); + return { + title: $t({defaultMessage: "You have no private messages with these people yet!"}), + html: $t_html( + { + defaultMessage: "Why not start the conversation?", + }, + { + "z-link": (content_html) => + `${content_html}`, + }, + ), + }; case "sender": if (people.get_by_email(first_operand)) { - return $("#silent_user"); + return { + title: $t({ + defaultMessage: "You haven't received any messages sent by this user yet!", + }), + }; } - return $("#non_existing_user"); + return { + title: $t({defaultMessage: "This user does not exist!"}), + }; case "group-pm-with": - return $("#empty_narrow_group_private_message"); + return { + title: $t({ + defaultMessage: "You have no group private messages with this person yet!", + }), + html: $t_html( + { + defaultMessage: "Why not start the conversation?", + }, + { + "z-link": (content_html) => + `${content_html}`, + }, + ), + }; } return default_banner; } export function show_empty_narrow_message() { - $(".empty_feed_notice").hide(); - pick_empty_narrow_banner().show(); + $(".empty_feed_notice_main").empty(); + const rendered_narrow_banner = narrow_error(pick_empty_narrow_banner()); + $(".empty_feed_notice_main").html(rendered_narrow_banner); } export function hide_empty_narrow_message() { - $(".empty_feed_notice").hide(); + $(".empty_feed_notice_main").empty(); } diff --git a/static/js/narrow_error.js b/static/js/narrow_error.js new file mode 100644 index 0000000000..45d715827a --- /dev/null +++ b/static/js/narrow_error.js @@ -0,0 +1,10 @@ +import render_empty_feed_notice from "../templates/empty_feed_notice.hbs"; + +export function narrow_error(narrow_banner_data) { + const title = narrow_banner_data.title; + const html = narrow_banner_data.html; + const search_data = narrow_banner_data.search_data; + + const $empty_feed_notice = render_empty_feed_notice({title, html, search_data}); + return $empty_feed_notice; +} diff --git a/static/styles/zulip.css b/static/styles/zulip.css index a65331b564..817b9580d2 100644 --- a/static/styles/zulip.css +++ b/static/styles/zulip.css @@ -2439,7 +2439,6 @@ div.topic_edit_spinner .loading_indicator_spinner { .empty_feed_notice { padding: 3em 1em; - display: none; text-align: center; } diff --git a/static/templates/empty_feed_notice.hbs b/static/templates/empty_feed_notice.hbs new file mode 100644 index 0000000000..ab32dcd087 --- /dev/null +++ b/static/templates/empty_feed_notice.hbs @@ -0,0 +1,23 @@ +
+

{{ title }}

+ {{#if (or search_data.query_words search.topic_query search_data.stream_query)}} +
+ {{#if search_data.has_stop_word}}{{#tr}}Some common words were excluded from your search.{{/tr}}
{{/if}}{{#tr}}You searched for:{{/tr}} + {{#if search_data.stream_query}} + stream: {{search_data.stream_query}} + {{/if}} + {{#if search_data.topic_query}} + topic: {{search_data.topic_query}} + {{/if}} + {{#each search_data.query_words}} + {{#if is_stop_word}} + {{query_word}} + {{else}} + {{query_word}} + {{/if}} + {{/each}} +
+ {{else}} + {{{ html }}} + {{/if}} +
diff --git a/templates/zerver/app/message_feed_errors.html b/templates/zerver/app/message_feed_errors.html index 9c2f076de5..129a41f4e0 100644 --- a/templates/zerver/app/message_feed_errors.html +++ b/templates/zerver/app/message_feed_errors.html @@ -19,113 +19,4 @@ {% endtrans %}

-
-

{{ _("Nothing's been sent here yet!") }}

- -

- {% trans %} - Why not - start the conversation? - {% endtrans %} -

-
-
-

{{ _('You have no private messages yet!') }}

- -

- {% trans %} - Why not - start the conversation? - {% endtrans %} -

-
-
-

{{ _('You have no private messages with this person yet!') }}

- -

- {% trans %} - Why not - start the conversation? - {% endtrans %} -

-
-
-

{{ _('You have not sent any private messages to yourself yet!') }}

- -

- {% trans %} - Why not - start a conversation with yourself? - {% endtrans %} -

-
-
-

{{ _('You have no group private messages with this person yet!') }}

- -

- {% trans %} - Why not - start the conversation? - {% endtrans %} -

-
-
-

{{ _('You have no private messages with these people yet!') }}

- -

- {% trans %} - Why not - start the conversation? - {% endtrans %} -

-
-
-

{{ _("You haven't received any messages sent by this user yet!") }}

-
-
-

{{ _("This user does not exist!") }}

-
-
-

{{ _("One or more of these users do not exist!") }}

-
-
-

{{ _("You aren't subscribed to this stream and nobody has talked about that yet!") }}

-
- -
-
-
-

{{ _("This stream does not exist or is private.") }}

-
-
-

{{ _("You haven't starred anything yet!") }}

- -

- {% trans %} - Learn more about starring messages - here. - {% endtrans %} -

-
-
-

{{ _("You have no unread messages!") }}

-
-
-

{{ _("You haven't been mentioned yet!") }}

- -

- {% trans %} - Learn more about mentions - here. - {% endtrans %} -

-
-
-

{{ _('No search results') }}

-

-
-
-

{{ _("No topics are marked as resolved.") }}

-
+
diff --git a/zerver/tests/test_home.py b/zerver/tests/test_home.py index c0e783424f..c6bac88235 100644 --- a/zerver/tests/test_home.py +++ b/zerver/tests/test_home.py @@ -219,7 +219,7 @@ class HomeTest(ZulipTestCase): def test_home(self) -> None: # Keep this list sorted!!! html_bits = [ - "start the conversation", + "empty_feed_notice_main", "Loading...", # Verify that the app styles get included "app-stubentry.js", @@ -446,7 +446,7 @@ class HomeTest(ZulipTestCase): which still want the home page to load properly. """ html = result.content.decode() - if "start a conversation" not in html: + if "empty_feed_notice_main" not in html: raise AssertionError("Home page probably did not load.") def test_terms_of_service(self) -> None: