mirror of
				https://github.com/zulip/zulip.git
				synced 2025-11-04 14:03:30 +00:00 
			
		
		
		
	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:
		
				
					committed by
					
						
						Tim Abbott
					
				
			
			
				
	
			
			
			
						parent
						
							8b11deedb3
						
					
				
				
					commit
					1948cb6a89
				
			@@ -547,12 +547,12 @@ run(function (override, capture, args) {
 | 
			
		||||
 | 
			
		||||
    event = event_fixtures.realm_bot__update;
 | 
			
		||||
    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);
 | 
			
		||||
    assert_same(args.email, event.bot.email);
 | 
			
		||||
    assert_same(args.bot, event.bot);
 | 
			
		||||
    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');
 | 
			
		||||
}());
 | 
			
		||||
 | 
			
		||||
(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() {
 | 
			
		||||
    var args = {
 | 
			
		||||
        email: 'hamlet@zulip.com',
 | 
			
		||||
 
 | 
			
		||||
@@ -12,7 +12,7 @@ set_global('activity', {
 | 
			
		||||
    redraw: function () {},
 | 
			
		||||
});
 | 
			
		||||
set_global('admin', {
 | 
			
		||||
    update_user_full_name: function () {},
 | 
			
		||||
    update_user_data: function () {},
 | 
			
		||||
    show_or_hide_menu_item: function () {},
 | 
			
		||||
});
 | 
			
		||||
set_global('page_params', {
 | 
			
		||||
@@ -79,6 +79,3 @@ initialize();
 | 
			
		||||
    assert.equal(full_name, 'Me V2');
 | 
			
		||||
 | 
			
		||||
}());
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -30,19 +30,28 @@ function get_email_for_user_row(row) {
 | 
			
		||||
    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) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    var user_info = get_user_info(user_id);
 | 
			
		||||
 | 
			
		||||
    var user_row = user_info.user_row;
 | 
			
		||||
    var form_row = user_info.form_row;
 | 
			
		||||
 | 
			
		||||
    // Update the full name in the table
 | 
			
		||||
    user_row.find(".user_name").text(new_full_name);
 | 
			
		||||
    form_row.find("input[name='full_name']").val(new_full_name);
 | 
			
		||||
    if (new_data.full_name !== undefined) {
 | 
			
		||||
        // Update the full name in the table
 | 
			
		||||
        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
 | 
			
		||||
    form_row.hide();
 | 
			
		||||
@@ -58,10 +67,6 @@ function failed_listing_streams(xhr) {
 | 
			
		||||
    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) {
 | 
			
		||||
    var users_table = $("#admin_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) {
 | 
			
		||||
        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_info = get_user_info(user_id);
 | 
			
		||||
        var user_row = user_info.user_row;
 | 
			
		||||
@@ -798,19 +806,25 @@ function _setup_page() {
 | 
			
		||||
        var reset_button = form_row.find(".reset_edit_user");
 | 
			
		||||
        var submit_button = form_row.find(".submit_name_changes");
 | 
			
		||||
        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 person = people.get_person_from_user_id(user_id);
 | 
			
		||||
 | 
			
		||||
        if (!person) {
 | 
			
		||||
            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.
 | 
			
		||||
        user_row.hide();
 | 
			
		||||
        form_row.show();
 | 
			
		||||
 | 
			
		||||
        reset_button.on("click", function () {
 | 
			
		||||
            owner_select.remove();
 | 
			
		||||
            form_row.hide();
 | 
			
		||||
            user_row.show();
 | 
			
		||||
        });
 | 
			
		||||
@@ -819,18 +833,24 @@ function _setup_page() {
 | 
			
		||||
            e.preventDefault();
 | 
			
		||||
            e.stopPropagation();
 | 
			
		||||
 | 
			
		||||
            var url = "/json/users/" + encodeURIComponent(person.email);
 | 
			
		||||
            var url = "/json/bots/" + encodeURIComponent(person.email);
 | 
			
		||||
            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({
 | 
			
		||||
                url: url,
 | 
			
		||||
                data: data,
 | 
			
		||||
                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') {
 | 
			
		||||
            bot_data.remove(event.bot.email);
 | 
			
		||||
        } 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);
 | 
			
		||||
            admin.update_user_full_name(event.bot.user_id, event.bot.full_name);
 | 
			
		||||
            admin.update_user_data(event.bot.user_id, event.bot);
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -719,15 +719,21 @@ function _setup_page() {
 | 
			
		||||
    var image_version = 0;
 | 
			
		||||
 | 
			
		||||
    $("#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 edit_div = li.find('div.edit_bot');
 | 
			
		||||
        var form = li.find('.edit_bot_form');
 | 
			
		||||
        var image = li.find(".image");
 | 
			
		||||
        var bot_info = li.find(".bot_info");
 | 
			
		||||
        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_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-owner .controls").append(owner_select);
 | 
			
		||||
        form.find(".edit-bot-owner select").val(old_owner);
 | 
			
		||||
 | 
			
		||||
        image.hide();
 | 
			
		||||
        bot_info.hide();
 | 
			
		||||
@@ -744,6 +750,7 @@ function _setup_page() {
 | 
			
		||||
 | 
			
		||||
        reset_edit_bot.click(function (event) {
 | 
			
		||||
            form.find(".edit_bot_name").val(old_full_name);
 | 
			
		||||
            owner_select.remove();
 | 
			
		||||
            show_row_again();
 | 
			
		||||
            $(this).off(event);
 | 
			
		||||
        });
 | 
			
		||||
@@ -758,6 +765,7 @@ function _setup_page() {
 | 
			
		||||
            submitHandler: function () {
 | 
			
		||||
                var email = form.data('email');
 | 
			
		||||
                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 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();
 | 
			
		||||
@@ -767,6 +775,7 @@ function _setup_page() {
 | 
			
		||||
 | 
			
		||||
                formData.append('csrfmiddlewaretoken', csrf_token);
 | 
			
		||||
                formData.append('full_name', full_name);
 | 
			
		||||
                formData.append('bot_owner', bot_owner);
 | 
			
		||||
                add_bot_default_streams_to_form(formData, default_sending_stream,
 | 
			
		||||
                                                default_events_register_stream);
 | 
			
		||||
                jQuery.each(file_input[0].files, function (i, file) {
 | 
			
		||||
@@ -784,6 +793,7 @@ function _setup_page() {
 | 
			
		||||
                        loading.destroy_indicator(spinner);
 | 
			
		||||
                        errors.hide();
 | 
			
		||||
                        edit_button.show();
 | 
			
		||||
                        owner_select.remove();
 | 
			
		||||
                        show_row_again();
 | 
			
		||||
                        bot_info.find('.name').text(full_name);
 | 
			
		||||
                        if (data.avatar_url) {
 | 
			
		||||
 
 | 
			
		||||
@@ -33,7 +33,7 @@ exports.update_person = function update(person) {
 | 
			
		||||
    if (_.has(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();
 | 
			
		||||
        message_live_update.update_user_full_name(person.user_id, person.full_name);
 | 
			
		||||
        pm_list.update_private_messages();
 | 
			
		||||
 
 | 
			
		||||
@@ -52,6 +52,11 @@
 | 
			
		||||
        <label for="full_name">{{t "Full name" }}</label>
 | 
			
		||||
        <input type="text" name="full_name" value="{{ full_name }}" />
 | 
			
		||||
      </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">
 | 
			
		||||
        <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>
 | 
			
		||||
 
 | 
			
		||||
@@ -44,6 +44,11 @@
 | 
			
		||||
                  <div><label for="edit_bot_name{{id_suffix}}" generated="true" class="text-error"></label></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">
 | 
			
		||||
                <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>
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										6
									
								
								static/templates/bot_owner_select.handlebars
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								static/templates/bot_owner_select.handlebars
									
									
									
									
									
										Normal file
									
								
							@@ -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>
 | 
			
		||||
		Reference in New Issue
	
	Block a user