diff --git a/.eslintrc.json b/.eslintrc.json index e809c4ebed..4d2070f073 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -41,6 +41,7 @@ "settings_sections": false, "settings_emoji": false, "settings_org": false, + "settings_users": false, "settings": false, "resize": false, "loading": false, diff --git a/frontend_tests/node_tests/dispatch.js b/frontend_tests/node_tests/dispatch.js index df4b78e839..9b95d9df30 100644 --- a/frontend_tests/node_tests/dispatch.js +++ b/frontend_tests/node_tests/dispatch.js @@ -513,7 +513,7 @@ with_overrides(function (override) { global.with_stub(function (bot_stub) { global.with_stub(function (admin_stub) { override('bot_data.add', bot_stub.f); - override('admin.update_user_data', admin_stub.f); + override('settings_users.update_user_data', admin_stub.f); dispatch(event); var args = bot_stub.get_args('bot'); assert_same(args.bot, event.bot); @@ -526,7 +526,7 @@ with_overrides(function (override) { global.with_stub(function (bot_stub) { global.with_stub(function (admin_stub) { override('bot_data.deactivate', bot_stub.f); - override('admin.update_user_data', admin_stub.f); + override('settings_users.update_user_data', admin_stub.f); dispatch(event); var args = bot_stub.get_args('email'); assert_same(args.email, event.bot.email); @@ -539,7 +539,7 @@ with_overrides(function (override) { global.with_stub(function (bot_stub) { global.with_stub(function (admin_stub) { override('bot_data.update', bot_stub.f); - override('admin.update_user_data', admin_stub.f); + override('settings_users.update_user_data', admin_stub.f); dispatch(event); diff --git a/frontend_tests/node_tests/user_events.js b/frontend_tests/node_tests/user_events.js index f199fcc46c..72e9a34ddc 100644 --- a/frontend_tests/node_tests/user_events.js +++ b/frontend_tests/node_tests/user_events.js @@ -11,8 +11,10 @@ var user_events = require("js/user_events.js"); set_global('activity', { redraw: function () {}, }); -set_global('admin', { +set_global('settings_users', { update_user_data: function () {}, +}); +set_global('admin', { show_or_hide_menu_item: function () {}, }); set_global('page_params', { diff --git a/static/js/admin.js b/static/js/admin.js index 2dcc8e2851..0ddee4d8d3 100644 --- a/static/js/admin.js +++ b/static/js/admin.js @@ -17,151 +17,10 @@ exports.show_or_hide_menu_item = function () { } }; -function get_user_info(user_id) { - var self = {}; - self.user_row = $("tr.user_row[data-user-id='" + user_id + "']"); - self.form_row = $("tr.user-name-form[data-user-id='" + user_id + "']"); - - return self; -} - -function get_email_for_user_row(row) { - var email = row.find('.email').text(); - return email; -} - -function update_view_on_deactivate(row) { - var button = row.find("button.deactivate"); - row.find('button.open-user-form').hide(); - button.addClass("btn-warning"); - button.removeClass("btn-danger"); - button.addClass("reactivate"); - button.removeClass("deactivate"); - button.text(i18n.t("Reactivate")); - row.addClass("deactivated_user"); -} - -function update_view_on_reactivate(row) { - row.find(".user-admin-settings").show(); - var button = row.find("button.reactivate"); - row.find("button.open-user-form").show(); - button.addClass("btn-danger"); - button.removeClass("btn-warning"); - button.addClass("deactivate"); - button.removeClass("reactivate"); - button.text(i18n.t("Deactivate")); - row.removeClass("deactivated_user"); -} - -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; - - 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); - } - - if (new_data.is_active !== undefined) { - if (new_data.is_active === false) { - // Deactivate the bot in the table - update_view_on_deactivate(user_row); - } else { - // Reactivate the bot in the table - update_view_on_reactivate(user_row); - } - } - - // Remove the bot owner select control. - form_row.find(".edit_bot_owner_container select").remove(); - - // Hide name change form - form_row.hide(); - user_row.show(); -}; - -function failed_listing_users(xhr) { - loading.destroy_indicator($('#subs_page_loading_indicator')); - ui_report.error(i18n.t("Error listing users or bots"), xhr, $("#organization-status")); -} - function failed_listing_streams(xhr) { ui_report.error(i18n.t("Error listing streams"), xhr, $("#organization-status")); } -function populate_users(realm_people_data) { - var users_table = $("#admin_users_table"); - var deactivated_users_table = $("#admin_deactivated_users_table"); - var bots_table = $("#admin_bots_table"); - // Clear table rows, but not the table headers - users_table.find("tr.user_row").remove(); - deactivated_users_table.find("tr.user_row").remove(); - bots_table.find("tr.user_row").remove(); - - var active_users = []; - var deactivated_users = []; - var bots = []; - _.each(realm_people_data.members, function (user) { - user.is_active_human = user.is_active && !user.is_bot; - if (user.is_bot) { - bots.push(user); - } else if (user.is_active) { - active_users.push(user); - } else { - deactivated_users.push(user); - } - }); - - active_users = _.sortBy(active_users, 'full_name'); - deactivated_users = _.sortBy(deactivated_users, 'full_name'); - bots = _.sortBy(bots, 'full_name'); - - var bots_table_html = ""; - _.each(bots, function (user) { - var bot_html = templates.render("admin_user_list", {user: user}); - bots_table_html = bots_table_html.concat(bot_html); - }); - bots_table.append(bots_table_html); - - _.each(active_users, function (user) { - var activity_rendered; - var row = $(templates.render("admin_user_list", {user: user})); - if (people.is_current_user(user.email)) { - activity_rendered = timerender.render_date(new XDate()); - } else { - var last_active_date = presence.last_active_date(user.user_id); - if (last_active_date) { - activity_rendered = timerender.render_date(last_active_date); - } else { - activity_rendered = $("").text(i18n.t("Unknown")); - } - } - row.find(".last_active").append(activity_rendered); - users_table.append(row); - }); - - var deactivated_table_html = ""; - _.each(deactivated_users, function (user) { - var user_html = templates.render("admin_user_list", {user: user}); - deactivated_table_html = deactivated_table_html.concat(user_html); - }); - deactivated_users_table.append(deactivated_table_html); - loading.destroy_indicator($('#admin_page_users_loading_indicator')); - loading.destroy_indicator($('#admin_page_bots_loading_indicator')); - loading.destroy_indicator($('#admin_page_deactivated_users_loading_indicator')); -} - function populate_streams(streams_data) { var streams_table = $("#admin_streams_table").expectOne(); all_streams = streams_data; @@ -347,21 +206,9 @@ function _setup_page() { $("#id_realm_default_language").val(page_params.realm_default_language); // create loading indicators - loading.make_indicator($('#admin_page_users_loading_indicator')); - loading.make_indicator($('#admin_page_bots_loading_indicator')); loading.make_indicator($('#admin_page_streams_loading_indicator')); - loading.make_indicator($('#admin_page_deactivated_users_loading_indicator')); loading.make_indicator($('#admin_page_filters_loading_indicator')); - // Populate users and bots tables - channel.get({ - url: '/json/users', - idempotent: true, - timeout: 10*1000, - success: populate_users, - error: failed_listing_users, - }); - // Populate streams table channel.get({ url: '/json/streams?include_public=true&include_subscribed=true&include_default=true', @@ -377,29 +224,13 @@ function _setup_page() { settings_org.set_up(); settings_emoji.set_up(); + settings_users.set_up(); exports.update_default_streams_table(); // Populate filters table exports.populate_filters(page_params.realm_filters); - // Setup click handlers - $(".admin_user_table").on("click", ".deactivate", function (e) { - e.preventDefault(); - e.stopPropagation(); - - var row = $(e.target).closest(".user_row"); - - var user_name = row.find('.user_name').text(); - var email = get_email_for_user_row(row); - - $("#deactivation_user_modal .email").text(email); - $("#deactivation_user_modal .user_name").text(user_name); - $("#deactivation_user_modal").modal("show"); - - meta.current_deactivate_user_modal_row = row; - }); - $(".admin_stream_table").on("click", ".deactivate", function (e) { e.preventDefault(); e.stopPropagation(); @@ -433,211 +264,6 @@ function _setup_page() { }, }); - $("#do_deactivate_user_button").expectOne().click(function () { - var email = meta.current_deactivate_user_modal_row.find(".email").text(); - - if ($("#deactivation_user_modal .email").html() !== email) { - blueslip.error("User deactivation canceled due to non-matching fields."); - ui_report.message("Deactivation encountered an error. Please reload and try again.", - $("#home-error"), 'alert-error'); - } - $("#deactivation_user_modal").modal("hide"); - meta.current_deactivate_user_modal_row.find("button").eq(0).prop("disabled", true).text(i18n.t("Working…")); - channel.del({ - url: '/json/users/' + encodeURIComponent(email), - error: function (xhr) { - if (xhr.status.toString().charAt(0) === "4") { - meta.current_deactivate_user_modal_row.find("button").closest("td").html( - $("
").addClass("text-error").text(JSON.parse(xhr.responseText).msg) - ); - } else { - meta.current_deactivate_user_modal_row.find("button").text(i18n.t("Failed!")); - } - }, - success: function () { - var button = meta.current_deactivate_user_modal_row.find("button.deactivate"); - button.prop("disabled", false); - button.addClass("btn-warning reactivate").removeClass("btn-danger deactivate"); - button.text(i18n.t("Reactivate")); - meta.current_deactivate_user_modal_row.addClass("deactivated_user"); - meta.current_deactivate_user_modal_row.find('button.open-user-form').hide(); - meta.current_deactivate_user_modal_row.find(".user-admin-settings").hide(); - }, - }); - }); - - $(".admin_bot_table").on("click", ".deactivate", function (e) { - e.preventDefault(); - e.stopPropagation(); - - var row = $(e.target).closest(".user_row"); - - var email = get_email_for_user_row(row); - - channel.del({ - url: '/json/bots/' + encodeURIComponent(email), - error: function (xhr) { - if (xhr.status.toString().charAt(0) === "4") { - row.find("button").closest("td").html( - $("
").addClass("text-error").text(JSON.parse(xhr.responseText).msg) - ); - } else { - row.find("button").text(i18n.t("Failed!")); - } - }, - success: function () { - update_view_on_deactivate(row); - }, - }); - }); - - $(".admin_user_table, .admin_bot_table").on("click", ".reactivate", function (e) { - e.preventDefault(); - e.stopPropagation(); - - // Go up the tree until we find the user row, then grab the email element - var row = $(e.target).closest(".user_row"); - var email = get_email_for_user_row(row); - - channel.post({ - url: '/json/users/' + encodeURIComponent(email) + "/reactivate", - error: function (xhr) { - var button = row.find("button"); - if (xhr.status.toString().charAt(0) === "4") { - button.closest("td").html( - $("
").addClass("text-error").text(JSON.parse(xhr.responseText).msg) - ); - } else { - button.text(i18n.t("Failed!")); - } - }, - success: function () { - update_view_on_reactivate(row); - }, - }); - }); - - $(".admin_user_table").on("click", ".make-admin", function (e) { - e.preventDefault(); - e.stopPropagation(); - - // Go up the tree until we find the user row, then grab the email element - var row = $(e.target).closest(".user_row"); - var email = get_email_for_user_row(row); - - var url = "/json/users/" + encodeURIComponent(email); - var data = { - is_admin: JSON.stringify(true), - }; - - channel.patch({ - url: url, - data: data, - success: function () { - var button = row.find("button.make-admin"); - button.addClass("btn-danger"); - button.removeClass("btn-warning"); - button.addClass("remove-admin"); - button.removeClass("make-admin"); - button.text(i18n.t("Remove admin")); - }, - error: function (xhr) { - var status = row.find(".admin-user-status"); - ui_report.error(i18n.t("Failed!"), xhr, status); - }, - }); - }); - - $(".admin_user_table").on("click", ".remove-admin", function (e) { - e.preventDefault(); - e.stopPropagation(); - - // Go up the tree until we find the user row, then grab the email element - var row = $(e.target).closest(".user_row"); - var email = get_email_for_user_row(row); - - var url = "/json/users/" + encodeURIComponent(email); - var data = { - is_admin: JSON.stringify(false), - }; - - channel.patch({ - url: url, - data: data, - success: function () { - var button = row.find("button.remove-admin"); - button.addClass("btn-warning"); - button.removeClass("btn-danger"); - button.addClass("make-admin"); - button.removeClass("remove-admin"); - button.text(i18n.t("Make admin")); - }, - error: function (xhr) { - var status = row.find(".admin-user-status"); - ui_report.error(i18n.t("Failed!"), xhr, status); - }, - }); - }); - - $(".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; - var form_row = user_info.form_row; - 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 = $('#organization-status').expectOne(); - var person = people.get_person_from_user_id(user_id); - if (!person) { - return; - } else if (person.is_bot) { - // 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(); - }); - - submit_button.on("click", function (e) { - e.preventDefault(); - e.stopPropagation(); - - var url = "/json/bots/" + encodeURIComponent(person.email); - var data = { - 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('Updated successfully!'), admin_status); - }, - error: function () { - ui_report.error(i18n.t('Update failed!'), admin_status); - }, - }); - }); - }); - $("#do_deactivate_stream_button").click(function () { if ($("#deactivation_stream_modal .stream_name").text() !== $(".active_stream_row").find('.stream_name').text()) { blueslip.error("Stream deactivation canceled due to non-matching fields."); diff --git a/static/js/server_events.js b/static/js/server_events.js index 0719b66b01..213db8d827 100644 --- a/static/js/server_events.js +++ b/static/js/server_events.js @@ -112,17 +112,17 @@ function dispatch_normal_event(event) { case 'realm_bot': if (event.op === 'add') { bot_data.add(event.bot); - admin.update_user_data(event.bot.user_id, event.bot); + settings_users.update_user_data(event.bot.user_id, event.bot); } else if (event.op === 'remove') { bot_data.deactivate(event.bot.email); event.bot.is_active = false; - admin.update_user_data(event.bot.user_id, event.bot); + settings_users.update_user_data(event.bot.user_id, event.bot); } 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_data(event.bot.user_id, event.bot); + settings_users.update_user_data(event.bot.user_id, event.bot); } break; diff --git a/static/js/settings_users.js b/static/js/settings_users.js new file mode 100644 index 0000000000..0658ddebad --- /dev/null +++ b/static/js/settings_users.js @@ -0,0 +1,399 @@ +var settings_users = (function () { + +var exports = {}; + +var meta = { + loaded: false, +}; + +function get_user_info(user_id) { + var self = {}; + self.user_row = $("tr.user_row[data-user-id='" + user_id + "']"); + self.form_row = $("tr.user-name-form[data-user-id='" + user_id + "']"); + + return self; +} + +function get_email_for_user_row(row) { + var email = row.find('.email').text(); + return email; +} + +function update_view_on_deactivate(row) { + var button = row.find("button.deactivate"); + row.find('button.open-user-form').hide(); + button.addClass("btn-warning"); + button.removeClass("btn-danger"); + button.addClass("reactivate"); + button.removeClass("deactivate"); + button.text(i18n.t("Reactivate")); + row.addClass("deactivated_user"); +} + +function update_view_on_reactivate(row) { + row.find(".user-admin-settings").show(); + var button = row.find("button.reactivate"); + row.find("button.open-user-form").show(); + button.addClass("btn-danger"); + button.removeClass("btn-warning"); + button.addClass("deactivate"); + button.removeClass("reactivate"); + button.text(i18n.t("Deactivate")); + row.removeClass("deactivated_user"); +} + +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; + + 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); + } + + if (new_data.is_active !== undefined) { + if (new_data.is_active === false) { + // Deactivate the bot in the table + update_view_on_deactivate(user_row); + } else { + // Reactivate the bot in the table + update_view_on_reactivate(user_row); + } + } + + // Remove the bot owner select control. + form_row.find(".edit_bot_owner_container select").remove(); + + // Hide name change form + form_row.hide(); + user_row.show(); +}; + +function failed_listing_users(xhr) { + loading.destroy_indicator($('#subs_page_loading_indicator')); + ui_report.error(i18n.t("Error listing users or bots"), xhr, $("#organization-status")); +} + +function populate_users(realm_people_data) { + var users_table = $("#admin_users_table"); + var deactivated_users_table = $("#admin_deactivated_users_table"); + var bots_table = $("#admin_bots_table"); + // Clear table rows, but not the table headers + users_table.find("tr.user_row").remove(); + deactivated_users_table.find("tr.user_row").remove(); + bots_table.find("tr.user_row").remove(); + + var active_users = []; + var deactivated_users = []; + var bots = []; + _.each(realm_people_data.members, function (user) { + user.is_active_human = user.is_active && !user.is_bot; + if (user.is_bot) { + bots.push(user); + } else if (user.is_active) { + active_users.push(user); + } else { + deactivated_users.push(user); + } + }); + + active_users = _.sortBy(active_users, 'full_name'); + deactivated_users = _.sortBy(deactivated_users, 'full_name'); + bots = _.sortBy(bots, 'full_name'); + + var bots_table_html = ""; + _.each(bots, function (user) { + var bot_html = templates.render("admin_user_list", {user: user}); + bots_table_html = bots_table_html.concat(bot_html); + }); + bots_table.append(bots_table_html); + + _.each(active_users, function (user) { + var activity_rendered; + var row = $(templates.render("admin_user_list", {user: user})); + if (people.is_current_user(user.email)) { + activity_rendered = timerender.render_date(new XDate()); + } else { + var last_active_date = presence.last_active_date(user.user_id); + if (last_active_date) { + activity_rendered = timerender.render_date(last_active_date); + } else { + activity_rendered = $("").text(i18n.t("Unknown")); + } + } + row.find(".last_active").append(activity_rendered); + users_table.append(row); + }); + + var deactivated_table_html = ""; + _.each(deactivated_users, function (user) { + var user_html = templates.render("admin_user_list", {user: user}); + deactivated_table_html = deactivated_table_html.concat(user_html); + }); + deactivated_users_table.append(deactivated_table_html); + loading.destroy_indicator($('#admin_page_users_loading_indicator')); + loading.destroy_indicator($('#admin_page_bots_loading_indicator')); + loading.destroy_indicator($('#admin_page_deactivated_users_loading_indicator')); +} + +exports.set_up = function () { + loading.make_indicator($('#admin_page_users_loading_indicator')); + loading.make_indicator($('#admin_page_bots_loading_indicator')); + loading.make_indicator($('#admin_page_deactivated_users_loading_indicator')); + + // Populate users and bots tables + channel.get({ + url: '/json/users', + idempotent: true, + timeout: 10*1000, + success: exports.on_load_success, + error: failed_listing_users, + }); +}; + +exports.on_load_success = function (realm_people_data) { + meta.loaded = true; + + populate_users(realm_people_data); + + // Setup click handlers + $(".admin_user_table").on("click", ".deactivate", function (e) { + e.preventDefault(); + e.stopPropagation(); + + var row = $(e.target).closest(".user_row"); + + var user_name = row.find('.user_name').text(); + var email = get_email_for_user_row(row); + + $("#deactivation_user_modal .email").text(email); + $("#deactivation_user_modal .user_name").text(user_name); + $("#deactivation_user_modal").modal("show"); + + meta.current_deactivate_user_modal_row = row; + }); + + $("#do_deactivate_user_button").expectOne().click(function () { + var email = meta.current_deactivate_user_modal_row.find(".email").text(); + + if ($("#deactivation_user_modal .email").html() !== email) { + blueslip.error("User deactivation canceled due to non-matching fields."); + ui_report.message("Deactivation encountered an error. Please reload and try again.", + $("#home-error"), 'alert-error'); + } + $("#deactivation_user_modal").modal("hide"); + meta.current_deactivate_user_modal_row.find("button").eq(0).prop("disabled", true).text(i18n.t("Working…")); + channel.del({ + url: '/json/users/' + encodeURIComponent(email), + error: function (xhr) { + if (xhr.status.toString().charAt(0) === "4") { + meta.current_deactivate_user_modal_row.find("button").closest("td").html( + $("
").addClass("text-error").text(JSON.parse(xhr.responseText).msg) + ); + } else { + meta.current_deactivate_user_modal_row.find("button").text(i18n.t("Failed!")); + } + }, + success: function () { + var button = meta.current_deactivate_user_modal_row.find("button.deactivate"); + button.prop("disabled", false); + button.addClass("btn-warning reactivate").removeClass("btn-danger deactivate"); + button.text(i18n.t("Reactivate")); + meta.current_deactivate_user_modal_row.addClass("deactivated_user"); + meta.current_deactivate_user_modal_row.find('button.open-user-form').hide(); + meta.current_deactivate_user_modal_row.find(".user-admin-settings").hide(); + }, + }); + }); + + $(".admin_bot_table").on("click", ".deactivate", function (e) { + e.preventDefault(); + e.stopPropagation(); + + var row = $(e.target).closest(".user_row"); + + var email = get_email_for_user_row(row); + + channel.del({ + url: '/json/bots/' + encodeURIComponent(email), + error: function (xhr) { + if (xhr.status.toString().charAt(0) === "4") { + row.find("button").closest("td").html( + $("
").addClass("text-error").text(JSON.parse(xhr.responseText).msg) + ); + } else { + row.find("button").text(i18n.t("Failed!")); + } + }, + success: function () { + update_view_on_deactivate(row); + }, + }); + }); + + $(".admin_user_table, .admin_bot_table").on("click", ".reactivate", function (e) { + e.preventDefault(); + e.stopPropagation(); + + // Go up the tree until we find the user row, then grab the email element + var row = $(e.target).closest(".user_row"); + var email = get_email_for_user_row(row); + + channel.post({ + url: '/json/users/' + encodeURIComponent(email) + "/reactivate", + error: function (xhr) { + var button = row.find("button"); + if (xhr.status.toString().charAt(0) === "4") { + button.closest("td").html( + $("
").addClass("text-error").text(JSON.parse(xhr.responseText).msg) + ); + } else { + button.text(i18n.t("Failed!")); + } + }, + success: function () { + update_view_on_reactivate(row); + }, + }); + }); + + $(".admin_user_table").on("click", ".make-admin", function (e) { + e.preventDefault(); + e.stopPropagation(); + + // Go up the tree until we find the user row, then grab the email element + var row = $(e.target).closest(".user_row"); + var email = get_email_for_user_row(row); + + var url = "/json/users/" + encodeURIComponent(email); + var data = { + is_admin: JSON.stringify(true), + }; + + channel.patch({ + url: url, + data: data, + success: function () { + var button = row.find("button.make-admin"); + button.addClass("btn-danger"); + button.removeClass("btn-warning"); + button.addClass("remove-admin"); + button.removeClass("make-admin"); + button.text(i18n.t("Remove admin")); + }, + error: function (xhr) { + var status = row.find(".admin-user-status"); + ui_report.error(i18n.t("Failed!"), xhr, status); + }, + }); + }); + + $(".admin_user_table").on("click", ".remove-admin", function (e) { + e.preventDefault(); + e.stopPropagation(); + + // Go up the tree until we find the user row, then grab the email element + var row = $(e.target).closest(".user_row"); + var email = get_email_for_user_row(row); + + var url = "/json/users/" + encodeURIComponent(email); + var data = { + is_admin: JSON.stringify(false), + }; + + channel.patch({ + url: url, + data: data, + success: function () { + var button = row.find("button.remove-admin"); + button.addClass("btn-warning"); + button.removeClass("btn-danger"); + button.addClass("make-admin"); + button.removeClass("remove-admin"); + button.text(i18n.t("Make admin")); + }, + error: function (xhr) { + var status = row.find(".admin-user-status"); + ui_report.error(i18n.t("Failed!"), xhr, status); + }, + }); + }); + + $(".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; + var form_row = user_info.form_row; + 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 = $('#organization-status').expectOne(); + var person = people.get_person_from_user_id(user_id); + if (!person) { + return; + } else if (person.is_bot) { + // 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(); + }); + + submit_button.on("click", function (e) { + e.preventDefault(); + e.stopPropagation(); + + var url = "/json/bots/" + encodeURIComponent(person.email); + var data = { + 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('Updated successfully!'), admin_status); + }, + error: function () { + ui_report.error(i18n.t('Update failed!'), admin_status); + }, + }); + }); + }); + +}; + +return exports; +}()); + +if (typeof module !== 'undefined') { + module.exports = settings_users; +} diff --git a/static/js/user_events.js b/static/js/user_events.js index 2884ac90e0..708ff6085a 100644 --- a/static/js/user_events.js +++ b/static/js/user_events.js @@ -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_data(person.user_id, person); + settings_users.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(); diff --git a/zproject/settings.py b/zproject/settings.py index 21d9c5bebf..d58419ecfb 100644 --- a/zproject/settings.py +++ b/zproject/settings.py @@ -915,6 +915,7 @@ JS_SPECS = { 'js/settings_sections.js', 'js/settings_emoji.js', 'js/settings_org.js', + 'js/settings_users.js', 'js/settings.js', 'js/admin.js', 'js/tab_bar.js',