mirror of https://github.com/zulip/zulip.git
stream_settings: Add 'Default stream' option in create stream UI.
In this commit, we introduce a new option in the stream creation UI - a 'Default stream for new users' checkbox. By default, the checkbox is set to 'off' and is only visible to admins. This allow admins to easily designate a stream as the default stream for new users during stream creation. Fixes #24048.
This commit is contained in:
parent
a81715786c
commit
63173ce1bc
|
@ -23,8 +23,11 @@ format used by the Zulip server that they are interacting with.
|
|||
**Feature level 200**
|
||||
|
||||
* [`PATCH /streams/{stream_id}`](/api/update-stream): Added
|
||||
`is_default_stream` parameter to add or remove the stream as a default
|
||||
stream for new users.
|
||||
`is_default_stream` parameter to change whether the stream is a
|
||||
default stream for new users in the organization.
|
||||
* [`POST /users/me/subscriptions`](/api/subscribe): Added
|
||||
`is_default_stream` parameter which determines whether any streams
|
||||
created by this request will be default streams for new users.
|
||||
|
||||
**Feature level 199**
|
||||
|
||||
|
|
|
@ -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 = 199
|
||||
API_FEATURE_LEVEL = 200
|
||||
|
||||
# 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
|
||||
|
|
|
@ -217,6 +217,9 @@ function create_stream() {
|
|||
data.invite_only = JSON.stringify(invite_only);
|
||||
data.history_public_to_subscribers = JSON.stringify(history_public_to_subscribers);
|
||||
|
||||
const default_stream = $("#stream_creation_form .is_default_stream").prop("checked");
|
||||
data.is_default_stream = JSON.stringify(default_stream);
|
||||
|
||||
const stream_post_policy = Number.parseInt(
|
||||
$("#stream_creation_form select[name=stream-post-policy]").val(),
|
||||
10,
|
||||
|
@ -370,8 +373,10 @@ export function show_new_stream_modal() {
|
|||
true,
|
||||
);
|
||||
|
||||
// set default state for "announce stream" option.
|
||||
// set default state for "announce stream" and "default stream" option.
|
||||
$("#stream_creation_form .default-stream input").prop("checked", false);
|
||||
update_announce_stream_state();
|
||||
stream_ui_updates.update_default_stream_and_stream_privacy_state($("#stream-creation"));
|
||||
clear_error_display();
|
||||
}
|
||||
|
||||
|
@ -381,7 +386,14 @@ export function set_up_handlers() {
|
|||
|
||||
const $container = $("#stream-creation").expectOne();
|
||||
|
||||
$container.on("change", ".stream-privacy-values input", update_announce_stream_state);
|
||||
$container.on("change", ".stream-privacy-values input", () => {
|
||||
update_announce_stream_state();
|
||||
stream_ui_updates.update_default_stream_and_stream_privacy_state($container);
|
||||
});
|
||||
|
||||
$container.on("change", ".default-stream input", () => {
|
||||
stream_ui_updates.update_default_stream_and_stream_privacy_state($container);
|
||||
});
|
||||
|
||||
$container.on("click", ".finalize_create_stream", (e) => {
|
||||
e.preventDefault();
|
||||
|
|
|
@ -717,6 +717,7 @@ export function setup_page(callback) {
|
|||
stream_privacy_policy_values: stream_data.stream_privacy_policy_values,
|
||||
stream_privacy_policy,
|
||||
stream_post_policy_values: stream_data.stream_post_policy_values,
|
||||
check_default_stream: false,
|
||||
zulip_plan_is_not_limited: page_params.zulip_plan_is_not_limited,
|
||||
org_level_message_retention_setting:
|
||||
stream_edit.get_display_text_for_realm_message_retention_setting(),
|
||||
|
|
|
@ -115,6 +115,15 @@ export function update_regular_sub_settings(sub) {
|
|||
|
||||
export function update_default_stream_and_stream_privacy_state($container) {
|
||||
const $default_stream = $container.find(".default-stream");
|
||||
const is_stream_creation = $container.attr("id") === "stream-creation";
|
||||
|
||||
// In the stream creation UI, if the user is a non-admin hide the
|
||||
// "Default stream for new users" widget
|
||||
if (is_stream_creation && !page_params.is_admin) {
|
||||
$default_stream.hide();
|
||||
return;
|
||||
}
|
||||
|
||||
const privacy_type = $container.find("input[type=radio][name=privacy]:checked").val();
|
||||
const is_invite_only =
|
||||
privacy_type === "invite-only" || privacy_type === "invite-only-public-history";
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
{{#if is_stream_edit}}
|
||||
<div class="default-stream">
|
||||
{{> ../settings/settings_checkbox
|
||||
prefix="id_"
|
||||
|
@ -26,7 +25,6 @@
|
|||
help_link="/help/set-default-streams-for-new-users"
|
||||
}}
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
<div class="input-group">
|
||||
<label class="dropdown-title">{{t 'Who can post to the stream?'}}
|
||||
|
|
|
@ -670,6 +670,7 @@ def list_to_streams(
|
|||
user_profile: UserProfile,
|
||||
autocreate: bool = False,
|
||||
unsubscribing_others: bool = False,
|
||||
is_default_stream: bool = False,
|
||||
) -> Tuple[List[Stream], List[Stream]]:
|
||||
"""Converts list of dicts to a list of Streams, validating input in the process
|
||||
|
||||
|
@ -736,6 +737,10 @@ def list_to_streams(
|
|||
raise JsonableError(_("Insufficient permission"))
|
||||
if not invite_only and not user_profile.can_create_public_streams():
|
||||
raise JsonableError(_("Insufficient permission"))
|
||||
if is_default_stream and not user_profile.is_realm_admin:
|
||||
raise JsonableError(_("Insufficient permission"))
|
||||
if invite_only and is_default_stream:
|
||||
raise JsonableError(_("A default stream cannot be private."))
|
||||
|
||||
if not autocreate:
|
||||
raise JsonableError(
|
||||
|
|
|
@ -8657,6 +8657,21 @@ paths:
|
|||
type: boolean
|
||||
default: false
|
||||
example: true
|
||||
- name: is_default_stream
|
||||
in: query
|
||||
description: |
|
||||
This parameter determines whether any newly created streams will be
|
||||
added as [default streams][default-streams] for new users joining
|
||||
the organization.
|
||||
|
||||
[default-streams]: /help/set-default-streams-for-new-users
|
||||
|
||||
**Changes**: New in Zulip 8.0 (feature level 200). Previously, default stream status
|
||||
could only be changed using the [dedicated API endpoint](/api/add-default-stream).
|
||||
schema:
|
||||
type: boolean
|
||||
default: false
|
||||
example: true
|
||||
- $ref: "#/components/parameters/HistoryPublicToSubscribers"
|
||||
- $ref: "#/components/parameters/StreamPostPolicy"
|
||||
- $ref: "#/components/parameters/MessageRetentionDays"
|
||||
|
|
|
@ -383,6 +383,47 @@ class TestCreateStreams(ZulipTestCase):
|
|||
if stream.name == "publictrywithouthistory":
|
||||
self.assertTrue(stream.history_public_to_subscribers)
|
||||
|
||||
def test_add_stream_as_default_on_stream_creation(self) -> None:
|
||||
user_profile = self.example_user("hamlet")
|
||||
self.login_user(user_profile)
|
||||
realm = user_profile.realm
|
||||
|
||||
post_data = {
|
||||
"subscriptions": orjson.dumps(
|
||||
[{"name": "default_stream", "description": "This stream is default for new users"}]
|
||||
).decode(),
|
||||
"is_default_stream": orjson.dumps(True).decode(),
|
||||
}
|
||||
result = self.api_post(
|
||||
user_profile, "/api/v1/users/me/subscriptions", post_data, subdomain="zulip"
|
||||
)
|
||||
self.assert_json_error(result, "Insufficient permission")
|
||||
|
||||
do_change_user_role(user_profile, UserProfile.ROLE_REALM_ADMINISTRATOR, acting_user=None)
|
||||
result = self.api_post(
|
||||
user_profile, "/api/v1/users/me/subscriptions", post_data, subdomain="zulip"
|
||||
)
|
||||
self.assert_json_success(result)
|
||||
default_stream = get_stream("default_stream", realm)
|
||||
self.assertTrue(default_stream.id in get_default_stream_ids_for_realm(realm.id))
|
||||
|
||||
post_data = {
|
||||
"subscriptions": orjson.dumps(
|
||||
[
|
||||
{
|
||||
"name": "private_default_stream",
|
||||
"description": "This stream is private and default for new users",
|
||||
}
|
||||
]
|
||||
).decode(),
|
||||
"invite_only": orjson.dumps(True).decode(),
|
||||
"is_default_stream": orjson.dumps(True).decode(),
|
||||
}
|
||||
result = self.api_post(
|
||||
user_profile, "/api/v1/users/me/subscriptions", post_data, subdomain="zulip"
|
||||
)
|
||||
self.assert_json_error(result, "A default stream cannot be private.")
|
||||
|
||||
def test_history_public_to_subscribers_zephyr_realm(self) -> None:
|
||||
realm = get_realm("zephyr")
|
||||
|
||||
|
|
|
@ -578,6 +578,7 @@ def add_subscriptions_backend(
|
|||
),
|
||||
invite_only: bool = REQ(json_validator=check_bool, default=False),
|
||||
is_web_public: bool = REQ(json_validator=check_bool, default=False),
|
||||
is_default_stream: bool = REQ(json_validator=check_bool, default=False),
|
||||
stream_post_policy: int = REQ(
|
||||
json_validator=check_int_in(Stream.STREAM_POST_POLICY_TYPES),
|
||||
default=Stream.STREAM_POST_POLICY_EVERYONE,
|
||||
|
@ -660,7 +661,9 @@ def add_subscriptions_backend(
|
|||
# Validation of the streams arguments, including enforcement of
|
||||
# can_create_streams policy and check_stream_name policy is inside
|
||||
# list_to_streams.
|
||||
existing_streams, created_streams = list_to_streams(stream_dicts, user_profile, autocreate=True)
|
||||
existing_streams, created_streams = list_to_streams(
|
||||
stream_dicts, user_profile, autocreate=True, is_default_stream=is_default_stream
|
||||
)
|
||||
authorized_streams, unauthorized_streams = filter_stream_authorization(
|
||||
user_profile, existing_streams
|
||||
)
|
||||
|
@ -682,6 +685,10 @@ def add_subscriptions_backend(
|
|||
_("You can only invite other Zephyr mirroring users to private streams.")
|
||||
)
|
||||
|
||||
if is_default_stream:
|
||||
for stream in created_streams:
|
||||
do_add_default_stream(stream)
|
||||
|
||||
(subscribed, already_subscribed) = bulk_add_subscriptions(
|
||||
realm, streams, subscribers, acting_user=user_profile, color_map=color_map
|
||||
)
|
||||
|
|
Loading…
Reference in New Issue