home: Add a modal to replace /try-zulip landing page.

This commit adds a modal which will be displayed when
a spectator visits `/?show_try_zulip_modal`.

When a user visits `/?show_try_zulip_modal` and is a spectator,
we set a new `show_try_zulip_modal` field in `page_params` to
`true` (in all other cases, it's `false`).

Based on the `show_try_zulip_modal` page param, the web client
shows the modal.

Fixes part of #34181.
This commit is contained in:
Prakhar Pratyush
2025-03-31 18:20:36 +05:30
committed by Tim Abbott
parent a7d3d61b41
commit f64d7b6e28
5 changed files with 67 additions and 0 deletions

View File

@@ -43,6 +43,7 @@ const home_params_schema = default_params_schema
// it isn't displayed for logged-in users and requires markdown // it isn't displayed for logged-in users and requires markdown
// processor time to compute. // processor time to compute.
realm_rendered_description: z.optional(z.string()), realm_rendered_description: z.optional(z.string()),
show_try_zulip_modal: z.boolean(),
show_webathena: z.boolean(), show_webathena: z.boolean(),
state_data: state_data_schema.nullable(), state_data: state_data_schema.nullable(),
translation_data: z.record(z.string()), translation_data: z.record(z.string()),

View File

@@ -8,6 +8,7 @@ import render_compose from "../templates/compose.hbs";
import render_message_feed_bottom_whitespace from "../templates/message_feed_bottom_whitespace.hbs"; import render_message_feed_bottom_whitespace from "../templates/message_feed_bottom_whitespace.hbs";
import render_message_feed_errors from "../templates/message_feed_errors.hbs"; import render_message_feed_errors from "../templates/message_feed_errors.hbs";
import render_navbar from "../templates/navbar.hbs"; import render_navbar from "../templates/navbar.hbs";
import render_try_zulip_modal from "../templates/try_zulip_modal.hbs";
import * as about_zulip from "./about_zulip.ts"; import * as about_zulip from "./about_zulip.ts";
import * as activity from "./activity.ts"; import * as activity from "./activity.ts";
@@ -40,6 +41,7 @@ import * as condense from "./condense.ts";
import * as copy_messages from "./copy_messages.ts"; import * as copy_messages from "./copy_messages.ts";
import * as desktop_integration from "./desktop_integration.ts"; import * as desktop_integration from "./desktop_integration.ts";
import * as desktop_notifications from "./desktop_notifications.ts"; import * as desktop_notifications from "./desktop_notifications.ts";
import * as dialog_widget from "./dialog_widget.ts";
import * as drafts from "./drafts.ts"; import * as drafts from "./drafts.ts";
import * as drafts_overlay_ui from "./drafts_overlay_ui.ts"; import * as drafts_overlay_ui from "./drafts_overlay_ui.ts";
import * as echo from "./echo.ts"; import * as echo from "./echo.ts";
@@ -719,8 +721,33 @@ export function initialize_everything(state_data) {
$("#app-loading").addClass("loaded"); $("#app-loading").addClass("loaded");
} }
function show_try_zulip_modal() {
const html_body = render_try_zulip_modal();
dialog_widget.launch({
text_heading: i18n.$t({defaultMessage: "Welcome to the Zulip development community!"}),
html_body,
html_submit_button: i18n.$t({defaultMessage: "Let's go!"}),
on_click() {
// Do nothing
},
single_footer_button: true,
focus_submit_on_open: true,
close_on_submit: true,
});
}
$(() => { $(() => {
// Remove '?show_try_zulip_modal', if present.
const url = new URL(window.location.href);
if (url.searchParams.has("show_try_zulip_modal")) {
url.searchParams.delete("show_try_zulip_modal");
window.history.replaceState(window.history.state, "", url.toString());
}
if (page_params.is_spectator) { if (page_params.is_spectator) {
if (page_params.show_try_zulip_modal) {
show_try_zulip_modal();
}
const data = { const data = {
apply_markdown: true, apply_markdown: true,
client_capabilities: JSON.stringify({ client_capabilities: JSON.stringify({

View File

@@ -0,0 +1,24 @@
<p>
{{t "Explore how hundreds of community participants use Zulip to brainstorm ideas, discuss technical challenges, ask questions, and give feedback:" }}
<ul>
<li>
{{#tr}}
You'll see a list of <b>recent conversations</b>, where each conversation is
labeled with a topic by the person who started it. Click on a conversation to
view it. You can always get back to recent conversations from the left sidebar.
{{/tr}}
</li>
<li>
{{#tr}}
Click the name of a channel in the left sidebar, and click on any topic underneath
to view one conversation at a time. You can explore discussions of changes to the
design of the Zulip app in <b>#design</b>, or see ongoing issue investigations in <b>#issues</b>.
{{/tr}}
</li>
</ul>
{{#tr}}
If you have any questions, please post in the <b>#user questions</b> channel, and we'll be happy to help.
{{/tr}}
</p>

View File

@@ -2,6 +2,7 @@ import calendar
import os import os
import time import time
from dataclasses import dataclass from dataclasses import dataclass
from urllib.parse import urlsplit
from django.conf import settings from django.conf import settings
from django.http import HttpRequest from django.http import HttpRequest
@@ -135,12 +136,17 @@ def build_page_params_for_home_page_load(
if user_profile is None: if user_profile is None:
request_language = request.COOKIES.get(settings.LANGUAGE_COOKIE_NAME, default_language) request_language = request.COOKIES.get(settings.LANGUAGE_COOKIE_NAME, default_language)
split_url = urlsplit(request.build_absolute_uri())
show_try_zulip_modal = (
settings.DEVELOPMENT or split_url.hostname == "chat.zulip.org"
) and split_url.query == "show_try_zulip_modal"
else: else:
request_language = get_and_set_request_language( request_language = get_and_set_request_language(
request, request,
default_language, default_language,
translation.get_language_from_path(request.path_info), translation.get_language_from_path(request.path_info),
) )
show_try_zulip_modal = False
furthest_read_time = get_furthest_read_time(user_profile) furthest_read_time = get_furthest_read_time(user_profile)
two_fa_enabled = settings.TWO_FACTOR_AUTHENTICATION_ENABLED and user_profile is not None two_fa_enabled = settings.TWO_FACTOR_AUTHENTICATION_ENABLED and user_profile is not None
@@ -175,6 +181,7 @@ def build_page_params_for_home_page_load(
# There is no event queue for spectators since # There is no event queue for spectators since
# events support for spectators is not implemented yet. # events support for spectators is not implemented yet.
no_event_queue=user_profile is None, no_event_queue=user_profile is None,
show_try_zulip_modal=show_try_zulip_modal,
) )
page_params["state_data"] = state_data page_params["state_data"] = state_data

View File

@@ -57,6 +57,7 @@ class HomeTest(ZulipTestCase):
"presence_history_limit_days_for_web_app", "presence_history_limit_days_for_web_app",
"promote_sponsoring_zulip", "promote_sponsoring_zulip",
"request_language", "request_language",
"show_try_zulip_modal",
"show_webathena", "show_webathena",
"state_data", "state_data",
"test_suite", "test_suite",
@@ -375,6 +376,7 @@ class HomeTest(ZulipTestCase):
"promote_sponsoring_zulip", "promote_sponsoring_zulip",
"realm_rendered_description", "realm_rendered_description",
"request_language", "request_language",
"show_try_zulip_modal",
"show_webathena", "show_webathena",
"state_data", "state_data",
"test_suite", "test_suite",
@@ -386,6 +388,12 @@ class HomeTest(ZulipTestCase):
self.assertCountEqual(page_params, expected_keys) self.assertCountEqual(page_params, expected_keys)
self.assertIsNone(page_params["state_data"]) self.assertIsNone(page_params["state_data"])
with self.settings(DEVELOPMENT=True):
result = self.client_get("/?show_try_zulip_modal")
self.assertEqual(result.status_code, 200)
page_params = self._get_page_params(result)
self.assertEqual(page_params["show_try_zulip_modal"], True)
def test_realm_authentication_methods(self) -> None: def test_realm_authentication_methods(self) -> None:
realm = get_realm("zulip") realm = get_realm("zulip")
self.login("desdemona") self.login("desdemona")