settings: Rename notifications_stream to new_stream_announce..._stream.

This commit renames the realm-level setting 'notifications_stream'
to 'new_stream_announcements_stream'.

The new name reflects better what the setting does.
This commit is contained in:
Prakhar Pratyush 2024-02-07 16:43:02 +05:30 committed by Tim Abbott
parent 0c83bca81e
commit ab453fbe20
40 changed files with 254 additions and 195 deletions

View File

@ -20,6 +20,12 @@ format used by the Zulip server that they are interacting with.
## Changes in Zulip 9.0
**Feature level 241**
* [`POST /register`](/api/register-queue), [`POST /events`](/api/get-events),
`PATCH /realm`: Renamed the realm setting `notifications_stream`
to `new_stream_announcements_stream`.
**Feature level 240**
* [`GET /events`](/api/get-events): The `restart` event no longer contains an

View File

@ -33,7 +33,7 @@ DESKTOP_WARNING_VERSION = "5.9.3"
# Changes should be accompanied by documentation explaining what the
# new level means in api_docs/changelog.md, as well as "**Changes**"
# entries in the endpoint's documentation in `zulip.yaml`.
API_FEATURE_LEVEL = 240
API_FEATURE_LEVEL = 241
# Bump the minor PROVISION_VERSION to indicate that folks should provision
# only when going from an old version of the code to a newer version. Bump

View File

@ -4,7 +4,7 @@ import type {Page} from "puppeteer";
import * as common from "./lib/common";
async function submit_notifications_stream_settings(page: Page): Promise<void> {
async function submit_announcements_stream_settings(page: Page): Promise<void> {
await page.waitForSelector('#org-notifications .save-button[data-status="unsaved"]', {
visible: true,
});
@ -29,8 +29,8 @@ async function submit_notifications_stream_settings(page: Page): Promise<void> {
await page.waitForSelector("#org-notifications .save-button", {hidden: true});
}
async function test_change_new_stream_notifications_setting(page: Page): Promise<void> {
await page.click("#realm_notifications_stream_id_widget.dropdown-widget-button");
async function test_change_new_stream_announcements_stream(page: Page): Promise<void> {
await page.click("#realm_new_stream_announcements_stream_id_widget.dropdown-widget-button");
await page.waitForSelector(".dropdown-list-container", {
visible: true,
});
@ -44,7 +44,7 @@ async function test_change_new_stream_notifications_setting(page: Page): Promise
assert.ok(rome_in_dropdown);
await rome_in_dropdown.click();
await submit_notifications_stream_settings(page);
await submit_announcements_stream_settings(page);
}
async function test_change_signup_notifications_stream(page: Page): Promise<void> {
@ -57,7 +57,7 @@ async function test_change_signup_notifications_stream(page: Page): Promise<void
await page.waitForSelector(".dropdown-list .list-item", {visible: true});
await page.keyboard.press("ArrowDown");
await page.keyboard.press("Enter");
await submit_notifications_stream_settings(page);
await submit_announcements_stream_settings(page);
}
async function test_permissions_change_save_worked(page: Page): Promise<void> {
@ -263,7 +263,7 @@ async function admin_test(page: Page): Promise<void> {
await common.log_in(page);
await common.manage_organization(page);
await test_change_new_stream_notifications_setting(page);
await test_change_new_stream_announcements_stream(page);
await test_change_signup_notifications_stream(page);
await test_organization_permissions(page);

View File

@ -30,7 +30,7 @@ const admin_settings_label = {
// Organization settings
realm_allow_edit_history: $t({defaultMessage: "Enable message edit history"}),
realm_mandatory_topics: $t({defaultMessage: "Require topics in stream messages"}),
realm_notifications_stream: $t({defaultMessage: "New stream announcements"}),
realm_new_stream_announcements_stream: $t({defaultMessage: "New stream announcements"}),
realm_signup_notifications_stream: $t({defaultMessage: "New user announcements"}),
realm_inline_image_preview: $t({
defaultMessage: "Show previews of uploaded and linked images and videos",
@ -137,7 +137,7 @@ export function build_page() {
realm_default_language_name: get_language_name(realm.realm_default_language),
realm_default_language_code: realm.realm_default_language,
realm_waiting_period_threshold: realm.realm_waiting_period_threshold,
realm_notifications_stream_id: realm.realm_notifications_stream_id,
realm_new_stream_announcements_stream_id: realm.realm_new_stream_announcements_stream_id,
realm_signup_notifications_stream_id: realm.realm_signup_notifications_stream_id,
is_admin: current_user.is_admin,
is_guest: current_user.is_guest,

View File

@ -318,7 +318,7 @@ function open_invite_user_modal(e: JQuery.ClickEvent<Document, undefined>): void
expires_in_options: settings_config.expires_in_values,
time_choices: time_unit_choices,
streams: get_invite_streams(),
notifications_stream: stream_data.get_notifications_stream(),
new_stream_announcements_stream: stream_data.get_new_stream_announcements_stream(),
show_select_default_streams_option: stream_data.get_default_stream_ids().length !== 0,
user_has_email_set: !settings_data.user_email_not_configured(),
});

View File

@ -233,7 +233,7 @@ export function dispatch_normal_event(event) {
move_messages_between_streams_policy: noop,
name: narrow_title.redraw_title,
name_changes_disabled: settings_account.update_name_change_display,
notifications_stream_id: stream_ui_updates.update_announce_stream_option,
new_stream_announcements_stream_id: stream_ui_updates.update_announce_stream_option,
org_type: noop,
private_message_policy: compose_recipient.check_posting_policy_for_compose_box,
push_notifications_enabled: noop,
@ -560,9 +560,9 @@ export function dispatch_normal_event(event) {
}
settings_streams.update_default_streams_table();
stream_data.remove_default_stream(stream.stream_id);
if (realm.realm_notifications_stream_id === stream.stream_id) {
realm.realm_notifications_stream_id = -1;
settings_org.sync_realm_settings("notifications_stream_id");
if (realm.realm_new_stream_announcements_stream_id === stream.stream_id) {
realm.realm_new_stream_announcements_stream_id = -1;
settings_org.sync_realm_settings("new_stream_announcements_stream_id");
}
if (realm.realm_signup_notifications_stream_id === stream.stream_id) {
realm.realm_signup_notifications_stream_id = -1;

View File

@ -239,7 +239,7 @@ export function sort_object_by_key(obj) {
}
export let default_code_language_widget = null;
export let notifications_stream_widget = null;
export let new_stream_announcements_stream_widget = null;
export let signup_notifications_stream_widget = null;
export let create_multiuse_invite_group_widget = null;
export let can_remove_subscribers_group_widget = null;
@ -249,8 +249,8 @@ export let new_group_can_mention_group_widget = null;
export function get_widget_for_dropdown_list_settings(property_name) {
switch (property_name) {
case "realm_notifications_stream_id":
return notifications_stream_widget;
case "realm_new_stream_announcements_stream_id":
return new_stream_announcements_stream_widget;
case "realm_signup_notifications_stream_id":
return signup_notifications_stream_widget;
case "realm_default_code_block_language":
@ -273,8 +273,8 @@ export function set_default_code_language_widget(widget) {
default_code_language_widget = widget;
}
export function set_notifications_stream_widget(widget) {
notifications_stream_widget = widget;
export function set_new_stream_announcements_stream_widget(widget) {
new_stream_announcements_stream_widget = widget;
}
export function set_signup_notifications_stream_widget(widget) {
@ -504,7 +504,7 @@ export function check_property_changed(elem, for_realm_default_settings, sub, gr
proposed_val = get_auth_method_list_data();
proposed_val = JSON.stringify(proposed_val);
break;
case "realm_notifications_stream_id":
case "realm_new_stream_announcements_stream_id":
case "realm_signup_notifications_stream_id":
case "realm_default_code_block_language":
case "can_remove_subscribers_group":

View File

@ -474,7 +474,7 @@ export function discard_property_element_changes(elem, for_realm_default_setting
case "realm_authentication_methods":
populate_auth_methods(property_value);
break;
case "realm_notifications_stream_id":
case "realm_new_stream_announcements_stream_id":
case "realm_signup_notifications_stream_id":
case "realm_default_code_block_language":
case "can_remove_subscribers_group":
@ -637,26 +637,28 @@ export function init_dropdown_widgets() {
return options;
};
const notifications_stream_widget = new dropdown_widget.DropdownWidget({
widget_name: "realm_notifications_stream_id",
const new_stream_announcements_stream_widget = new dropdown_widget.DropdownWidget({
widget_name: "realm_new_stream_announcements_stream_id",
get_options: notification_stream_options,
$events_container: $("#settings_overlay_container #organization-settings"),
item_click_callback(event, dropdown) {
dropdown.hide();
event.preventDefault();
event.stopPropagation();
settings_components.notifications_stream_widget.render();
settings_components.new_stream_announcements_stream_widget.render();
settings_components.save_discard_widget_status_handler($("#org-notifications"));
},
tippy_props: {
placement: "bottom-start",
},
default_id: realm.realm_notifications_stream_id,
default_id: realm.realm_new_stream_announcements_stream_id,
unique_id_type: dropdown_widget.DATA_TYPES.NUMBER,
text_if_current_value_not_in_options: $t({defaultMessage: "Cannot view stream"}),
});
settings_components.set_notifications_stream_widget(notifications_stream_widget);
notifications_stream_widget.setup();
settings_components.set_new_stream_announcements_stream_widget(
new_stream_announcements_stream_widget,
);
new_stream_announcements_stream_widget.setup();
const signup_notifications_stream_widget = new dropdown_widget.DropdownWidget({
widget_name: "realm_signup_notifications_stream_id",

View File

@ -96,9 +96,9 @@ export const realm_schema = z.object({
realm_move_messages_between_streams_policy: z.number(),
realm_name_changes_disabled: z.boolean(),
realm_name: z.string(),
realm_new_stream_announcements_stream_id: z.number(),
realm_night_logo_source: z.string(),
realm_night_logo_url: z.string(),
realm_notifications_stream_id: z.number(),
realm_org_type: z.number(),
realm_plan_type: z.number(),
realm_private_message_policy: z.number(),

View File

@ -121,8 +121,8 @@ let stream_announce_previous_value;
// Within the new stream modal...
function update_announce_stream_state() {
// If there is no notifications_stream, we simply hide the widget.
if (stream_data.get_notifications_stream() === "") {
// If there is no new_stream_announcements_stream, we simply hide the widget.
if (stream_data.get_new_stream_announcements_stream() === "") {
$("#announce-new-stream").hide();
return;
}
@ -238,12 +238,12 @@ function create_stream() {
data.message_retention_days = JSON.stringify(message_retention_selection);
let announce =
stream_data.get_notifications_stream() !== "" &&
stream_data.get_new_stream_announcements_stream() !== "" &&
$("#announce-new-stream input").prop("checked");
if (
stream_data.get_notifications_stream() === "" &&
stream_data.realm_has_notifications_stream() &&
stream_data.get_new_stream_announcements_stream() === "" &&
stream_data.realm_has_new_stream_announcements_stream() &&
!invite_only
) {
announce = true;
@ -449,7 +449,8 @@ export function set_up_handlers() {
content: () =>
parse_html(
render_announce_stream_docs({
notifications_stream: stream_data.get_notifications_stream(),
new_stream_announcements_stream:
stream_data.get_new_stream_announcements_stream(),
}),
),
});

View File

@ -483,8 +483,8 @@ export function is_stream_muted_by_name(stream_name: string): boolean {
return sub.is_muted;
}
export function is_notifications_stream_muted(): boolean {
return is_muted(realm.realm_notifications_stream_id);
export function is_new_stream_announcements_stream_muted(): boolean {
return is_muted(realm.realm_new_stream_announcements_stream_id);
}
export function can_toggle_subscription(sub: StreamSubscription): boolean {
@ -808,12 +808,12 @@ export function get_streams_for_admin(): StreamSubscription[] {
is the authoritative source of this data, and it will be updated by
server_events_dispatch in case of changes.
*/
export function realm_has_notifications_stream(): boolean {
return realm.realm_notifications_stream_id !== -1;
export function realm_has_new_stream_announcements_stream(): boolean {
return realm.realm_new_stream_announcements_stream_id !== -1;
}
export function get_notifications_stream(): string {
const stream_id = realm.realm_notifications_stream_id;
export function get_new_stream_announcements_stream(): string {
const stream_id = realm.realm_new_stream_announcements_stream_id;
if (stream_id !== -1) {
const stream_obj = sub_store.get(stream_id);
if (stream_obj) {

View File

@ -606,17 +606,18 @@ export function initialize() {
const stream_name_with_privacy_symbol_html = render_inline_decorated_stream_name({stream});
const is_new_stream_notification_stream = stream_id === realm.realm_notifications_stream_id;
const is_new_stream_announcements_stream =
stream_id === realm.realm_new_stream_announcements_stream_id;
const is_signup_notification_stream =
stream_id === realm.realm_signup_notifications_stream_id;
const is_notification_stream =
is_new_stream_notification_stream || is_signup_notification_stream;
const is_announcement_stream =
is_new_stream_announcements_stream || is_signup_notification_stream;
const html_body = render_settings_deactivation_stream_modal({
stream_name_with_privacy_symbol_html,
is_new_stream_notification_stream,
is_new_stream_announcements_stream,
is_signup_notification_stream,
is_notification_stream,
is_announcement_stream,
});
confirm_dialog.launch({

View File

@ -596,11 +596,13 @@ export function setup_page(callback) {
// TODO: Ideally we'd indicate in some way what stream types
// the user can create, by showing other options as disabled.
const stream_privacy_policy = settings_config.stream_privacy_policy_values.public.code;
const notifications_stream = stream_data.get_notifications_stream();
const notifications_stream_sub = stream_data.get_sub_by_name(notifications_stream);
const new_stream_announcements_stream = stream_data.get_new_stream_announcements_stream();
const new_stream_announcements_stream_sub = stream_data.get_sub_by_name(
new_stream_announcements_stream,
);
const template_data = {
notifications_stream_sub,
new_stream_announcements_stream_sub,
ask_to_announce_stream: true,
can_create_streams:
settings_data.user_can_create_private_streams() ||

View File

@ -283,16 +283,18 @@ export function update_announce_stream_option() {
if (!hash_parser.is_create_new_stream_narrow()) {
return;
}
if (stream_data.get_notifications_stream() === "") {
if (stream_data.get_new_stream_announcements_stream() === "") {
$("#announce-new-stream").hide();
return;
}
$("#announce-new-stream").show();
const notifications_stream = stream_data.get_notifications_stream();
const notifications_stream_sub = stream_data.get_sub_by_name(notifications_stream);
const new_stream_announcements_stream = stream_data.get_new_stream_announcements_stream();
const new_stream_announcements_stream_sub = stream_data.get_sub_by_name(
new_stream_announcements_stream,
);
const rendered_announce_stream = render_announce_stream_checkbox({
notifications_stream_sub,
new_stream_announcements_stream_sub,
});
$("#announce-new-stream").expectOne().html(rendered_announce_stream);
}

View File

@ -585,9 +585,9 @@ export function initialize_everything(state_data) {
"realm_move_messages_within_stream_limit_seconds",
"realm_name",
"realm_name_changes_disabled",
"realm_new_stream_announcements_stream_id",
"realm_night_logo_source",
"realm_night_logo_url",
"realm_notifications_stream_id",
"realm_org_type",
"realm_password_auth_enabled",
"realm_plan_type",

View File

@ -2,7 +2,7 @@
<div>
{{#tr}}
<p>Stream will be announced in <b>#{notifications_stream}</b>.</p>
<p>Stream will be announced in <b>#{new_stream_announcements_stream}</b>.</p>
{{/tr}}
<p>{{t 'Organization administrators can change the announcement stream in the organization settings.' }}</p>

View File

@ -4,10 +4,10 @@
{{#*inline "z-stream"}}<strong>{{{stream_name_with_privacy_symbol_html}}}</strong>{{/inline}}
{{/tr}}
</p>
{{#if is_notification_stream}}
{{#if is_announcement_stream}}
<p class="notification_stream_archive_warning">{{#tr}}Archiving this stream will also disable settings that were configured to use this stream:{{/tr}}</p>
<ul>
{{#if is_new_stream_notification_stream}}
{{#if is_new_stream_announcements_stream}}
<li>{{#tr}}New stream notifications{{/tr}}</li>
{{/if}}
{{#if is_signup_notification_stream}}

View File

@ -94,7 +94,7 @@
{{else}}
#{{name}}
{{/if}}
{{#if (eq name ../notifications_stream)}}
{{#if (eq name ../new_stream_announcements_stream)}}
<i>({{t 'Receives new stream announcements' }})</i>
{{/if}}
</label>

View File

@ -17,8 +17,8 @@
</div>
{{> ../dropdown_widget_with_label
widget_name="realm_notifications_stream_id"
label=admin_settings_label.realm_notifications_stream
widget_name="realm_new_stream_announcements_stream_id"
label=admin_settings_label.realm_new_stream_announcements_stream
value_type="number"}}
{{> ../dropdown_widget_with_label

View File

@ -2,10 +2,10 @@
<input type="checkbox" name="announce" value="announce" checked />
<span></span>
{{t "Announce new stream in"}}
{{#if notifications_stream_sub}}
{{#if new_stream_announcements_stream_sub}}
<strong>
{{> ../inline_decorated_stream_name
stream=notifications_stream_sub
stream=new_stream_announcements_stream_sub
}}
</strong>
{{/if}}

View File

@ -527,10 +527,10 @@ run_test("realm settings", ({override}) => {
event = event_fixtures.realm__update__disallow_disposable_email_addresses;
test_realm_boolean(event, "realm_disallow_disposable_email_addresses");
event = event_fixtures.realm__update__notifications_stream_id;
event = event_fixtures.realm__update__new_stream_announcements_stream_id;
dispatch(event);
assert_same(realm.realm_notifications_stream_id, 42);
realm.realm_notifications_stream_id = -1; // make sure to reset for future tests
assert_same(realm.realm_new_stream_announcements_stream_id, 42);
realm.realm_new_stream_announcements_stream_id = -1; // make sure to reset for future tests
event = event_fixtures.realm__update__signup_notifications_stream_id;
dispatch(event);

View File

@ -241,7 +241,7 @@ test("stream delete (special streams)", ({override}) => {
// sanity check data
assert.equal(event.streams.length, 2);
realm.realm_notifications_stream_id = event.streams[0].stream_id;
realm.realm_new_stream_announcements_stream_id = event.streams[0].stream_id;
realm.realm_signup_notifications_stream_id = event.streams[1].stream_id;
override(stream_settings_ui, "remove_stream", noop);
@ -253,7 +253,7 @@ test("stream delete (special streams)", ({override}) => {
dispatch(event);
assert.equal(realm.realm_notifications_stream_id, -1);
assert.equal(realm.realm_new_stream_announcements_stream_id, -1);
assert.equal(realm.realm_signup_notifications_stream_id, -1);
});

View File

@ -344,10 +344,10 @@ exports.fixtures = {
value: "new_realm_name",
},
realm__update__notifications_stream_id: {
realm__update__new_stream_announcements_stream_id: {
type: "realm",
op: "update",
property: "notifications_stream_id",
property: "new_stream_announcements_stream_id",
value: 42,
},

View File

@ -689,15 +689,15 @@ test("is_muted", () => {
assert.ok(stream_data.is_stream_muted_by_name("EEXISTS"));
});
test("is_notifications_stream_muted", () => {
test("is_new_stream_announcements_stream_muted", () => {
stream_data.add_sub(tony);
stream_data.add_sub(jazy);
realm.realm_notifications_stream_id = tony.stream_id;
assert.ok(!stream_data.is_notifications_stream_muted());
realm.realm_new_stream_announcements_stream_id = tony.stream_id;
assert.ok(!stream_data.is_new_stream_announcements_stream_muted());
realm.realm_notifications_stream_id = jazy.stream_id;
assert.ok(stream_data.is_notifications_stream_muted());
realm.realm_new_stream_announcements_stream_id = jazy.stream_id;
assert.ok(stream_data.is_new_stream_announcements_stream_muted());
});
test("muted_stream_ids", () => {
@ -746,11 +746,11 @@ test("muted_stream_ids", () => {
assert.deepEqual(stream_data.muted_stream_ids(), [1, 3]);
});
test("realm_has_notifications_stream", () => {
realm.realm_notifications_stream_id = 10;
assert.ok(stream_data.realm_has_notifications_stream());
realm.realm_notifications_stream_id = -1;
assert.ok(!stream_data.realm_has_notifications_stream());
test("realm_has_new_stream_announcements_stream", () => {
realm.realm_new_stream_announcements_stream_id = 10;
assert.ok(stream_data.realm_has_new_stream_announcements_stream());
realm.realm_new_stream_announcements_stream_id = -1;
assert.ok(!stream_data.realm_has_new_stream_announcements_stream());
});
test("remove_default_stream", () => {
@ -843,7 +843,7 @@ test("initialize", () => {
stream_data.initialize(get_params());
}
realm.realm_notifications_stream_id = -1;
realm.realm_new_stream_announcements_stream_id = -1;
initialize();
@ -851,12 +851,12 @@ test("initialize", () => {
assert.ok(stream_names.has("subscriptions"));
assert.ok(stream_names.has("unsubscribed"));
assert.ok(stream_names.has("never_subscribed"));
assert.equal(stream_data.get_notifications_stream(), "");
assert.equal(stream_data.get_new_stream_announcements_stream(), "");
// Simulate a private stream the user isn't subscribed to
realm.realm_notifications_stream_id = 89;
realm.realm_new_stream_announcements_stream_id = 89;
initialize();
assert.equal(stream_data.get_notifications_stream(), "");
assert.equal(stream_data.get_new_stream_announcements_stream(), "");
// Now actually subscribe the user to the stream
initialize();
@ -867,7 +867,7 @@ test("initialize", () => {
stream_data.add_sub(foo);
initialize();
assert.equal(stream_data.get_notifications_stream(), "foo");
assert.equal(stream_data.get_new_stream_announcements_stream(), "foo");
});
test("edge_cases", () => {

View File

@ -272,17 +272,17 @@ def do_create_realm(
maybe_enqueue_audit_log_upload(realm)
# Create stream once Realm object has been saved
notifications_stream = ensure_stream(
new_stream_announcements_stream = ensure_stream(
realm,
Realm.DEFAULT_NOTIFICATION_STREAM_NAME,
stream_description="Everyone is added to this stream by default. Welcome! :octopus:",
acting_user=None,
)
realm.notifications_stream = notifications_stream
realm.new_stream_announcements_stream = new_stream_announcements_stream
# With the current initial streams situation, the only public
# stream is the notifications_stream.
DefaultStream.objects.create(stream=notifications_stream, realm=realm)
# stream is the new_stream_announcements_stream.
DefaultStream.objects.create(stream=new_stream_announcements_stream, realm=realm)
signup_notifications_stream = ensure_stream(
realm,
@ -293,7 +293,7 @@ def do_create_realm(
)
realm.signup_notifications_stream = signup_notifications_stream
realm.save(update_fields=["notifications_stream", "signup_notifications_stream"])
realm.save(update_fields=["new_stream_announcements_stream", "signup_notifications_stream"])
if plan_type is None and settings.BILLING_ENABLED:
# We use acting_user=None for setting the initial plan type.

View File

@ -260,7 +260,7 @@ def do_set_realm_authentication_methods(
def do_set_realm_stream(
realm: Realm,
field: Literal["notifications_stream", "signup_notifications_stream"],
field: Literal["new_stream_announcements_stream", "signup_notifications_stream"],
stream: Optional[Stream],
stream_id: int,
*,
@ -268,10 +268,10 @@ def do_set_realm_stream(
) -> None:
# We could calculate more of these variables from `field`, but
# it's probably more readable to not do so.
if field == "notifications_stream":
old_value = realm.notifications_stream_id
realm.notifications_stream = stream
property = "notifications_stream_id"
if field == "new_stream_announcements_stream":
old_value = realm.new_stream_announcements_stream_id
realm.new_stream_announcements_stream = stream
property = "new_stream_announcements_stream_id"
elif field == "signup_notifications_stream":
old_value = realm.signup_notifications_stream_id
realm.signup_notifications_stream = stream
@ -304,10 +304,12 @@ def do_set_realm_stream(
send_event(realm, event, active_user_ids(realm.id))
def do_set_realm_notifications_stream(
def do_set_realm_new_stream_announcements_stream(
realm: Realm, stream: Optional[Stream], stream_id: int, *, acting_user: Optional[UserProfile]
) -> None:
do_set_realm_stream(realm, "notifications_stream", stream, stream_id, acting_user=acting_user)
do_set_realm_stream(
realm, "new_stream_announcements_stream", stream, stream_id, acting_user=acting_user
)
def do_set_realm_signup_notifications_stream(

View File

@ -918,7 +918,7 @@ def check_realm_update(
assert "extra_data" not in event
if prop in ["notifications_stream_id", "signup_notifications_stream_id", "org_type"]:
if prop in ["new_stream_announcements_stream_id", "signup_notifications_stream_id", "org_type"]:
assert isinstance(value, int)
return

View File

@ -362,11 +362,11 @@ def fetch_initial_state_data(
else server_default_jitsi_server_url
)
notifications_stream = realm.get_notifications_stream()
if notifications_stream:
state["realm_notifications_stream_id"] = notifications_stream.id
new_stream_announcements_stream = realm.get_new_stream_announcements_stream()
if new_stream_announcements_stream:
state["realm_new_stream_announcements_stream_id"] = new_stream_announcements_stream.id
else:
state["realm_notifications_stream_id"] = -1
state["realm_new_stream_announcements_stream_id"] = -1
signup_notifications_stream = realm.get_signup_notifications_stream()
if signup_notifications_stream:

View File

@ -906,10 +906,10 @@ def import_uploads(
# have to import the dependencies first.)
#
# * Client [no deps]
# * Realm [-notifications_stream,-group_permissions]
# * Realm [-announcements_streams,-group_permissions]
# * UserGroup
# * Stream [only depends on realm]
# * Realm's notifications_stream and group_permissions
# * Realm's announcements_streams and group_permissions
# * UserProfile, in order by ID to avoid bot loop issues
# * Now can do all realm_tables
# * Huddle
@ -951,9 +951,11 @@ def do_import_realm(import_dir: Path, subdomain: str, processes: int = 1) -> Rea
# We don't import the Stream and UserGroup models yet, since
# they depend on Realm, which isn't imported yet.
# But we need the Stream and UserGroup model IDs for
# notifications_stream and group permissions, respectively
# announcements streams and group permissions, respectively
update_model_ids(Stream, data, "stream")
re_map_foreign_keys(data, "zerver_realm", "notifications_stream", related_table="stream")
re_map_foreign_keys(
data, "zerver_realm", "new_stream_announcements_stream", related_table="stream"
)
re_map_foreign_keys(data, "zerver_realm", "signup_notifications_stream", related_table="stream")
if "zerver_usergroup" in data:
update_model_ids(UserGroup, data, "usergroup")

View File

@ -0,0 +1,18 @@
# Generated by Django 4.2.9 on 2024-02-07 11:09
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
("zerver", "0496_alter_scheduledmessage_read_by_sender"),
]
operations = [
migrations.RenameField(
model_name="realm",
old_name="notifications_stream",
new_name="new_stream_announcements_stream",
),
]

View File

@ -335,7 +335,7 @@ class Realm(models.Model): # type: ignore[django-manager-missing] # django-stub
DEFAULT_NOTIFICATION_STREAM_NAME = "general"
INITIAL_PRIVATE_STREAM_NAME = "core team"
STREAM_EVENTS_NOTIFICATION_TOPIC_NAME = gettext_lazy("stream events")
notifications_stream = models.ForeignKey(
new_stream_announcements_stream = models.ForeignKey(
"Stream",
related_name="+",
null=True,
@ -784,9 +784,12 @@ class Realm(models.Model): # type: ignore[django-manager-missing] # django-stub
def get_bot_domain(self) -> str:
return get_fake_email_domain(self.host)
def get_notifications_stream(self) -> Optional["Stream"]:
if self.notifications_stream is not None and not self.notifications_stream.deactivated:
return self.notifications_stream
def get_new_stream_announcements_stream(self) -> Optional["Stream"]:
if (
self.new_stream_announcements_stream is not None
and not self.new_stream_announcements_stream.deactivated
):
return self.new_stream_announcements_stream
return None
def get_signup_notifications_stream(self) -> Optional["Stream"]:

View File

@ -4474,7 +4474,7 @@ paths:
description: |
The URL of the organization's dark theme wide-format logo configured in the
[organization profile](/help/create-your-organization-profile).
notifications_stream_id:
new_stream_announcements_stream_id:
type: integer
description: |
The ID of the stream to which automated messages announcing the
@ -4486,6 +4486,9 @@ paths:
primarily relevant to clients containing UI for changing it.
[new-stream-announce]: /help/configure-notification-bot#new-stream-announcements
**Changes**: In Zulip 9.0 (feature level 241), renamed 'notifications_stream_id'
to `new_stream_announcements_stream_id`.
org_type:
type: integer
description: |
@ -15114,7 +15117,7 @@ paths:
**Changes**: New in Zulip 5.0 (feature level 74). Previously,
this was hardcoded to 90 seconds, and clients should use that as a fallback
value when interacting with servers where this field is not present.
realm_notifications_stream_id:
realm_new_stream_announcements_stream_id:
type: integer
description: |
Present if `realm` is present in `fetch_event_types`.
@ -15128,6 +15131,9 @@ paths:
primarily relevant to clients containing UI for changing it.
[new-stream-announce]: /help/configure-notification-bot#new-stream-announcements
**Changes**: In Zulip 9.0 (feature level 241), renamed 'realm_notifications_stream_id'
to `realm_new_stream_announcements_stream_id`.
realm_signup_notifications_stream_id:
type: integer
description: |

View File

@ -34,7 +34,7 @@ from zerver.actions.realm_settings import (
do_deactivate_realm,
do_reactivate_realm,
do_set_realm_authentication_methods,
do_set_realm_notifications_stream,
do_set_realm_new_stream_announcements_stream,
do_set_realm_property,
do_set_realm_signup_notifications_stream,
)
@ -556,15 +556,15 @@ class TestRealmAuditLog(ZulipTestCase):
1,
)
def test_set_realm_notifications_stream(self) -> None:
def test_set_realm_new_stream_announcements_stream(self) -> None:
now = timezone_now()
realm = get_realm("zulip")
user = self.example_user("hamlet")
old_value = realm.notifications_stream_id
old_value = realm.new_stream_announcements_stream_id
stream_name = "test"
stream = self.make_stream(stream_name, realm)
do_set_realm_notifications_stream(realm, stream, stream.id, acting_user=user)
do_set_realm_new_stream_announcements_stream(realm, stream, stream.id, acting_user=user)
self.assertEqual(
RealmAuditLog.objects.filter(
realm=realm,
@ -574,7 +574,7 @@ class TestRealmAuditLog(ZulipTestCase):
extra_data={
RealmAuditLog.OLD_VALUE: old_value,
RealmAuditLog.NEW_VALUE: stream.id,
"property": "notifications_stream",
"property": "new_stream_announcements_stream",
},
).count(),
1,

View File

@ -78,7 +78,7 @@ from zerver.actions.realm_settings import (
do_deactivate_realm,
do_set_push_notifications_enabled_end_timestamp,
do_set_realm_authentication_methods,
do_set_realm_notifications_stream,
do_set_realm_new_stream_announcements_stream,
do_set_realm_property,
do_set_realm_signup_notifications_stream,
do_set_realm_user_default_setting,
@ -2289,20 +2289,23 @@ class NormalActionsTest(BaseAction):
value=value,
)
def test_change_realm_notifications_stream(self) -> None:
def test_change_realm_new_stream_announcements_stream(self) -> None:
stream = get_stream("Rome", self.user_profile.realm)
for notifications_stream, notifications_stream_id in ((stream, stream.id), (None, -1)):
for new_stream_announcements_stream, new_stream_announcements_stream_id in (
(stream, stream.id),
(None, -1),
):
events = self.verify_action(
partial(
do_set_realm_notifications_stream,
do_set_realm_new_stream_announcements_stream,
self.user_profile.realm,
notifications_stream,
notifications_stream_id,
new_stream_announcements_stream,
new_stream_announcements_stream_id,
acting_user=None,
)
)
check_realm_update("events[0]", events[0], "notifications_stream_id")
check_realm_update("events[0]", events[0], "new_stream_announcements_stream_id")
def test_change_realm_signup_notifications_stream(self) -> None:
stream = get_stream("Rome", self.user_profile.realm)

View File

@ -175,10 +175,10 @@ class HomeTest(ZulipTestCase):
"realm_move_messages_within_stream_limit_seconds",
"realm_name",
"realm_name_changes_disabled",
"realm_new_stream_announcements_stream_id",
"realm_night_logo_source",
"realm_night_logo_url",
"realm_non_active_users",
"realm_notifications_stream_id",
"realm_org_type",
"realm_password_auth_enabled",
"realm_plan_type",
@ -626,15 +626,15 @@ class HomeTest(ZulipTestCase):
set(result["Cache-Control"].split(", ")), {"must-revalidate", "no-store", "no-cache"}
)
def test_notifications_stream(self) -> None:
def test_new_stream_announcements_stream(self) -> None:
realm = get_realm("zulip")
realm.notifications_stream_id = get_stream("Denmark", realm).id
realm.new_stream_announcements_stream_id = get_stream("Denmark", realm).id
realm.save()
self.login("hamlet")
result = self._get_home_page()
page_params = self._get_page_params(result)
self.assertEqual(
page_params["state_data"]["realm_notifications_stream_id"],
page_params["state_data"]["realm_new_stream_announcements_stream_id"],
get_stream("Denmark", realm).id,
)

View File

@ -480,58 +480,62 @@ class RealmTest(ZulipTestCase):
"The organization reactivation link has expired or is not valid.", response
)
def test_change_notifications_stream(self) -> None:
def test_change_new_stream_announcements_stream(self) -> None:
# We need an admin user.
self.login("iago")
disabled_notif_stream_id = -1
req = dict(notifications_stream_id=orjson.dumps(disabled_notif_stream_id).decode())
req = dict(
new_stream_announcements_stream_id=orjson.dumps(disabled_notif_stream_id).decode()
)
result = self.client_patch("/json/realm", req)
self.assert_json_success(result)
realm = get_realm("zulip")
self.assertEqual(realm.notifications_stream, None)
self.assertEqual(realm.new_stream_announcements_stream, None)
new_notif_stream_id = Stream.objects.get(name="Denmark").id
req = dict(notifications_stream_id=orjson.dumps(new_notif_stream_id).decode())
req = dict(new_stream_announcements_stream_id=orjson.dumps(new_notif_stream_id).decode())
result = self.client_patch("/json/realm", req)
self.assert_json_success(result)
realm = get_realm("zulip")
assert realm.notifications_stream is not None
self.assertEqual(realm.notifications_stream.id, new_notif_stream_id)
assert realm.new_stream_announcements_stream is not None
self.assertEqual(realm.new_stream_announcements_stream.id, new_notif_stream_id)
# Test that admin can set the setting to an unsubscribed private stream as well.
new_notif_stream_id = self.make_stream("private_stream", invite_only=True).id
req = dict(notifications_stream_id=orjson.dumps(new_notif_stream_id).decode())
req = dict(new_stream_announcements_stream_id=orjson.dumps(new_notif_stream_id).decode())
result = self.client_patch("/json/realm", req)
self.assert_json_success(result)
realm = get_realm("zulip")
assert realm.notifications_stream is not None
self.assertEqual(realm.notifications_stream.id, new_notif_stream_id)
assert realm.new_stream_announcements_stream is not None
self.assertEqual(realm.new_stream_announcements_stream.id, new_notif_stream_id)
invalid_notif_stream_id = 1234
req = dict(notifications_stream_id=orjson.dumps(invalid_notif_stream_id).decode())
req = dict(
new_stream_announcements_stream_id=orjson.dumps(invalid_notif_stream_id).decode()
)
result = self.client_patch("/json/realm", req)
self.assert_json_error(result, "Invalid stream ID")
realm = get_realm("zulip")
assert realm.notifications_stream is not None
self.assertNotEqual(realm.notifications_stream.id, invalid_notif_stream_id)
assert realm.new_stream_announcements_stream is not None
self.assertNotEqual(realm.new_stream_announcements_stream.id, invalid_notif_stream_id)
def test_get_default_notifications_stream(self) -> None:
def test_get_default_new_stream_announcements_stream(self) -> None:
realm = get_realm("zulip")
verona = get_stream("verona", realm)
notifications_stream = realm.get_notifications_stream()
assert notifications_stream is not None
self.assertEqual(notifications_stream.id, verona.id)
do_deactivate_stream(notifications_stream, acting_user=None)
self.assertIsNone(realm.get_notifications_stream())
new_stream_announcements_stream = realm.get_new_stream_announcements_stream()
assert new_stream_announcements_stream is not None
self.assertEqual(new_stream_announcements_stream.id, verona.id)
do_deactivate_stream(new_stream_announcements_stream, acting_user=None)
self.assertIsNone(realm.get_new_stream_announcements_stream())
def test_merge_streams(self) -> None:
realm = get_realm("zulip")
denmark = get_stream("Denmark", realm)
cordelia = self.example_user("cordelia")
notifications_stream = realm.get_notifications_stream()
assert notifications_stream is not None
new_stream_announcements_stream = realm.get_new_stream_announcements_stream()
assert new_stream_announcements_stream is not None
create_stream_if_needed(realm, "Atlantis")
self.subscribe(cordelia, "Atlantis")
@ -547,9 +551,9 @@ class RealmTest(ZulipTestCase):
with self.assertRaises(Stream.DoesNotExist):
get_stream("Atlantis", realm)
stats = merge_streams(realm, denmark, notifications_stream)
stats = merge_streams(realm, denmark, new_stream_announcements_stream)
self.assertEqual(stats, (2, 1, 10))
self.assertIsNone(realm.get_notifications_stream())
self.assertIsNone(realm.get_new_stream_announcements_stream())
def test_change_signup_notifications_stream(self) -> None:
# We need an admin user.
@ -965,9 +969,9 @@ class RealmTest(ZulipTestCase):
).exists()
)
assert realm.notifications_stream is not None
self.assertEqual(realm.notifications_stream.name, "general")
self.assertEqual(realm.notifications_stream.realm, realm)
assert realm.new_stream_announcements_stream is not None
self.assertEqual(realm.new_stream_announcements_stream.name, "general")
self.assertEqual(realm.new_stream_announcements_stream.realm, realm)
assert realm.signup_notifications_stream is not None
self.assertEqual(realm.signup_notifications_stream.name, "core team")
@ -1012,9 +1016,9 @@ class RealmTest(ZulipTestCase):
).exists()
)
assert realm.notifications_stream is not None
self.assertEqual(realm.notifications_stream.name, "general")
self.assertEqual(realm.notifications_stream.realm, realm)
assert realm.new_stream_announcements_stream is not None
self.assertEqual(realm.new_stream_announcements_stream.name, "general")
self.assertEqual(realm.new_stream_announcements_stream.realm, realm)
assert realm.signup_notifications_stream is not None
self.assertEqual(realm.signup_notifications_stream.name, "core team")

View File

@ -453,8 +453,8 @@ class TestCreateStreams(ZulipTestCase):
announce_stream = ensure_stream(
realm, "announce", False, "announcements here.", acting_user=None
)
realm.notifications_stream_id = announce_stream.id
realm.save(update_fields=["notifications_stream_id"])
realm.new_stream_announcements_stream_id = announce_stream.id
realm.save(update_fields=["new_stream_announcements_stream_id"])
self.subscribe(iago, announce_stream.name)
self.subscribe(hamlet, announce_stream.name)
@ -4138,8 +4138,8 @@ class SubscriptionAPITest(ZulipTestCase):
other_params = {
"announce": "true",
}
notifications_stream = get_stream(self.streams[0], self.test_realm)
self.test_realm.notifications_stream_id = notifications_stream.id
new_stream_announcements_stream = get_stream(self.streams[0], self.test_realm)
self.test_realm.new_stream_announcements_stream_id = new_stream_announcements_stream.id
self.test_realm.save()
with self.capture_send_event_calls(expected_num_events=7) as events:
@ -4187,8 +4187,8 @@ class SubscriptionAPITest(ZulipTestCase):
current_stream = self.get_streams(invitee)[0]
invite_streams = self.make_random_stream_names([current_stream])[:1]
notifications_stream = get_stream(current_stream, self.test_realm)
self.test_realm.notifications_stream_id = notifications_stream.id
new_stream_announcements_stream = get_stream(current_stream, self.test_realm)
self.test_realm.new_stream_announcements_stream_id = new_stream_announcements_stream.id
self.test_realm.save()
self.common_subscribe_to_streams(
@ -4203,7 +4203,7 @@ class SubscriptionAPITest(ZulipTestCase):
msg = self.get_second_to_last_message()
self.assertEqual(msg.recipient.type, Recipient.STREAM)
self.assertEqual(msg.recipient.type_id, notifications_stream.id)
self.assertEqual(msg.recipient.type_id, new_stream_announcements_stream.id)
self.assertEqual(msg.sender_id, self.notification_bot(self.test_realm).id)
expected_msg = (
f"@_**{invitee_full_name}|{invitee.id}** created a new stream #**{invite_streams[0]}**."
@ -4227,8 +4227,8 @@ class SubscriptionAPITest(ZulipTestCase):
"""
realm = do_create_realm("testrealm", "Test Realm")
notifications_stream = Stream.objects.get(name="general", realm=realm)
realm.notifications_stream = notifications_stream
new_stream_announcements_stream = Stream.objects.get(name="general", realm=realm)
realm.new_stream_announcements_stream = new_stream_announcements_stream
realm.save()
invite_streams = ["cross_stream"]
@ -4248,7 +4248,7 @@ class SubscriptionAPITest(ZulipTestCase):
msg = self.get_second_to_last_message()
self.assertEqual(msg.recipient.type, Recipient.STREAM)
self.assertEqual(msg.recipient.type_id, notifications_stream.id)
self.assertEqual(msg.recipient.type_id, new_stream_announcements_stream.id)
self.assertEqual(msg.sender_id, self.notification_bot(realm).id)
stream_id = Stream.objects.latest("id").id
expected_rendered_msg = f'<p><span class="user-mention silent" data-user-id="{user.id}">{user.full_name}</span> created a new stream <a class="stream" data-stream-id="{stream_id}" href="/#narrow/stream/{stream_id}-{invite_streams[0]}">#{invite_streams[0]}</a>.</p>'
@ -4262,8 +4262,8 @@ class SubscriptionAPITest(ZulipTestCase):
invitee = self.example_user("iago")
current_stream = self.get_streams(invitee)[0]
notifications_stream = get_stream(current_stream, self.test_realm)
self.test_realm.notifications_stream_id = notifications_stream.id
new_stream_announcements_stream = get_stream(current_stream, self.test_realm)
self.test_realm.new_stream_announcements_stream_id = new_stream_announcements_stream.id
self.test_realm.save()
invite_streams = ["strange ) \\ test"]
@ -4277,7 +4277,9 @@ class SubscriptionAPITest(ZulipTestCase):
)
msg = self.get_second_to_last_message()
self.assertEqual(msg.sender_id, self.notification_bot(notifications_stream.realm).id)
self.assertEqual(
msg.sender_id, self.notification_bot(new_stream_announcements_stream.realm).id
)
expected_msg = (
f"@_**{invitee_full_name}|{invitee.id}** created a new stream #**{invite_streams[0]}**."
)
@ -5538,9 +5540,9 @@ class SubscriptionAPITest(ZulipTestCase):
invite_only=True,
)
# Test creating a public stream with announce when realm has a notification stream.
notifications_stream = get_stream(self.streams[0], self.test_realm)
self.test_realm.notifications_stream_id = notifications_stream.id
# Test creating a public stream with announce when realm has a new_stream_announcements_stream.
new_stream_announcements_stream = get_stream(self.streams[0], self.test_realm)
self.test_realm.new_stream_announcements_stream_id = new_stream_announcements_stream.id
self.test_realm.save()
with self.assert_database_query_count(47):
self.common_subscribe_to_streams(

View File

@ -14,7 +14,7 @@ from zerver.actions.realm_settings import (
do_deactivate_realm,
do_reactivate_realm,
do_set_realm_authentication_methods,
do_set_realm_notifications_stream,
do_set_realm_new_stream_announcements_stream,
do_set_realm_property,
do_set_realm_signup_notifications_stream,
do_set_realm_user_default_setting,
@ -110,7 +110,7 @@ def update_realm(
),
# Note: push_notifications_enabled and push_notifications_enabled_end_timestamp
# are not offered here as it is maintained by the server, not via the API.
notifications_stream_id: Optional[int] = REQ(json_validator=check_int, default=None),
new_stream_announcements_stream_id: Optional[int] = REQ(json_validator=check_int, default=None),
signup_notifications_stream_id: Optional[int] = REQ(json_validator=check_int, default=None),
message_retention_days_raw: Optional[Union[int, str]] = REQ(
"message_retention_days", json_validator=check_string_or_int, default=None
@ -389,21 +389,24 @@ def update_realm(
do_set_realm_authentication_methods(realm, authentication_methods, acting_user=user_profile)
data["authentication_methods"] = authentication_methods
# Realm.notifications_stream and Realm.signup_notifications_stream are not boolean,
# Realm.new_stream_announcements_stream and Realm.signup_notifications_stream are not boolean,
# str or integer field, and thus doesn't fit into the do_set_realm_property framework.
if notifications_stream_id is not None and (
realm.notifications_stream is None
or (realm.notifications_stream.id != notifications_stream_id)
if new_stream_announcements_stream_id is not None and (
realm.new_stream_announcements_stream is None
or (realm.new_stream_announcements_stream.id != new_stream_announcements_stream_id)
):
new_notifications_stream = None
if notifications_stream_id >= 0:
(new_notifications_stream, sub) = access_stream_by_id(
user_profile, notifications_stream_id, allow_realm_admin=True
new_stream_announcements_stream_new = None
if new_stream_announcements_stream_id >= 0:
(new_stream_announcements_stream_new, sub) = access_stream_by_id(
user_profile, new_stream_announcements_stream_id, allow_realm_admin=True
)
do_set_realm_notifications_stream(
realm, new_notifications_stream, notifications_stream_id, acting_user=user_profile
do_set_realm_new_stream_announcements_stream(
realm,
new_stream_announcements_stream_new,
new_stream_announcements_stream_id,
acting_user=user_profile,
)
data["notifications_stream_id"] = notifications_stream_id
data["new_stream_announcements_stream_id"] = new_stream_announcements_stream_id
if signup_notifications_stream_id is not None and (
realm.signup_notifications_stream is None

View File

@ -767,9 +767,9 @@ def send_messages_for_new_subscribers(
)
if announce and len(created_streams) > 0:
notifications_stream = user_profile.realm.get_notifications_stream()
if notifications_stream is not None:
with override_language(notifications_stream.realm.default_language):
new_stream_announcements_stream = user_profile.realm.get_new_stream_announcements_stream()
if new_stream_announcements_stream is not None:
with override_language(new_stream_announcements_stream.realm.default_language):
if len(created_streams) > 1:
content = _("{user_name} created the following streams: {stream_str}.")
else:
@ -781,12 +781,14 @@ def send_messages_for_new_subscribers(
stream_str=", ".join(f"#**{s.name}**" for s in created_streams),
)
sender = get_system_bot(settings.NOTIFICATION_BOT, notifications_stream.realm_id)
sender = get_system_bot(
settings.NOTIFICATION_BOT, new_stream_announcements_stream.realm_id
)
notifications.append(
internal_prep_stream_message(
sender=sender,
stream=notifications_stream,
stream=new_stream_announcements_stream,
topic_name=topic_name,
content=content,
),

View File

@ -339,10 +339,10 @@ class Command(BaseCommand):
enable_spectator_access=True,
)
RealmDomain.objects.create(realm=zulip_realm, domain="zulip.com")
assert zulip_realm.notifications_stream is not None
zulip_realm.notifications_stream.name = "Verona"
zulip_realm.notifications_stream.description = "A city in Italy"
zulip_realm.notifications_stream.save(update_fields=["name", "description"])
assert zulip_realm.new_stream_announcements_stream is not None
zulip_realm.new_stream_announcements_stream.name = "Verona"
zulip_realm.new_stream_announcements_stream.description = "A city in Italy"
zulip_realm.new_stream_announcements_stream.save(update_fields=["name", "description"])
realm_user_default = RealmUserDefault.objects.get(realm=zulip_realm)
realm_user_default.enter_sends = True
@ -1027,9 +1027,9 @@ class Command(BaseCommand):
}
bulk_create_streams(zulip_realm, zulip_stream_dict)
# Now that we've created the notifications stream, configure it properly.
zulip_realm.notifications_stream = get_stream("announce", zulip_realm)
zulip_realm.save(update_fields=["notifications_stream"])
# Now that we've created the new_stream_announcements_stream, configure it properly.
zulip_realm.new_stream_announcements_stream = get_stream("announce", zulip_realm)
zulip_realm.save(update_fields=["new_stream_announcements_stream"])
# Add a few default streams
for default_stream_name in ["design", "devel", "social", "support"]: