2021-03-11 05:43:45 +01:00
|
|
|
import $ from "jquery";
|
|
|
|
|
2021-02-10 16:55:52 +01:00
|
|
|
import render_announce_stream_docs from "../templates/announce_stream_docs.hbs";
|
|
|
|
import render_new_stream_users from "../templates/new_stream_users.hbs";
|
|
|
|
import render_subscription_invites_warning_modal from "../templates/subscription_invites_warning_modal.hbs";
|
2020-08-01 03:43:15 +02:00
|
|
|
|
2021-03-16 23:38:59 +01:00
|
|
|
import * as blueslip from "./blueslip";
|
2021-02-28 00:39:51 +01:00
|
|
|
import * as channel from "./channel";
|
2021-02-28 00:36:14 +01:00
|
|
|
import * as loading from "./loading";
|
2021-02-10 16:55:52 +01:00
|
|
|
import * as peer_data from "./peer_data";
|
|
|
|
import * as people from "./people";
|
2021-02-28 00:53:59 +01:00
|
|
|
import * as stream_data from "./stream_data";
|
2021-02-28 21:32:47 +01:00
|
|
|
import * as subs from "./subs";
|
2021-02-28 00:58:55 +01:00
|
|
|
import * as ui_report from "./ui_report";
|
2020-08-20 21:24:06 +02:00
|
|
|
|
2019-11-02 00:06:25 +01:00
|
|
|
let created_stream;
|
2017-04-22 22:22:25 +02:00
|
|
|
|
2021-02-10 16:55:52 +01:00
|
|
|
export function reset_created_stream() {
|
2017-04-22 22:22:25 +02:00
|
|
|
created_stream = undefined;
|
2021-02-10 16:55:52 +01:00
|
|
|
}
|
2017-04-22 22:22:25 +02:00
|
|
|
|
2021-02-10 16:55:52 +01:00
|
|
|
export function set_name(stream) {
|
2017-04-22 22:22:25 +02:00
|
|
|
created_stream = stream;
|
2021-02-10 16:55:52 +01:00
|
|
|
}
|
2017-04-22 22:22:25 +02:00
|
|
|
|
2021-02-10 16:55:52 +01:00
|
|
|
export function get_name() {
|
2017-04-22 22:22:25 +02:00
|
|
|
return created_stream;
|
2021-02-10 16:55:52 +01:00
|
|
|
}
|
2017-04-22 22:22:25 +02:00
|
|
|
|
2020-07-23 02:37:12 +02:00
|
|
|
class StreamSubscriptionError {
|
|
|
|
report_no_subs_to_stream() {
|
2020-07-15 00:34:28 +02:00
|
|
|
$("#stream_subscription_error").text(
|
|
|
|
i18n.t("You cannot create a stream with no subscribers!"),
|
|
|
|
);
|
2018-01-21 09:34:50 +01:00
|
|
|
$("#stream_subscription_error").show();
|
2020-07-23 02:37:12 +02:00
|
|
|
}
|
2018-01-21 09:34:50 +01:00
|
|
|
|
2020-07-23 02:37:12 +02:00
|
|
|
cant_create_stream_without_susbscribing() {
|
2020-07-15 00:34:28 +02:00
|
|
|
$("#stream_subscription_error").text(
|
|
|
|
i18n.t(
|
|
|
|
"You must be an organization administrator to create a stream without subscribing.",
|
|
|
|
),
|
|
|
|
);
|
2018-02-03 09:04:45 +01:00
|
|
|
$("#stream_subscription_error").show();
|
2020-07-23 02:37:12 +02:00
|
|
|
}
|
2018-02-03 09:04:45 +01:00
|
|
|
|
2020-07-23 02:37:12 +02:00
|
|
|
clear_errors() {
|
2018-01-21 09:34:50 +01:00
|
|
|
$("#stream_subscription_error").hide();
|
2020-07-23 02:37:12 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
const stream_subscription_error = new StreamSubscriptionError();
|
2018-01-21 09:34:50 +01:00
|
|
|
|
2020-07-23 02:39:41 +02:00
|
|
|
class StreamNameError {
|
|
|
|
report_already_exists() {
|
2017-04-28 22:04:32 +02:00
|
|
|
$("#stream_name_error").text(i18n.t("A stream with this name already exists"));
|
|
|
|
$("#stream_name_error").show();
|
2020-07-23 02:39:41 +02:00
|
|
|
}
|
2017-04-28 22:04:32 +02:00
|
|
|
|
2020-07-23 02:39:41 +02:00
|
|
|
clear_errors() {
|
2017-04-28 22:04:32 +02:00
|
|
|
$("#stream_name_error").hide();
|
2020-07-23 02:39:41 +02:00
|
|
|
}
|
2017-04-28 22:04:32 +02:00
|
|
|
|
2020-07-23 02:39:41 +02:00
|
|
|
report_empty_stream() {
|
2017-04-28 22:04:32 +02:00
|
|
|
$("#stream_name_error").text(i18n.t("A stream needs to have a name"));
|
|
|
|
$("#stream_name_error").show();
|
2020-07-23 02:39:41 +02:00
|
|
|
}
|
2017-04-28 22:04:32 +02:00
|
|
|
|
2020-07-23 02:39:41 +02:00
|
|
|
select() {
|
2020-07-20 21:24:26 +02:00
|
|
|
$("#create_stream_name").trigger("focus").trigger("select");
|
2020-07-23 02:39:41 +02:00
|
|
|
}
|
2017-04-28 22:04:32 +02:00
|
|
|
|
2020-07-23 02:39:41 +02:00
|
|
|
pre_validate(stream_name) {
|
2017-04-28 22:04:32 +02:00
|
|
|
// Don't worry about empty strings...we just want to call this
|
|
|
|
// to warn users early before they start doing too much work
|
|
|
|
// after they make the effort to type in a stream name. (The
|
|
|
|
// use case here is that I go to create a stream, only to find
|
|
|
|
// out it already exists, and I was just too lazy to look at
|
|
|
|
// the public streams that I'm not subscribed to yet. Once I
|
|
|
|
// realize the stream already exists, I may want to cancel.)
|
|
|
|
if (stream_name && stream_data.get_sub(stream_name)) {
|
2020-07-23 02:39:41 +02:00
|
|
|
this.report_already_exists();
|
2017-04-28 22:04:32 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-07-23 02:39:41 +02:00
|
|
|
this.clear_errors();
|
|
|
|
}
|
2017-04-28 22:04:32 +02:00
|
|
|
|
2020-07-23 02:39:41 +02:00
|
|
|
validate_for_submit(stream_name) {
|
2017-04-28 22:04:32 +02:00
|
|
|
if (!stream_name) {
|
2020-07-23 02:39:41 +02:00
|
|
|
this.report_empty_stream();
|
|
|
|
this.select();
|
2017-04-28 22:04:32 +02:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (stream_data.get_sub(stream_name)) {
|
2020-07-23 02:39:41 +02:00
|
|
|
this.report_already_exists();
|
|
|
|
this.select();
|
2017-04-28 22:04:32 +02:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// If we got this far, then we think we have a new unique stream
|
|
|
|
// name, so we'll submit to the server. (It's still plausible,
|
|
|
|
// however, that there's some invite-only stream that we don't
|
|
|
|
// know about locally that will cause a name collision.)
|
|
|
|
return true;
|
2020-07-23 02:39:41 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
const stream_name_error = new StreamNameError();
|
2017-04-28 22:04:32 +02:00
|
|
|
|
2017-04-22 22:22:25 +02:00
|
|
|
// Within the new stream modal...
|
|
|
|
function update_announce_stream_state() {
|
2017-05-16 18:34:36 +02:00
|
|
|
// If there is no notifications_stream, we simply hide the widget.
|
2020-04-15 18:29:26 +02:00
|
|
|
if (!stream_data.realm_has_notifications_stream()) {
|
2020-07-15 01:29:15 +02:00
|
|
|
$("#announce-new-stream").hide();
|
2017-05-16 18:34:36 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2017-12-29 11:02:24 +01:00
|
|
|
// If the stream is invite only, disable the "Announce stream" option.
|
|
|
|
// Otherwise enable it.
|
2020-07-15 01:29:15 +02:00
|
|
|
const announce_stream_checkbox = $("#announce-new-stream input");
|
|
|
|
const announce_stream_label = $("#announce-new-stream");
|
2019-11-02 00:06:25 +01:00
|
|
|
let disable_it = false;
|
2020-07-15 01:29:15 +02:00
|
|
|
const privacy_type = $("input:radio[name=privacy]:checked").val();
|
2020-07-15 00:34:28 +02:00
|
|
|
const is_invite_only =
|
|
|
|
privacy_type === "invite-only" || privacy_type === "invite-only-public-history";
|
2017-12-29 11:06:12 +01:00
|
|
|
announce_stream_label.removeClass("control-label-disabled");
|
2017-04-22 22:22:25 +02:00
|
|
|
|
|
|
|
if (is_invite_only) {
|
|
|
|
disable_it = true;
|
2020-07-15 01:29:15 +02:00
|
|
|
announce_stream_checkbox.prop("checked", false);
|
2017-12-29 11:06:12 +01:00
|
|
|
announce_stream_label.addClass("control-label-disabled");
|
2017-04-22 22:22:25 +02:00
|
|
|
}
|
|
|
|
|
2020-07-15 01:29:15 +02:00
|
|
|
announce_stream_checkbox.prop("disabled", disable_it);
|
|
|
|
$("#announce-new-stream").show();
|
2017-04-22 22:22:25 +02:00
|
|
|
}
|
|
|
|
|
2017-07-08 04:04:55 +02:00
|
|
|
function get_principals() {
|
2020-07-02 01:39:34 +02:00
|
|
|
return Array.from($("#stream_creation_form input:checkbox[name=user]:checked"), (elem) => {
|
2020-02-08 02:24:21 +01:00
|
|
|
const label = $(elem).closest(".add-user-label");
|
2020-10-07 09:17:30 +02:00
|
|
|
return Number.parseInt(label.attr("data-user-id"), 10);
|
2020-02-08 02:24:21 +01:00
|
|
|
});
|
2017-07-08 04:04:55 +02:00
|
|
|
}
|
|
|
|
|
2017-07-08 04:07:36 +02:00
|
|
|
function create_stream() {
|
2020-02-08 06:45:49 +01:00
|
|
|
const data = {};
|
2020-07-22 03:39:41 +02:00
|
|
|
const stream_name = $("#create_stream_name").val().trim();
|
|
|
|
const description = $("#create_stream_description").val().trim();
|
2020-02-08 06:45:49 +01:00
|
|
|
created_stream = stream_name;
|
|
|
|
|
|
|
|
// Even though we already check to make sure that while typing the user cannot enter
|
2020-08-11 02:09:14 +02:00
|
|
|
// newline characters (by pressing the Enter key) it would still be possible to copy
|
2020-02-08 06:45:49 +01:00
|
|
|
// and paste over a description with newline characters in it. Prevent that.
|
2020-07-15 01:29:15 +02:00
|
|
|
if (description.includes("\n")) {
|
2021-01-27 08:16:28 +01:00
|
|
|
ui_report.client_error(
|
2020-07-15 00:34:28 +02:00
|
|
|
i18n.t("The stream description cannot contain newline characters."),
|
|
|
|
$(".stream_create_info"),
|
|
|
|
);
|
2020-09-24 07:50:36 +02:00
|
|
|
return undefined;
|
2020-02-08 06:45:49 +01:00
|
|
|
}
|
2020-07-20 22:18:43 +02:00
|
|
|
data.subscriptions = JSON.stringify([{name: stream_name, description}]);
|
2017-07-08 04:07:36 +02:00
|
|
|
|
2019-11-02 00:06:25 +01:00
|
|
|
let invite_only;
|
|
|
|
let history_public_to_subscribers;
|
2020-07-15 01:29:15 +02:00
|
|
|
const privacy_setting = $("#stream_creation_form input[name=privacy]:checked").val();
|
2020-02-04 21:50:55 +01:00
|
|
|
|
2020-07-15 01:29:15 +02:00
|
|
|
if (privacy_setting === "invite-only") {
|
2018-05-03 18:52:39 +02:00
|
|
|
invite_only = true;
|
|
|
|
history_public_to_subscribers = false;
|
2020-07-15 01:29:15 +02:00
|
|
|
} else if (privacy_setting === "invite-only-public-history") {
|
2018-05-03 18:52:39 +02:00
|
|
|
invite_only = true;
|
|
|
|
history_public_to_subscribers = true;
|
|
|
|
} else {
|
|
|
|
invite_only = false;
|
|
|
|
history_public_to_subscribers = true;
|
|
|
|
}
|
2020-02-08 06:45:49 +01:00
|
|
|
data.invite_only = JSON.stringify(invite_only);
|
|
|
|
data.history_public_to_subscribers = JSON.stringify(history_public_to_subscribers);
|
2018-05-03 18:52:39 +02:00
|
|
|
|
2020-10-07 09:17:30 +02:00
|
|
|
const stream_post_policy = Number.parseInt(
|
2020-07-15 00:34:28 +02:00
|
|
|
$("#stream_creation_form input[name=stream-post-policy]:checked").val(),
|
|
|
|
10,
|
|
|
|
);
|
2020-02-08 06:45:49 +01:00
|
|
|
|
|
|
|
data.stream_post_policy = JSON.stringify(stream_post_policy);
|
2017-07-08 04:07:36 +02:00
|
|
|
|
2020-07-15 00:34:28 +02:00
|
|
|
let message_retention_selection = $(
|
|
|
|
"#stream_creation_form select[name=stream_message_retention_setting]",
|
|
|
|
).val();
|
2020-06-15 17:00:00 +02:00
|
|
|
if (message_retention_selection === "retain_for_period") {
|
2020-10-07 09:17:30 +02:00
|
|
|
message_retention_selection = Number.parseInt(
|
2020-07-15 00:34:28 +02:00
|
|
|
$("#stream_creation_form input[name=stream-message-retention-days]").val(),
|
|
|
|
10,
|
|
|
|
);
|
2020-06-15 17:00:00 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
data.message_retention_days = JSON.stringify(message_retention_selection);
|
|
|
|
|
2020-07-15 00:34:28 +02:00
|
|
|
const announce =
|
|
|
|
stream_data.realm_has_notifications_stream() &&
|
2020-07-15 01:29:15 +02:00
|
|
|
$("#announce-new-stream input").prop("checked");
|
2020-02-08 06:45:49 +01:00
|
|
|
data.announce = JSON.stringify(announce);
|
2017-07-08 04:07:36 +02:00
|
|
|
|
2020-02-08 06:45:49 +01:00
|
|
|
// TODO: We can eliminate the user_ids -> principals conversion
|
|
|
|
// once we upgrade the backend to accept user_ids.
|
|
|
|
const user_ids = get_principals();
|
2020-06-03 21:38:43 +02:00
|
|
|
data.principals = JSON.stringify(user_ids);
|
2019-02-20 18:36:46 +01:00
|
|
|
|
2020-07-15 01:29:15 +02:00
|
|
|
loading.make_indicator($("#stream_creating_indicator"), {text: i18n.t("Creating stream...")});
|
2017-11-04 19:19:12 +01:00
|
|
|
|
2020-02-08 06:45:49 +01:00
|
|
|
// Subscribe yourself and possible other people to a new stream.
|
|
|
|
return channel.post({
|
|
|
|
url: "/json/users/me/subscriptions",
|
2020-07-20 22:18:43 +02:00
|
|
|
data,
|
|
|
|
success() {
|
2020-02-08 06:45:49 +01:00
|
|
|
$("#create_stream_name").val("");
|
|
|
|
$("#create_stream_description").val("");
|
|
|
|
ui_report.success(i18n.t("Stream successfully created!"), $(".stream_create_info"));
|
2020-07-15 01:29:15 +02:00
|
|
|
loading.destroy_indicator($("#stream_creating_indicator"));
|
2020-02-08 06:45:49 +01:00
|
|
|
// The rest of the work is done via the subscribe event we will get
|
|
|
|
},
|
2020-07-20 22:18:43 +02:00
|
|
|
error(xhr) {
|
2020-02-08 06:45:49 +01:00
|
|
|
const msg = JSON.parse(xhr.responseText).msg;
|
2020-07-15 01:29:15 +02:00
|
|
|
if (msg.includes("access")) {
|
2020-02-08 06:45:49 +01:00
|
|
|
// If we can't access the stream, we can safely assume it's
|
|
|
|
// a duplicate stream that we are not invited to.
|
|
|
|
//
|
|
|
|
// BUG: This check should be using error codes, not
|
|
|
|
// parsing the error string, so it works correctly
|
|
|
|
// with i18n. And likely we should be reporting the
|
|
|
|
// error text directly rather than turning it into
|
|
|
|
// "Error creating stream"?
|
|
|
|
stream_name_error.report_already_exists(stream_name);
|
2020-07-20 21:24:26 +02:00
|
|
|
stream_name_error.trigger("select");
|
2020-02-08 06:45:49 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
ui_report.error(i18n.t("Error creating stream"), xhr, $(".stream_create_info"));
|
2020-07-15 01:29:15 +02:00
|
|
|
loading.destroy_indicator($("#stream_creating_indicator"));
|
2020-02-08 06:45:49 +01:00
|
|
|
},
|
|
|
|
});
|
2017-07-08 04:07:36 +02:00
|
|
|
}
|
2017-06-02 15:06:33 +02:00
|
|
|
|
2021-02-10 16:55:52 +01:00
|
|
|
export function new_stream_clicked(stream_name) {
|
2017-04-22 22:22:25 +02:00
|
|
|
// this changes the tab switcher (settings/preview) which isn't necessary
|
|
|
|
// to a add new stream title.
|
2020-07-08 23:54:13 +02:00
|
|
|
subs.show_subs_pane.create_stream();
|
2017-04-22 22:22:25 +02:00
|
|
|
$(".stream-row.active").removeClass("active");
|
|
|
|
|
2020-07-15 01:29:15 +02:00
|
|
|
if (stream_name !== "") {
|
|
|
|
$("#create_stream_name").val(stream_name);
|
2017-04-22 22:22:25 +02:00
|
|
|
}
|
2021-02-10 16:55:52 +01:00
|
|
|
show_new_stream_modal();
|
2020-11-01 04:05:19 +01:00
|
|
|
$("#create_stream_name").trigger("focus");
|
2021-02-10 16:55:52 +01:00
|
|
|
}
|
2017-04-22 22:22:25 +02:00
|
|
|
|
2018-03-10 03:14:48 +01:00
|
|
|
function clear_error_display() {
|
|
|
|
stream_name_error.clear_errors();
|
|
|
|
$(".stream_create_info").hide();
|
|
|
|
stream_subscription_error.clear_errors();
|
|
|
|
}
|
|
|
|
|
2021-02-10 16:55:52 +01:00
|
|
|
export function show_new_stream_modal() {
|
2017-04-22 22:22:25 +02:00
|
|
|
$("#stream-creation").removeClass("hide");
|
|
|
|
$(".right .settings").hide();
|
2017-11-26 12:57:03 +01:00
|
|
|
|
2021-02-04 00:30:50 +01:00
|
|
|
const html = blueslip.measure_time("render new stream users", () => {
|
2021-01-31 13:57:52 +01:00
|
|
|
const all_users = people.get_people_for_stream_create();
|
|
|
|
// Add current user on top of list
|
|
|
|
all_users.unshift(people.get_by_user_id(page_params.user_id));
|
2021-02-04 00:30:50 +01:00
|
|
|
return render_new_stream_users({
|
2021-01-31 13:57:52 +01:00
|
|
|
users: all_users,
|
|
|
|
streams: stream_data.get_streams_for_settings_page(),
|
|
|
|
is_admin: page_params.is_admin,
|
|
|
|
});
|
2018-03-25 18:11:23 +02:00
|
|
|
});
|
|
|
|
|
2020-07-15 01:29:15 +02:00
|
|
|
const container = $("#people_to_add");
|
2018-03-25 18:11:23 +02:00
|
|
|
container.html(html);
|
2021-02-10 16:55:52 +01:00
|
|
|
create_handlers_for_users(container);
|
2017-04-22 22:22:25 +02:00
|
|
|
|
|
|
|
// Make the options default to the same each time:
|
|
|
|
// public, "announce stream" on.
|
2020-07-15 01:29:15 +02:00
|
|
|
$("#make-invite-only input:radio[value=public]").prop("checked", true);
|
2020-06-15 17:00:00 +02:00
|
|
|
$("#stream_creation_form .stream-message-retention-days-input").hide();
|
|
|
|
$("#stream_creation_form select[name=stream_message_retention_setting]").val("realm_default");
|
2017-05-16 18:34:36 +02:00
|
|
|
|
2020-04-15 18:29:26 +02:00
|
|
|
if (stream_data.realm_has_notifications_stream()) {
|
2020-07-15 01:29:15 +02:00
|
|
|
$("#announce-new-stream").show();
|
|
|
|
$("#announce-new-stream input").prop("disabled", false);
|
|
|
|
$("#announce-new-stream input").prop("checked", true);
|
2017-05-16 18:34:36 +02:00
|
|
|
} else {
|
2020-07-15 01:29:15 +02:00
|
|
|
$("#announce-new-stream").hide();
|
2017-05-16 18:34:36 +02:00
|
|
|
}
|
2018-03-10 03:14:48 +01:00
|
|
|
clear_error_display();
|
2017-04-22 22:22:25 +02:00
|
|
|
|
2020-07-15 01:29:15 +02:00
|
|
|
$("#stream-checkboxes label.checkbox").on("change", function (e) {
|
2019-11-02 00:06:25 +01:00
|
|
|
const elem = $(this);
|
2020-10-07 09:17:30 +02:00
|
|
|
const stream_id = Number.parseInt(elem.attr("data-stream-id"), 10);
|
2020-07-15 01:29:15 +02:00
|
|
|
const checked = elem.find("input").prop("checked");
|
2021-01-12 21:38:01 +01:00
|
|
|
const subscriber_ids = new Set(peer_data.get_subscribers(stream_id));
|
2017-04-22 22:22:25 +02:00
|
|
|
|
2020-07-15 01:29:15 +02:00
|
|
|
$("#user-checkboxes label.checkbox").each(function () {
|
2019-11-02 00:06:25 +01:00
|
|
|
const user_elem = $(this);
|
2020-10-07 09:17:30 +02:00
|
|
|
const user_id = Number.parseInt(user_elem.attr("data-user-id"), 10);
|
2017-04-22 22:22:25 +02:00
|
|
|
|
|
|
|
if (subscriber_ids.has(user_id)) {
|
2020-07-15 01:29:15 +02:00
|
|
|
user_elem.find("input").prop("checked", checked);
|
2017-04-22 22:22:25 +02:00
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
e.preventDefault();
|
|
|
|
});
|
2021-02-10 16:55:52 +01:00
|
|
|
}
|
2017-04-22 22:22:25 +02:00
|
|
|
|
2021-02-10 16:55:52 +01:00
|
|
|
export function create_handlers_for_users(container) {
|
2018-03-25 18:11:23 +02:00
|
|
|
// container should be $('#people_to_add')...see caller to verify
|
2020-07-15 01:29:15 +02:00
|
|
|
container.on("change", "#user-checkboxes input", update_announce_stream_state);
|
2017-04-22 22:22:25 +02:00
|
|
|
|
|
|
|
// 'Check all' and 'Uncheck all' visible users
|
2020-07-15 01:29:15 +02:00
|
|
|
container.on("click", ".subs_set_all_users", (e) => {
|
|
|
|
$("#user-checkboxes .checkbox").each((idx, li) => {
|
2020-07-16 23:29:01 +02:00
|
|
|
if (li.style.display !== "none") {
|
2020-07-15 01:29:15 +02:00
|
|
|
$(li.firstElementChild).prop("checked", true);
|
2017-04-22 22:22:25 +02:00
|
|
|
}
|
|
|
|
});
|
|
|
|
e.preventDefault();
|
|
|
|
update_announce_stream_state();
|
|
|
|
});
|
|
|
|
|
2020-07-15 01:29:15 +02:00
|
|
|
container.on("click", ".subs_unset_all_users", (e) => {
|
|
|
|
$("#user-checkboxes .checkbox").each((idx, li) => {
|
2018-02-03 09:04:45 +01:00
|
|
|
if (li.style.display !== "none") {
|
|
|
|
// The first checkbox is the one for ourself; this is the code path for:
|
|
|
|
// `stream_subscription_error.cant_create_stream_without_susbscribing`
|
|
|
|
if (idx === 0 && !page_params.is_admin) {
|
|
|
|
return;
|
|
|
|
}
|
2020-07-15 01:29:15 +02:00
|
|
|
$(li.firstElementChild).prop("checked", false);
|
2017-04-22 22:22:25 +02:00
|
|
|
}
|
|
|
|
});
|
|
|
|
e.preventDefault();
|
|
|
|
update_announce_stream_state();
|
|
|
|
});
|
|
|
|
|
2020-07-15 01:29:15 +02:00
|
|
|
container.on("click", "#copy-from-stream-expand-collapse", (e) => {
|
|
|
|
$("#stream-checkboxes").toggle();
|
|
|
|
$("#copy-from-stream-expand-collapse .toggle").toggleClass("fa-caret-right fa-caret-down");
|
2017-04-22 22:22:25 +02:00
|
|
|
e.preventDefault();
|
|
|
|
});
|
|
|
|
|
2020-10-23 02:43:28 +02:00
|
|
|
// Search people or streams
|
2020-07-15 01:29:15 +02:00
|
|
|
container.on("input", ".add-user-list-filter", (e) => {
|
2019-11-02 00:06:25 +01:00
|
|
|
const user_list = $(".add-user-list-filter");
|
2017-04-22 22:22:25 +02:00
|
|
|
if (user_list === 0) {
|
|
|
|
return;
|
|
|
|
}
|
2019-11-02 00:06:25 +01:00
|
|
|
const search_term = user_list.expectOne().val().trim();
|
|
|
|
const search_terms = search_term.toLowerCase().split(",");
|
2017-04-22 22:22:25 +02:00
|
|
|
|
|
|
|
(function filter_user_checkboxes() {
|
2019-11-02 00:06:25 +01:00
|
|
|
const user_labels = $("#user-checkboxes label.add-user-label");
|
2017-04-22 22:22:25 +02:00
|
|
|
|
2020-07-15 01:29:15 +02:00
|
|
|
if (search_term === "") {
|
|
|
|
user_labels.css({display: "block"});
|
2017-04-22 22:22:25 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-01-01 23:20:49 +01:00
|
|
|
const users = people.get_people_for_stream_create();
|
2019-11-02 00:06:25 +01:00
|
|
|
const filtered_users = people.filter_people_by_search_terms(users, search_terms);
|
2017-04-22 22:22:25 +02:00
|
|
|
|
|
|
|
// Be careful about modifying the follow code. A naive implementation
|
|
|
|
// will work very poorly with a large user population (~1000 users).
|
|
|
|
//
|
|
|
|
// I tested using: `./manage.py populate_db --extra-users 3500`
|
|
|
|
//
|
|
|
|
// This would break the previous implementation, whereas the new
|
|
|
|
// implementation is merely sluggish.
|
|
|
|
user_labels.each(function () {
|
2019-11-02 00:06:25 +01:00
|
|
|
const elem = $(this);
|
2020-10-07 09:17:30 +02:00
|
|
|
const user_id = Number.parseInt(elem.attr("data-user-id"), 10);
|
2019-11-02 00:06:25 +01:00
|
|
|
const user_checked = filtered_users.has(user_id);
|
|
|
|
const display = user_checked ? "block" : "none";
|
2020-07-20 22:18:43 +02:00
|
|
|
elem.css({display});
|
2017-04-22 22:22:25 +02:00
|
|
|
});
|
2020-07-16 22:35:58 +02:00
|
|
|
})();
|
2017-04-22 22:22:25 +02:00
|
|
|
|
|
|
|
e.preventDefault();
|
|
|
|
});
|
2021-02-10 16:55:52 +01:00
|
|
|
}
|
2018-03-25 17:43:17 +02:00
|
|
|
|
2021-02-10 16:55:52 +01:00
|
|
|
export function set_up_handlers() {
|
2020-07-15 01:29:15 +02:00
|
|
|
const container = $("#stream-creation").expectOne();
|
2017-04-22 22:22:25 +02:00
|
|
|
|
2020-07-15 01:29:15 +02:00
|
|
|
container.on("change", "#make-invite-only input", update_announce_stream_state);
|
2018-03-25 18:46:10 +02:00
|
|
|
|
2020-07-02 01:45:54 +02:00
|
|
|
container.on("submit", "#stream_creation_form", (e) => {
|
2017-04-22 22:22:25 +02:00
|
|
|
e.preventDefault();
|
2018-03-10 03:14:48 +01:00
|
|
|
clear_error_display();
|
|
|
|
|
2020-07-22 03:39:41 +02:00
|
|
|
const stream_name = $("#create_stream_name").val().trim();
|
2019-11-02 00:06:25 +01:00
|
|
|
const name_ok = stream_name_error.validate_for_submit(stream_name);
|
2017-04-28 22:04:32 +02:00
|
|
|
|
|
|
|
if (!name_ok) {
|
|
|
|
return;
|
2017-04-22 22:22:25 +02:00
|
|
|
}
|
2017-06-02 15:06:33 +02:00
|
|
|
|
2019-11-02 00:06:25 +01:00
|
|
|
const principals = get_principals();
|
2018-01-21 09:34:50 +01:00
|
|
|
if (principals.length === 0) {
|
|
|
|
stream_subscription_error.report_no_subs_to_stream();
|
|
|
|
return;
|
|
|
|
}
|
js: Convert a.indexOf(…) !== -1 to a.includes(…).
Babel polyfills this for us for Internet Explorer.
import * as babelParser from "recast/parsers/babel";
import * as recast from "recast";
import * as tsParser from "recast/parsers/typescript";
import { builders as b, namedTypes as n } from "ast-types";
import K from "ast-types/gen/kinds";
import fs from "fs";
import path from "path";
import process from "process";
const checkExpression = (node: n.Node): node is K.ExpressionKind =>
n.Expression.check(node);
for (const file of process.argv.slice(2)) {
console.log("Parsing", file);
const ast = recast.parse(fs.readFileSync(file, { encoding: "utf8" }), {
parser: path.extname(file) === ".ts" ? tsParser : babelParser,
});
let changed = false;
recast.visit(ast, {
visitBinaryExpression(path) {
const { operator, left, right } = path.node;
if (
n.CallExpression.check(left) &&
n.MemberExpression.check(left.callee) &&
!left.callee.computed &&
n.Identifier.check(left.callee.property) &&
left.callee.property.name === "indexOf" &&
left.arguments.length === 1 &&
checkExpression(left.arguments[0]) &&
((["===", "!==", "==", "!=", ">", "<="].includes(operator) &&
n.UnaryExpression.check(right) &&
right.operator == "-" &&
n.Literal.check(right.argument) &&
right.argument.value === 1) ||
([">=", "<"].includes(operator) &&
n.Literal.check(right) &&
right.value === 0))
) {
const test = b.callExpression(
b.memberExpression(left.callee.object, b.identifier("includes")),
[left.arguments[0]]
);
path.replace(
["!==", "!=", ">", ">="].includes(operator)
? test
: b.unaryExpression("!", test)
);
changed = true;
}
this.traverse(path);
},
});
if (changed) {
console.log("Writing", file);
fs.writeFileSync(file, recast.print(ast).code, { encoding: "utf8" });
}
}
Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
2020-02-08 04:55:06 +01:00
|
|
|
if (!principals.includes(people.my_current_user_id()) && !page_params.is_admin) {
|
2018-02-03 09:04:45 +01:00
|
|
|
stream_subscription_error.cant_create_stream_without_susbscribing();
|
|
|
|
return;
|
|
|
|
}
|
2018-01-21 09:34:50 +01:00
|
|
|
|
2017-07-08 04:21:19 +02:00
|
|
|
if (principals.length >= 50) {
|
2019-11-02 00:06:25 +01:00
|
|
|
const invites_warning_modal = render_subscription_invites_warning_modal({
|
2020-07-20 22:18:43 +02:00
|
|
|
stream_name,
|
2019-07-09 21:24:00 +02:00
|
|
|
count: principals.length,
|
|
|
|
});
|
2020-07-15 01:29:15 +02:00
|
|
|
$("#stream-creation").append(invites_warning_modal);
|
2017-06-02 15:06:33 +02:00
|
|
|
} else {
|
|
|
|
create_stream();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2020-07-02 01:45:54 +02:00
|
|
|
container.on("click", ".close-invites-warning-modal", () => {
|
2017-06-02 15:06:33 +02:00
|
|
|
$("#invites-warning-overlay").remove();
|
|
|
|
});
|
|
|
|
|
2020-07-02 01:45:54 +02:00
|
|
|
container.on("click", ".confirm-invites-warning-modal", () => {
|
2017-07-08 04:07:36 +02:00
|
|
|
create_stream();
|
2017-06-02 15:06:33 +02:00
|
|
|
$("#invites-warning-overlay").remove();
|
2017-04-22 22:22:25 +02:00
|
|
|
});
|
|
|
|
|
2020-07-02 01:45:54 +02:00
|
|
|
container.on("input", "#create_stream_name", () => {
|
2020-07-22 03:39:41 +02:00
|
|
|
const stream_name = $("#create_stream_name").val().trim();
|
2017-04-22 22:22:25 +02:00
|
|
|
|
2017-04-28 22:04:32 +02:00
|
|
|
// This is an inexpensive check.
|
2017-07-08 04:31:11 +02:00
|
|
|
stream_name_error.pre_validate(stream_name);
|
2017-04-22 22:22:25 +02:00
|
|
|
});
|
|
|
|
|
2020-07-02 01:45:54 +02:00
|
|
|
container.on("mouseover", "#announce-stream-docs", (e) => {
|
2019-11-02 00:06:25 +01:00
|
|
|
const announce_stream_docs = $("#announce-stream-docs");
|
2018-05-06 21:43:17 +02:00
|
|
|
announce_stream_docs.popover({
|
|
|
|
placement: "right",
|
2019-07-09 21:24:00 +02:00
|
|
|
content: render_announce_stream_docs({
|
2020-04-14 12:55:18 +02:00
|
|
|
notifications_stream: stream_data.get_notifications_stream(),
|
|
|
|
}),
|
2019-09-17 23:54:52 +02:00
|
|
|
html: true,
|
2020-07-15 00:34:28 +02:00
|
|
|
trigger: "manual",
|
|
|
|
});
|
2020-07-15 01:29:15 +02:00
|
|
|
announce_stream_docs.popover("show");
|
|
|
|
announce_stream_docs.data("popover").tip().css("z-index", 2000);
|
2020-07-15 00:34:28 +02:00
|
|
|
announce_stream_docs
|
|
|
|
.data("popover")
|
|
|
|
.tip()
|
|
|
|
.find(".popover-content")
|
|
|
|
.css("margin", "9px 14px");
|
2017-04-22 22:22:25 +02:00
|
|
|
e.stopPropagation();
|
|
|
|
});
|
2020-07-02 01:45:54 +02:00
|
|
|
container.on("mouseout", "#announce-stream-docs", (e) => {
|
2020-07-15 01:29:15 +02:00
|
|
|
$("#announce-stream-docs").popover("hide");
|
2017-04-22 22:22:25 +02:00
|
|
|
e.stopPropagation();
|
|
|
|
});
|
|
|
|
|
2019-02-20 18:36:46 +01:00
|
|
|
// Do not allow the user to enter newline characters while typing out the
|
|
|
|
// stream's description during it's creation.
|
2020-07-02 01:45:54 +02:00
|
|
|
container.on("keydown", "#create_stream_description", (e) => {
|
2019-02-20 18:36:46 +01:00
|
|
|
if ((e.keyCode || e.which) === 13) {
|
|
|
|
e.preventDefault();
|
|
|
|
}
|
|
|
|
});
|
2021-02-10 16:55:52 +01:00
|
|
|
}
|