mirror of
https://github.com/zulip/zulip.git
synced 2025-10-27 18:13:58 +00:00
settings_bots: Move "Add a new bot" tab inside a modal.
"Add a new bot" tab from personal `settings > bots` moving this into a modal form, so we can trigger this form from other places too without duplicating the code. Fixes part of #20309.
This commit is contained in:
committed by
Tim Abbott
parent
bca41fd29f
commit
6db88f0d39
@@ -2,7 +2,7 @@
|
||||
|
||||
const {strict: assert} = require("assert");
|
||||
|
||||
const {mock_cjs, mock_esm, zrequire} = require("../zjsunit/namespace");
|
||||
const {mock_cjs, zrequire} = require("../zjsunit/namespace");
|
||||
const {run_test} = require("../zjsunit/test");
|
||||
const $ = require("../zjsunit/zjquery");
|
||||
const {page_params} = require("../zjsunit/zpage_params");
|
||||
@@ -19,8 +19,6 @@ const bot_data_params = {
|
||||
],
|
||||
};
|
||||
|
||||
const avatar = mock_esm("../../static/js/avatar");
|
||||
|
||||
function ClipboardJS(sel) {
|
||||
assert.equal(sel, "#copy_zuliprc");
|
||||
}
|
||||
@@ -90,59 +88,14 @@ test("generate_botserverrc_content", () => {
|
||||
assert.equal(content, expected);
|
||||
});
|
||||
|
||||
function test_create_bot_type_input_box_toggle(f) {
|
||||
const $create_payload_url = $("#create_payload_url");
|
||||
const $payload_url_inputbox = $("#payload_url_inputbox");
|
||||
const $config_inputbox = $("#config_inputbox");
|
||||
const EMBEDDED_BOT_TYPE = "4";
|
||||
const OUTGOING_WEBHOOK_BOT_TYPE = "3";
|
||||
const GENERIC_BOT_TYPE = "1";
|
||||
|
||||
$("#create_bot_type :selected").val(EMBEDDED_BOT_TYPE);
|
||||
f();
|
||||
assert.ok(!$create_payload_url.hasClass("required"));
|
||||
assert.ok(!$payload_url_inputbox.visible());
|
||||
assert.ok($("#select_service_name").hasClass("required"));
|
||||
assert.ok($("#service_name_list").visible());
|
||||
assert.ok($config_inputbox.visible());
|
||||
|
||||
$("#create_bot_type :selected").val(OUTGOING_WEBHOOK_BOT_TYPE);
|
||||
f();
|
||||
assert.ok($create_payload_url.hasClass("required"));
|
||||
assert.ok($payload_url_inputbox.visible());
|
||||
assert.ok(!$config_inputbox.visible());
|
||||
|
||||
$("#create_bot_type :selected").val(GENERIC_BOT_TYPE);
|
||||
f();
|
||||
assert.ok(!$create_payload_url.hasClass("required"));
|
||||
assert.ok(!$payload_url_inputbox.visible());
|
||||
assert.ok(!$config_inputbox.visible());
|
||||
}
|
||||
|
||||
test("test tab clicks", ({override}) => {
|
||||
override($.validator, "addMethod", () => {});
|
||||
|
||||
$("#create_bot_form").validate = () => {};
|
||||
|
||||
$("#config_inputbox").children = () => {
|
||||
const $mock_children = {
|
||||
hide: () => {},
|
||||
};
|
||||
return $mock_children;
|
||||
};
|
||||
|
||||
override(avatar, "build_bot_create_widget", () => {});
|
||||
|
||||
test("test tab clicks", () => {
|
||||
settings_bots.set_up();
|
||||
|
||||
test_create_bot_type_input_box_toggle(() => $("#create_bot_type").trigger("change"));
|
||||
|
||||
function click_on_tab($tab_elem) {
|
||||
$tab_elem.trigger("click");
|
||||
}
|
||||
|
||||
const tabs = {
|
||||
$add: $("#bots_lists_navbar .add-a-new-bot-tab"),
|
||||
$active: $("#bots_lists_navbar .active-bots-tab"),
|
||||
$inactive: $("#bots_lists_navbar .inactive-bots-tab"),
|
||||
};
|
||||
@@ -155,35 +108,21 @@ test("test tab clicks", ({override}) => {
|
||||
};
|
||||
|
||||
const forms = {
|
||||
$add: $("#add-a-new-bot-form"),
|
||||
$active: $("#active_bots_list"),
|
||||
$inactive: $("#inactive_bots_list"),
|
||||
};
|
||||
|
||||
click_on_tab(tabs.$add);
|
||||
assert.ok(tabs.$add.hasClass("active"));
|
||||
assert.ok(!tabs.$active.hasClass("active"));
|
||||
assert.ok(!tabs.$inactive.hasClass("active"));
|
||||
|
||||
assert.ok(forms.$add.visible());
|
||||
assert.ok(!forms.$active.visible());
|
||||
assert.ok(!forms.$inactive.visible());
|
||||
|
||||
click_on_tab(tabs.$active);
|
||||
assert.ok(!tabs.$add.hasClass("active"));
|
||||
assert.ok(tabs.$active.hasClass("active"));
|
||||
assert.ok(!tabs.$inactive.hasClass("active"));
|
||||
|
||||
assert.ok(!forms.$add.visible());
|
||||
assert.ok(forms.$active.visible());
|
||||
assert.ok(!forms.$inactive.visible());
|
||||
|
||||
click_on_tab(tabs.$inactive);
|
||||
assert.ok(!tabs.$add.hasClass("active"));
|
||||
assert.ok(!tabs.$active.hasClass("active"));
|
||||
assert.ok(tabs.$inactive.hasClass("active"));
|
||||
|
||||
assert.ok(!forms.$add.visible());
|
||||
assert.ok(!forms.$active.visible());
|
||||
assert.ok(forms.$inactive.visible());
|
||||
});
|
||||
|
||||
@@ -94,15 +94,26 @@ async function test_get_api_key(page: Page): Promise<void> {
|
||||
}
|
||||
|
||||
async function test_webhook_bot_creation(page: Page): Promise<void> {
|
||||
await page.click("#bot-settings .add-a-new-bot");
|
||||
await common.wait_for_micromodal_to_open(page);
|
||||
assert.strictEqual(
|
||||
await common.get_text_from_selector(page, ".dialog_heading"),
|
||||
"Add a new bot",
|
||||
"Unexpected title for deactivate user modal",
|
||||
);
|
||||
assert.strictEqual(
|
||||
await common.get_text_from_selector(page, "#dialog_widget_modal .dialog_submit_button"),
|
||||
"Add",
|
||||
"Deactivate button has incorrect text.",
|
||||
);
|
||||
await common.fill_form(page, "#create_bot_form", {
|
||||
bot_name: "Bot 1",
|
||||
bot_short_name: "1",
|
||||
bot_type: OUTGOING_WEBHOOK_BOT_TYPE,
|
||||
payload_url: "http://hostname.example.com/bots/followup",
|
||||
});
|
||||
|
||||
await page.waitForSelector("#create_bot_button", {visible: true});
|
||||
await page.click("#create_bot_button");
|
||||
await page.click("#dialog_widget_modal .dialog_submit_button");
|
||||
await common.wait_for_micromodal_to_close(page);
|
||||
|
||||
const bot_email = "1-bot@zulip.testserver";
|
||||
const download_zuliprc_selector = `.download_bot_zuliprc[data-email="${CSS.escape(
|
||||
@@ -123,16 +134,25 @@ async function test_webhook_bot_creation(page: Page): Promise<void> {
|
||||
}
|
||||
|
||||
async function test_normal_bot_creation(page: Page): Promise<void> {
|
||||
await page.click(".add-a-new-bot-tab");
|
||||
await page.waitForSelector("#create_bot_button", {visible: true});
|
||||
|
||||
await page.click("#bot-settings .add-a-new-bot");
|
||||
await common.wait_for_micromodal_to_open(page);
|
||||
assert.strictEqual(
|
||||
await common.get_text_from_selector(page, ".dialog_heading"),
|
||||
"Add a new bot",
|
||||
"Unexpected title for deactivate user modal",
|
||||
);
|
||||
assert.strictEqual(
|
||||
await common.get_text_from_selector(page, "#dialog_widget_modal .dialog_submit_button"),
|
||||
"Add",
|
||||
"Deactivate button has incorrect text.",
|
||||
);
|
||||
await common.fill_form(page, "#create_bot_form", {
|
||||
bot_name: "Bot 2",
|
||||
bot_short_name: "2",
|
||||
bot_type: GENERIC_BOT_TYPE,
|
||||
});
|
||||
|
||||
await page.click("#create_bot_button");
|
||||
await page.click("#dialog_widget_modal .dialog_submit_button");
|
||||
await common.wait_for_micromodal_to_close(page);
|
||||
|
||||
const bot_email = "2-bot@zulip.testserver";
|
||||
const download_zuliprc_selector = `.download_bot_zuliprc[data-email="${CSS.escape(
|
||||
@@ -238,7 +258,6 @@ async function test_invalid_edit_bot_form(page: Page): Promise<void> {
|
||||
|
||||
async function test_your_bots_section(page: Page): Promise<void> {
|
||||
await page.click('[data-section="your-bots"]');
|
||||
await page.click(".add-a-new-bot-tab");
|
||||
await test_webhook_bot_creation(page);
|
||||
await test_normal_bot_creation(page);
|
||||
await test_botserverrc(page);
|
||||
|
||||
@@ -2,6 +2,7 @@ import ClipboardJS from "clipboard";
|
||||
import $ from "jquery";
|
||||
|
||||
import render_settings_deactivation_bot_modal from "../templates/confirm_dialog/confirm_deactivate_bot.hbs";
|
||||
import render_add_new_bot_form from "../templates/settings/add_new_bot_form.hbs";
|
||||
import render_bot_avatar_row from "../templates/settings/bot_avatar_row.hbs";
|
||||
import render_edit_bot_form from "../templates/settings/edit_bot_form.hbs";
|
||||
import render_settings_edit_embedded_bot_service from "../templates/settings/edit_embedded_bot_service.hbs";
|
||||
@@ -15,7 +16,6 @@ import {csrf_token} from "./csrf";
|
||||
import * as dialog_widget from "./dialog_widget";
|
||||
import {DropdownListWidget} from "./dropdown_list_widget";
|
||||
import {$t, $t_html} from "./i18n";
|
||||
import * as loading from "./loading";
|
||||
import {page_params} from "./page_params";
|
||||
import * as people from "./people";
|
||||
import * as settings_config from "./settings_config";
|
||||
@@ -23,7 +23,6 @@ import * as ui_report from "./ui_report";
|
||||
import * as user_profile from "./user_profile";
|
||||
|
||||
const OUTGOING_WEBHOOK_BOT_TYPE = "3";
|
||||
const GENERIC_BOT_TYPE = "1";
|
||||
const EMBEDDED_BOT_TYPE = "4";
|
||||
|
||||
export function hide_errors() {
|
||||
@@ -32,18 +31,9 @@ export function hide_errors() {
|
||||
}
|
||||
|
||||
const focus_tab = {
|
||||
add_a_new_bot_tab() {
|
||||
$("#bots_lists_navbar .active").removeClass("active");
|
||||
$("#bots_lists_navbar .add-a-new-bot-tab").addClass("active");
|
||||
$("#add-a-new-bot-form").show();
|
||||
$("#active_bots_list").hide();
|
||||
$("#inactive_bots_list").hide();
|
||||
hide_errors();
|
||||
},
|
||||
active_bots_tab() {
|
||||
$("#bots_lists_navbar .active").removeClass("active");
|
||||
$("#bots_lists_navbar .active-bots-tab").addClass("active");
|
||||
$("#add-a-new-bot-form").hide();
|
||||
$("#active_bots_list").show();
|
||||
$("#inactive_bots_list").hide();
|
||||
hide_errors();
|
||||
@@ -51,7 +41,6 @@ const focus_tab = {
|
||||
inactive_bots_tab() {
|
||||
$("#bots_lists_navbar .active").removeClass("active");
|
||||
$("#bots_lists_navbar .inactive-bots-tab").addClass("active");
|
||||
$("#add-a-new-bot-form").hide();
|
||||
$("#active_bots_list").hide();
|
||||
$("#inactive_bots_list").show();
|
||||
hide_errors();
|
||||
@@ -81,12 +70,9 @@ function add_bot_row(info) {
|
||||
}
|
||||
}
|
||||
|
||||
function is_local_part(value, element) {
|
||||
function is_local_part(value) {
|
||||
// Adapted from Django's EmailValidator
|
||||
return (
|
||||
this.optional(element) ||
|
||||
/^[\w!#$%&'*+/=?^`{|}~-]+(\.[\w!#$%&'*+/=?^`{|}~-]+)*$/i.test(value)
|
||||
);
|
||||
return /^[\w!#$%&'*+/=?^`{|}~-]+(\.[\w!#$%&'*+/=?^`{|}~-]+)*$/i.test(value);
|
||||
}
|
||||
|
||||
export function type_id_to_string(type_id) {
|
||||
@@ -113,11 +99,6 @@ export function render_bots() {
|
||||
});
|
||||
user_owns_an_active_bot = user_owns_an_active_bot || elem.is_active;
|
||||
}
|
||||
|
||||
if (can_create_new_bots() && !user_owns_an_active_bot) {
|
||||
focus_tab.add_a_new_bot_tab();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
export function generate_zuliprc_uri(bot_id) {
|
||||
@@ -215,14 +196,137 @@ export function update_bot_permissions_ui() {
|
||||
update_bot_settings_tip();
|
||||
hide_errors();
|
||||
$("#id_realm_bot_creation_policy").val(page_params.realm_bot_creation_policy);
|
||||
if (!can_create_new_bots()) {
|
||||
$("#create_bot_form").hide();
|
||||
$(".add-a-new-bot-tab").hide();
|
||||
focus_tab.active_bots_tab();
|
||||
} else {
|
||||
$("#create_bot_form").show();
|
||||
$(".add-a-new-bot-tab").show();
|
||||
}
|
||||
|
||||
export function add_a_new_bot() {
|
||||
const html_body = render_add_new_bot_form({
|
||||
bot_types: page_params.bot_types,
|
||||
realm_embedded_bots: page_params.realm_embedded_bots,
|
||||
realm_bot_domain: page_params.realm_bot_domain,
|
||||
});
|
||||
|
||||
let create_avatar_widget;
|
||||
|
||||
function create_a_new_bot() {
|
||||
const bot_type = $("#create_bot_type :selected").val();
|
||||
const full_name = $("#create_bot_name").val();
|
||||
const short_name = $("#create_bot_short_name").val() || $("#create_bot_short_name").text();
|
||||
const payload_url = $("#create_payload_url").val();
|
||||
const interface_type = $("#create_interface_type").val();
|
||||
const service_name = $("#select_service_name :selected").val();
|
||||
const formData = new FormData();
|
||||
|
||||
formData.append("csrfmiddlewaretoken", csrf_token);
|
||||
formData.append("bot_type", bot_type);
|
||||
formData.append("full_name", full_name);
|
||||
formData.append("short_name", short_name);
|
||||
|
||||
// If the selected bot_type is Outgoing webhook
|
||||
if (bot_type === OUTGOING_WEBHOOK_BOT_TYPE) {
|
||||
formData.append("payload_url", JSON.stringify(payload_url));
|
||||
formData.append("interface_type", interface_type);
|
||||
} else if (bot_type === EMBEDDED_BOT_TYPE) {
|
||||
formData.append("service_name", service_name);
|
||||
const config_data = {};
|
||||
$(`#config_inputbox [name*='${CSS.escape(service_name)}'] 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(
|
||||
$("#bot_avatar_file_input")[0].files,
|
||||
)) {
|
||||
formData.append("file-" + i, file);
|
||||
}
|
||||
|
||||
channel.post({
|
||||
url: "/json/bots",
|
||||
data: formData,
|
||||
cache: false,
|
||||
processData: false,
|
||||
contentType: false,
|
||||
success() {
|
||||
hide_errors();
|
||||
create_avatar_widget.clear();
|
||||
dialog_widget.close_modal();
|
||||
},
|
||||
error(xhr) {
|
||||
ui_report.error($t_html({defaultMessage: "Failed"}), xhr, $("#dialog_error"));
|
||||
dialog_widget.hide_dialog_spinner();
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
function set_up_form_fields() {
|
||||
$("#payload_url_inputbox").hide();
|
||||
$("#create_payload_url").val("");
|
||||
$("#service_name_list").hide();
|
||||
$("#config_inputbox").hide();
|
||||
const selected_embedded_bot = "converter";
|
||||
$("#select_service_name").val(selected_embedded_bot); // TODO: Use 'select a bot'.
|
||||
$("#config_inputbox").children().hide();
|
||||
$(`[name*='${CSS.escape(selected_embedded_bot)}']`).show();
|
||||
|
||||
create_avatar_widget = avatar.build_bot_create_widget();
|
||||
|
||||
$("#create_bot_type").on("change", () => {
|
||||
const bot_type = $("#create_bot_type :selected").val();
|
||||
// For "generic bot" or "incoming webhook" both these fields need not be displayed.
|
||||
$("#service_name_list").hide();
|
||||
$("#select_service_name").removeClass("required");
|
||||
$("#config_inputbox").hide();
|
||||
|
||||
$("#payload_url_inputbox").hide();
|
||||
$("#create_payload_url").removeClass("required");
|
||||
if (bot_type === OUTGOING_WEBHOOK_BOT_TYPE) {
|
||||
$("#payload_url_inputbox").show();
|
||||
$("#create_payload_url").addClass("required");
|
||||
} else if (bot_type === EMBEDDED_BOT_TYPE) {
|
||||
$("#service_name_list").show();
|
||||
$("#select_service_name").addClass("required");
|
||||
$("#select_service_name").trigger("change");
|
||||
$("#config_inputbox").show();
|
||||
}
|
||||
});
|
||||
|
||||
$("#select_service_name").on("change", () => {
|
||||
$("#config_inputbox").children().hide();
|
||||
const selected_bot = $("#select_service_name :selected").val();
|
||||
$(`[name*='${CSS.escape(selected_bot)}']`).show();
|
||||
});
|
||||
}
|
||||
|
||||
function validate_input(e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
const bot_short_name = $("#create_bot_short_name").val();
|
||||
|
||||
if (is_local_part(bot_short_name)) {
|
||||
return true;
|
||||
}
|
||||
ui_report.error(
|
||||
$t_html({
|
||||
defaultMessage: "Please only use characters that are valid in an email address",
|
||||
}),
|
||||
undefined,
|
||||
$("#dialog_error"),
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
dialog_widget.launch({
|
||||
form_id: "create_bot_form",
|
||||
help_link: "/help/add-a-bot-or-integration",
|
||||
html_body,
|
||||
html_heading: $t_html({defaultMessage: "Add a new bot"}),
|
||||
html_submit_button: $t_html({defaultMessage: "Add"}),
|
||||
loading_spinner: true,
|
||||
on_click: create_a_new_bot,
|
||||
on_shown: () => $("#create_bot_type").trigger("focus"),
|
||||
post_render: set_up_form_fields,
|
||||
validate_input,
|
||||
});
|
||||
}
|
||||
|
||||
export function confirm_bot_deactivation(bot_id, handle_confirm, loading_spinner) {
|
||||
@@ -382,15 +486,6 @@ export function show_edit_bot_info_modal(user_id, from_user_info_popover) {
|
||||
}
|
||||
|
||||
export function set_up() {
|
||||
$("#payload_url_inputbox").hide();
|
||||
$("#create_payload_url").val("");
|
||||
$("#service_name_list").hide();
|
||||
$("#config_inputbox").hide();
|
||||
const selected_embedded_bot = "converter";
|
||||
$("#select_service_name").val(selected_embedded_bot); // TODO: Use 'select a bot'.
|
||||
$("#config_inputbox").children().hide();
|
||||
$(`[name*='${CSS.escape(selected_embedded_bot)}']`).show();
|
||||
|
||||
$("#download_botserverrc").on("click", function () {
|
||||
const OUTGOING_WEBHOOK_BOT_TYPE_INT = 3;
|
||||
let content = "";
|
||||
@@ -413,117 +508,6 @@ export function set_up() {
|
||||
focus_tab.active_bots_tab();
|
||||
render_bots();
|
||||
|
||||
$.validator.addMethod(
|
||||
"bot_local_part",
|
||||
function (value, element) {
|
||||
return is_local_part.call(this, value + "-bot", element);
|
||||
},
|
||||
"Please only use characters that are valid in an email address",
|
||||
);
|
||||
|
||||
const create_avatar_widget = avatar.build_bot_create_widget();
|
||||
|
||||
const GENERIC_INTERFACE = "1";
|
||||
|
||||
$("#create_bot_form").validate({
|
||||
errorClass: "text-error",
|
||||
success() {
|
||||
hide_errors();
|
||||
},
|
||||
submitHandler() {
|
||||
const bot_type = $("#create_bot_type :selected").val();
|
||||
const full_name = $("#create_bot_name").val();
|
||||
const short_name =
|
||||
$("#create_bot_short_name").val() || $("#create_bot_short_name").text();
|
||||
const payload_url = $("#create_payload_url").val();
|
||||
const interface_type = $("#create_interface_type").val();
|
||||
const service_name = $("#select_service_name :selected").val();
|
||||
const formData = new FormData();
|
||||
const $spinner = $(".create_bot_spinner");
|
||||
|
||||
formData.append("csrfmiddlewaretoken", csrf_token);
|
||||
formData.append("bot_type", bot_type);
|
||||
formData.append("full_name", full_name);
|
||||
formData.append("short_name", short_name);
|
||||
|
||||
// If the selected bot_type is Outgoing webhook
|
||||
if (bot_type === OUTGOING_WEBHOOK_BOT_TYPE) {
|
||||
formData.append("payload_url", JSON.stringify(payload_url));
|
||||
formData.append("interface_type", interface_type);
|
||||
} else if (bot_type === EMBEDDED_BOT_TYPE) {
|
||||
formData.append("service_name", service_name);
|
||||
const config_data = {};
|
||||
$(`#config_inputbox [name*='${CSS.escape(service_name)}'] 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(
|
||||
$("#bot_avatar_file_input")[0].files,
|
||||
)) {
|
||||
formData.append("file-" + i, file);
|
||||
}
|
||||
loading.make_indicator($spinner, {text: $t({defaultMessage: "Creating bot"})});
|
||||
channel.post({
|
||||
url: "/json/bots",
|
||||
data: formData,
|
||||
cache: false,
|
||||
processData: false,
|
||||
contentType: false,
|
||||
success() {
|
||||
hide_errors();
|
||||
$("#create_bot_name").val("");
|
||||
$("#create_bot_short_name").val("");
|
||||
$("#create_payload_url").val("");
|
||||
$("#payload_url_inputbox").hide();
|
||||
$("#config_inputbox").hide();
|
||||
$(`[name*='${CSS.escape(service_name)}'] input`).each(function () {
|
||||
$(this).val("");
|
||||
});
|
||||
$("#create_bot_type").val(GENERIC_BOT_TYPE);
|
||||
$("#select_service_name").val("converter"); // TODO: Later we can change this to hello bot or similar
|
||||
$("#service_name_list").hide();
|
||||
$("#create_bot_button").show();
|
||||
$("#create_interface_type").val(GENERIC_INTERFACE);
|
||||
create_avatar_widget.clear();
|
||||
focus_tab.active_bots_tab();
|
||||
},
|
||||
error(xhr) {
|
||||
$("#bot_table_error").text(JSON.parse(xhr.responseText).msg).show();
|
||||
},
|
||||
complete() {
|
||||
loading.destroy_indicator($spinner);
|
||||
},
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
$("#create_bot_type").on("change", () => {
|
||||
const bot_type = $("#create_bot_type :selected").val();
|
||||
// For "generic bot" or "incoming webhook" both these fields need not be displayed.
|
||||
$("#service_name_list").hide();
|
||||
$("#select_service_name").removeClass("required");
|
||||
$("#config_inputbox").hide();
|
||||
|
||||
$("#payload_url_inputbox").hide();
|
||||
$("#create_payload_url").removeClass("required");
|
||||
if (bot_type === OUTGOING_WEBHOOK_BOT_TYPE) {
|
||||
$("#payload_url_inputbox").show();
|
||||
$("#create_payload_url").addClass("required");
|
||||
} else if (bot_type === EMBEDDED_BOT_TYPE) {
|
||||
$("#service_name_list").show();
|
||||
$("#select_service_name").addClass("required");
|
||||
$("#select_service_name").trigger("change");
|
||||
$("#config_inputbox").show();
|
||||
}
|
||||
});
|
||||
|
||||
$("#select_service_name").on("change", () => {
|
||||
$("#config_inputbox").children().hide();
|
||||
const selected_bot = $("#select_service_name :selected").val();
|
||||
$(`[name*='${CSS.escape(selected_bot)}']`).show();
|
||||
});
|
||||
|
||||
$("#active_bots_list").on("click", "button.deactivate_bot", (e) => {
|
||||
const bot_id = Number.parseInt($(e.currentTarget).attr("data-user-id"), 10);
|
||||
|
||||
@@ -601,12 +585,6 @@ export function set_up() {
|
||||
},
|
||||
});
|
||||
|
||||
$("#bots_lists_navbar .add-a-new-bot-tab").on("click", (e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
focus_tab.add_a_new_bot_tab();
|
||||
});
|
||||
|
||||
$("#bots_lists_navbar .active-bots-tab").on("click", (e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
@@ -618,4 +596,10 @@ export function set_up() {
|
||||
e.stopPropagation();
|
||||
focus_tab.inactive_bots_tab();
|
||||
});
|
||||
|
||||
$("#bot-settings .add-a-new-bot").on("click", (e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
add_a_new_bot();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -692,6 +692,10 @@ input[type="checkbox"] {
|
||||
max-height: calc(95vh - 280px);
|
||||
}
|
||||
|
||||
#bot-settings .add-a-new-bot {
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
|
||||
.bots_list {
|
||||
display: none;
|
||||
list-style-type: none;
|
||||
|
||||
73
static/templates/settings/add_new_bot_form.hbs
Normal file
73
static/templates/settings/add_new_bot_form.hbs
Normal file
@@ -0,0 +1,73 @@
|
||||
<form id="create_bot_form" class="form-horizontal new-style">
|
||||
<div class="new-bot-form">
|
||||
<div class="input-group">
|
||||
<label for="bot_type">
|
||||
{{t "Bot type" }}
|
||||
<i class="fa fa-question-circle settings-info-icon bot_type_tooltip tippy-zulip-tooltip" aria-hidden="true" data-tippy-content='{{t "Incoming webhooks can only send messages." }}'></i>
|
||||
</label>
|
||||
<select name="bot_type" id="create_bot_type">
|
||||
{{#each bot_types}}
|
||||
{{#if this.allowed}}
|
||||
<option value="{{this.type_id}}">{{this.name}}</option>
|
||||
{{/if}}
|
||||
{{/each}}
|
||||
</select>
|
||||
</div>
|
||||
<div class="input-group" id="service_name_list">
|
||||
<label for="select_service_name">{{t "Bot"}}</label>
|
||||
<select name="service_name" id="select_service_name">
|
||||
{{#each realm_embedded_bots}}
|
||||
<option value="{{this.name}}">{{this.name}}</option>
|
||||
{{/each}}
|
||||
</select>
|
||||
</div>
|
||||
<div class="input-group">
|
||||
<label for="create_bot_name">{{t "Full name" }}</label>
|
||||
<input type="text" name="bot_name" id="create_bot_name" class="required"
|
||||
maxlength=100 placeholder="{{t 'Cookie Bot' }}" value="" />
|
||||
<div><label for="create_bot_name" generated="true" class="text-error"></label></div>
|
||||
</div>
|
||||
<div class="input-group">
|
||||
<label for="bot_short_name">{{t "Bot email (a-z, 0-9, and dashes only)" }}</label>
|
||||
<input type="text" name="bot_short_name" id="create_bot_short_name" class="required bot_local_part"
|
||||
placeholder="{{t 'cookie' }}" value="" />
|
||||
-bot@{{ realm_bot_domain }}
|
||||
<div>
|
||||
<label for="create_bot_short_name" generated="true" class="text-error"></label>
|
||||
</div>
|
||||
</div>
|
||||
<div id="payload_url_inputbox">
|
||||
<div class="input-group">
|
||||
<label for="create_payload_url">{{t "Endpoint URL" }}</label>
|
||||
<input type="text" name="payload_url" id="create_payload_url"
|
||||
maxlength=2083 placeholder="https://hostname.example.com" value="" />
|
||||
<div><label for="create_payload_url" generated="true" class="text-error"></label></div>
|
||||
</div>
|
||||
<div class="input-group">
|
||||
<label for="interface_type">{{t "Outgoing webhook message format" }}</label>
|
||||
<select name="interface_type" id="create_interface_type">
|
||||
<option value="1">Zulip</option>
|
||||
<option value="2">{{t "Slack compatible" }}</option>
|
||||
</select>
|
||||
<div><label for="create_interface_type" generated="true" class="text-error"></label></div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="config_inputbox">
|
||||
{{#each realm_embedded_bots as |bot index|}}
|
||||
{{#each bot.config as |config_value config_key|}}
|
||||
{{> ../embedded_bot_config_item botname=bot.name key=config_key value=config_value}}
|
||||
{{/each}}
|
||||
{{/each}}
|
||||
</div>
|
||||
<div class="input-group">
|
||||
<label for="bot_avatar_file_input">Avatar</label>
|
||||
<div id="bot_avatar_file"></div>
|
||||
<input type="file" name="bot_avatar_file_input" class="notvisible" id="bot_avatar_file_input" value="{{t 'Upload profile picture' }}" />
|
||||
<button class="button white rounded small btn-danger" style="display: none;" id="bot_avatar_clear_button">{{t "Clear profile picture" }}</button>
|
||||
<button class="button white rounded" id="bot_avatar_upload_button">{{t "Customize profile picture" }}</button> ({{t "Optional" }})
|
||||
</div>
|
||||
<p>
|
||||
<div id="bot_avatar_file_input_error" class="text-error"></div>
|
||||
</p>
|
||||
</div>
|
||||
</form>
|
||||
@@ -9,7 +9,9 @@
|
||||
{{/tr}}
|
||||
</div>
|
||||
<div class="tip bot-settings-tip"></div>
|
||||
|
||||
<div>
|
||||
<button class="button rounded sea-green add-a-new-bot {{#unless can_create_new_bots}}hide{{/unless}}">{{t "Add a new bot" }}</button>
|
||||
</div>
|
||||
<div>
|
||||
<span>{{t 'Download config of all active outgoing webhook bots in Zulip Botserver format.' }}</span>
|
||||
<a type="submit" download="{{botserverrc}}" id= "download_botserverrc" class="btn" title="{{t 'Download botserverrc' }}">
|
||||
@@ -21,7 +23,6 @@
|
||||
<ul class="nav nav-tabs nav-justified" id="bots_lists_navbar">
|
||||
<li class="active active-bots-tab"><a>{{t "Active bots" }}</a></li>
|
||||
<li class="inactive-bots-tab"><a>{{t "Inactive bots" }}</a></li>
|
||||
<li class="add-a-new-bot-tab {{#unless can_create_new_bots}}hide{{/unless}}"><a>{{t "Add a new bot" }}</a></li>
|
||||
</ul>
|
||||
|
||||
<ol class="bots_list required-text" id="active_bots_list" data-empty="{{t 'You have no active bots.' }}">
|
||||
@@ -31,86 +32,5 @@
|
||||
</ol>
|
||||
|
||||
<div id="bot_table_error" class="alert alert-error hide"></div>
|
||||
|
||||
<div id="add-a-new-bot-form">
|
||||
<form id="create_bot_form"
|
||||
class="form-horizontal no-padding {{#unless can_create_new_bots}}hide{{/unless}}">
|
||||
<div class="new-bot-form">
|
||||
<div class="input-group">
|
||||
<label for="bot_type">
|
||||
{{t "Bot type" }}
|
||||
<i class="fa fa-question-circle settings-info-icon bot_type_tooltip tippy-zulip-tooltip" aria-hidden="true" data-tippy-content='{{t "Incoming webhooks can only send messages." }}'></i>
|
||||
</label>
|
||||
<select name="bot_type" id="create_bot_type">
|
||||
{{#each page_params.bot_types}}
|
||||
{{#if this.allowed}}
|
||||
<option value="{{this.type_id}}">{{this.name}}</option>
|
||||
{{/if}}
|
||||
{{/each}}
|
||||
</select>
|
||||
</div>
|
||||
<div class="input-group" id="service_name_list">
|
||||
<label for="select_service_name">{{t "Bot"}}</label>
|
||||
<select name="service_name" id="select_service_name">
|
||||
{{#each page_params.realm_embedded_bots}}
|
||||
<option value="{{this.name}}">{{this.name}}</option>
|
||||
{{/each}}
|
||||
</select>
|
||||
</div>
|
||||
<div class="input-group">
|
||||
<label for="create_bot_name">{{t "Full name" }}</label>
|
||||
<input type="text" name="bot_name" id="create_bot_name" class="required"
|
||||
maxlength=100 placeholder="{{t 'Cookie Bot' }}" value="" />
|
||||
<div><label for="create_bot_name" generated="true" class="text-error"></label></div>
|
||||
</div>
|
||||
<div class="input-group">
|
||||
<label for="bot_short_name">{{t "Bot email (a-z, 0-9, and dashes only)" }}</label>
|
||||
<input type="text" name="bot_short_name" id="create_bot_short_name" class="required bot_local_part"
|
||||
placeholder="{{t 'cookie' }}" value="" />
|
||||
-bot@{{ page_params.realm_bot_domain }}
|
||||
<div>
|
||||
<label for="create_bot_short_name" generated="true" class="text-error"></label>
|
||||
</div>
|
||||
</div>
|
||||
<div id="payload_url_inputbox">
|
||||
<div class="input-group">
|
||||
<label for="create_payload_url">{{t "Endpoint URL" }}</label>
|
||||
<input type="text" name="payload_url" id="create_payload_url"
|
||||
maxlength=2083 placeholder="https://hostname.example.com" value="" />
|
||||
<div><label for="create_payload_url" generated="true" class="text-error"></label></div>
|
||||
</div>
|
||||
<div class="input-group">
|
||||
<label for="interface_type">{{t "Outgoing webhook message format" }}</label>
|
||||
<select name="interface_type" id="create_interface_type">
|
||||
<option value="1">Zulip</option>
|
||||
<option value="2">{{t "Slack compatible" }}</option>
|
||||
</select>
|
||||
<div><label for="create_interface_type" generated="true" class="text-error"></label></div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="config_inputbox">
|
||||
{{#each page_params.realm_embedded_bots as |bot index|}}
|
||||
{{#each bot.config as |config_value config_key|}}
|
||||
{{> ../embedded_bot_config_item botname=bot.name key=config_key value=config_value}}
|
||||
{{/each}}
|
||||
{{/each}}
|
||||
</div>
|
||||
<div class="input-group">
|
||||
<div id="bot_avatar_file"></div>
|
||||
<input type="file" name="bot_avatar_file_input" class="notvisible" id="bot_avatar_file_input" value="{{t 'Upload profile picture' }}" />
|
||||
<button class="button white rounded small btn-danger" style="display: none;" id="bot_avatar_clear_button">{{t "Clear profile picture" }}</button>
|
||||
<button class="button white rounded" id="bot_avatar_upload_button">{{t "Customize profile picture" }}</button> ({{t "Optional" }})
|
||||
</div>
|
||||
<p>
|
||||
<div id="bot_avatar_file_input_error" class="text-error"></div>
|
||||
</p>
|
||||
<button type="submit" class="button white rounded sea-green" id="create_bot_button">
|
||||
{{t 'Create bot' }}
|
||||
</button>
|
||||
<div class="create_bot_spinner"></div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user