mirror of
https://github.com/zulip/zulip.git
synced 2025-11-11 17:36:27 +00:00
compose: Migrate generic error to use shared banner template.
Error banners were rendered in a different place than warnings. Now compose errors and warnings share the same template and styling in compose_banner.hbs Testing notes: * I removed test_message_overflow since it seemed not to test anything that test_check_overflow_text wasn't already testing. * private_message_recipient() can't be called to set emails to non-valid emails, so `invalid_recipient` cannot be tested (and is likely very difficult to trigger in production, if possible at all).
This commit is contained in:
@@ -4,7 +4,7 @@ const {strict: assert} = require("assert");
|
|||||||
|
|
||||||
const MockDate = require("mockdate");
|
const MockDate = require("mockdate");
|
||||||
|
|
||||||
const {$t, $t_html} = require("../zjsunit/i18n");
|
const {$t} = require("../zjsunit/i18n");
|
||||||
const {mock_esm, set_global, zrequire} = require("../zjsunit/namespace");
|
const {mock_esm, set_global, zrequire} = require("../zjsunit/namespace");
|
||||||
const {run_test} = require("../zjsunit/test");
|
const {run_test} = require("../zjsunit/test");
|
||||||
const blueslip = require("../zjsunit/zblueslip");
|
const blueslip = require("../zjsunit/zblueslip");
|
||||||
@@ -135,7 +135,7 @@ test_ui("send_message_success", ({override_rewire}) => {
|
|||||||
assert.ok(reify_message_id_checked);
|
assert.ok(reify_message_id_checked);
|
||||||
});
|
});
|
||||||
|
|
||||||
test_ui("send_message", ({override, override_rewire}) => {
|
test_ui("send_message", ({override, override_rewire, mock_template}) => {
|
||||||
mock_banners();
|
mock_banners();
|
||||||
MockDate.set(new Date(fake_now * 1000));
|
MockDate.set(new Date(fake_now * 1000));
|
||||||
|
|
||||||
@@ -258,6 +258,12 @@ test_ui("send_message", ({override, override_rewire}) => {
|
|||||||
})();
|
})();
|
||||||
|
|
||||||
(function test_error_codepath_local_id_undefined() {
|
(function test_error_codepath_local_id_undefined() {
|
||||||
|
let banner_rendered = false;
|
||||||
|
mock_template("compose_banner/compose_banner.hbs", false, (data) => {
|
||||||
|
assert.equal(data.classname, "generic_compose_error");
|
||||||
|
assert.equal(data.banner_text, "Error sending message: Server says 408");
|
||||||
|
banner_rendered = true;
|
||||||
|
});
|
||||||
stub_state = initialize_state_stub_dict();
|
stub_state = initialize_state_stub_dict();
|
||||||
$("#compose-textarea").val("foobarfoobar");
|
$("#compose-textarea").val("foobarfoobar");
|
||||||
$("#compose-textarea").trigger("blur");
|
$("#compose-textarea").trigger("blur");
|
||||||
@@ -278,7 +284,7 @@ test_ui("send_message", ({override, override_rewire}) => {
|
|||||||
};
|
};
|
||||||
assert.deepEqual(stub_state, state);
|
assert.deepEqual(stub_state, state);
|
||||||
assert.ok(!echo_error_msg_checked);
|
assert.ok(!echo_error_msg_checked);
|
||||||
assert.equal($("#compose-error-msg").html(), "Error sending message: Server says 408");
|
assert.ok(banner_rendered);
|
||||||
assert.equal($("#compose-textarea").val(), "foobarfoobar");
|
assert.equal($("#compose-textarea").val(), "foobarfoobar");
|
||||||
assert.ok($("#compose-textarea").is_focused());
|
assert.ok($("#compose-textarea").is_focused());
|
||||||
assert.ok($("#compose-send-status").visible());
|
assert.ok($("#compose-send-status").visible());
|
||||||
@@ -335,7 +341,7 @@ test_ui("enter_with_preview_open", ({override, override_rewire}) => {
|
|||||||
assert.equal($("#compose-error-msg").html(), "never-been-set");
|
assert.equal($("#compose-error-msg").html(), "never-been-set");
|
||||||
});
|
});
|
||||||
|
|
||||||
test_ui("finish", ({override, override_rewire}) => {
|
test_ui("finish", ({override, override_rewire, mock_template}) => {
|
||||||
mock_banners();
|
mock_banners();
|
||||||
override(notifications, "clear_compose_notifications", () => {});
|
override(notifications, "clear_compose_notifications", () => {});
|
||||||
override(reminder, "is_deferred_delivery", () => false);
|
override(reminder, "is_deferred_delivery", () => false);
|
||||||
@@ -347,6 +353,10 @@ test_ui("finish", ({override, override_rewire}) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
(function test_when_compose_validation_fails() {
|
(function test_when_compose_validation_fails() {
|
||||||
|
mock_template("compose_banner/compose_banner.hbs", false, (data) => {
|
||||||
|
assert.equal(data.classname, "empty_message");
|
||||||
|
assert.equal(data.banner_text, $t({defaultMessage: "You have nothing to send!"}));
|
||||||
|
});
|
||||||
$("#compose_invite_users").show();
|
$("#compose_invite_users").show();
|
||||||
$("#compose-send-button").prop("disabled", false);
|
$("#compose-send-button").prop("disabled", false);
|
||||||
$("#compose-send-button").trigger("focus");
|
$("#compose-send-button").trigger("focus");
|
||||||
@@ -357,10 +367,6 @@ test_ui("finish", ({override, override_rewire}) => {
|
|||||||
assert.equal(res, false);
|
assert.equal(res, false);
|
||||||
assert.ok(!$("#compose_invite_users").visible());
|
assert.ok(!$("#compose_invite_users").visible());
|
||||||
assert.ok(!$("#compose-send-button .loader").visible());
|
assert.ok(!$("#compose-send-button .loader").visible());
|
||||||
assert.equal(
|
|
||||||
$("#compose-error-msg").html(),
|
|
||||||
$t_html({defaultMessage: "You have nothing to send!"}),
|
|
||||||
);
|
|
||||||
assert.ok(show_button_spinner_called);
|
assert.ok(show_button_spinner_called);
|
||||||
})();
|
})();
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
const {strict: assert} = require("assert");
|
const {strict: assert} = require("assert");
|
||||||
|
|
||||||
const {$t, $t_html} = require("../zjsunit/i18n");
|
const {$t} = require("../zjsunit/i18n");
|
||||||
const {mock_esm, zrequire} = require("../zjsunit/namespace");
|
const {mock_esm, zrequire} = require("../zjsunit/namespace");
|
||||||
const {run_test} = require("../zjsunit/test");
|
const {run_test} = require("../zjsunit/test");
|
||||||
const blueslip = require("../zjsunit/zblueslip");
|
const blueslip = require("../zjsunit/zblueslip");
|
||||||
@@ -13,7 +13,6 @@ const {mock_banners} = require("./lib/compose_banner");
|
|||||||
|
|
||||||
const channel = mock_esm("../../static/js/channel");
|
const channel = mock_esm("../../static/js/channel");
|
||||||
const compose_actions = mock_esm("../../static/js/compose_actions");
|
const compose_actions = mock_esm("../../static/js/compose_actions");
|
||||||
const ui_util = mock_esm("../../static/js/ui_util");
|
|
||||||
|
|
||||||
const compose_error = zrequire("compose_error");
|
const compose_error = zrequire("compose_error");
|
||||||
const compose_pm_pill = zrequire("compose_pm_pill");
|
const compose_pm_pill = zrequire("compose_pm_pill");
|
||||||
@@ -70,6 +69,7 @@ function test_ui(label, f) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
test_ui("validate_stream_message_address_info", ({mock_template}) => {
|
test_ui("validate_stream_message_address_info", ({mock_template}) => {
|
||||||
|
mock_banners();
|
||||||
const sub = {
|
const sub = {
|
||||||
stream_id: 101,
|
stream_id: 101,
|
||||||
name: "social",
|
name: "social",
|
||||||
@@ -103,25 +103,31 @@ test_ui("validate_stream_message_address_info", ({mock_template}) => {
|
|||||||
assert.ok(!compose_validate.validate_stream_message_address_info("Frontend"));
|
assert.ok(!compose_validate.validate_stream_message_address_info("Frontend"));
|
||||||
assert.equal($("#compose-error-msg").html(), "compose_not_subscribed_stub");
|
assert.equal($("#compose-error-msg").html(), "compose_not_subscribed_stub");
|
||||||
|
|
||||||
|
let stream_does_not_exist_rendered = false;
|
||||||
|
mock_template("compose_banner/stream_does_not_exist_error.hbs", false, (data) => {
|
||||||
|
assert.equal(data.classname, compose_error.CLASSNAMES.stream_does_not_exist);
|
||||||
|
assert.equal(data.stream_name, "Frontend");
|
||||||
|
stream_does_not_exist_rendered = true;
|
||||||
|
});
|
||||||
channel.post = (payload) => {
|
channel.post = (payload) => {
|
||||||
assert.equal(payload.data.stream, "Frontend");
|
assert.equal(payload.data.stream, "Frontend");
|
||||||
payload.error({status: 404});
|
payload.error({status: 404});
|
||||||
};
|
};
|
||||||
assert.ok(!compose_validate.validate_stream_message_address_info("Frontend"));
|
assert.ok(!compose_validate.validate_stream_message_address_info("Frontend"));
|
||||||
assert.equal(
|
assert.ok(stream_does_not_exist_rendered);
|
||||||
$("#compose-error-msg").html(),
|
|
||||||
"translated HTML: <p>The stream <b>Frontend</b> does not exist.</p><p>Manage your subscriptions <a href='#streams/all'>on your Streams page</a>.</p>",
|
|
||||||
);
|
|
||||||
|
|
||||||
|
let subscription_error_rendered = false;
|
||||||
|
mock_template("compose_banner/compose_banner.hbs", false, (data) => {
|
||||||
|
assert.equal(data.classname, "subscription_error");
|
||||||
|
assert.equal(data.banner_text, $t({defaultMessage: "Error checking subscription."}));
|
||||||
|
subscription_error_rendered = true;
|
||||||
|
});
|
||||||
channel.post = (payload) => {
|
channel.post = (payload) => {
|
||||||
assert.equal(payload.data.stream, "social");
|
assert.equal(payload.data.stream, "social");
|
||||||
payload.error({status: 500});
|
payload.error({status: 500});
|
||||||
};
|
};
|
||||||
assert.ok(!compose_validate.validate_stream_message_address_info("social"));
|
assert.ok(!compose_validate.validate_stream_message_address_info("social"));
|
||||||
assert.equal(
|
assert.ok(subscription_error_rendered);
|
||||||
$("#compose-error-msg").html(),
|
|
||||||
$t_html({defaultMessage: "Error checking subscription"}),
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test_ui("validate", ({override, mock_template}) => {
|
test_ui("validate", ({override, mock_template}) => {
|
||||||
@@ -142,26 +148,87 @@ test_ui("validate", ({override, mock_template}) => {
|
|||||||
|
|
||||||
compose_pm_pill.initialize();
|
compose_pm_pill.initialize();
|
||||||
|
|
||||||
ui_util.place_caret_at_end = () => {};
|
|
||||||
|
|
||||||
$("#zephyr-mirror-error").is = () => {};
|
$("#zephyr-mirror-error").is = () => {};
|
||||||
|
|
||||||
mock_template("input_pill.hbs", false, () => "<div>pill-html</div>");
|
mock_template("input_pill.hbs", false, () => "<div>pill-html</div>");
|
||||||
|
|
||||||
|
mock_banners();
|
||||||
}
|
}
|
||||||
|
|
||||||
function add_content_to_compose_box() {
|
function add_content_to_compose_box() {
|
||||||
$("#compose-textarea").val("foobarfoobar");
|
$("#compose-textarea").val("foobarfoobar");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// test validating private messages
|
||||||
|
compose_state.set_message_type("private");
|
||||||
|
|
||||||
initialize_pm_pill();
|
initialize_pm_pill();
|
||||||
|
add_content_to_compose_box();
|
||||||
|
compose_state.private_message_recipient("");
|
||||||
|
let pm_recipient_error_rendered = false;
|
||||||
|
mock_template("compose_banner/compose_banner.hbs", false, (data) => {
|
||||||
|
assert.equal(data.classname, compose_error.CLASSNAMES.missing_private_message_recipient);
|
||||||
|
assert.equal(
|
||||||
|
data.banner_text,
|
||||||
|
$t({defaultMessage: "Please specify at least one valid recipient."}),
|
||||||
|
);
|
||||||
|
pm_recipient_error_rendered = true;
|
||||||
|
});
|
||||||
|
assert.ok(!compose_validate.validate());
|
||||||
|
assert.ok(pm_recipient_error_rendered);
|
||||||
|
|
||||||
|
pm_recipient_error_rendered = false;
|
||||||
|
|
||||||
|
people.add_active_user(bob);
|
||||||
|
compose_state.private_message_recipient("bob@example.com");
|
||||||
|
assert.ok(compose_validate.validate());
|
||||||
|
assert.ok(!pm_recipient_error_rendered);
|
||||||
|
|
||||||
|
people.deactivate(bob);
|
||||||
|
let deactivated_user_error_rendered = false;
|
||||||
|
mock_template("compose_banner/compose_banner.hbs", false, (data) => {
|
||||||
|
assert.equal(data.classname, compose_error.CLASSNAMES.deactivated_user);
|
||||||
|
assert.equal(
|
||||||
|
data.banner_text,
|
||||||
|
$t({defaultMessage: "You cannot send messages to deactivated users."}),
|
||||||
|
);
|
||||||
|
deactivated_user_error_rendered = true;
|
||||||
|
});
|
||||||
|
assert.ok(!compose_validate.validate());
|
||||||
|
assert.ok(deactivated_user_error_rendered);
|
||||||
|
|
||||||
|
page_params.realm_is_zephyr_mirror_realm = true;
|
||||||
|
assert.ok(compose_validate.validate());
|
||||||
|
page_params.realm_is_zephyr_mirror_realm = false;
|
||||||
|
|
||||||
|
initialize_pm_pill();
|
||||||
|
add_content_to_compose_box();
|
||||||
|
compose_state.private_message_recipient("welcome-bot@example.com");
|
||||||
|
assert.ok(compose_validate.validate());
|
||||||
|
|
||||||
|
let zephyr_error_rendered = false;
|
||||||
|
let empty_message_error_rendered = false;
|
||||||
|
mock_template("compose_banner/compose_banner.hbs", false, (data) => {
|
||||||
|
if (data.classname === compose_error.CLASSNAMES.zephyr_not_running) {
|
||||||
|
assert.equal(
|
||||||
|
data.banner_text,
|
||||||
|
$t({
|
||||||
|
defaultMessage:
|
||||||
|
"You need to be running Zephyr mirroring in order to send messages!",
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
zephyr_error_rendered = true;
|
||||||
|
} else if (data.classname === compose_error.CLASSNAMES.empty_message) {
|
||||||
|
assert.equal(data.banner_text, $t({defaultMessage: "You have nothing to send!"}));
|
||||||
|
empty_message_error_rendered = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
initialize_pm_pill();
|
||||||
|
compose_state.private_message_recipient("welcome-bot@example.com");
|
||||||
assert.ok(!compose_validate.validate());
|
assert.ok(!compose_validate.validate());
|
||||||
assert.ok(!$("#compose-send-button .loader").visible());
|
assert.ok(!$("#compose-send-button .loader").visible());
|
||||||
assert.equal($("#compose-send-button").prop("disabled"), false);
|
assert.equal($("#compose-send-button").prop("disabled"), false);
|
||||||
assert.equal(
|
assert.ok(empty_message_error_rendered);
|
||||||
$("#compose-error-msg").html(),
|
|
||||||
$t_html({defaultMessage: "You have nothing to send!"}),
|
|
||||||
);
|
|
||||||
|
|
||||||
compose_validate.validate();
|
compose_validate.validate();
|
||||||
|
|
||||||
add_content_to_compose_box();
|
add_content_to_compose_box();
|
||||||
@@ -173,88 +240,42 @@ test_ui("validate", ({override, mock_template}) => {
|
|||||||
};
|
};
|
||||||
assert.ok(!compose_validate.validate());
|
assert.ok(!compose_validate.validate());
|
||||||
assert.ok(zephyr_checked);
|
assert.ok(zephyr_checked);
|
||||||
assert.equal(
|
assert.ok(zephyr_error_rendered);
|
||||||
$("#compose-error-msg").html(),
|
|
||||||
$t_html({
|
|
||||||
defaultMessage: "You need to be running Zephyr mirroring in order to send messages!",
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
|
|
||||||
initialize_pm_pill();
|
initialize_pm_pill();
|
||||||
add_content_to_compose_box();
|
add_content_to_compose_box();
|
||||||
|
|
||||||
// test validating private messages
|
// test validating stream messages
|
||||||
compose_state.set_message_type("private");
|
|
||||||
|
|
||||||
compose_state.private_message_recipient("");
|
|
||||||
assert.ok(!compose_validate.validate());
|
|
||||||
assert.equal(
|
|
||||||
$("#compose-error-msg").html(),
|
|
||||||
$t_html({defaultMessage: "Please specify at least one valid recipient"}),
|
|
||||||
);
|
|
||||||
|
|
||||||
initialize_pm_pill();
|
|
||||||
add_content_to_compose_box();
|
|
||||||
compose_state.private_message_recipient("foo@zulip.com");
|
|
||||||
|
|
||||||
assert.ok(!compose_validate.validate());
|
|
||||||
|
|
||||||
assert.equal(
|
|
||||||
$("#compose-error-msg").html(),
|
|
||||||
$t_html({defaultMessage: "Please specify at least one valid recipient"}),
|
|
||||||
);
|
|
||||||
|
|
||||||
compose_state.private_message_recipient("foo@zulip.com,alice@zulip.com");
|
|
||||||
assert.ok(!compose_validate.validate());
|
|
||||||
|
|
||||||
assert.equal(
|
|
||||||
$("#compose-error-msg").html(),
|
|
||||||
$t_html({defaultMessage: "Please specify at least one valid recipient"}),
|
|
||||||
);
|
|
||||||
|
|
||||||
people.add_active_user(bob);
|
|
||||||
compose_state.private_message_recipient("bob@example.com");
|
|
||||||
assert.ok(compose_validate.validate());
|
|
||||||
|
|
||||||
people.deactivate(bob);
|
|
||||||
assert.ok(!compose_validate.validate());
|
|
||||||
assert.equal(
|
|
||||||
$("#compose-error-msg").html(),
|
|
||||||
$t_html({defaultMessage: "You cannot send messages to deactivated users."}),
|
|
||||||
);
|
|
||||||
|
|
||||||
page_params.realm_is_zephyr_mirror_realm = true;
|
|
||||||
assert.ok(compose_validate.validate());
|
|
||||||
page_params.realm_is_zephyr_mirror_realm = false;
|
|
||||||
|
|
||||||
initialize_pm_pill();
|
|
||||||
add_content_to_compose_box();
|
|
||||||
compose_state.private_message_recipient("welcome-bot@example.com");
|
|
||||||
assert.ok(compose_validate.validate());
|
|
||||||
|
|
||||||
compose_state.set_message_type("stream");
|
compose_state.set_message_type("stream");
|
||||||
compose_state.stream_name("");
|
compose_state.stream_name("");
|
||||||
|
let empty_stream_error_rendered = false;
|
||||||
|
mock_template("compose_banner/compose_banner.hbs", false, (data) => {
|
||||||
|
assert.equal(data.classname, compose_error.CLASSNAMES.missing_stream);
|
||||||
|
assert.equal(data.banner_text, $t({defaultMessage: "Please specify a stream."}));
|
||||||
|
empty_stream_error_rendered = true;
|
||||||
|
});
|
||||||
assert.ok(!compose_validate.validate());
|
assert.ok(!compose_validate.validate());
|
||||||
assert.equal(
|
assert.ok(empty_stream_error_rendered);
|
||||||
$("#compose-error-msg").html(),
|
|
||||||
$t_html({defaultMessage: "Please specify a stream"}),
|
|
||||||
);
|
|
||||||
|
|
||||||
compose_state.stream_name("Denmark");
|
compose_state.stream_name("Denmark");
|
||||||
page_params.realm_mandatory_topics = true;
|
page_params.realm_mandatory_topics = true;
|
||||||
compose_state.topic("");
|
compose_state.topic("");
|
||||||
|
let missing_topic_error_rendered = false;
|
||||||
|
mock_template("compose_banner/compose_banner.hbs", false, (data) => {
|
||||||
|
assert.equal(data.classname, compose_error.CLASSNAMES.topic_missing);
|
||||||
|
assert.equal(
|
||||||
|
data.banner_text,
|
||||||
|
$t({defaultMessage: "Topics are required in this organization."}),
|
||||||
|
);
|
||||||
|
missing_topic_error_rendered = true;
|
||||||
|
});
|
||||||
assert.ok(!compose_validate.validate());
|
assert.ok(!compose_validate.validate());
|
||||||
assert.equal(
|
assert.ok(missing_topic_error_rendered);
|
||||||
$("#compose-error-msg").html(),
|
|
||||||
$t_html({defaultMessage: "Topics are required in this organization"}),
|
|
||||||
);
|
|
||||||
|
|
||||||
|
missing_topic_error_rendered = false;
|
||||||
compose_state.topic("(no topic)");
|
compose_state.topic("(no topic)");
|
||||||
assert.ok(!compose_validate.validate());
|
assert.ok(!compose_validate.validate());
|
||||||
assert.equal(
|
assert.ok(missing_topic_error_rendered);
|
||||||
$("#compose-error-msg").html(),
|
|
||||||
$t_html({defaultMessage: "Topics are required in this organization"}),
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test_ui("get_invalid_recipient_emails", ({override_rewire}) => {
|
test_ui("get_invalid_recipient_emails", ({override_rewire}) => {
|
||||||
@@ -334,6 +355,7 @@ test_ui("validate_stream_message", ({override_rewire, mock_template}) => {
|
|||||||
// primarily used to get coverage over functions called from validate()
|
// primarily used to get coverage over functions called from validate()
|
||||||
// we are separating it up in different test. Though their relative position
|
// we are separating it up in different test. Though their relative position
|
||||||
// of execution should not be changed.
|
// of execution should not be changed.
|
||||||
|
mock_banners();
|
||||||
page_params.user_id = me.user_id;
|
page_params.user_id = me.user_id;
|
||||||
page_params.realm_mandatory_topics = false;
|
page_params.realm_mandatory_topics = false;
|
||||||
const sub = {
|
const sub = {
|
||||||
@@ -368,21 +390,30 @@ test_ui("validate_stream_message", ({override_rewire, mock_template}) => {
|
|||||||
assert.equal(compose_content, "compose_all_everyone_stub");
|
assert.equal(compose_content, "compose_all_everyone_stub");
|
||||||
assert.ok($("#compose-all-everyone").visible());
|
assert.ok($("#compose-all-everyone").visible());
|
||||||
|
|
||||||
|
let wildcards_not_allowed_rendered = false;
|
||||||
|
mock_template("compose_banner/compose_banner.hbs", false, (data) => {
|
||||||
|
assert.equal(data.classname, compose_error.CLASSNAMES.wildcards_not_allowed);
|
||||||
|
assert.equal(
|
||||||
|
data.banner_text,
|
||||||
|
$t({
|
||||||
|
defaultMessage:
|
||||||
|
"You do not have permission to use wildcard mentions in this stream.",
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
wildcards_not_allowed_rendered = true;
|
||||||
|
return "wildcard_warning_stub";
|
||||||
|
});
|
||||||
override_rewire(compose_validate, "wildcard_mention_allowed", () => false);
|
override_rewire(compose_validate, "wildcard_mention_allowed", () => false);
|
||||||
assert.ok(!compose_validate.validate());
|
assert.ok(!compose_validate.validate());
|
||||||
assert.equal(
|
assert.ok(wildcards_not_allowed_rendered);
|
||||||
$("#compose-error-msg").html(),
|
|
||||||
$t_html({
|
|
||||||
defaultMessage: "You do not have permission to use wildcard mentions in this stream.",
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test_ui("test_validate_stream_message_post_policy_admin_only", () => {
|
test_ui("test_validate_stream_message_post_policy_admin_only", ({mock_template}) => {
|
||||||
// This test is in continuation with test_validate but it has been separated out
|
// This test is in continuation with test_validate but it has been separated out
|
||||||
// for better readability. Their relative position of execution should not be changed.
|
// for better readability. Their relative position of execution should not be changed.
|
||||||
// Although the position with respect to test_validate_stream_message does not matter
|
// Although the position with respect to test_validate_stream_message does not matter
|
||||||
// as different stream is used for this test.
|
// as different stream is used for this test.
|
||||||
|
mock_banners();
|
||||||
page_params.is_admin = false;
|
page_params.is_admin = false;
|
||||||
const sub = {
|
const sub = {
|
||||||
stream_id: 102,
|
stream_id: 102,
|
||||||
@@ -394,11 +425,20 @@ test_ui("test_validate_stream_message_post_policy_admin_only", () => {
|
|||||||
compose_state.topic("topic102");
|
compose_state.topic("topic102");
|
||||||
compose_state.stream_name("stream102");
|
compose_state.stream_name("stream102");
|
||||||
stream_data.add_sub(sub);
|
stream_data.add_sub(sub);
|
||||||
|
|
||||||
|
let banner_rendered = false;
|
||||||
|
mock_template("compose_banner/compose_banner.hbs", false, (data) => {
|
||||||
|
assert.equal(data.classname, compose_error.CLASSNAMES.no_post_permissions);
|
||||||
|
assert.equal(
|
||||||
|
data.banner_text,
|
||||||
|
$t({
|
||||||
|
defaultMessage: "You do not have permission to post in this stream.",
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
banner_rendered = true;
|
||||||
|
});
|
||||||
assert.ok(!compose_validate.validate());
|
assert.ok(!compose_validate.validate());
|
||||||
assert.equal(
|
assert.ok(banner_rendered);
|
||||||
$("#compose-error-msg").html(),
|
|
||||||
$t_html({defaultMessage: "You do not have permission to post in this stream."}),
|
|
||||||
);
|
|
||||||
|
|
||||||
// Reset error message.
|
// Reset error message.
|
||||||
compose_state.stream_name("social");
|
compose_state.stream_name("social");
|
||||||
@@ -408,14 +448,13 @@ test_ui("test_validate_stream_message_post_policy_admin_only", () => {
|
|||||||
|
|
||||||
compose_state.topic("topic102");
|
compose_state.topic("topic102");
|
||||||
compose_state.stream_name("stream102");
|
compose_state.stream_name("stream102");
|
||||||
|
banner_rendered = false;
|
||||||
assert.ok(!compose_validate.validate());
|
assert.ok(!compose_validate.validate());
|
||||||
assert.equal(
|
assert.ok(banner_rendered);
|
||||||
$("#compose-error-msg").html(),
|
|
||||||
$t_html({defaultMessage: "You do not have permission to post in this stream."}),
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test_ui("test_validate_stream_message_post_policy_moderators_only", () => {
|
test_ui("test_validate_stream_message_post_policy_moderators_only", ({mock_template}) => {
|
||||||
|
mock_banners();
|
||||||
page_params.is_admin = false;
|
page_params.is_admin = false;
|
||||||
page_params.is_moderator = false;
|
page_params.is_moderator = false;
|
||||||
page_params.is_guest = false;
|
page_params.is_guest = false;
|
||||||
@@ -430,27 +469,29 @@ test_ui("test_validate_stream_message_post_policy_moderators_only", () => {
|
|||||||
compose_state.topic("topic104");
|
compose_state.topic("topic104");
|
||||||
compose_state.stream_name("stream104");
|
compose_state.stream_name("stream104");
|
||||||
stream_data.add_sub(sub);
|
stream_data.add_sub(sub);
|
||||||
|
let banner_rendered = false;
|
||||||
|
mock_template("compose_banner/compose_banner.hbs", false, (data) => {
|
||||||
|
assert.equal(data.classname, compose_error.CLASSNAMES.no_post_permissions);
|
||||||
|
assert.equal(
|
||||||
|
data.banner_text,
|
||||||
|
$t({
|
||||||
|
defaultMessage: "You do not have permission to post in this stream.",
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
banner_rendered = true;
|
||||||
|
});
|
||||||
assert.ok(!compose_validate.validate());
|
assert.ok(!compose_validate.validate());
|
||||||
assert.equal(
|
assert.ok(banner_rendered);
|
||||||
$("#compose-error-msg").html(),
|
|
||||||
$t_html({
|
|
||||||
defaultMessage: "You do not have permission to post in this stream.",
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
|
|
||||||
// Reset error message.
|
// Reset error message.
|
||||||
compose_state.stream_name("social");
|
compose_state.stream_name("social");
|
||||||
|
|
||||||
page_params.is_guest = true;
|
page_params.is_guest = true;
|
||||||
assert.equal(
|
assert.ok(!compose_validate.validate());
|
||||||
$("#compose-error-msg").html(),
|
assert.ok(banner_rendered);
|
||||||
$t_html({
|
|
||||||
defaultMessage: "You do not have permission to post in this stream.",
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test_ui("test_validate_stream_message_post_policy_full_members_only", () => {
|
test_ui("test_validate_stream_message_post_policy_full_members_only", ({mock_template}) => {
|
||||||
|
mock_banners();
|
||||||
page_params.is_admin = false;
|
page_params.is_admin = false;
|
||||||
page_params.is_guest = true;
|
page_params.is_guest = true;
|
||||||
const sub = {
|
const sub = {
|
||||||
@@ -463,19 +504,39 @@ test_ui("test_validate_stream_message_post_policy_full_members_only", () => {
|
|||||||
compose_state.topic("topic103");
|
compose_state.topic("topic103");
|
||||||
compose_state.stream_name("stream103");
|
compose_state.stream_name("stream103");
|
||||||
stream_data.add_sub(sub);
|
stream_data.add_sub(sub);
|
||||||
|
let banner_rendered = false;
|
||||||
|
mock_template("compose_banner/compose_banner.hbs", false, (data) => {
|
||||||
|
assert.equal(data.classname, compose_error.CLASSNAMES.no_post_permissions);
|
||||||
|
assert.equal(
|
||||||
|
data.banner_text,
|
||||||
|
$t({
|
||||||
|
defaultMessage: "You do not have permission to post in this stream.",
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
banner_rendered = true;
|
||||||
|
});
|
||||||
assert.ok(!compose_validate.validate());
|
assert.ok(!compose_validate.validate());
|
||||||
assert.equal(
|
assert.ok(banner_rendered);
|
||||||
$("#compose-error-msg").html(),
|
|
||||||
$t_html({defaultMessage: "You do not have permission to post in this stream."}),
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test_ui("test_check_overflow_text", () => {
|
test_ui("test_check_overflow_text", ({mock_template}) => {
|
||||||
|
mock_banners();
|
||||||
page_params.max_message_length = 10000;
|
page_params.max_message_length = 10000;
|
||||||
|
|
||||||
const $textarea = $("#compose-textarea");
|
const $textarea = $("#compose-textarea");
|
||||||
const $indicator = $("#compose_limit_indicator");
|
const $indicator = $("#compose_limit_indicator");
|
||||||
const $send_button = $("#compose-send-button");
|
const $send_button = $("#compose-send-button");
|
||||||
|
let banner_rendered = false;
|
||||||
|
mock_template("compose_banner/compose_banner.hbs", false, (data) => {
|
||||||
|
assert.equal(data.classname, compose_error.CLASSNAMES.message_too_long);
|
||||||
|
assert.equal(
|
||||||
|
data.banner_text,
|
||||||
|
$t({
|
||||||
|
defaultMessage: "Message length shouldn't be greater than 10000 characters.",
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
banner_rendered = true;
|
||||||
|
});
|
||||||
|
|
||||||
// Indicator should show red colored text
|
// Indicator should show red colored text
|
||||||
$textarea.val("a".repeat(10000 + 1));
|
$textarea.val("a".repeat(10000 + 1));
|
||||||
@@ -483,52 +544,27 @@ test_ui("test_check_overflow_text", () => {
|
|||||||
assert.ok($indicator.hasClass("over_limit"));
|
assert.ok($indicator.hasClass("over_limit"));
|
||||||
assert.equal($indicator.text(), "10001/10000");
|
assert.equal($indicator.text(), "10001/10000");
|
||||||
assert.ok($textarea.hasClass("over_limit"));
|
assert.ok($textarea.hasClass("over_limit"));
|
||||||
assert.equal(
|
assert.ok(banner_rendered);
|
||||||
$("#compose-error-msg").html(),
|
|
||||||
"translated HTML: Message length shouldn't be greater than 10000 characters.",
|
|
||||||
);
|
|
||||||
assert.ok($send_button.prop("disabled"));
|
assert.ok($send_button.prop("disabled"));
|
||||||
|
|
||||||
$("#compose-send-status").stop = () => ({fadeOut() {}});
|
|
||||||
|
|
||||||
// Indicator should show orange colored text
|
// Indicator should show orange colored text
|
||||||
|
banner_rendered = false;
|
||||||
$textarea.val("a".repeat(9000 + 1));
|
$textarea.val("a".repeat(9000 + 1));
|
||||||
compose_validate.check_overflow_text();
|
compose_validate.check_overflow_text();
|
||||||
assert.ok(!$indicator.hasClass("over_limit"));
|
assert.ok(!$indicator.hasClass("over_limit"));
|
||||||
assert.equal($indicator.text(), "9001/10000");
|
assert.equal($indicator.text(), "9001/10000");
|
||||||
assert.ok(!$textarea.hasClass("over_limit"));
|
assert.ok(!$textarea.hasClass("over_limit"));
|
||||||
assert.ok(!$send_button.prop("disabled"));
|
assert.ok(!$send_button.prop("disabled"));
|
||||||
|
assert.ok(!banner_rendered);
|
||||||
|
|
||||||
// Indicator must be empty
|
// Indicator must be empty
|
||||||
|
banner_rendered = false;
|
||||||
$textarea.val("a".repeat(9000));
|
$textarea.val("a".repeat(9000));
|
||||||
compose_validate.check_overflow_text();
|
compose_validate.check_overflow_text();
|
||||||
assert.ok(!$indicator.hasClass("over_limit"));
|
assert.ok(!$indicator.hasClass("over_limit"));
|
||||||
assert.equal($indicator.text(), "");
|
assert.equal($indicator.text(), "");
|
||||||
assert.ok(!$textarea.hasClass("over_limit"));
|
assert.ok(!$textarea.hasClass("over_limit"));
|
||||||
});
|
assert.ok(!banner_rendered);
|
||||||
|
|
||||||
test_ui("test_message_overflow", () => {
|
|
||||||
page_params.max_message_length = 10000;
|
|
||||||
|
|
||||||
const sub = {
|
|
||||||
stream_id: 101,
|
|
||||||
name: "social",
|
|
||||||
subscribed: true,
|
|
||||||
};
|
|
||||||
|
|
||||||
stream_data.add_sub(sub);
|
|
||||||
page_params.user_id = 30;
|
|
||||||
const message = "a".repeat(10000 + 1);
|
|
||||||
|
|
||||||
compose_state.stream_name("social");
|
|
||||||
compose_state.topic("priyam");
|
|
||||||
$("#compose-textarea").val(message);
|
|
||||||
|
|
||||||
assert.ok(!compose_validate.validate());
|
|
||||||
assert.equal($("#compose-error-msg").html(), "never-been-set");
|
|
||||||
|
|
||||||
$("#compose-textarea").val("a");
|
|
||||||
assert.ok(compose_validate.validate());
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test_ui("needs_subscribe_warning", () => {
|
test_ui("needs_subscribe_warning", () => {
|
||||||
@@ -767,7 +803,7 @@ test_ui("warn_if_mentioning_unsubscribed_user", ({override, override_rewire, moc
|
|||||||
test_ui("test warn_if_topic_resolved", ({override, mock_template}) => {
|
test_ui("test warn_if_topic_resolved", ({override, mock_template}) => {
|
||||||
mock_banners();
|
mock_banners();
|
||||||
$("#compose_banners .topic_resolved").length = 0;
|
$("#compose_banners .topic_resolved").length = 0;
|
||||||
override(settings_data, "user_can_move_messages_between_streams", () => true);
|
override(settings_data, "user_can_edit_topic_of_any_message", () => true);
|
||||||
|
|
||||||
let error_shown = false;
|
let error_shown = false;
|
||||||
mock_template("compose_banner/compose_banner.hbs", false, (data) => {
|
mock_template("compose_banner/compose_banner.hbs", false, (data) => {
|
||||||
|
|||||||
@@ -253,7 +253,11 @@ export function send_message(request = create_message_object()) {
|
|||||||
// If we're not local echo'ing messages, or if this message was not
|
// If we're not local echo'ing messages, or if this message was not
|
||||||
// locally echoed, show error in compose box
|
// locally echoed, show error in compose box
|
||||||
if (!locally_echoed) {
|
if (!locally_echoed) {
|
||||||
compose_error.show(_.escape(response), $("#compose-textarea"));
|
compose_error.show_error_message(
|
||||||
|
response,
|
||||||
|
compose_error.CLASSNAMES.generic_compose_error,
|
||||||
|
$("#compose-textarea"),
|
||||||
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -510,7 +514,11 @@ export function initialize() {
|
|||||||
|
|
||||||
function failure(error_msg) {
|
function failure(error_msg) {
|
||||||
clear_invites();
|
clear_invites();
|
||||||
compose_error.show(_.escape(error_msg), $("#compose-textarea"));
|
compose_error.show_error_message(
|
||||||
|
error_msg,
|
||||||
|
compose_error.CLASSNAMES.generic_compose_error,
|
||||||
|
$("#compose-textarea"),
|
||||||
|
);
|
||||||
$(event.target).prop("disabled", true);
|
$(event.target).prop("disabled", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,15 +1,63 @@
|
|||||||
import $ from "jquery";
|
import $ from "jquery";
|
||||||
|
|
||||||
|
import render_compose_banner from "../templates/compose_banner/compose_banner.hbs";
|
||||||
|
import render_stream_does_not_exist_error from "../templates/compose_banner/stream_does_not_exist_error.hbs";
|
||||||
|
|
||||||
import * as common from "./common";
|
import * as common from "./common";
|
||||||
|
|
||||||
// banner types
|
// banner types
|
||||||
export const WARNING = "warning";
|
export const WARNING = "warning";
|
||||||
|
export const ERROR = "error";
|
||||||
|
|
||||||
export const CLASSNAMES = {
|
export const CLASSNAMES = {
|
||||||
// warnings
|
// warnings
|
||||||
topic_resolved: "topic_resolved",
|
topic_resolved: "topic_resolved",
|
||||||
|
// errors
|
||||||
|
empty_message: "empty_message",
|
||||||
|
wildcards_not_allowed: "wildcards_not_allowed",
|
||||||
|
subscription_error: "subscription_error",
|
||||||
|
stream_does_not_exist: "stream_does_not_exist",
|
||||||
|
missing_stream: "missing_stream",
|
||||||
|
no_post_permissions: "no_post_permissions",
|
||||||
|
private_messages_disabled: "private_messages_disabled",
|
||||||
|
missing_private_message_recipient: "missing_private_message_recipient",
|
||||||
|
invalid_recipient: "invalid_recipient",
|
||||||
|
invalid_recipients: "invalid_recipients",
|
||||||
|
deactivated_user: "deactivated_user",
|
||||||
|
message_too_long: "message_too_long",
|
||||||
|
topic_missing: "topic_missing",
|
||||||
|
zephyr_not_running: "zephyr_not_running",
|
||||||
|
generic_compose_error: "generic_compose_error",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// TODO: Replace with compose_ui.hide_compose_spinner() when it is converted to ts.
|
||||||
|
function hide_compose_spinner(): void {
|
||||||
|
$("#compose-send-button .loader").hide();
|
||||||
|
$("#compose-send-button span").show();
|
||||||
|
$("#compose-send-button").removeClass("disable-btn");
|
||||||
|
}
|
||||||
|
|
||||||
|
export function show_error_message(message: string, classname: string, $bad_input?: JQuery): void {
|
||||||
|
$(`#compose_banners .${classname}`).remove();
|
||||||
|
|
||||||
|
const new_row = render_compose_banner({
|
||||||
|
banner_type: ERROR,
|
||||||
|
stream_id: null,
|
||||||
|
topic_name: null,
|
||||||
|
banner_text: message,
|
||||||
|
button_text: null,
|
||||||
|
classname,
|
||||||
|
});
|
||||||
|
const $compose_banner_area = $("#compose_banners");
|
||||||
|
$compose_banner_area.append(new_row);
|
||||||
|
|
||||||
|
hide_compose_spinner();
|
||||||
|
|
||||||
|
if ($bad_input !== undefined) {
|
||||||
|
$bad_input.trigger("focus").trigger("select");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export function show(error_html: string, $bad_input?: JQuery, alert_class = "alert-error"): void {
|
export function show(error_html: string, $bad_input?: JQuery, alert_class = "alert-error"): void {
|
||||||
$("#compose-send-status")
|
$("#compose-send-status")
|
||||||
.removeClass(common.status_classes)
|
.removeClass(common.status_classes)
|
||||||
@@ -17,16 +65,28 @@ export function show(error_html: string, $bad_input?: JQuery, alert_class = "ale
|
|||||||
.stop(true)
|
.stop(true)
|
||||||
.fadeTo(0, 1);
|
.fadeTo(0, 1);
|
||||||
$("#compose-error-msg").html(error_html);
|
$("#compose-error-msg").html(error_html);
|
||||||
// TODO: Replace with compose_ui.hide_compose_spinner() when it is converted to ts.
|
hide_compose_spinner();
|
||||||
$("#compose-send-button .loader").hide();
|
|
||||||
$("#compose-send-button span").show();
|
|
||||||
$("#compose-send-button").removeClass("disable-btn");
|
|
||||||
|
|
||||||
if ($bad_input !== undefined) {
|
if ($bad_input !== undefined) {
|
||||||
$bad_input.trigger("focus").trigger("select");
|
$bad_input.trigger("focus").trigger("select");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function show_stream_does_not_exist_error(stream_name: string): void {
|
||||||
|
// Remove any existing banners with this warning.
|
||||||
|
$(`#compose_banners .${CLASSNAMES.stream_does_not_exist}`).remove();
|
||||||
|
|
||||||
|
const new_row = render_stream_does_not_exist_error({
|
||||||
|
banner_type: ERROR,
|
||||||
|
stream_name,
|
||||||
|
classname: CLASSNAMES.stream_does_not_exist,
|
||||||
|
});
|
||||||
|
const $compose_banner_area = $("#compose_banners");
|
||||||
|
$compose_banner_area.append(new_row);
|
||||||
|
hide_compose_spinner();
|
||||||
|
$("#stream_message_recipient_stream").trigger("focus").trigger("select");
|
||||||
|
}
|
||||||
|
|
||||||
export function show_not_subscribed(error_html: string, $bad_input?: JQuery): void {
|
export function show_not_subscribed(error_html: string, $bad_input?: JQuery): void {
|
||||||
show(error_html, $bad_input, "home-error-bar");
|
show(error_html, $bad_input, "home-error-bar");
|
||||||
$(".compose-send-status-close").hide();
|
$(".compose-send-status-close").hide();
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import * as compose_error from "./compose_error";
|
|||||||
import * as compose_pm_pill from "./compose_pm_pill";
|
import * as compose_pm_pill from "./compose_pm_pill";
|
||||||
import * as compose_state from "./compose_state";
|
import * as compose_state from "./compose_state";
|
||||||
import * as compose_ui from "./compose_ui";
|
import * as compose_ui from "./compose_ui";
|
||||||
import {$t, $t_html} from "./i18n";
|
import {$t} from "./i18n";
|
||||||
import {page_params} from "./page_params";
|
import {page_params} from "./page_params";
|
||||||
import * as peer_data from "./peer_data";
|
import * as peer_data from "./peer_data";
|
||||||
import * as people from "./people";
|
import * as people from "./people";
|
||||||
@@ -346,11 +346,12 @@ function validate_stream_message_mentions(stream_id) {
|
|||||||
// stream, check if they permission to do so.
|
// stream, check if they permission to do so.
|
||||||
if (wildcard_mention !== null && stream_count > wildcard_mention_large_stream_threshold) {
|
if (wildcard_mention !== null && stream_count > wildcard_mention_large_stream_threshold) {
|
||||||
if (!wildcard_mention_allowed()) {
|
if (!wildcard_mention_allowed()) {
|
||||||
compose_error.show(
|
compose_error.show_error_message(
|
||||||
$t_html({
|
$t({
|
||||||
defaultMessage:
|
defaultMessage:
|
||||||
"You do not have permission to use wildcard mentions in this stream.",
|
"You do not have permission to use wildcard mentions in this stream.",
|
||||||
}),
|
}),
|
||||||
|
compose_error.CLASSNAMES.wildcards_not_allowed,
|
||||||
);
|
);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -377,26 +378,14 @@ function validate_stream_message_mentions(stream_id) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function validation_error(error_type, stream_name) {
|
export function validation_error(error_type, stream_name) {
|
||||||
let response;
|
|
||||||
|
|
||||||
switch (error_type) {
|
switch (error_type) {
|
||||||
case "does-not-exist":
|
case "does-not-exist":
|
||||||
response = $t_html(
|
compose_error.show_stream_does_not_exist_error(stream_name);
|
||||||
{
|
|
||||||
defaultMessage:
|
|
||||||
"<p>The stream <b>{stream_name}</b> does not exist.</p><p>Manage your subscriptions <z-link>on your Streams page</z-link>.</p>",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
stream_name,
|
|
||||||
"z-link": (content_html) =>
|
|
||||||
`<a href='#streams/all'>${content_html.join("")}</a>`,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
compose_error.show(response, $("#stream_message_recipient_stream"));
|
|
||||||
return false;
|
return false;
|
||||||
case "error":
|
case "error":
|
||||||
compose_error.show(
|
compose_error.show_error_message(
|
||||||
$t_html({defaultMessage: "Error checking subscription"}),
|
$t({defaultMessage: "Error checking subscription."}),
|
||||||
|
compose_error.CLASSNAMES.subscription_error,
|
||||||
$("#stream_message_recipient_stream"),
|
$("#stream_message_recipient_stream"),
|
||||||
);
|
);
|
||||||
return false;
|
return false;
|
||||||
@@ -424,8 +413,9 @@ export function validate_stream_message_address_info(stream_name) {
|
|||||||
function validate_stream_message() {
|
function validate_stream_message() {
|
||||||
const stream_name = compose_state.stream_name();
|
const stream_name = compose_state.stream_name();
|
||||||
if (stream_name === "") {
|
if (stream_name === "") {
|
||||||
compose_error.show(
|
compose_error.show_error_message(
|
||||||
$t_html({defaultMessage: "Please specify a stream"}),
|
$t({defaultMessage: "Please specify a stream."}),
|
||||||
|
compose_error.CLASSNAMES.missing_stream,
|
||||||
$("#stream_message_recipient_stream"),
|
$("#stream_message_recipient_stream"),
|
||||||
);
|
);
|
||||||
return false;
|
return false;
|
||||||
@@ -436,8 +426,9 @@ function validate_stream_message() {
|
|||||||
// TODO: We plan to migrate the empty topic to only using the
|
// TODO: We plan to migrate the empty topic to only using the
|
||||||
// `""` representation for i18n reasons, but have not yet done so.
|
// `""` representation for i18n reasons, but have not yet done so.
|
||||||
if (topic === "" || topic === "(no topic)") {
|
if (topic === "" || topic === "(no topic)") {
|
||||||
compose_error.show(
|
compose_error.show_error_message(
|
||||||
$t_html({defaultMessage: "Topics are required in this organization"}),
|
$t({defaultMessage: "Topics are required in this organization."}),
|
||||||
|
compose_error.CLASSNAMES.topic_missing,
|
||||||
$("#stream_message_recipient_topic"),
|
$("#stream_message_recipient_topic"),
|
||||||
);
|
);
|
||||||
return false;
|
return false;
|
||||||
@@ -450,10 +441,11 @@ function validate_stream_message() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!stream_data.can_post_messages_in_stream(sub)) {
|
if (!stream_data.can_post_messages_in_stream(sub)) {
|
||||||
compose_error.show(
|
compose_error.show_error_message(
|
||||||
$t_html({
|
$t({
|
||||||
defaultMessage: "You do not have permission to post in this stream.",
|
defaultMessage: "You do not have permission to post in this stream.",
|
||||||
}),
|
}),
|
||||||
|
compose_error.CLASSNAMES.no_post_permissions,
|
||||||
);
|
);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -484,16 +476,18 @@ function validate_private_message() {
|
|||||||
(user_ids.length !== 1 || !people.get_by_user_id(user_ids[0]).is_bot)
|
(user_ids.length !== 1 || !people.get_by_user_id(user_ids[0]).is_bot)
|
||||||
) {
|
) {
|
||||||
// Unless we're composing to a bot
|
// Unless we're composing to a bot
|
||||||
compose_error.show(
|
compose_error.show_error_message(
|
||||||
$t_html({defaultMessage: "Private messages are disabled in this organization."}),
|
$t({defaultMessage: "Private messages are disabled in this organization."}),
|
||||||
|
compose_error.CLASSNAMES.private_messages_disabled,
|
||||||
$("#private_message_recipient"),
|
$("#private_message_recipient"),
|
||||||
);
|
);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (compose_state.private_message_recipient().length === 0) {
|
if (compose_state.private_message_recipient().length === 0) {
|
||||||
compose_error.show(
|
compose_error.show_error_message(
|
||||||
$t_html({defaultMessage: "Please specify at least one valid recipient"}),
|
$t({defaultMessage: "Please specify at least one valid recipient."}),
|
||||||
|
compose_error.CLASSNAMES.missing_private_message_recipient,
|
||||||
$("#private_message_recipient"),
|
$("#private_message_recipient"),
|
||||||
);
|
);
|
||||||
return false;
|
return false;
|
||||||
@@ -507,15 +501,17 @@ function validate_private_message() {
|
|||||||
let context = {};
|
let context = {};
|
||||||
if (invalid_recipients.length === 1) {
|
if (invalid_recipients.length === 1) {
|
||||||
context = {recipient: invalid_recipients.join(",")};
|
context = {recipient: invalid_recipients.join(",")};
|
||||||
compose_error.show(
|
compose_error.show_error_message(
|
||||||
$t_html({defaultMessage: "The recipient {recipient} is not valid"}, context),
|
$t({defaultMessage: "The recipient {recipient} is not valid."}, context),
|
||||||
|
compose_error.CLASSNAMES.invalid_recipient,
|
||||||
$("#private_message_recipient"),
|
$("#private_message_recipient"),
|
||||||
);
|
);
|
||||||
return false;
|
return false;
|
||||||
} else if (invalid_recipients.length > 1) {
|
} else if (invalid_recipients.length > 1) {
|
||||||
context = {recipients: invalid_recipients.join(",")};
|
context = {recipients: invalid_recipients.join(",")};
|
||||||
compose_error.show(
|
compose_error.show_error_message(
|
||||||
$t_html({defaultMessage: "The recipients {recipients} are not valid"}, context),
|
$t({defaultMessage: "The recipients {recipients} are not valid."}, context),
|
||||||
|
compose_error.CLASSNAMES.invalid_recipients,
|
||||||
$("#private_message_recipient"),
|
$("#private_message_recipient"),
|
||||||
);
|
);
|
||||||
return false;
|
return false;
|
||||||
@@ -524,11 +520,9 @@ function validate_private_message() {
|
|||||||
for (const user_id of user_ids) {
|
for (const user_id of user_ids) {
|
||||||
if (!people.is_person_active(user_id)) {
|
if (!people.is_person_active(user_id)) {
|
||||||
context = {full_name: people.get_by_user_id(user_id).full_name};
|
context = {full_name: people.get_by_user_id(user_id).full_name};
|
||||||
compose_error.show(
|
compose_error.show_error_message(
|
||||||
$t_html(
|
$t({defaultMessage: "You cannot send messages to deactivated users."}, context),
|
||||||
{defaultMessage: "You cannot send messages to deactivated users."},
|
compose_error.CLASSNAMES.deactivated_user,
|
||||||
context,
|
|
||||||
),
|
|
||||||
$("#private_message_recipient"),
|
$("#private_message_recipient"),
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -551,14 +545,15 @@ export function check_overflow_text() {
|
|||||||
$indicator.addClass("over_limit");
|
$indicator.addClass("over_limit");
|
||||||
$("#compose-textarea").addClass("over_limit");
|
$("#compose-textarea").addClass("over_limit");
|
||||||
$indicator.text(text.length + "/" + max_length);
|
$indicator.text(text.length + "/" + max_length);
|
||||||
compose_error.show(
|
compose_error.show_error_message(
|
||||||
$t_html(
|
$t(
|
||||||
{
|
{
|
||||||
defaultMessage:
|
defaultMessage:
|
||||||
"Message length shouldn't be greater than {max_length} characters.",
|
"Message length shouldn't be greater than {max_length} characters.",
|
||||||
},
|
},
|
||||||
{max_length},
|
{max_length},
|
||||||
),
|
),
|
||||||
|
compose_error.CLASSNAMES.message_too_long,
|
||||||
);
|
);
|
||||||
$("#compose-send-button").prop("disabled", true);
|
$("#compose-send-button").prop("disabled", true);
|
||||||
} else if (text.length > 0.9 * max_length) {
|
} else if (text.length > 0.9 * max_length) {
|
||||||
@@ -567,17 +562,13 @@ export function check_overflow_text() {
|
|||||||
$indicator.text(text.length + "/" + max_length);
|
$indicator.text(text.length + "/" + max_length);
|
||||||
|
|
||||||
$("#compose-send-button").prop("disabled", false);
|
$("#compose-send-button").prop("disabled", false);
|
||||||
if ($("#compose-send-status").hasClass("alert-error")) {
|
$(`#compose_banners .${compose_error.CLASSNAMES.message_too_long}`).remove();
|
||||||
$("#compose-send-status").stop(true).fadeOut();
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
$indicator.text("");
|
$indicator.text("");
|
||||||
$("#compose-textarea").removeClass("over_limit");
|
$("#compose-textarea").removeClass("over_limit");
|
||||||
|
|
||||||
$("#compose-send-button").prop("disabled", false);
|
$("#compose-send-button").prop("disabled", false);
|
||||||
if ($("#compose-send-status").hasClass("alert-error")) {
|
$(`#compose_banners .${compose_error.CLASSNAMES.message_too_long}`).remove();
|
||||||
$("#compose-send-status").stop(true).fadeOut();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return text.length;
|
return text.length;
|
||||||
@@ -598,20 +589,23 @@ export function validate() {
|
|||||||
// Avoid showing an error message when "enter sends" is enabled,
|
// Avoid showing an error message when "enter sends" is enabled,
|
||||||
// as it is more likely that the user has hit "Enter" accidentally.
|
// as it is more likely that the user has hit "Enter" accidentally.
|
||||||
if (!user_settings.enter_sends) {
|
if (!user_settings.enter_sends) {
|
||||||
compose_error.show(
|
compose_error.show_error_message(
|
||||||
$t_html({defaultMessage: "You have nothing to send!"}),
|
$t({defaultMessage: "You have nothing to send!"}),
|
||||||
|
compose_error.CLASSNAMES.empty_message,
|
||||||
$("#compose-textarea"),
|
$("#compose-textarea"),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
$(`#compose_banners .${compose_error.CLASSNAMES.empty_message}`).remove();
|
||||||
|
|
||||||
if ($("#zephyr-mirror-error").is(":visible")) {
|
if ($("#zephyr-mirror-error").is(":visible")) {
|
||||||
compose_error.show(
|
compose_error.show_error_message(
|
||||||
$t_html({
|
$t({
|
||||||
defaultMessage:
|
defaultMessage:
|
||||||
"You need to be running Zephyr mirroring in order to send messages!",
|
"You need to be running Zephyr mirroring in order to send messages!",
|
||||||
}),
|
}),
|
||||||
|
compose_error.CLASSNAMES.zephyr_not_running,
|
||||||
);
|
);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import $ from "jquery";
|
import $ from "jquery";
|
||||||
import _ from "lodash";
|
|
||||||
|
|
||||||
import * as channel from "./channel";
|
import * as channel from "./channel";
|
||||||
import * as compose from "./compose";
|
import * as compose from "./compose";
|
||||||
@@ -72,7 +71,11 @@ export function schedule_message(request = compose.create_message_object()) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (error_message) {
|
if (error_message) {
|
||||||
compose_error.show(error_message, $("#compose-textarea"));
|
compose_error.show_error_message(
|
||||||
|
error_message,
|
||||||
|
compose_error.CLASSNAMES.generic_compose_error,
|
||||||
|
$("#compose-textarea"),
|
||||||
|
);
|
||||||
$("#compose-textarea").prop("disabled", false);
|
$("#compose-textarea").prop("disabled", false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -96,7 +99,11 @@ export function schedule_message(request = compose.create_message_object()) {
|
|||||||
};
|
};
|
||||||
const error = function (response) {
|
const error = function (response) {
|
||||||
$("#compose-textarea").prop("disabled", false);
|
$("#compose-textarea").prop("disabled", false);
|
||||||
compose_error.show(_.escape(response), $("#compose-textarea"));
|
compose_error.show_error_message(
|
||||||
|
response,
|
||||||
|
compose_error.CLASSNAMES.generic_compose_error,
|
||||||
|
$("#compose-textarea"),
|
||||||
|
);
|
||||||
};
|
};
|
||||||
/* We are adding a disable on compose under this block because we
|
/* We are adding a disable on compose under this block because we
|
||||||
want slash commands to be blocking in nature. */
|
want slash commands to be blocking in nature. */
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
import $ from "jquery";
|
|
||||||
|
|
||||||
import * as channel from "./channel";
|
import * as channel from "./channel";
|
||||||
import * as common from "./common";
|
import * as compose_error from "./compose_error";
|
||||||
import * as dark_theme from "./dark_theme";
|
import * as dark_theme from "./dark_theme";
|
||||||
import * as feedback_widget from "./feedback_widget";
|
import * as feedback_widget from "./feedback_widget";
|
||||||
import {$t} from "./i18n";
|
import {$t} from "./i18n";
|
||||||
@@ -50,12 +48,7 @@ export function send(opts) {
|
|||||||
export function tell_user(msg) {
|
export function tell_user(msg) {
|
||||||
// This is a bit hacky, but we don't have a super easy API now
|
// This is a bit hacky, but we don't have a super easy API now
|
||||||
// for just telling users stuff.
|
// for just telling users stuff.
|
||||||
$("#compose-send-status")
|
compose_error.show_error_message(msg, compose_error.CLASSNAMES.generic_compose_error);
|
||||||
.removeClass(common.status_classes)
|
|
||||||
.addClass("alert-error")
|
|
||||||
.stop(true)
|
|
||||||
.fadeTo(0, 1);
|
|
||||||
$("#compose-error-msg").text(msg);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function switch_to_light_theme() {
|
export function switch_to_light_theme() {
|
||||||
|
|||||||
@@ -348,6 +348,37 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.error {
|
||||||
|
background-color: hsl(4, 35%, 90%);
|
||||||
|
border-color: hsla(3, 57%, 33%, 0.4);
|
||||||
|
color: hsl(4, 58%, 33%);
|
||||||
|
|
||||||
|
.compose_banner_close_button {
|
||||||
|
color: hsla(4, 58%, 33%, 0.5);
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: hsl(4, 58%, 33%);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:active {
|
||||||
|
color: hsla(4, 58%, 33%, 0.75);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.compose_banner_action_button {
|
||||||
|
background-color: hsla(3, 57%, 33%, 0.1);
|
||||||
|
color: inherit;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: hsla(3, 57%, 33%, 0.12);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:active {
|
||||||
|
background-color: hsla(3, 57%, 33%, 0.15);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.compose_invite_user,
|
.compose_invite_user,
|
||||||
|
|||||||
@@ -202,6 +202,37 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.error {
|
||||||
|
background-color: hsl(0, 60%, 19%);
|
||||||
|
border-color: hsla(3, 73%, 74%, 0.4);
|
||||||
|
color: hsl(3, 73%, 74%);
|
||||||
|
|
||||||
|
.compose_banner_close_button {
|
||||||
|
color: hsla(3, 73%, 74%, 0.5);
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: hsl(3, 73%, 74%);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:active {
|
||||||
|
color: hsl(3, 73%, 74%, 0.75);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.compose_banner_action_button {
|
||||||
|
background-color: hsla(3, 73%, 74%, 0.1);
|
||||||
|
color: inherit;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: hsla(3, 73%, 74%, 0.15);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:active {
|
||||||
|
background: hsla(3, 73%, 74%, 0.2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.message_embed .data-container::after {
|
.message_embed .data-container::after {
|
||||||
|
|||||||
@@ -2,7 +2,11 @@
|
|||||||
class="compose_banner {{banner_type}} {{classname}}"
|
class="compose_banner {{banner_type}} {{classname}}"
|
||||||
{{#if stream_id}}data-stream-id="{{stream_id}}"{{/if}}
|
{{#if stream_id}}data-stream-id="{{stream_id}}"{{/if}}
|
||||||
{{#if topic_name}}data-topic-name="{{topic_name}}"{{/if}}>
|
{{#if topic_name}}data-topic-name="{{topic_name}}"{{/if}}>
|
||||||
|
{{#if banner_text}}
|
||||||
<p class="banner_content">{{banner_text}}</p>
|
<p class="banner_content">{{banner_text}}</p>
|
||||||
|
{{else}}
|
||||||
|
<div class="banner_content">{{> @partial-block}}</div>
|
||||||
|
{{/if}}
|
||||||
{{#if button_text}}
|
{{#if button_text}}
|
||||||
<button class="compose_banner_action_button" >{{button_text}}</button>
|
<button class="compose_banner_action_button" >{{button_text}}</button>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
{{#> compose_banner }}
|
||||||
|
<p>
|
||||||
|
{{#tr}}
|
||||||
|
The stream <b>#{stream_name}</b> does not exist. Manage your subscriptions
|
||||||
|
<z-link>on your Streams page</z-link>.
|
||||||
|
{{#*inline "z-link"}}<a href='#streams/all'>{{> @partial-block}}</a>{{/inline}}
|
||||||
|
{{/tr}}
|
||||||
|
</p>
|
||||||
|
{{/compose_banner}}
|
||||||
Reference in New Issue
Block a user