mirror of
https://github.com/zulip/zulip.git
synced 2025-11-05 14:35:27 +00:00
compose: Show warning while composing to a resolved topic.
This commit creates the function warn_if_topic_resolved that checks if the topic to which the user is composing is resolved or not. First it checks if the stream exists and then if the topic name starts with the RESOLVED_TOPIC_PREFIX. If the conditions are true, a warning banner is shown to the user. It also shows to the user a button to unresolve the topic, if he has the permission to do so. Fixes #20584.
This commit is contained in:
@@ -16,6 +16,7 @@ const ui_util = mock_esm("../../static/js/ui_util");
|
|||||||
|
|
||||||
const compose_pm_pill = zrequire("compose_pm_pill");
|
const compose_pm_pill = zrequire("compose_pm_pill");
|
||||||
const compose_validate = zrequire("compose_validate");
|
const compose_validate = zrequire("compose_validate");
|
||||||
|
const message_edit = zrequire("message_edit");
|
||||||
const peer_data = zrequire("peer_data");
|
const peer_data = zrequire("peer_data");
|
||||||
const people = zrequire("people");
|
const people = zrequire("people");
|
||||||
const settings_config = zrequire("settings_config");
|
const settings_config = zrequire("settings_config");
|
||||||
@@ -753,3 +754,53 @@ test_ui("warn_if_mentioning_unsubscribed_user", ({override, override_rewire, moc
|
|||||||
assert.equal($("#compose_invite_users").visible(), true);
|
assert.equal($("#compose_invite_users").visible(), true);
|
||||||
assert.ok(looked_for_existing);
|
assert.ok(looked_for_existing);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test_ui("test clear_topic_resolved_warning", () => {
|
||||||
|
$("#compose_resolved_topic").show();
|
||||||
|
$("#compose-send-status").show();
|
||||||
|
|
||||||
|
compose_validate.clear_topic_resolved_warning();
|
||||||
|
|
||||||
|
assert.ok(!$("#compose_resolved_topic").visible());
|
||||||
|
assert.ok(!$("#compose-send-status").visible());
|
||||||
|
});
|
||||||
|
|
||||||
|
test_ui("test warn_if_topic_resolved", ({override, mock_template}) => {
|
||||||
|
override(settings_data, "user_can_move_messages_between_streams", () => true);
|
||||||
|
|
||||||
|
mock_template("compose_resolved_topic.hbs", false, (context) => {
|
||||||
|
assert.ok(context.can_move_topic);
|
||||||
|
assert.ok(context.topic_name.startsWith(message_edit.RESOLVED_TOPIC_PREFIX));
|
||||||
|
return "fake-compose_resolved_topic";
|
||||||
|
});
|
||||||
|
|
||||||
|
const sub = {
|
||||||
|
stream_id: 111,
|
||||||
|
name: "random",
|
||||||
|
};
|
||||||
|
stream_data.add_sub(sub);
|
||||||
|
|
||||||
|
// The error message area where it is shown
|
||||||
|
const error_area = $("#compose_resolved_topic");
|
||||||
|
error_area.html("");
|
||||||
|
|
||||||
|
compose_state.set_message_type("stream");
|
||||||
|
compose_state.stream_name("Do not exist");
|
||||||
|
compose_state.topic(message_edit.RESOLVED_TOPIC_PREFIX + "hello");
|
||||||
|
|
||||||
|
// Do not show a warning if stream name does not exist
|
||||||
|
compose_validate.warn_if_topic_resolved();
|
||||||
|
assert.ok(!error_area.visible());
|
||||||
|
|
||||||
|
compose_state.stream_name("random");
|
||||||
|
|
||||||
|
// Show the warning now as stream also exists
|
||||||
|
compose_validate.warn_if_topic_resolved();
|
||||||
|
assert.ok(error_area.visible());
|
||||||
|
|
||||||
|
compose_state.topic("hello");
|
||||||
|
|
||||||
|
// The warning will be cleared now
|
||||||
|
compose_validate.warn_if_topic_resolved();
|
||||||
|
assert.ok(!error_area.visible());
|
||||||
|
});
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import * as flatpickr from "./flatpickr";
|
|||||||
import {$t, $t_html} from "./i18n";
|
import {$t, $t_html} from "./i18n";
|
||||||
import * as loading from "./loading";
|
import * as loading from "./loading";
|
||||||
import * as markdown from "./markdown";
|
import * as markdown from "./markdown";
|
||||||
|
import * as message_edit from "./message_edit";
|
||||||
import * as notifications from "./notifications";
|
import * as notifications from "./notifications";
|
||||||
import {page_params} from "./page_params";
|
import {page_params} from "./page_params";
|
||||||
import * as people from "./people";
|
import * as people from "./people";
|
||||||
@@ -92,6 +93,7 @@ export function update_fade() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const msg_type = compose_state.get_message_type();
|
const msg_type = compose_state.get_message_type();
|
||||||
|
compose_validate.warn_if_topic_resolved();
|
||||||
compose_fade.set_focused_recipient(msg_type);
|
compose_fade.set_focused_recipient(msg_type);
|
||||||
compose_fade.update_all();
|
compose_fade.update_all();
|
||||||
}
|
}
|
||||||
@@ -447,6 +449,25 @@ export function initialize() {
|
|||||||
$("#compose-send-status").hide();
|
$("#compose-send-status").hide();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$("#compose_resolved_topic").on("click", ".compose_unresolve_topic", (event) => {
|
||||||
|
event.preventDefault();
|
||||||
|
|
||||||
|
const target = $(event.target).parents(".compose_resolved_topic");
|
||||||
|
const stream_id = Number.parseInt(target.attr("data-stream-id"), 10);
|
||||||
|
const topic_name = target.attr("data-topic-name");
|
||||||
|
|
||||||
|
message_edit.with_first_message_id(stream_id, topic_name, (message_id) => {
|
||||||
|
message_edit.toggle_resolve_topic(message_id, topic_name);
|
||||||
|
compose_validate.clear_topic_resolved_warning();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
$("#compose_resolved_topic").on("click", ".compose_resolved_topic_close", (event) => {
|
||||||
|
event.preventDefault();
|
||||||
|
|
||||||
|
compose_validate.clear_topic_resolved_warning();
|
||||||
|
});
|
||||||
|
|
||||||
$("#compose_invite_users").on("click", ".compose_invite_link", (event) => {
|
$("#compose_invite_users").on("click", ".compose_invite_link", (event) => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
|
||||||
|
|||||||
@@ -106,6 +106,7 @@ function clear_box() {
|
|||||||
compose.clear_invites();
|
compose.clear_invites();
|
||||||
|
|
||||||
// TODO: Better encapsulate at-mention warnings.
|
// TODO: Better encapsulate at-mention warnings.
|
||||||
|
compose_validate.clear_topic_resolved_warning();
|
||||||
compose_validate.clear_all_everyone_warnings();
|
compose_validate.clear_all_everyone_warnings();
|
||||||
compose_validate.clear_announce_warnings();
|
compose_validate.clear_announce_warnings();
|
||||||
compose.clear_private_stream_alert();
|
compose.clear_private_stream_alert();
|
||||||
@@ -285,6 +286,9 @@ export function start(msg_type, opts) {
|
|||||||
// Show either stream/topic fields or "You and" field.
|
// Show either stream/topic fields or "You and" field.
|
||||||
show_box(msg_type, opts);
|
show_box(msg_type, opts);
|
||||||
|
|
||||||
|
// Show a warning if topic is resolved
|
||||||
|
compose_validate.warn_if_topic_resolved();
|
||||||
|
|
||||||
// Reset the `max-height` property of `compose-textarea` so that the
|
// Reset the `max-height` property of `compose-textarea` so that the
|
||||||
// compose-box do not cover the last messages of the current stream
|
// compose-box do not cover the last messages of the current stream
|
||||||
// while writing a long message.
|
// while writing a long message.
|
||||||
@@ -460,6 +464,7 @@ export function on_topic_narrow() {
|
|||||||
// See #3300 for context--a couple users specifically asked for
|
// See #3300 for context--a couple users specifically asked for
|
||||||
// this convenience.
|
// this convenience.
|
||||||
compose_state.topic(narrow_state.topic());
|
compose_state.topic(narrow_state.topic());
|
||||||
|
compose_validate.warn_if_topic_resolved();
|
||||||
compose_fade.set_focused_recipient("stream");
|
compose_fade.set_focused_recipient("stream");
|
||||||
compose_fade.update_message_list();
|
compose_fade.update_message_list();
|
||||||
$("#compose-textarea").trigger("focus").trigger("select");
|
$("#compose-textarea").trigger("focus").trigger("select");
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import render_compose_announce from "../templates/compose_announce.hbs";
|
|||||||
import render_compose_invite_users from "../templates/compose_invite_users.hbs";
|
import render_compose_invite_users from "../templates/compose_invite_users.hbs";
|
||||||
import render_compose_not_subscribed from "../templates/compose_not_subscribed.hbs";
|
import render_compose_not_subscribed from "../templates/compose_not_subscribed.hbs";
|
||||||
import render_compose_private_stream_alert from "../templates/compose_private_stream_alert.hbs";
|
import render_compose_private_stream_alert from "../templates/compose_private_stream_alert.hbs";
|
||||||
|
import render_compose_resolved_topic from "../templates/compose_resolved_topic.hbs";
|
||||||
|
|
||||||
import * as channel from "./channel";
|
import * as channel from "./channel";
|
||||||
import * as compose_error from "./compose_error";
|
import * as compose_error from "./compose_error";
|
||||||
@@ -12,6 +13,7 @@ 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_html} from "./i18n";
|
import {$t_html} from "./i18n";
|
||||||
|
import * as message_edit from "./message_edit";
|
||||||
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";
|
||||||
@@ -164,6 +166,40 @@ export function warn_if_mentioning_unsubscribed_user(mentioned) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function clear_topic_resolved_warning() {
|
||||||
|
$("#compose_resolved_topic").hide();
|
||||||
|
$("#compose_resolved_topic").empty();
|
||||||
|
$("#compose-send-status").hide();
|
||||||
|
}
|
||||||
|
|
||||||
|
export function warn_if_topic_resolved() {
|
||||||
|
const stream_name = compose_state.stream_name();
|
||||||
|
const topic_name = compose_state.topic();
|
||||||
|
|
||||||
|
const sub = stream_data.get_sub(stream_name);
|
||||||
|
|
||||||
|
if (sub && topic_name.startsWith(message_edit.RESOLVED_TOPIC_PREFIX)) {
|
||||||
|
const error_area = $("#compose_resolved_topic");
|
||||||
|
|
||||||
|
if (error_area.html()) {
|
||||||
|
clear_topic_resolved_warning(); // This warning already exists
|
||||||
|
}
|
||||||
|
|
||||||
|
const context = {
|
||||||
|
stream_id: sub.stream_id,
|
||||||
|
topic_name,
|
||||||
|
can_move_topic: settings_data.user_can_move_messages_between_streams(),
|
||||||
|
};
|
||||||
|
|
||||||
|
const new_row = render_compose_resolved_topic(context);
|
||||||
|
error_area.append(new_row);
|
||||||
|
|
||||||
|
error_area.show();
|
||||||
|
} else {
|
||||||
|
clear_topic_resolved_warning();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function show_all_everyone_warnings(stream_id) {
|
function show_all_everyone_warnings(stream_id) {
|
||||||
const stream_count = peer_data.get_subscriber_count(stream_id) || 0;
|
const stream_count = peer_data.get_subscriber_count(stream_id) || 0;
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import {all_messages_data} from "./all_messages_data";
|
|||||||
import * as channel from "./channel";
|
import * as channel from "./channel";
|
||||||
import * as compose_fade from "./compose_fade";
|
import * as compose_fade from "./compose_fade";
|
||||||
import * as compose_state from "./compose_state";
|
import * as compose_state from "./compose_state";
|
||||||
|
import * as compose_validate from "./compose_validate";
|
||||||
import * as condense from "./condense";
|
import * as condense from "./condense";
|
||||||
import * as huddle_data from "./huddle_data";
|
import * as huddle_data from "./huddle_data";
|
||||||
import * as message_edit from "./message_edit";
|
import * as message_edit from "./message_edit";
|
||||||
@@ -218,6 +219,7 @@ export function update_messages(events) {
|
|||||||
) {
|
) {
|
||||||
changed_compose = true;
|
changed_compose = true;
|
||||||
compose_state.topic(new_topic);
|
compose_state.topic(new_topic);
|
||||||
|
compose_validate.warn_if_topic_resolved();
|
||||||
compose_fade.set_focused_recipient("stream");
|
compose_fade.set_focused_recipient("stream");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -255,6 +255,7 @@
|
|||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.compose_resolved_topic,
|
||||||
.compose_invite_user,
|
.compose_invite_user,
|
||||||
.compose_private_stream_alert,
|
.compose_private_stream_alert,
|
||||||
.compose-all-everyone,
|
.compose-all-everyone,
|
||||||
@@ -272,6 +273,7 @@
|
|||||||
position: absolute;
|
position: absolute;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.compose_resolved_topic_close,
|
||||||
.compose_invite_close,
|
.compose_invite_close,
|
||||||
.compose_private_stream_alert_close {
|
.compose_private_stream_alert_close {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
@@ -280,6 +282,7 @@
|
|||||||
width: 10px;
|
width: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.compose_resolved_topic_user_controls,
|
||||||
.compose-all-everyone-controls,
|
.compose-all-everyone-controls,
|
||||||
.compose-announce-controls,
|
.compose-announce-controls,
|
||||||
.compose_invite_user_controls,
|
.compose_invite_user_controls,
|
||||||
@@ -289,8 +292,9 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.compose_invite_user p,
|
.compose_invite_user p,
|
||||||
|
.compose_resolved_topic p,
|
||||||
.compose_not_subscribed p {
|
.compose_not_subscribed p {
|
||||||
margin: 0 20px;
|
margin: 5px 20px;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
max-width: calc(100% - 100px);
|
max-width: calc(100% - 100px);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,6 +43,7 @@
|
|||||||
<span class="compose-send-status-close">×</span>
|
<span class="compose-send-status-close">×</span>
|
||||||
<span id="compose-error-msg"></span>
|
<span id="compose-error-msg"></span>
|
||||||
</div>
|
</div>
|
||||||
|
<div id="compose_resolved_topic" class="alert home-error-bar"></div>
|
||||||
<div id="compose_invite_users" class="alert home-error-bar"></div>
|
<div id="compose_invite_users" class="alert home-error-bar"></div>
|
||||||
<div id="compose-all-everyone" class="alert home-error-bar"></div>
|
<div id="compose-all-everyone" class="alert home-error-bar"></div>
|
||||||
<div id="compose-announce" class="alert home-error-bar"></div>
|
<div id="compose-announce" class="alert home-error-bar"></div>
|
||||||
|
|||||||
9
static/templates/compose_resolved_topic.hbs
Normal file
9
static/templates/compose_resolved_topic.hbs
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
<div class="compose_resolved_topic" data-stream-id="{{stream_id}}" data-topic-name="{{topic_name}}">
|
||||||
|
<p>{{#tr}}You are sending a message to a resolved topic. You can send as-is or unresolve the topic first.{{/tr}}</p>
|
||||||
|
<div class="compose_resolved_topic_user_controls">
|
||||||
|
{{#if can_move_topic}}
|
||||||
|
<button class="btn btn-warning compose_unresolve_topic" >{{t "Unresolve topic" }}</button>
|
||||||
|
{{/if}}
|
||||||
|
<button type="button" class="compose_resolved_topic_close close">×</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
Reference in New Issue
Block a user