diff --git a/web/e2e-tests/stream_create.test.ts b/web/e2e-tests/stream_create.test.ts index 7c2cc40108..41b3a6c76c 100644 --- a/web/e2e-tests/stream_create.test.ts +++ b/web/e2e-tests/stream_create.test.ts @@ -81,6 +81,13 @@ async function create_stream(page: Page): Promise { stream_description: "Everything Puppeteer", }); await page.click("form#stream_creation_form .finalize_create_stream"); + // an explanatory modal is shown for the first stream created + await common.wait_for_micromodal_to_open(page); + await page.click(".dialog_submit_button"); + await common.wait_for_micromodal_to_close(page); + await page.waitForSelector(".message-header-stream-settings-button"); + await page.click(".message-header-stream-settings-button"); + await page.waitForSelector(".stream_section"); await page.waitForSelector( `xpath///*[${common.has_class_x("stream-name")} and text()="Puppeteer"]`, ); diff --git a/web/src/stream_create.js b/web/src/stream_create.js index af8dfec580..b2b9d3f68e 100644 --- a/web/src/stream_create.js +++ b/web/src/stream_create.js @@ -9,6 +9,7 @@ import * as confirm_dialog from "./confirm_dialog"; import {$t, $t_html} from "./i18n"; import * as keydown_util from "./keydown_util"; import * as loading from "./loading"; +import * as onboarding_steps from "./onboarding_steps"; import * as people from "./people"; import * as settings_data from "./settings_data"; import {current_user, realm} from "./state_data"; @@ -33,6 +34,14 @@ export function get_name() { return created_stream; } +export function set_first_stream_created_modal_shown() { + onboarding_steps.post_onboarding_step_as_read("first_stream_created_banner"); +} + +export function should_show_first_stream_created_modal() { + return onboarding_steps.ONE_TIME_NOTICES_TO_DISPLAY.has("first_stream_created_banner"); +} + class StreamSubscriptionError { report_no_subs_to_stream() { $("#stream_subscription_error").text( diff --git a/web/src/stream_settings_ui.js b/web/src/stream_settings_ui.js index 507a2ed83b..0d1e12d7e2 100644 --- a/web/src/stream_settings_ui.js +++ b/web/src/stream_settings_ui.js @@ -1,9 +1,11 @@ import $ from "jquery"; import _ from "lodash"; +import render_inline_decorated_stream_name from "../templates/inline_decorated_stream_name.hbs"; import render_stream_creation_confirmation_banner from "../templates/modal_banner/stream_creation_confirmation_banner.hbs"; import render_browse_streams_list from "../templates/stream_settings/browse_streams_list.hbs"; import render_browse_streams_list_item from "../templates/stream_settings/browse_streams_list_item.hbs"; +import render_first_stream_created_modal from "../templates/stream_settings/first_stream_created_modal.hbs"; import render_stream_settings from "../templates/stream_settings/stream_settings.hbs"; import render_stream_settings_overlay from "../templates/stream_settings/stream_settings_overlay.hbs"; @@ -13,9 +15,10 @@ import * as components from "./components"; import * as compose_banner from "./compose_banner"; import * as compose_recipient from "./compose_recipient"; import * as compose_state from "./compose_state"; +import * as dialog_widget from "./dialog_widget"; import * as hash_parser from "./hash_parser"; import * as hash_util from "./hash_util"; -import {$t} from "./i18n"; +import {$t, $t_html} from "./i18n"; import * as keydown_util from "./keydown_util"; import * as message_lists from "./message_lists"; import * as message_live_update from "./message_live_update"; @@ -244,9 +247,33 @@ export function add_sub_to_table(sub) { render_stream_creation_confirmation_banner(context), ); stream_create.reset_created_stream(); + // goto topic `stream events` of the newly created stream + browser_history.go_to_location( + hash_util.by_stream_topic_url(sub.stream_id, "stream events"), + ); + if (stream_create.should_show_first_stream_created_modal()) { + stream_create.set_first_stream_created_modal_shown(); + show_first_stream_created_modal(sub); + } } update_empty_left_panel_message(); } +function show_first_stream_created_modal(stream) { + dialog_widget.launch({ + html_heading: $t_html( + {defaultMessage: "Stream created!"}, + { + "z-stream": () => render_inline_decorated_stream_name({stream}), + }, + ), + html_body: render_first_stream_created_modal({stream}), + id: "first_stream_created_modal", + on_click() {}, + html_submit_button: $t({defaultMessage: "Continue"}), + close_on_submit: true, + single_footer_button: true, + }); +} export function remove_stream(stream_id) { // It is possible that row is empty when we deactivate a diff --git a/web/templates/stream_settings/first_stream_created_modal.hbs b/web/templates/stream_settings/first_stream_created_modal.hbs new file mode 100644 index 0000000000..394eb4f5cc --- /dev/null +++ b/web/templates/stream_settings/first_stream_created_modal.hbs @@ -0,0 +1,14 @@ +{{t 'You will now see the stream you created. To go back to stream settings, you can:' }} + diff --git a/zerver/lib/hotspots.py b/zerver/lib/hotspots.py index ea2302a162..95882fce49 100644 --- a/zerver/lib/hotspots.py +++ b/zerver/lib/hotspots.py @@ -89,6 +89,9 @@ ONE_TIME_NOTICES: List[OneTimeNotice] = [ OneTimeNotice( name="intro_recent_view_modal", ), + OneTimeNotice( + name="first_stream_created_banner", + ), ] # We would most likely implement new hotspots in the future that aren't diff --git a/zerver/tests/test_hotspots.py b/zerver/tests/test_hotspots.py index accb02ada4..0da8ec6e37 100644 --- a/zerver/tests/test_hotspots.py +++ b/zerver/tests/test_hotspots.py @@ -39,11 +39,12 @@ class TestGetNextOnboardingSteps(ZulipTestCase): do_mark_onboarding_step_as_read(self.user, "intro_streams") do_mark_onboarding_step_as_read(self.user, "intro_compose") onboarding_steps = get_next_onboarding_steps(self.user) - self.assert_length(onboarding_steps, 4) + self.assert_length(onboarding_steps, 5) self.assertEqual(onboarding_steps[0]["name"], "visibility_policy_banner") self.assertEqual(onboarding_steps[1]["name"], "intro_inbox_view_modal") self.assertEqual(onboarding_steps[2]["name"], "intro_recent_view_modal") - self.assertEqual(onboarding_steps[3]["name"], "intro_topics") + self.assertEqual(onboarding_steps[3]["name"], "first_stream_created_banner") + self.assertEqual(onboarding_steps[4]["name"], "intro_topics") def test_all_onboarding_steps_done(self) -> None: with self.settings(TUTORIAL_ENABLED=True):