mirror of https://github.com/zulip/zulip.git
events: Add 'onboarding_steps' event deprecating 'hotspots'.
Earlier, the event sent when an onboarding step (hotspot till now) is marked as read generated an event with type='hotspots' and 'hotspots' named array in it. This commit renames the type to 'onboarding_steps' and the array to 'onboarding_steps' to reflect the fact that it'll also contain data for elements other than hotspots.
This commit is contained in:
parent
dde3d72100
commit
83bd9955e3
|
@ -22,6 +22,14 @@ format used by the Zulip server that they are interacting with.
|
|||
|
||||
**Feature level 233**
|
||||
|
||||
* [`POST /register`](/api/register-queue), [`GET /events`](/api/get-events):
|
||||
Renamed the event type `hotspots` and the `hotspots` array field in it
|
||||
to `onboarding_steps` as this event is sent to clients with remaining
|
||||
onboarding steps data that includes hotspots and one-time notices to display.
|
||||
Earlier, we had hotspots only. Added a `type` field to the objects in
|
||||
the renamed `onboarding_steps` array to distinguish between the two type
|
||||
of onboarding steps.
|
||||
|
||||
* `POST /users/me/onboarding_steps`: Added a new endpoint that
|
||||
deprecates the `/users/me/hotspots` endpoint. Added support for
|
||||
displaying one-time notices in addition to existing hotspots.
|
||||
|
|
|
@ -336,7 +336,7 @@ export function load_new(new_hotspots) {
|
|||
}
|
||||
|
||||
export function initialize() {
|
||||
load_new(page_params.hotspots);
|
||||
load_new(onboarding_steps.filter_new_hotspots(page_params.onboarding_steps));
|
||||
|
||||
// open
|
||||
$("body").on("click", ".hotspot-icon", function (e) {
|
||||
|
|
|
@ -16,3 +16,7 @@ export function post_onboarding_step_as_read(onboarding_step_name) {
|
|||
},
|
||||
});
|
||||
}
|
||||
|
||||
export function filter_new_hotspots(onboarding_steps) {
|
||||
return onboarding_steps.filter((onboarding_step) => onboarding_step.type === "hotspot");
|
||||
}
|
||||
|
|
|
@ -30,6 +30,7 @@ import * as muted_users_ui from "./muted_users_ui";
|
|||
import * as narrow_state from "./narrow_state";
|
||||
import * as narrow_title from "./narrow_title";
|
||||
import * as navbar_alerts from "./navbar_alerts";
|
||||
import * as onboarding_steps from "./onboarding_steps";
|
||||
import * as overlays from "./overlays";
|
||||
import {page_params} from "./page_params";
|
||||
import * as peer_data from "./peer_data";
|
||||
|
@ -142,11 +143,11 @@ export function dispatch_normal_event(event) {
|
|||
}
|
||||
break;
|
||||
|
||||
case "hotspots":
|
||||
hotspots.load_new(event.hotspots);
|
||||
page_params.hotspots = page_params.hotspots
|
||||
? [...page_params.hotspots, ...event.hotspots]
|
||||
: event.hotspots;
|
||||
case "onboarding_steps":
|
||||
hotspots.load_new(onboarding_steps.filter_new_hotspots(event.onboarding_steps));
|
||||
page_params.onboarding_steps = page_params.onboarding_steps
|
||||
? [...page_params.onboarding_steps, ...event.onboarding_steps]
|
||||
: event.onboarding_steps;
|
||||
break;
|
||||
|
||||
case "invites_changed":
|
||||
|
|
|
@ -306,12 +306,12 @@ run_test("default_streams", ({override}) => {
|
|||
assert_same(args.realm_default_streams, event.default_streams);
|
||||
});
|
||||
|
||||
run_test("hotspots", ({override}) => {
|
||||
page_params.hotspots = [];
|
||||
const event = event_fixtures.hotspots;
|
||||
run_test("onboarding_steps", ({override}) => {
|
||||
page_params.onboarding_steps = [];
|
||||
const event = event_fixtures.onboarding_steps;
|
||||
override(hotspots, "load_new", noop);
|
||||
dispatch(event);
|
||||
assert_same(page_params.hotspots, event.hotspots);
|
||||
assert_same(page_params.onboarding_steps, event.onboarding_steps);
|
||||
});
|
||||
|
||||
run_test("invites_changed", ({override}) => {
|
||||
|
|
|
@ -169,26 +169,6 @@ exports.fixtures = {
|
|||
value: true,
|
||||
},
|
||||
|
||||
hotspots: {
|
||||
type: "hotspots",
|
||||
hotspots: [
|
||||
{
|
||||
name: "topics",
|
||||
title: "About topics",
|
||||
description: "Topics are good.",
|
||||
delay: 1.5,
|
||||
has_trigger: false,
|
||||
},
|
||||
{
|
||||
name: "compose",
|
||||
title: "Compose box",
|
||||
description: "This is where you compose messages.",
|
||||
delay: 3.14159,
|
||||
has_trigger: false,
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
invites_changed: {
|
||||
type: "invites_changed",
|
||||
},
|
||||
|
@ -207,6 +187,28 @@ exports.fixtures = {
|
|||
],
|
||||
},
|
||||
|
||||
onboarding_steps: {
|
||||
type: "onboarding_steps",
|
||||
onboarding_steps: [
|
||||
{
|
||||
type: "hotspot",
|
||||
name: "topics",
|
||||
title: "About topics",
|
||||
description: "Topics are good.",
|
||||
delay: 1.5,
|
||||
has_trigger: false,
|
||||
},
|
||||
{
|
||||
type: "hotspot",
|
||||
name: "compose",
|
||||
title: "Compose box",
|
||||
description: "This is where you compose messages.",
|
||||
delay: 3.14159,
|
||||
has_trigger: false,
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
presence: {
|
||||
type: "presence",
|
||||
email: "alice@example.com",
|
||||
|
|
|
@ -5,5 +5,5 @@ from zerver.tornado.django_api import send_event
|
|||
|
||||
def do_mark_onboarding_step_as_read(user: UserProfile, onboarding_step: str) -> None:
|
||||
OnboardingStep.objects.get_or_create(user=user, onboarding_step=onboarding_step)
|
||||
event = dict(type="hotspots", hotspots=get_next_onboarding_steps(user))
|
||||
event = dict(type="onboarding_steps", onboarding_steps=get_next_onboarding_steps(user))
|
||||
send_event(user.realm, event, [user.id])
|
||||
|
|
|
@ -332,27 +332,29 @@ def check_heartbeat(
|
|||
_check_heartbeat(var_name, event)
|
||||
|
||||
|
||||
_hotspot = DictType(
|
||||
_onboarding_steps = DictType(
|
||||
required_keys=[
|
||||
("type", str),
|
||||
("name", str),
|
||||
],
|
||||
optional_keys=[
|
||||
("title", str),
|
||||
("description", str),
|
||||
("delay", NumberType()),
|
||||
("has_trigger", bool),
|
||||
]
|
||||
],
|
||||
)
|
||||
|
||||
hotspots_event = event_dict_type(
|
||||
onboarding_steps_event = event_dict_type(
|
||||
required_keys=[
|
||||
("type", Equals("hotspots")),
|
||||
("type", Equals("onboarding_steps")),
|
||||
(
|
||||
"hotspots",
|
||||
ListType(_hotspot),
|
||||
"onboarding_steps",
|
||||
ListType(_onboarding_steps),
|
||||
),
|
||||
]
|
||||
)
|
||||
check_hotspots = make_checker(hotspots_event)
|
||||
check_onboarding_steps = make_checker(onboarding_steps_event)
|
||||
|
||||
invites_changed_event = event_dict_type(
|
||||
required_keys=[
|
||||
|
|
|
@ -184,11 +184,13 @@ def fetch_initial_state_data(
|
|||
|
||||
del state["custom_profile_field_types"]["PRONOUNS"]
|
||||
|
||||
if want("hotspots"):
|
||||
# Even if we offered special hotspots for guests without an
|
||||
if want("onboarding_steps"):
|
||||
# Even if we offered special onboarding steps for guests without an
|
||||
# account, we'd maybe need to store their state using cookies
|
||||
# or local storage, rather than in the database.
|
||||
state["hotspots"] = [] if user_profile is None else get_next_onboarding_steps(user_profile)
|
||||
state["onboarding_steps"] = (
|
||||
[] if user_profile is None else get_next_onboarding_steps(user_profile)
|
||||
)
|
||||
|
||||
if want("message"):
|
||||
# Since the introduction of `anchor="latest"` in the API,
|
||||
|
@ -854,8 +856,8 @@ def apply_event(
|
|||
if scheduled_message["scheduled_message_id"] == event["scheduled_message_id"]:
|
||||
del state["scheduled_messages"][idx]
|
||||
|
||||
elif event["type"] == "hotspots":
|
||||
state["hotspots"] = event["hotspots"]
|
||||
elif event["type"] == "onboarding_steps":
|
||||
state["onboarding_steps"] = event["onboarding_steps"]
|
||||
elif event["type"] == "custom_profile_fields":
|
||||
state["custom_profile_fields"] = event["fields"]
|
||||
custom_profile_field_ids = {field["id"] for field in state["custom_profile_fields"]}
|
||||
|
|
|
@ -2272,11 +2272,14 @@ paths:
|
|||
- type: object
|
||||
additionalProperties: false
|
||||
description: |
|
||||
Event sent when the set of onboarding "hotspots" to show for
|
||||
Event sent when the set of onboarding steps to show for
|
||||
the current user have changed (E.g. because the user dismissed one).
|
||||
|
||||
Clients that feature a similar tutorial experience to the Zulip
|
||||
web app may want to handle these events.
|
||||
|
||||
**Changes**: Before Zulip 8.0 (feature level 233), this was named
|
||||
as `Hotspots`. One-time notice wasn't available earlier.
|
||||
properties:
|
||||
id:
|
||||
$ref: "#/components/schemas/EventIdSchema"
|
||||
|
@ -2284,18 +2287,21 @@ paths:
|
|||
allOf:
|
||||
- $ref: "#/components/schemas/EventTypeSchema"
|
||||
- enum:
|
||||
- hotspots
|
||||
hotspots:
|
||||
- onboarding_steps
|
||||
onboarding_steps:
|
||||
type: array
|
||||
description: |
|
||||
An array of dictionaries where each
|
||||
dictionary contains details about a single hotspot.
|
||||
dictionary contains details about a single onboarding step.
|
||||
|
||||
**Changes**: Before Zulip 8.0 (feature level 233), this array
|
||||
was named as `hotspots`. One-time notice wasn't available earlier.
|
||||
items:
|
||||
$ref: "#/components/schemas/Hotspot"
|
||||
$ref: "#/components/schemas/OnboardingStep"
|
||||
example:
|
||||
{
|
||||
"type": "hotspots",
|
||||
"hotspots":
|
||||
"type": "onboarding_steps",
|
||||
"onboarding_steps":
|
||||
[
|
||||
{
|
||||
"type": "hotspot",
|
||||
|
@ -11815,17 +11821,17 @@ paths:
|
|||
array will be empty if `enable_drafts_synchronization` is set to `false`.
|
||||
items:
|
||||
$ref: "#/components/schemas/Draft"
|
||||
hotspots:
|
||||
onboarding_steps:
|
||||
type: array
|
||||
description: |
|
||||
Present if `hotspots` is present in `fetch_event_types`.
|
||||
Present if `onboarding_steps` is present in `fetch_event_types`.
|
||||
|
||||
An array of dictionaries, where each dictionary contains details about
|
||||
a single onboarding hotspot that should be shown to new users.
|
||||
a single onboarding step that should be shown to new users.
|
||||
|
||||
We expect that only official Zulip clients will interact with these data.
|
||||
items:
|
||||
$ref: "#/components/schemas/Hotspot"
|
||||
$ref: "#/components/schemas/OnboardingStep"
|
||||
max_message_id:
|
||||
type: integer
|
||||
deprecated: true
|
||||
|
@ -18552,17 +18558,22 @@ components:
|
|||
[profile field types](/help/custom-profile-fields#profile-field-types).
|
||||
|
||||
**Changes**: New in Zulip 6.0 (feature level 146).
|
||||
Hotspot:
|
||||
OnboardingStep:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
description: |
|
||||
Dictionary containing details of a single hotspot.
|
||||
Dictionary containing details of a single onboarding step.
|
||||
|
||||
**Changes**: Before Zulip 8.0 (feature level 233), this was
|
||||
named as `Hotspot`. One-time notice wasn't available earlier.
|
||||
properties:
|
||||
type:
|
||||
type: string
|
||||
description: |
|
||||
The type of the onboarding step. Valid values are either
|
||||
'hotspot' or 'one_time_notice'.
|
||||
|
||||
**Changes**: New in Zulip 8.0 (feature level 233).
|
||||
name:
|
||||
type: string
|
||||
description: |
|
||||
|
|
|
@ -1259,10 +1259,10 @@ class FetchQueriesTest(ZulipTestCase):
|
|||
default_streams=1,
|
||||
default_stream_groups=1,
|
||||
drafts=1,
|
||||
hotspots=1,
|
||||
message=1,
|
||||
muted_topics=1,
|
||||
muted_users=1,
|
||||
onboarding_steps=1,
|
||||
presence=1,
|
||||
realm=1,
|
||||
realm_bot=1,
|
||||
|
|
|
@ -145,11 +145,11 @@ from zerver.lib.event_schema import (
|
|||
check_draft_update,
|
||||
check_has_zoom_token,
|
||||
check_heartbeat,
|
||||
check_hotspots,
|
||||
check_invites_changed,
|
||||
check_message,
|
||||
check_muted_topics,
|
||||
check_muted_users,
|
||||
check_onboarding_steps,
|
||||
check_presence,
|
||||
check_reaction_add,
|
||||
check_reaction_remove,
|
||||
|
@ -3055,7 +3055,7 @@ class NormalActionsTest(BaseAction):
|
|||
events = self.verify_action(
|
||||
lambda: do_mark_onboarding_step_as_read(self.user_profile, "intro_streams")
|
||||
)
|
||||
check_hotspots("events[0]", events[0])
|
||||
check_onboarding_steps("events[0]", events[0])
|
||||
|
||||
def test_rename_stream(self) -> None:
|
||||
for i, include_streams in enumerate([True, False]):
|
||||
|
|
|
@ -73,7 +73,6 @@ class HomeTest(ZulipTestCase):
|
|||
"giphy_api_key",
|
||||
"giphy_rating_options",
|
||||
"has_zoom_token",
|
||||
"hotspots",
|
||||
"insecure_desktop_app",
|
||||
"is_admin",
|
||||
"is_billing_admin",
|
||||
|
@ -101,6 +100,7 @@ class HomeTest(ZulipTestCase):
|
|||
"needs_tutorial",
|
||||
"never_subscribed",
|
||||
"no_event_queue",
|
||||
"onboarding_steps",
|
||||
"password_min_guesses",
|
||||
"password_min_length",
|
||||
"presences",
|
||||
|
|
Loading…
Reference in New Issue