mirror of https://github.com/zulip/zulip.git
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:
parent
5dfa8ac9fe
commit
e60711f871
|
@ -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(
|
ui_report.error(message, undefined, $(".stream_create_info"));
|
||||||
$t_html({defaultMessage: "Error creating channel"}),
|
} else {
|
||||||
xhr,
|
ui_report.error(
|
||||||
$(".stream_create_info"),
|
$t_html({defaultMessage: "Error creating channel"}),
|
||||||
);
|
xhr,
|
||||||
|
$(".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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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">
|
||||||
|
|
Loading…
Reference in New Issue