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:
Priyam Seth
2021-07-28 01:18:11 +05:30
committed by Tim Abbott
parent d1234ef18c
commit 17f74a3f57
8 changed files with 130 additions and 1 deletions

View File

@@ -16,6 +16,7 @@ const ui_util = mock_esm("../../static/js/ui_util");
const compose_pm_pill = zrequire("compose_pm_pill");
const compose_validate = zrequire("compose_validate");
const message_edit = zrequire("message_edit");
const peer_data = zrequire("peer_data");
const people = zrequire("people");
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.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());
});

View File

@@ -14,6 +14,7 @@ import * as flatpickr from "./flatpickr";
import {$t, $t_html} from "./i18n";
import * as loading from "./loading";
import * as markdown from "./markdown";
import * as message_edit from "./message_edit";
import * as notifications from "./notifications";
import {page_params} from "./page_params";
import * as people from "./people";
@@ -92,6 +93,7 @@ export function update_fade() {
}
const msg_type = compose_state.get_message_type();
compose_validate.warn_if_topic_resolved();
compose_fade.set_focused_recipient(msg_type);
compose_fade.update_all();
}
@@ -447,6 +449,25 @@ export function initialize() {
$("#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) => {
event.preventDefault();

View File

@@ -106,6 +106,7 @@ function clear_box() {
compose.clear_invites();
// TODO: Better encapsulate at-mention warnings.
compose_validate.clear_topic_resolved_warning();
compose_validate.clear_all_everyone_warnings();
compose_validate.clear_announce_warnings();
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_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
// compose-box do not cover the last messages of the current stream
// while writing a long message.
@@ -460,6 +464,7 @@ export function on_topic_narrow() {
// See #3300 for context--a couple users specifically asked for
// this convenience.
compose_state.topic(narrow_state.topic());
compose_validate.warn_if_topic_resolved();
compose_fade.set_focused_recipient("stream");
compose_fade.update_message_list();
$("#compose-textarea").trigger("focus").trigger("select");

View File

@@ -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_not_subscribed from "../templates/compose_not_subscribed.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 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_ui from "./compose_ui";
import {$t_html} from "./i18n";
import * as message_edit from "./message_edit";
import {page_params} from "./page_params";
import * as peer_data from "./peer_data";
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) {
const stream_count = peer_data.get_subscriber_count(stream_id) || 0;

View File

@@ -5,6 +5,7 @@ import {all_messages_data} from "./all_messages_data";
import * as channel from "./channel";
import * as compose_fade from "./compose_fade";
import * as compose_state from "./compose_state";
import * as compose_validate from "./compose_validate";
import * as condense from "./condense";
import * as huddle_data from "./huddle_data";
import * as message_edit from "./message_edit";
@@ -218,6 +219,7 @@ export function update_messages(events) {
) {
changed_compose = true;
compose_state.topic(new_topic);
compose_validate.warn_if_topic_resolved();
compose_fade.set_focused_recipient("stream");
}

View File

@@ -255,6 +255,7 @@
display: none;
}
.compose_resolved_topic,
.compose_invite_user,
.compose_private_stream_alert,
.compose-all-everyone,
@@ -272,6 +273,7 @@
position: absolute;
}
.compose_resolved_topic_close,
.compose_invite_close,
.compose_private_stream_alert_close {
display: inline-block;
@@ -280,6 +282,7 @@
width: 10px;
}
.compose_resolved_topic_user_controls,
.compose-all-everyone-controls,
.compose-announce-controls,
.compose_invite_user_controls,
@@ -289,8 +292,9 @@
}
.compose_invite_user p,
.compose_resolved_topic p,
.compose_not_subscribed p {
margin: 0 20px;
margin: 5px 20px;
display: inline-block;
max-width: calc(100% - 100px);
}

View File

@@ -43,6 +43,7 @@
<span class="compose-send-status-close">&times;</span>
<span id="compose-error-msg"></span>
</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-all-everyone" class="alert home-error-bar"></div>
<div id="compose-announce" class="alert home-error-bar"></div>

View 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">&times;</button>
</div>
</div>