mirror of
https://github.com/zulip/zulip.git
synced 2025-11-10 08:56:10 +00:00
edit_bot: Migrate modal to dialog_widget.
This commit is contained in:
@@ -176,7 +176,7 @@ async function test_edit_bot_form(page: Page): Promise<void> {
|
|||||||
);
|
);
|
||||||
|
|
||||||
await common.fill_form(page, edit_form_selector, {bot_name: "Bot one"});
|
await common.fill_form(page, edit_form_selector, {bot_name: "Bot one"});
|
||||||
const save_btn_selector = edit_form_selector + " .edit_bot_button";
|
const save_btn_selector = "#edit_bot_modal .dialog_submit_button";
|
||||||
await page.click(save_btn_selector);
|
await page.click(save_btn_selector);
|
||||||
|
|
||||||
// The form gets closed on saving. So, assert it's closed by waiting for it to be hidden.
|
// The form gets closed on saving. So, assert it's closed by waiting for it to be hidden.
|
||||||
@@ -186,7 +186,7 @@ async function test_edit_bot_form(page: Page): Promise<void> {
|
|||||||
`//*[@class="btn open_edit_bot_form" and @data-email="${bot1_email}"]/ancestor::*[@class="details"]/*[@class="name" and text()="Bot one"]`,
|
`//*[@class="btn open_edit_bot_form" and @data-email="${bot1_email}"]/ancestor::*[@class="details"]/*[@class="name" and text()="Bot one"]`,
|
||||||
);
|
);
|
||||||
|
|
||||||
await common.wait_for_modal_to_close(page);
|
await common.wait_for_micromodal_to_close(page);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function test_invalid_edit_bot_form(page: Page): Promise<void> {
|
async function test_invalid_edit_bot_form(page: Page): Promise<void> {
|
||||||
@@ -203,7 +203,7 @@ async function test_invalid_edit_bot_form(page: Page): Promise<void> {
|
|||||||
);
|
);
|
||||||
|
|
||||||
await common.fill_form(page, edit_form_selector, {bot_name: "Bot 2"});
|
await common.fill_form(page, edit_form_selector, {bot_name: "Bot 2"});
|
||||||
const save_btn_selector = edit_form_selector + " .edit_bot_button";
|
const save_btn_selector = "#edit_bot_modal .dialog_submit_button";
|
||||||
await page.click(save_btn_selector);
|
await page.click(save_btn_selector);
|
||||||
|
|
||||||
// The form should not get closed on saving. Errors should be visible on the form.
|
// The form should not get closed on saving. Errors should be visible on the form.
|
||||||
@@ -213,14 +213,14 @@ async function test_invalid_edit_bot_form(page: Page): Promise<void> {
|
|||||||
await common.get_text_from_selector(page, "div.bot_edit_errors"),
|
await common.get_text_from_selector(page, "div.bot_edit_errors"),
|
||||||
"Name is already in use!",
|
"Name is already in use!",
|
||||||
);
|
);
|
||||||
await page.click("button.cancel_bot_button");
|
await page.click("#edit_bot_modal .dialog_cancel_button");
|
||||||
await page.waitForSelector("#edit_bot_modal", {hidden: true});
|
await page.waitForSelector("#edit_bot_modal", {hidden: true});
|
||||||
|
|
||||||
await page.waitForXPath(
|
await page.waitForXPath(
|
||||||
`//*[@class="btn open_edit_bot_form" and @data-email="${bot1_email}"]/ancestor::*[@class="details"]/*[@class="name" and text()="Bot one"]`,
|
`//*[@class="btn open_edit_bot_form" and @data-email="${bot1_email}"]/ancestor::*[@class="details"]/*[@class="name" and text()="Bot one"]`,
|
||||||
);
|
);
|
||||||
|
|
||||||
await common.wait_for_modal_to_close(page);
|
await common.wait_for_micromodal_to_close(page);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function test_your_bots_section(page: Page): Promise<void> {
|
async function test_your_bots_section(page: Page): Promise<void> {
|
||||||
|
|||||||
@@ -10,10 +10,10 @@ import * as avatar from "./avatar";
|
|||||||
import * as bot_data from "./bot_data";
|
import * as bot_data from "./bot_data";
|
||||||
import * as channel from "./channel";
|
import * as channel from "./channel";
|
||||||
import {csrf_token} from "./csrf";
|
import {csrf_token} from "./csrf";
|
||||||
|
import * as dialog_widget from "./dialog_widget";
|
||||||
import {DropdownListWidget} from "./dropdown_list_widget";
|
import {DropdownListWidget} from "./dropdown_list_widget";
|
||||||
import {$t} from "./i18n";
|
import {$t, $t_html} from "./i18n";
|
||||||
import * as loading from "./loading";
|
import * as loading from "./loading";
|
||||||
import * as overlays from "./overlays";
|
|
||||||
import {page_params} from "./page_params";
|
import {page_params} from "./page_params";
|
||||||
import * as people from "./people";
|
import * as people from "./people";
|
||||||
|
|
||||||
@@ -412,7 +412,6 @@ export function set_up() {
|
|||||||
$("#active_bots_list").on("click", "button.open_edit_bot_form", (e) => {
|
$("#active_bots_list").on("click", "button.open_edit_bot_form", (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
overlays.open_modal("#edit_bot_modal");
|
|
||||||
const li = $(e.currentTarget).closest("li");
|
const li = $(e.currentTarget).closest("li");
|
||||||
const bot_id = Number.parseInt(li.find(".bot_info").attr("data-user-id"), 10);
|
const bot_id = Number.parseInt(li.find(".bot_info").attr("data-user-id"), 10);
|
||||||
const bot = bot_data.get(bot_id);
|
const bot = bot_data.get(bot_id);
|
||||||
@@ -422,112 +421,121 @@ export function set_up() {
|
|||||||
value: user_id.toString(),
|
value: user_id.toString(),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
$("#edit_bot_modal").empty();
|
const rendered_edit_bot = render_edit_bot({
|
||||||
$("#edit_bot_modal").append(
|
bot,
|
||||||
render_edit_bot({
|
users_list,
|
||||||
bot,
|
|
||||||
users_list,
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
const avatar_widget = avatar.build_bot_edit_widget($("#settings_page"));
|
|
||||||
const form = $("#settings_page .edit_bot_form");
|
|
||||||
const image = li.find(".image");
|
|
||||||
const errors = form.find(".bot_edit_errors");
|
|
||||||
|
|
||||||
const opts = {
|
|
||||||
widget_name: "bot_owner",
|
|
||||||
data: users_list,
|
|
||||||
default_text: $t({defaultMessage: "No owner"}),
|
|
||||||
value: bot.owner_id,
|
|
||||||
};
|
|
||||||
const owner_widget = new DropdownListWidget(opts);
|
|
||||||
|
|
||||||
const service = bot_data.get_services(bot_id)[0];
|
|
||||||
if (bot.bot_type.toString() === OUTGOING_WEBHOOK_BOT_TYPE) {
|
|
||||||
$("#service_data").append(
|
|
||||||
render_settings_edit_outgoing_webhook_service({
|
|
||||||
service,
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
$("#edit_service_interface").val(service.interface);
|
|
||||||
}
|
|
||||||
if (bot.bot_type.toString() === EMBEDDED_BOT_TYPE) {
|
|
||||||
$("#service_data").append(
|
|
||||||
render_settings_edit_embedded_bot_service({
|
|
||||||
service,
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
avatar_widget.clear();
|
|
||||||
|
|
||||||
form.validate({
|
|
||||||
errorClass: "text-error",
|
|
||||||
success() {
|
|
||||||
errors.hide();
|
|
||||||
},
|
|
||||||
submitHandler() {
|
|
||||||
const bot_id = Number.parseInt(form.attr("data-user-id"), 10);
|
|
||||||
const type = form.attr("data-type");
|
|
||||||
|
|
||||||
const full_name = form.find(".edit_bot_name").val();
|
|
||||||
const bot_owner_id = owner_widget.value();
|
|
||||||
const file_input = $(".edit_bot_form").find(".edit_bot_avatar_file_input");
|
|
||||||
const spinner = form.find(".edit_bot_spinner");
|
|
||||||
const edit_button = form.find(".edit_bot_button");
|
|
||||||
|
|
||||||
const formData = new FormData();
|
|
||||||
formData.append("csrfmiddlewaretoken", csrf_token);
|
|
||||||
formData.append("full_name", full_name);
|
|
||||||
formData.append("bot_owner_id", bot_owner_id);
|
|
||||||
|
|
||||||
if (type === OUTGOING_WEBHOOK_BOT_TYPE) {
|
|
||||||
const service_payload_url = $("#edit_service_base_url").val();
|
|
||||||
const service_interface = $("#edit_service_interface :selected").val();
|
|
||||||
formData.append("service_payload_url", JSON.stringify(service_payload_url));
|
|
||||||
formData.append("service_interface", service_interface);
|
|
||||||
} else if (type === EMBEDDED_BOT_TYPE) {
|
|
||||||
const config_data = {};
|
|
||||||
$("#config_edit_inputbox input").each(function () {
|
|
||||||
config_data[$(this).attr("name")] = $(this).val();
|
|
||||||
});
|
|
||||||
formData.append("config_data", JSON.stringify(config_data));
|
|
||||||
}
|
|
||||||
for (const [i, file] of Array.prototype.entries.call(file_input[0].files)) {
|
|
||||||
formData.append("file-" + i, file);
|
|
||||||
}
|
|
||||||
loading.make_indicator(spinner, {text: "Editing bot"});
|
|
||||||
edit_button.hide();
|
|
||||||
channel.patch({
|
|
||||||
url: "/json/bots/" + encodeURIComponent(bot_id),
|
|
||||||
data: formData,
|
|
||||||
cache: false,
|
|
||||||
processData: false,
|
|
||||||
contentType: false,
|
|
||||||
success(data) {
|
|
||||||
loading.destroy_indicator(spinner);
|
|
||||||
errors.hide();
|
|
||||||
edit_button.show();
|
|
||||||
avatar_widget.clear();
|
|
||||||
if (data.avatar_url) {
|
|
||||||
// Note that the avatar_url won't actually change on the backend
|
|
||||||
// when the user had a previous uploaded avatar. Only the content
|
|
||||||
// changes, so we version it to get an uncached copy.
|
|
||||||
image_version += 1;
|
|
||||||
image
|
|
||||||
.find("img")
|
|
||||||
.attr("src", data.avatar_url + "&v=" + image_version.toString());
|
|
||||||
}
|
|
||||||
overlays.close_modal("#edit_bot_modal");
|
|
||||||
},
|
|
||||||
error(xhr) {
|
|
||||||
loading.destroy_indicator(spinner);
|
|
||||||
edit_button.show();
|
|
||||||
errors.text(JSON.parse(xhr.responseText).msg).show();
|
|
||||||
},
|
|
||||||
});
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
|
dialog_widget.launch({
|
||||||
|
html_heading: $t_html({defaultMessage: "Edit bot"}),
|
||||||
|
html_body: rendered_edit_bot,
|
||||||
|
id: "edit_bot_modal",
|
||||||
|
on_click: () => {
|
||||||
|
$(".edit_bot_form").trigger("submit");
|
||||||
|
},
|
||||||
|
post_render: edit_bot_post_render,
|
||||||
|
loading_spinner: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
function edit_bot_post_render() {
|
||||||
|
// This links the submit button to the edit bot form, so submitting this form
|
||||||
|
// by pressing Enter on an input element triggers a click on the submit button.
|
||||||
|
$("#edit_bot_modal .dialog_submit_button").attr("form", "edit_bot_form");
|
||||||
|
|
||||||
|
const avatar_widget = avatar.build_bot_edit_widget($(".edit_bot_form"));
|
||||||
|
const form = $(".edit_bot_form");
|
||||||
|
const image = li.find(".image");
|
||||||
|
const errors = form.find(".bot_edit_errors");
|
||||||
|
|
||||||
|
const opts = {
|
||||||
|
widget_name: "bot_owner",
|
||||||
|
data: users_list,
|
||||||
|
default_text: $t({defaultMessage: "No owner"}),
|
||||||
|
value: bot.owner_id,
|
||||||
|
};
|
||||||
|
const owner_widget = new DropdownListWidget(opts);
|
||||||
|
|
||||||
|
const service = bot_data.get_services(bot_id)[0];
|
||||||
|
if (bot.bot_type.toString() === OUTGOING_WEBHOOK_BOT_TYPE) {
|
||||||
|
$("#service_data").append(
|
||||||
|
render_settings_edit_outgoing_webhook_service({
|
||||||
|
service,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
$("#edit_service_interface").val(service.interface);
|
||||||
|
}
|
||||||
|
if (bot.bot_type.toString() === EMBEDDED_BOT_TYPE) {
|
||||||
|
$("#service_data").append(
|
||||||
|
render_settings_edit_embedded_bot_service({
|
||||||
|
service,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
avatar_widget.clear();
|
||||||
|
|
||||||
|
form.validate({
|
||||||
|
errorClass: "text-error",
|
||||||
|
success() {
|
||||||
|
errors.hide();
|
||||||
|
},
|
||||||
|
submitHandler() {
|
||||||
|
const bot_id = Number.parseInt(form.attr("data-user-id"), 10);
|
||||||
|
const type = form.attr("data-type");
|
||||||
|
|
||||||
|
const full_name = form.find(".edit_bot_name").val();
|
||||||
|
const bot_owner_id = owner_widget.value();
|
||||||
|
const file_input = $(".edit_bot_form").find(".edit_bot_avatar_file_input");
|
||||||
|
|
||||||
|
const formData = new FormData();
|
||||||
|
formData.append("csrfmiddlewaretoken", csrf_token);
|
||||||
|
formData.append("full_name", full_name);
|
||||||
|
formData.append("bot_owner_id", bot_owner_id);
|
||||||
|
|
||||||
|
if (type === OUTGOING_WEBHOOK_BOT_TYPE) {
|
||||||
|
const service_payload_url = $("#edit_service_base_url").val();
|
||||||
|
const service_interface = $("#edit_service_interface :selected").val();
|
||||||
|
formData.append("service_payload_url", JSON.stringify(service_payload_url));
|
||||||
|
formData.append("service_interface", service_interface);
|
||||||
|
} else if (type === EMBEDDED_BOT_TYPE) {
|
||||||
|
const config_data = {};
|
||||||
|
$("#config_edit_inputbox input").each(function () {
|
||||||
|
config_data[$(this).attr("name")] = $(this).val();
|
||||||
|
});
|
||||||
|
formData.append("config_data", JSON.stringify(config_data));
|
||||||
|
}
|
||||||
|
for (const [i, file] of Array.prototype.entries.call(file_input[0].files)) {
|
||||||
|
formData.append("file-" + i, file);
|
||||||
|
}
|
||||||
|
channel.patch({
|
||||||
|
url: "/json/bots/" + encodeURIComponent(bot_id),
|
||||||
|
data: formData,
|
||||||
|
cache: false,
|
||||||
|
processData: false,
|
||||||
|
contentType: false,
|
||||||
|
success(data) {
|
||||||
|
avatar_widget.clear();
|
||||||
|
if (data.avatar_url) {
|
||||||
|
// Note that the avatar_url won't actually change on the backend
|
||||||
|
// when the user had a previous uploaded avatar. Only the content
|
||||||
|
// changes, so we version it to get an uncached copy.
|
||||||
|
image_version += 1;
|
||||||
|
image
|
||||||
|
.find("img")
|
||||||
|
.attr(
|
||||||
|
"src",
|
||||||
|
data.avatar_url + "&v=" + image_version.toString(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
dialog_widget.close_modal();
|
||||||
|
},
|
||||||
|
error(xhr) {
|
||||||
|
dialog_widget.hide_dialog_spinner();
|
||||||
|
errors.text(JSON.parse(xhr.responseText).msg).show();
|
||||||
|
},
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
$("#active_bots_list").on("click", "a.download_bot_zuliprc", function () {
|
$("#active_bots_list").on("click", "a.download_bot_zuliprc", function () {
|
||||||
|
|||||||
@@ -871,7 +871,7 @@ input[type="checkbox"] {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.bot_edit_errors {
|
.bot_edit_errors {
|
||||||
margin: 20px 20px 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#bots_lists_navbar .active a {
|
#bots_lists_navbar .active a {
|
||||||
@@ -882,8 +882,11 @@ input[type="checkbox"] {
|
|||||||
margin-top: 5px;
|
margin-top: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.edit_bot_form_container {
|
#edit_bot_modal {
|
||||||
padding: 15px;
|
/* Ensure that the dropdown can overflow the modal. */
|
||||||
|
.modal__content {
|
||||||
|
overflow: visible;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.edit_bot_form {
|
.edit_bot_form {
|
||||||
|
|||||||
@@ -1,12 +1,8 @@
|
|||||||
<div class="modal-header">
|
<form id="edit_bot_form" class="new-style edit_bot_form form-horizontal" data-target="edit-bot" data-title="{{t 'Edit bot' }}" data-user-id="{{bot.user_id}}"
|
||||||
<button type="button" class="close" data-dismiss="modal" aria-label="{{t 'Close' }}"><span aria-hidden="true">×</span></button>
|
|
||||||
<h3 class="inline-block">{{t "Edit bot" }}</h3>
|
|
||||||
</div>
|
|
||||||
<form class="edit_bot_form form-horizontal" data-target="edit-bot" data-title="{{t 'Edit bot' }}" data-user-id="{{bot.user_id}}"
|
|
||||||
data-email="{{bot.email}}" data-type="{{bot.bot_type}}">
|
data-email="{{bot.email}}" data-type="{{bot.bot_type}}">
|
||||||
<div class="bot_edit_errors alert alert-error hide"></div>
|
<div class="bot_edit_errors alert alert-error hide"></div>
|
||||||
<div class="edit_bot_form_container">
|
<div>
|
||||||
<div class="">
|
<div>
|
||||||
<label>{{t "Bot email" }}</label>
|
<label>{{t "Bot email" }}</label>
|
||||||
<div class="edit_bot_email">{{bot.email}}</div>
|
<div class="edit_bot_email">{{bot.email}}</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -35,11 +31,4 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
|
||||||
<div class="modal-footer">
|
|
||||||
<div class="edit_bot_spinner"></div>
|
|
||||||
<button class="button white rounded cancel_bot_button" type="button" data-dismiss="modal">{{t "Cancel" }}</button>
|
|
||||||
<input type="submit" class="button rounded sea-green edit_bot_button" value="{{t 'Save' }}" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</form>
|
</form>
|
||||||
|
|||||||
@@ -197,8 +197,5 @@
|
|||||||
<div class="settings-box">
|
<div class="settings-box">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="edit_bot_modal" class="modal modal-bg hide fade" tabindex="-1" role="dialog"
|
|
||||||
aria-labelledby="edit_bot_modal_label" aria-hidden="true">
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user