settings_users: Migrate manage user modal to full profile modal.

This commit migrates the "manage user" modal to the "Full Profile"
modal. Refactored the show_edit_user_info_modal function since
earlier, we used to have a separate "Manage User" modal.
Consequently, we checked if we were coming from the
user_info_popover and then built the dialog widget accordingly.
However, with this new change, we no longer need to build the
dialog widget. Therefore, removed that part and now just pass
the container of the 'user profile modal' to get the content.

Previously, for deactivation, we used to have a separate dialog
widget. But now, since we have a dedicated function to handle
this case, refactored the deactivation code to use the
'confirm_deactivation' function.

Additionally, created two new functions to handle the loading
spinner. Since we will need these functions in the future for
the "Manage Bot" modal, we marked them as exported.

"Since we do not want to show the 'Manage User' tab to the user
looking at their own profile, in the 'can_manage_user' function
that we use to render the 'Manage User' tab, we check if the user
profile popover belongs to the same user. If it does, we set it to
'false' instead of 'true,' ensuring that the 'Manage User' tab is
not visible.

Added a new tab in the user profile modal 'manage user'.

Fixes: #21806
This commit is contained in:
palashb01 2023-09-09 16:12:04 +05:30 committed by Tim Abbott
parent a844be8825
commit 61cca84b17
5 changed files with 111 additions and 52 deletions

View File

@ -958,7 +958,7 @@ export function register_click_handlers() {
if (user.is_bot) { if (user.is_bot) {
settings_bots.show_edit_bot_info_modal(user_id, true); settings_bots.show_edit_bot_info_modal(user_id, true);
} else { } else {
settings_users.show_edit_user_info_modal(user_id, true); user_profile.show_user_profile(user, "manage-profile-tab");
} }
}); });

View File

@ -24,7 +24,9 @@ import * as settings_bots from "./settings_bots";
import * as settings_config from "./settings_config"; import * as settings_config from "./settings_config";
import * as settings_panel_menu from "./settings_panel_menu"; import * as settings_panel_menu from "./settings_panel_menu";
import * as timerender from "./timerender"; import * as timerender from "./timerender";
import * as ui_report from "./ui_report";
import * as user_pill from "./user_pill"; import * as user_pill from "./user_pill";
import * as user_profile from "./user_profile";
const section = { const section = {
active: {}, active: {},
@ -32,6 +34,25 @@ const section = {
bots: {}, bots: {},
}; };
export function show_button_spinner($button) {
const $spinner = $button.find(".modal__spinner");
const dialog_submit_button_span_width = $button.find("span").width();
const dialog_submit_button_span_height = $button.find("span").height();
$button.prop("disabled", true);
$button.find("span").hide();
loading.make_indicator($spinner, {
width: dialog_submit_button_span_width,
height: dialog_submit_button_span_height,
});
}
export function hide_button_spinner($button) {
const $spinner = $button.find(".modal__spinner");
$button.prop("disabled", false);
$button.find("span").show();
loading.destroy_indicator($spinner);
}
function compare_a_b(a, b) { function compare_a_b(a, b) {
if (a > b) { if (a > b) {
return 1; return 1;
@ -623,7 +644,7 @@ function handle_reactivation($tbody) {
}); });
} }
export function show_edit_user_info_modal(user_id, from_user_info_popover) { export function show_edit_user_info_modal(user_id, $container) {
const person = people.maybe_get_user_by_id(user_id); const person = people.maybe_get_user_by_id(user_id);
if (!person) { if (!person) {
@ -638,43 +659,40 @@ export function show_edit_user_info_modal(user_id, from_user_info_popover) {
disable_role_dropdown: person.is_owner && !page_params.is_owner, disable_role_dropdown: person.is_owner && !page_params.is_owner,
}); });
let fields_user_pills; $container.append(html_body);
// Set role dropdown and fields user pills
function set_role_dropdown_and_fields_user_pills() { $("#user-role-select").val(person.role);
$("#user-role-select").val(person.role); if (!page_params.is_owner) {
if (!page_params.is_owner) { $("#user-role-select")
$("#user-role-select") .find(`option[value="${CSS.escape(settings_config.user_role_values.owner.code)}"]`)
.find(`option[value="${CSS.escape(settings_config.user_role_values.owner.code)}"]`) .hide();
.hide();
}
const element = "#edit-user-form .custom-profile-field-form";
$(element).empty();
settings_account.append_custom_profile_fields(element, user_id);
settings_account.initialize_custom_date_type_fields(element);
fields_user_pills = settings_account.initialize_custom_user_type_fields(
element,
user_id,
true,
false,
);
settings_account.initialize_custom_pronouns_type_fields(element);
$("#edit-user-form").on("click", ".deactivate_user_button", (e) => {
e.preventDefault();
e.stopPropagation();
const user_id = $("#edit-user-form").data("user-id");
function handle_confirm() {
const url = "/json/users/" + encodeURIComponent(user_id);
dialog_widget.submit_api_request(channel.del, url);
}
const open_deactivate_modal_callback = () =>
confirm_deactivation(user_id, handle_confirm, true);
dialog_widget.close_modal(open_deactivate_modal_callback);
});
} }
function submit_user_details() { const element = "#edit-user-form .custom-profile-field-form";
$(element).empty();
settings_account.append_custom_profile_fields(element, user_id);
settings_account.initialize_custom_date_type_fields(element);
settings_account.initialize_custom_pronouns_type_fields(element);
const fields_user_pills = settings_account.initialize_custom_user_type_fields(
element,
user_id,
true,
false,
);
// Handle deactivation
$("#edit-user-form").on("click", ".deactivate_user_button", (e) => {
e.preventDefault();
e.stopPropagation();
const user_id = $("#edit-user-form").data("user-id");
function handle_confirm() {
const url = "/json/users/" + encodeURIComponent(user_id);
dialog_widget.submit_api_request(channel.del, url);
}
confirm_deactivation(user_id, handle_confirm, true);
});
$("#edit-user-form").on("click", ".dialog_submit_button", () => {
const role = Number.parseInt($("#user-role-select").val().trim(), 10); const role = Number.parseInt($("#user-role-select").val().trim(), 10);
const $full_name = $("#edit-user-form").find("input[name='full_name']"); const $full_name = $("#edit-user-form").find("input[name='full_name']");
const profile_data = get_human_profile_data(fields_user_pills); const profile_data = get_human_profile_data(fields_user_pills);
@ -685,23 +703,31 @@ export function show_edit_user_info_modal(user_id, from_user_info_popover) {
role: JSON.stringify(role), role: JSON.stringify(role),
profile_data: JSON.stringify(profile_data), profile_data: JSON.stringify(profile_data),
}; };
const opts = { const $submit_btn = $("#edit-user-form .dialog_submit_button");
error_continuation() { const $cancel_btn = $("#edit-user-form .dialog_exit_button");
show_button_spinner($submit_btn);
$cancel_btn.prop("disabled", true);
channel.patch({
url,
data,
success() {
user_profile.hide_user_profile();
},
error(xhr) {
ui_report.error(
$t_html({defaultMessage: "Failed"}),
xhr,
$("#edit-user-form-error"),
);
// Scrolling modal to top, to make error visible to user. // Scrolling modal to top, to make error visible to user.
$("#edit-user-form") $("#edit-user-form")
.closest(".simplebar-content-wrapper") .closest(".simplebar-content-wrapper")
.animate({scrollTop: 0}, "fast"); .animate({scrollTop: 0}, "fast");
hide_button_spinner($submit_btn);
$cancel_btn.prop("disabled", false);
}, },
}; });
dialog_widget.submit_api_request(channel.patch, url, data, opts);
}
dialog_widget.launch({
html_heading: $t_html({defaultMessage: "Manage user"}),
html_body,
on_click: submit_user_details,
post_render: set_role_dropdown_and_fields_user_pills,
loading_spinner: from_user_info_popover,
}); });
} }
@ -712,7 +738,8 @@ function handle_human_form($tbody) {
popovers.hide_all(); popovers.hide_all();
const user_id = Number.parseInt($(e.currentTarget).attr("data-user-id"), 10); const user_id = Number.parseInt($(e.currentTarget).attr("data-user-id"), 10);
show_edit_user_info_modal(user_id, false); const user = people.get_by_user_id(user_id);
user_profile.show_user_profile(user, "manage-profile-tab");
}); });
} }

View File

@ -20,6 +20,7 @@ import * as popovers from "./popovers";
import * as settings_account from "./settings_account"; import * as settings_account from "./settings_account";
import * as settings_bots from "./settings_bots"; import * as settings_bots from "./settings_bots";
import * as settings_profile_fields from "./settings_profile_fields"; import * as settings_profile_fields from "./settings_profile_fields";
import * as settings_users from "./settings_users";
import * as stream_data from "./stream_data"; import * as stream_data from "./stream_data";
import * as stream_ui_updates from "./stream_ui_updates"; import * as stream_ui_updates from "./stream_ui_updates";
import * as sub_store from "./sub_store"; import * as sub_store from "./sub_store";
@ -189,6 +190,12 @@ function render_user_group_list(groups, user) {
}); });
} }
function render_manage_profile_content(user) {
const $container = $("#manage-profile-tab");
$container.empty();
settings_users.show_edit_user_info_modal(user.user_id, $container);
}
export function get_custom_profile_field_data(user, field, field_types) { export function get_custom_profile_field_data(user, field, field_types) {
const field_value = people.get_custom_profile_data(user.user_id, field.id); const field_value = people.get_custom_profile_data(user.user_id, field.id);
const field_type = field.type; const field_type = field.type;
@ -278,6 +285,10 @@ export function show_user_profile(user, default_tab_key = "profile-tab") {
!user.is_system_bot && !user.is_system_bot &&
people.is_person_active(user.user_id); people.is_person_active(user.user_id);
const groups_of_user = user_groups.get_user_groups_of_user(user.user_id); const groups_of_user = user_groups.get_user_groups_of_user(user.user_id);
const can_manage_profile =
people.is_person_active(user.user_id) &&
page_params.is_admin &&
!people.is_my_user_id(user.user_id);
const args = { const args = {
user_id: user.user_id, user_id: user.user_id,
full_name: user.full_name, full_name: user.full_name,
@ -315,10 +326,11 @@ export function show_user_profile(user, default_tab_key = "profile-tab") {
$(".tabcontent").hide(); $(".tabcontent").hide();
let default_tab = 0; let default_tab = 0;
// Only checking this tab key as currently we only open this tab directly
// other than profile-tab.
if (default_tab_key === "user-profile-streams-tab") { if (default_tab_key === "user-profile-streams-tab") {
default_tab = 1; default_tab = 1;
} else if (default_tab_key === "manage-profile-tab") {
default_tab = 3;
} }
const opts = { const opts = {
@ -345,10 +357,21 @@ export function show_user_profile(user, default_tab_key = "profile-tab") {
} }
render_user_stream_list(user_streams, user); render_user_stream_list(user_streams, user);
break; break;
case "manage-profile-tab":
render_manage_profile_content(user);
break;
} }
}, },
}; };
if (can_manage_profile) {
const manage_profile_tab = {
label: $t({defaultMessage: "Manage user"}),
key: "manage-profile-tab",
};
opts.values.push(manage_profile_tab);
}
const $elem = components.toggle(opts).get(); const $elem = components.toggle(opts).get();
$elem.addClass("large allow-overflow"); $elem.addClass("large allow-overflow");
$("#tab-toggle").append($elem); $("#tab-toggle").append($elem);

View File

@ -1,5 +1,6 @@
<div id="edit-user-form" data-user-id="{{user_id}}"> <div id="edit-user-form" data-user-id="{{user_id}}">
<form class="name-setting"> <form class="name-setting">
<div class="alert" id="edit-user-form-error"></div>
<input type="hidden" name="is_full_name" value="true" /> <input type="hidden" name="is_full_name" value="true" />
<div class="input-group name_change_container"> <div class="input-group name_change_container">
<label for="edit_user_full_name">{{t "Full name" }}</label> <label for="edit_user_full_name">{{t "Full name" }}</label>
@ -30,4 +31,11 @@
{{t 'Deactivate user' }} {{t 'Deactivate user' }}
</button> </button>
</div> </div>
<footer class="modal__footer">
<button type="button" class="modal__btn dialog_exit_button" aria-label="{{t 'Close this dialog window' }}" data-micromodal-close>{{t "Cancel" }}</button>
<button type="button" class="modal__btn dialog_submit_button">
<span>{{t "Save changes"}}</span>
<div class="modal__spinner"></div>
</button>
</footer>
</div> </div>

View File

@ -116,6 +116,7 @@
<table class="user-group-list" data-empty="{{t 'No user group subscriptions.'}}"></table> <table class="user-group-list" data-empty="{{t 'No user group subscriptions.'}}"></table>
</div> </div>
</div> </div>
<div class="tabcontent" id="manage-profile-tab"></div>
</div> </div>
</main> </main>
</div> </div>