mirror of https://github.com/zulip/zulip.git
Add UI for changing the bot owners.
Add neccesary UI in #administration and #settings for changing the bot owner. The bot owner select control is rendered dynamically in order to avoid performance issues in case of large number of users. Fixes: #2719.
This commit is contained in:
parent
8b11deedb3
commit
1948cb6a89
|
@ -547,12 +547,12 @@ run(function (override, capture, args) {
|
||||||
|
|
||||||
event = event_fixtures.realm_bot__update;
|
event = event_fixtures.realm_bot__update;
|
||||||
override('bot_data', 'update', capture(['email', 'bot']));
|
override('bot_data', 'update', capture(['email', 'bot']));
|
||||||
override('admin', 'update_user_full_name', capture(['update_user_id', 'name']));
|
override('admin', 'update_user_data', capture(['update_user_id', 'update_bot_data']));
|
||||||
dispatch(event);
|
dispatch(event);
|
||||||
assert_same(args.email, event.bot.email);
|
assert_same(args.email, event.bot.email);
|
||||||
assert_same(args.bot, event.bot);
|
assert_same(args.bot, event.bot);
|
||||||
assert_same(args.update_user_id, event.bot.user_id);
|
assert_same(args.update_user_id, event.bot.user_id);
|
||||||
assert_same(args.name, event.bot.full_name);
|
assert_same(args.update_bot_data, event.bot);
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -354,6 +354,25 @@ function render(template_name, args) {
|
||||||
assert.equal(img.attr('src'), '/hamlet/avatar/url');
|
assert.equal(img.attr('src'), '/hamlet/avatar/url');
|
||||||
}());
|
}());
|
||||||
|
|
||||||
|
(function bot_owner_select() {
|
||||||
|
var args = {
|
||||||
|
users_list: [
|
||||||
|
{
|
||||||
|
email: "hamlet@zulip.com",
|
||||||
|
api_key: "123456ABCD",
|
||||||
|
full_name: "Hamlet",
|
||||||
|
avatar_url: "/hamlet/avatar/url",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
var html = render('bot_owner_select', args);
|
||||||
|
global.write_handlebars_output("bot_owner_select", html);
|
||||||
|
var option = $(html).find("option:last");
|
||||||
|
assert.equal(option.val(), "hamlet@zulip.com");
|
||||||
|
assert.equal(option.text(), "Hamlet");
|
||||||
|
}());
|
||||||
|
|
||||||
|
|
||||||
(function compose_invite_users() {
|
(function compose_invite_users() {
|
||||||
var args = {
|
var args = {
|
||||||
email: 'hamlet@zulip.com',
|
email: 'hamlet@zulip.com',
|
||||||
|
|
|
@ -12,7 +12,7 @@ set_global('activity', {
|
||||||
redraw: function () {},
|
redraw: function () {},
|
||||||
});
|
});
|
||||||
set_global('admin', {
|
set_global('admin', {
|
||||||
update_user_full_name: function () {},
|
update_user_data: function () {},
|
||||||
show_or_hide_menu_item: function () {},
|
show_or_hide_menu_item: function () {},
|
||||||
});
|
});
|
||||||
set_global('page_params', {
|
set_global('page_params', {
|
||||||
|
@ -79,6 +79,3 @@ initialize();
|
||||||
assert.equal(full_name, 'Me V2');
|
assert.equal(full_name, 'Me V2');
|
||||||
|
|
||||||
}());
|
}());
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -30,19 +30,28 @@ function get_email_for_user_row(row) {
|
||||||
return email;
|
return email;
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.update_user_full_name = function (user_id, new_full_name) {
|
exports.update_user_data = function (user_id, new_data) {
|
||||||
if (!meta.loaded) {
|
if (!meta.loaded) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var user_info = get_user_info(user_id);
|
var user_info = get_user_info(user_id);
|
||||||
|
|
||||||
var user_row = user_info.user_row;
|
var user_row = user_info.user_row;
|
||||||
var form_row = user_info.form_row;
|
var form_row = user_info.form_row;
|
||||||
|
|
||||||
// Update the full name in the table
|
if (new_data.full_name !== undefined) {
|
||||||
user_row.find(".user_name").text(new_full_name);
|
// Update the full name in the table
|
||||||
form_row.find("input[name='full_name']").val(new_full_name);
|
user_row.find(".user_name").text(new_data.full_name);
|
||||||
|
form_row.find("input[name='full_name']").val(new_data.full_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (new_data.owner !== undefined) {
|
||||||
|
// Update the bot owner in the table
|
||||||
|
user_row.find(".owner").text(new_data.owner);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove the bot owner select control.
|
||||||
|
form_row.find(".edit_bot_owner_container select").remove();
|
||||||
|
|
||||||
// Hide name change form
|
// Hide name change form
|
||||||
form_row.hide();
|
form_row.hide();
|
||||||
|
@ -58,10 +67,6 @@ function failed_listing_streams(xhr) {
|
||||||
ui.report_error(i18n.t("Error listing streams"), xhr, $("#administration-status"));
|
ui.report_error(i18n.t("Error listing streams"), xhr, $("#administration-status"));
|
||||||
}
|
}
|
||||||
|
|
||||||
function failed_changing_name(xhr) {
|
|
||||||
ui.report_error(i18n.t("Error changing name"), xhr, $("#administration-status"));
|
|
||||||
}
|
|
||||||
|
|
||||||
function populate_users(realm_people_data) {
|
function populate_users(realm_people_data) {
|
||||||
var users_table = $("#admin_users_table");
|
var users_table = $("#admin_users_table");
|
||||||
var deactivated_users_table = $("#admin_deactivated_users_table");
|
var deactivated_users_table = $("#admin_deactivated_users_table");
|
||||||
|
@ -791,6 +796,9 @@ function _setup_page() {
|
||||||
});
|
});
|
||||||
|
|
||||||
$(".admin_user_table, .admin_bot_table").on("click", ".open-user-form", function (e) {
|
$(".admin_user_table, .admin_bot_table").on("click", ".open-user-form", function (e) {
|
||||||
|
var users_list = people.get_realm_persons().filter(function (person) {
|
||||||
|
return !person.is_bot;
|
||||||
|
});
|
||||||
var user_id = $(e.currentTarget).attr("data-user-id");
|
var user_id = $(e.currentTarget).attr("data-user-id");
|
||||||
var user_info = get_user_info(user_id);
|
var user_info = get_user_info(user_id);
|
||||||
var user_row = user_info.user_row;
|
var user_row = user_info.user_row;
|
||||||
|
@ -798,19 +806,25 @@ function _setup_page() {
|
||||||
var reset_button = form_row.find(".reset_edit_user");
|
var reset_button = form_row.find(".reset_edit_user");
|
||||||
var submit_button = form_row.find(".submit_name_changes");
|
var submit_button = form_row.find(".submit_name_changes");
|
||||||
var full_name = form_row.find("input[name='full_name']");
|
var full_name = form_row.find("input[name='full_name']");
|
||||||
|
var owner_select = $(templates.render("bot_owner_select", {users_list: users_list}));
|
||||||
var admin_status = $('#administration-status').expectOne();
|
var admin_status = $('#administration-status').expectOne();
|
||||||
|
|
||||||
var person = people.get_person_from_user_id(user_id);
|
var person = people.get_person_from_user_id(user_id);
|
||||||
|
|
||||||
if (!person) {
|
if (!person) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Dynamically add the owner select control in order to
|
||||||
|
// avoid performance issues in case of large number of users.
|
||||||
|
owner_select.val(bot_data.get(person.email).owner || "");
|
||||||
|
form_row.find(".edit_bot_owner_container").append(owner_select);
|
||||||
|
|
||||||
// Show user form.
|
// Show user form.
|
||||||
user_row.hide();
|
user_row.hide();
|
||||||
form_row.show();
|
form_row.show();
|
||||||
|
|
||||||
reset_button.on("click", function () {
|
reset_button.on("click", function () {
|
||||||
|
owner_select.remove();
|
||||||
form_row.hide();
|
form_row.hide();
|
||||||
user_row.show();
|
user_row.show();
|
||||||
});
|
});
|
||||||
|
@ -819,18 +833,24 @@ function _setup_page() {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
|
|
||||||
var url = "/json/users/" + encodeURIComponent(person.email);
|
var url = "/json/bots/" + encodeURIComponent(person.email);
|
||||||
var data = {
|
var data = {
|
||||||
full_name: JSON.stringify(full_name.val()),
|
full_name: full_name.val(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (owner_select.val() !== undefined && owner_select.val() !== "") {
|
||||||
|
data.bot_owner = owner_select.val();
|
||||||
|
}
|
||||||
|
|
||||||
channel.patch({
|
channel.patch({
|
||||||
url: url,
|
url: url,
|
||||||
data: data,
|
data: data,
|
||||||
success: function () {
|
success: function () {
|
||||||
ui.report_success(i18n.t('Name successfully updated!'), admin_status);
|
ui.report_success(i18n.t('Updated successfully!'), admin_status);
|
||||||
|
},
|
||||||
|
error: function () {
|
||||||
|
ui.report_error(i18n.t('Update failed!'), admin_status);
|
||||||
},
|
},
|
||||||
error: failed_changing_name,
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -96,8 +96,11 @@ function dispatch_normal_event(event) {
|
||||||
} else if (event.op === 'remove') {
|
} else if (event.op === 'remove') {
|
||||||
bot_data.remove(event.bot.email);
|
bot_data.remove(event.bot.email);
|
||||||
} else if (event.op === 'update') {
|
} else if (event.op === 'update') {
|
||||||
|
if (_.has(event.bot, 'owner_id')) {
|
||||||
|
event.bot.owner = people.get_person_from_user_id(event.bot.owner_id).email;
|
||||||
|
}
|
||||||
bot_data.update(event.bot.email, event.bot);
|
bot_data.update(event.bot.email, event.bot);
|
||||||
admin.update_user_full_name(event.bot.user_id, event.bot.full_name);
|
admin.update_user_data(event.bot.user_id, event.bot);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
|
@ -719,15 +719,21 @@ function _setup_page() {
|
||||||
var image_version = 0;
|
var image_version = 0;
|
||||||
|
|
||||||
$("#bots_list").on("click", "button.open_edit_bot_form", function (e) {
|
$("#bots_list").on("click", "button.open_edit_bot_form", function (e) {
|
||||||
|
var users_list = people.get_realm_persons().filter(function (person) {
|
||||||
|
return !person.is_bot;
|
||||||
|
});
|
||||||
var li = $(e.currentTarget).closest('li');
|
var li = $(e.currentTarget).closest('li');
|
||||||
var edit_div = li.find('div.edit_bot');
|
var edit_div = li.find('div.edit_bot');
|
||||||
var form = li.find('.edit_bot_form');
|
var form = li.find('.edit_bot_form');
|
||||||
var image = li.find(".image");
|
var image = li.find(".image");
|
||||||
var bot_info = li.find(".bot_info");
|
var bot_info = li.find(".bot_info");
|
||||||
var reset_edit_bot = li.find(".reset_edit_bot");
|
var reset_edit_bot = li.find(".reset_edit_bot");
|
||||||
|
var owner_select = $(templates.render("bot_owner_select", {users_list:users_list}));
|
||||||
var old_full_name = bot_info.find(".name").text();
|
var old_full_name = bot_info.find(".name").text();
|
||||||
|
var old_owner = bot_data.get(bot_info.find(".email .value").text()).owner;
|
||||||
form.find(".edit_bot_name").attr('value', old_full_name);
|
form.find(".edit_bot_name").attr('value', old_full_name);
|
||||||
|
form.find(".edit-bot-owner .controls").append(owner_select);
|
||||||
|
form.find(".edit-bot-owner select").val(old_owner);
|
||||||
|
|
||||||
image.hide();
|
image.hide();
|
||||||
bot_info.hide();
|
bot_info.hide();
|
||||||
|
@ -744,6 +750,7 @@ function _setup_page() {
|
||||||
|
|
||||||
reset_edit_bot.click(function (event) {
|
reset_edit_bot.click(function (event) {
|
||||||
form.find(".edit_bot_name").val(old_full_name);
|
form.find(".edit_bot_name").val(old_full_name);
|
||||||
|
owner_select.remove();
|
||||||
show_row_again();
|
show_row_again();
|
||||||
$(this).off(event);
|
$(this).off(event);
|
||||||
});
|
});
|
||||||
|
@ -758,6 +765,7 @@ function _setup_page() {
|
||||||
submitHandler: function () {
|
submitHandler: function () {
|
||||||
var email = form.data('email');
|
var email = form.data('email');
|
||||||
var full_name = form.find('.edit_bot_name').val();
|
var full_name = form.find('.edit_bot_name').val();
|
||||||
|
var bot_owner = form.find('.edit-bot-owner select').val();
|
||||||
var file_input = li.find('.edit_bot_avatar_file_input');
|
var file_input = li.find('.edit_bot_avatar_file_input');
|
||||||
var default_sending_stream = form.find('.edit_bot_default_sending_stream').val();
|
var default_sending_stream = form.find('.edit_bot_default_sending_stream').val();
|
||||||
var default_events_register_stream = form.find('.edit_bot_default_events_register_stream').val();
|
var default_events_register_stream = form.find('.edit_bot_default_events_register_stream').val();
|
||||||
|
@ -767,6 +775,7 @@ function _setup_page() {
|
||||||
|
|
||||||
formData.append('csrfmiddlewaretoken', csrf_token);
|
formData.append('csrfmiddlewaretoken', csrf_token);
|
||||||
formData.append('full_name', full_name);
|
formData.append('full_name', full_name);
|
||||||
|
formData.append('bot_owner', bot_owner);
|
||||||
add_bot_default_streams_to_form(formData, default_sending_stream,
|
add_bot_default_streams_to_form(formData, default_sending_stream,
|
||||||
default_events_register_stream);
|
default_events_register_stream);
|
||||||
jQuery.each(file_input[0].files, function (i, file) {
|
jQuery.each(file_input[0].files, function (i, file) {
|
||||||
|
@ -784,6 +793,7 @@ function _setup_page() {
|
||||||
loading.destroy_indicator(spinner);
|
loading.destroy_indicator(spinner);
|
||||||
errors.hide();
|
errors.hide();
|
||||||
edit_button.show();
|
edit_button.show();
|
||||||
|
owner_select.remove();
|
||||||
show_row_again();
|
show_row_again();
|
||||||
bot_info.find('.name').text(full_name);
|
bot_info.find('.name').text(full_name);
|
||||||
if (data.avatar_url) {
|
if (data.avatar_url) {
|
||||||
|
|
|
@ -33,7 +33,7 @@ exports.update_person = function update(person) {
|
||||||
if (_.has(person, 'full_name')) {
|
if (_.has(person, 'full_name')) {
|
||||||
people.set_full_name(person_obj, person.full_name);
|
people.set_full_name(person_obj, person.full_name);
|
||||||
|
|
||||||
admin.update_user_full_name(person.user_id, person.full_name);
|
admin.update_user_data(person.user_id, person);
|
||||||
activity.redraw();
|
activity.redraw();
|
||||||
message_live_update.update_user_full_name(person.user_id, person.full_name);
|
message_live_update.update_user_full_name(person.user_id, person.full_name);
|
||||||
pm_list.update_private_messages();
|
pm_list.update_private_messages();
|
||||||
|
|
|
@ -52,6 +52,11 @@
|
||||||
<label for="full_name">{{t "Full name" }}</label>
|
<label for="full_name">{{t "Full name" }}</label>
|
||||||
<input type="text" name="full_name" value="{{ full_name }}" />
|
<input type="text" name="full_name" value="{{ full_name }}" />
|
||||||
</div>
|
</div>
|
||||||
|
{{#if is_bot}}
|
||||||
|
<div class="input-group edit_bot_owner_container">
|
||||||
|
<label for="bot_owner_select">{{t "Owner" }}</label>
|
||||||
|
</div>
|
||||||
|
{{/if}}
|
||||||
<div class="input-group">
|
<div class="input-group">
|
||||||
<input type="button" class="btn btn-primary submit_name_changes" value="{{t 'Save changes' }}" />
|
<input type="button" class="btn btn-primary submit_name_changes" value="{{t 'Save changes' }}" />
|
||||||
<button type="button" class="btn btn-default reset_edit_user">{{t 'Cancel' }}</button>
|
<button type="button" class="btn btn-default reset_edit_user">{{t 'Cancel' }}</button>
|
||||||
|
|
|
@ -44,6 +44,11 @@
|
||||||
<div><label for="edit_bot_name{{id_suffix}}" generated="true" class="text-error"></label></div>
|
<div><label for="edit_bot_name{{id_suffix}}" generated="true" class="text-error"></label></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="control-group edit-bot-owner">
|
||||||
|
<label for="bot_owner_select" class="control-label">{{t "Owner" }}</label>
|
||||||
|
<div class="controls">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="control-group new-bot-ui">
|
<div class="control-group new-bot-ui">
|
||||||
<label for="edit_bot_default_sending_stream{{id_suffix}}" class="control-label">{{t "Send to stream" }}</label>
|
<label for="edit_bot_default_sending_stream{{id_suffix}}" class="control-label">{{t "Send to stream" }}</label>
|
||||||
<select name="bot_default_sending_stream" class="edit_bot_default_sending_stream" id="edit_bot_default_sending_stream{{id_suffix}}"></select>
|
<select name="bot_default_sending_stream" class="edit_bot_default_sending_stream" id="edit_bot_default_sending_stream{{id_suffix}}"></select>
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
<select name="bot_owner_select">
|
||||||
|
<option value=''></option>
|
||||||
|
{{#each users_list}}
|
||||||
|
<option value='{{this.email}}'>{{this.full_name}}</option>
|
||||||
|
{{/each}}
|
||||||
|
</select>
|
Loading…
Reference in New Issue