mirror of
https://github.com/zulip/zulip.git
synced 2025-10-23 04:52:12 +00:00
topic-move: Add warning banner if moving messages to existing topic.
In the move topic modal, when the user would merge messages into an existing conversation, then we display a warning banner in the modal. This is similar to the confirmation modal that appears when a user edits a topic via the message feed header. We do not show the warning for the empty/general topic for realms that do not require topics, even if there are messages in the general topic. Fixes #31151. Co-authored-by: Yiming He <heyimingfrog@gmail.com> Co-authored-by: Lauryn Menard <lauryn@zulip.com>
This commit is contained in:
@@ -5,6 +5,7 @@ import {z} from "zod";
|
||||
|
||||
import render_inline_decorated_stream_name from "../templates/inline_decorated_stream_name.hbs";
|
||||
import render_inline_stream_or_topic_reference from "../templates/inline_stream_or_topic_reference.hbs";
|
||||
import render_topic_already_exists_warning_banner from "../templates/modal_banner/topic_already_exists_warning_banner.hbs";
|
||||
import render_move_topic_to_stream from "../templates/move_topic_to_stream.hbs";
|
||||
import render_left_sidebar_stream_actions_popover from "../templates/popovers/left_sidebar/left_sidebar_stream_actions_popover.hbs";
|
||||
|
||||
@@ -12,6 +13,7 @@ import * as blueslip from "./blueslip.ts";
|
||||
import type {Typeahead} from "./bootstrap_typeahead.ts";
|
||||
import * as browser_history from "./browser_history.ts";
|
||||
import * as clipboard_handler from "./clipboard_handler.ts";
|
||||
import * as compose_banner from "./compose_banner.ts";
|
||||
import * as composebox_typeahead from "./composebox_typeahead.ts";
|
||||
import * as dialog_widget from "./dialog_widget.ts";
|
||||
import * as dropdown_widget from "./dropdown_widget.ts";
|
||||
@@ -32,6 +34,7 @@ import * as stream_data from "./stream_data.ts";
|
||||
import * as stream_settings_api from "./stream_settings_api.ts";
|
||||
import * as stream_settings_components from "./stream_settings_components.ts";
|
||||
import * as stream_settings_ui from "./stream_settings_ui.ts";
|
||||
import * as stream_topic_history from "./stream_topic_history.ts";
|
||||
import * as sub_store from "./sub_store.ts";
|
||||
import * as ui_report from "./ui_report.ts";
|
||||
import * as ui_util from "./ui_util.ts";
|
||||
@@ -606,6 +609,57 @@ export async function build_move_topic_to_stream_popover(
|
||||
);
|
||||
}
|
||||
|
||||
function show_topic_already_exists_warning(): boolean {
|
||||
// Don't show warning if the submit button is disabled.
|
||||
if ($("#move_topic_modal .dialog_submit_button").expectOne().prop("disabled")) {
|
||||
return false;
|
||||
}
|
||||
// Don't show warning if we are only moving one message.
|
||||
if ($("#move_topic_modal select.message_edit_topic_propagate").val() === "change_one") {
|
||||
return false;
|
||||
}
|
||||
const {new_topic_name} = get_params_from_form();
|
||||
assert(new_topic_name !== undefined);
|
||||
// Don't show warning for empty topic as the user is probably
|
||||
// about to type a new topic name. Note that if topics are
|
||||
// mandatory, then the submit button is disabled, which returns
|
||||
// early above.
|
||||
if (new_topic_name === "" || new_topic_name === "(no topic)") {
|
||||
return false;
|
||||
}
|
||||
let stream_id: number;
|
||||
if (stream_widget_value === undefined) {
|
||||
// Set stream_id to current_stream_id since the user is not
|
||||
// allowed to edit the stream in topic-edit only UI.
|
||||
stream_id = current_stream_id;
|
||||
} else {
|
||||
stream_id = stream_widget_value;
|
||||
}
|
||||
const stream_topics = stream_topic_history
|
||||
.get_recent_topic_names(stream_id)
|
||||
.map((topic) => topic.toLowerCase());
|
||||
if (stream_topics.includes(new_topic_name.trim().toLowerCase())) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function maybe_show_topic_already_exists_warning(): void {
|
||||
const $move_topic_warning_container = $("#move_topic_modal .move_topic_warning_container");
|
||||
if (show_topic_already_exists_warning()) {
|
||||
$move_topic_warning_container.html(
|
||||
render_topic_already_exists_warning_banner({
|
||||
banner_type: compose_banner.WARNING,
|
||||
hide_close_button: true,
|
||||
classname: "topic_already_exists_warning",
|
||||
}),
|
||||
);
|
||||
$move_topic_warning_container.show();
|
||||
} else {
|
||||
$move_topic_warning_container.hide();
|
||||
}
|
||||
}
|
||||
|
||||
function render_selected_stream(): void {
|
||||
assert(stream_widget_value !== undefined);
|
||||
const stream = stream_data.get_sub_by_id(stream_widget_value);
|
||||
@@ -626,6 +680,7 @@ export async function build_move_topic_to_stream_popover(
|
||||
update_submit_button_disabled_state(stream_widget_value);
|
||||
set_stream_topic_typeahead();
|
||||
render_selected_stream();
|
||||
maybe_show_topic_already_exists_warning();
|
||||
|
||||
dropdown.hide();
|
||||
event.preventDefault();
|
||||
@@ -705,6 +760,7 @@ export async function build_move_topic_to_stream_popover(
|
||||
|
||||
function move_topic_post_render(): void {
|
||||
$("#move_topic_modal .dialog_submit_button").prop("disabled", true);
|
||||
$("#move_topic_modal .move_topic_warning_container").hide();
|
||||
|
||||
const $topic_input = $<HTMLInputElement>("#move_topic_form input.move_messages_edit_topic");
|
||||
move_topic_to_stream_topic_typeahead = composebox_typeahead.initialize_topic_edit_typeahead(
|
||||
@@ -719,6 +775,7 @@ export async function build_move_topic_to_stream_popover(
|
||||
const select_stream_id = current_stream_id;
|
||||
$topic_input.on("input", () => {
|
||||
update_submit_button_disabled_state(select_stream_id);
|
||||
maybe_show_topic_already_exists_warning();
|
||||
});
|
||||
return;
|
||||
}
|
||||
@@ -749,10 +806,23 @@ export async function build_move_topic_to_stream_popover(
|
||||
|
||||
render_selected_stream();
|
||||
$("#move_topic_to_stream_widget").prop("disabled", disable_stream_input);
|
||||
$("#move_topic_modal .move_messages_edit_topic").on("input", () => {
|
||||
$topic_input.on("input", () => {
|
||||
update_submit_button_disabled_state(current_stream_id);
|
||||
maybe_show_topic_already_exists_warning();
|
||||
});
|
||||
|
||||
// Update position of topic typeahead because showing/hiding the
|
||||
// "topic already exists" warning changes the size of the modal.
|
||||
const update_topic_typeahead_position = new ResizeObserver((_entries) => {
|
||||
requestAnimationFrame(() => {
|
||||
$topic_input.trigger(new $.Event("typeahead.refreshPosition"));
|
||||
});
|
||||
});
|
||||
const move_topic_form = document.querySelector("#move_topic_form");
|
||||
if (move_topic_form) {
|
||||
update_topic_typeahead_position.observe(move_topic_form);
|
||||
}
|
||||
|
||||
if (!args.from_message_actions_popover) {
|
||||
update_move_messages_count_text("change_all");
|
||||
} else {
|
||||
@@ -776,6 +846,7 @@ export async function build_move_topic_to_stream_popover(
|
||||
$("#message_move_select_options").on("change", function () {
|
||||
selected_option = String($(this).val());
|
||||
last_propagate_mode_for_conversation.set(conversation_key, selected_option);
|
||||
maybe_show_topic_already_exists_warning();
|
||||
update_move_messages_count_text(selected_option, message?.id);
|
||||
});
|
||||
}
|
||||
|
@@ -0,0 +1,7 @@
|
||||
{{#> modal_banner . }}
|
||||
<p class="banner_message">
|
||||
{{#tr}}
|
||||
You are moving messages to a topic that already exists. Messages from these topics will be combined.
|
||||
{{/tr}}
|
||||
</p>
|
||||
{{/modal_banner}}
|
@@ -1,4 +1,5 @@
|
||||
<form id="move_topic_form">
|
||||
<div class="move_topic_warning_container"></div>
|
||||
<div class="topic_stream_edit_header">
|
||||
{{#unless only_topic_edit}}
|
||||
<div class="input-group">
|
||||
|
Reference in New Issue
Block a user