stream_create: Add functionality to rename archived streams.

Users with appropriate permissions will now have the option
to rename archived streams.
This commit is contained in:
sanchi-t 2024-05-14 19:27:11 +05:30 committed by Tim Abbott
parent 5dfa8ac9fe
commit e60711f871
4 changed files with 108 additions and 14 deletions

View File

@ -3,9 +3,11 @@ import assert from "minimalistic-assert";
import {z} from "zod"; import {z} from "zod";
import render_subscription_invites_warning_modal from "../templates/confirm_dialog/confirm_subscription_invites_warning.hbs"; import render_subscription_invites_warning_modal from "../templates/confirm_dialog/confirm_subscription_invites_warning.hbs";
import render_change_stream_info_modal from "../templates/stream_settings/change_stream_info_modal.hbs";
import * as channel from "./channel"; import * as channel from "./channel";
import * as confirm_dialog from "./confirm_dialog"; import * as confirm_dialog from "./confirm_dialog";
import * as dialog_widget from "./dialog_widget";
import {$t, $t_html} from "./i18n"; import {$t, $t_html} from "./i18n";
import * as keydown_util from "./keydown_util"; import * as keydown_util from "./keydown_util";
import * as loading from "./loading"; import * as loading from "./loading";
@ -16,6 +18,7 @@ import {current_user, realm} from "./state_data";
import * as stream_create_subscribers from "./stream_create_subscribers"; import * as stream_create_subscribers from "./stream_create_subscribers";
import * as stream_data from "./stream_data"; import * as stream_data from "./stream_data";
import * as stream_settings_components from "./stream_settings_components"; import * as stream_settings_components from "./stream_settings_components";
import * as stream_settings_data from "./stream_settings_data";
import * as stream_ui_updates from "./stream_ui_updates"; import * as stream_ui_updates from "./stream_ui_updates";
import type {HTMLSelectOneElement} from "./types"; import type {HTMLSelectOneElement} from "./types";
import * as ui_report from "./ui_report"; import * as ui_report from "./ui_report";
@ -58,6 +61,12 @@ export function should_show_first_stream_created_modal(): boolean {
return onboarding_steps.ONE_TIME_NOTICES_TO_DISPLAY.has("first_stream_created_banner"); return onboarding_steps.ONE_TIME_NOTICES_TO_DISPLAY.has("first_stream_created_banner");
} }
export function maybe_update_error_message(): void {
if ($("#stream_name_error").is(":visible") && $("#archived_stream_rename").is(":visible")) {
$("#create_stream_name").trigger("input");
}
}
class StreamSubscriptionError { class StreamSubscriptionError {
report_no_subs_to_stream(): void { report_no_subs_to_stream(): void {
$("#stream_subscription_error").text( $("#stream_subscription_error").text(
@ -83,15 +92,16 @@ class StreamSubscriptionError {
const stream_subscription_error = new StreamSubscriptionError(); const stream_subscription_error = new StreamSubscriptionError();
class StreamNameError { class StreamNameError {
report_already_exists(): void { report_already_exists(error?: string): void {
$("#stream_name_error").text( const error_message =
$t({defaultMessage: "A channel with this name already exists."}), error ?? $t({defaultMessage: "A channel with this name already exists."});
); $("#stream_name_error").text(error_message);
$("#stream_name_error").show(); $("#stream_name_error").show();
} }
clear_errors(): void { clear_errors(): void {
$("#stream_name_error").hide(); $("#stream_name_error").hide();
$("#archived_stream_rename").hide();
} }
report_empty_stream(): void { report_empty_stream(): void {
@ -103,6 +113,12 @@ class StreamNameError {
$("#create_stream_name").trigger("focus").trigger("select"); $("#create_stream_name").trigger("focus").trigger("select");
} }
rename_archived_stream(stream_id: number): void {
$("#archived_stream_rename").text($t({defaultMessage: "Rename archived channel"}));
$("#archived_stream_rename").attr("data-stream-id", stream_id);
$("#archived_stream_rename").show();
}
pre_validate(stream_name: string): void { pre_validate(stream_name: string): void {
// Don't worry about empty strings...we just want to call this // Don't worry about empty strings...we just want to call this
// to warn users early before they start doing too much work // to warn users early before they start doing too much work
@ -111,8 +127,16 @@ class StreamNameError {
// out it already exists, and I was just too lazy to look at // 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 // the public streams that I'm not subscribed to yet. Once I
// realize the stream already exists, I may want to cancel.) // realize the stream already exists, I may want to cancel.)
if (stream_name && stream_data.get_sub(stream_name)) { const stream = stream_data.get_sub(stream_name);
this.report_already_exists(); if (stream_name && stream) {
let error;
if (stream.is_archived) {
error = $t({defaultMessage: "An archived channel with this name already exists."});
if (stream_settings_data.get_sub_for_settings(stream).can_change_name_description) {
this.rename_archived_stream(stream.stream_id);
}
}
this.report_already_exists(error);
return; return;
} }
@ -126,8 +150,13 @@ class StreamNameError {
return false; return false;
} }
if (stream_data.get_sub(stream_name)) { const stream = stream_data.get_sub(stream_name);
this.report_already_exists(); if (stream) {
let error;
if (stream.is_archived) {
error = $t({defaultMessage: "An archived channel with this name already exists."});
}
this.report_already_exists(error);
this.select(); this.select();
return false; return false;
} }
@ -380,13 +409,19 @@ function create_stream(): void {
// "Error creating channel"? // "Error creating channel"?
stream_name_error.report_already_exists(); stream_name_error.report_already_exists();
stream_name_error.select(); stream_name_error.select();
} const message = $t_html({
defaultMessage:
"Error creating channel: A channel with this name already exists.",
});
ui_report.error(message, undefined, $(".stream_create_info"));
} else {
ui_report.error( ui_report.error(
$t_html({defaultMessage: "Error creating channel"}), $t_html({defaultMessage: "Error creating channel"}),
xhr, xhr,
$(".stream_create_info"), $(".stream_create_info"),
); );
}
loading.destroy_indicator($("#stream_creating_indicator")); loading.destroy_indicator($("#stream_creating_indicator"));
}, },
}); });
@ -548,3 +583,56 @@ export function set_up_handlers(): void {
assert(stream_settings_components.new_stream_can_remove_subscribers_group_widget !== null); assert(stream_settings_components.new_stream_can_remove_subscribers_group_widget !== null);
stream_settings_components.new_stream_can_remove_subscribers_group_widget.setup(); stream_settings_components.new_stream_can_remove_subscribers_group_widget.setup();
} }
export function initialize(): void {
$("#channels_overlay_container").on("click", "#archived_stream_rename", (e) => {
e.preventDefault();
e.stopPropagation();
const stream_id = Number.parseInt($("#archived_stream_rename").attr("data-stream-id")!, 10);
const stream = stream_data.get_sub_by_id(stream_id);
assert(stream !== undefined);
const template_data = {
stream_name: stream.name,
stream_description: stream.description,
max_stream_name_length: realm.max_stream_name_length,
max_stream_description_length: realm.max_stream_description_length,
};
const change_stream_info_modal = render_change_stream_info_modal(template_data);
dialog_widget.launch({
html_heading: $t_html(
{defaultMessage: "Edit #{stream_name} (<i>archived</i>)"},
{stream_name: stream.name},
),
html_body: change_stream_info_modal,
id: "change_stream_info_modal",
loading_spinner: true,
on_click: save_stream_info,
post_render() {
$("#change_stream_info_modal .dialog_submit_button")
.addClass("save-button")
.attr("data-stream-id", stream_id);
},
update_submit_disabled_state_on_change: true,
});
});
function save_stream_info(): void {
const stream_id = Number.parseInt($("#archived_stream_rename").attr("data-stream-id")!, 10);
const sub = stream_data.get_sub_by_id(stream_id);
const url = `/json/streams/${sub?.stream_id}`;
const data: {new_name?: string; description?: string} = {};
const new_name = $<HTMLInputElement>("#change_stream_name").val()!.trim();
const new_description = $<HTMLInputElement>("#change_stream_description").val()!.trim();
if (new_name !== sub?.name) {
data.new_name = new_name;
}
if (new_description !== sub?.description) {
data.description = new_description;
}
dialog_widget.submit_api_request(channel.patch, url, data);
}
}

View File

@ -124,6 +124,9 @@ export function update_stream_name(sub, new_name) {
// Update navbar if needed // Update navbar if needed
message_view_header.maybe_rerender_title_area_for_stream(sub); message_view_header.maybe_rerender_title_area_for_stream(sub);
// Update the create stream error if needed
stream_create.maybe_update_error_message();
} }
export function update_stream_description(sub, description, rendered_description) { export function update_stream_description(sub, description, rendered_description) {

View File

@ -117,6 +117,7 @@ import * as starred_messages from "./starred_messages";
import * as starred_messages_ui from "./starred_messages_ui"; import * as starred_messages_ui from "./starred_messages_ui";
import {current_user, realm, set_current_user, set_realm, state_data_schema} from "./state_data"; import {current_user, realm, set_current_user, set_realm, state_data_schema} from "./state_data";
import * as stream_card_popover from "./stream_card_popover"; import * as stream_card_popover from "./stream_card_popover";
import * as stream_create from "./stream_create";
import * as stream_data from "./stream_data"; import * as stream_data from "./stream_data";
import * as stream_edit from "./stream_edit"; import * as stream_edit from "./stream_edit";
import * as stream_edit_subscribers from "./stream_edit_subscribers"; import * as stream_edit_subscribers from "./stream_edit_subscribers";
@ -533,6 +534,7 @@ export function initialize_everything(state_data) {
on_send_message_success: compose.send_message_success, on_send_message_success: compose.send_message_success,
send_message: transmit.send_message, send_message: transmit.send_message,
}); });
stream_create.initialize();
stream_edit.initialize(); stream_edit.initialize();
user_group_edit.initialize(); user_group_edit.initialize();
stream_edit_subscribers.initialize(); stream_edit_subscribers.initialize();

View File

@ -13,6 +13,7 @@
<input type="text" name="stream_name" id="create_stream_name" class="settings_text_input" <input type="text" name="stream_name" id="create_stream_name" class="settings_text_input"
placeholder="{{t 'Channel name' }}" value="" autocomplete="off" maxlength="{{ max_stream_name_length }}" /> placeholder="{{t 'Channel name' }}" value="" autocomplete="off" maxlength="{{ max_stream_name_length }}" />
<div id="stream_name_error" class="stream_creation_error"></div> <div id="stream_name_error" class="stream_creation_error"></div>
<a id="archived_stream_rename"></a>
</section> </section>
<section id="create_stream_description_container"> <section id="create_stream_description_container">
<label for="create_stream_description" class="settings-field-label"> <label for="create_stream_description" class="settings-field-label">