mirror of https://github.com/zulip/zulip.git
settings: Separate "Your account" section in two different sections.
We separate "Your account" section to two different sections - "Profile" section for user name, custom profile fields, and avatar and "Account & Security" section for email, password, role, api-key and deactivating button. Another important change here is that the modal for changing name is removed and now the name has a simple input text box and it behaves similar to inputs for custom-profile-fields. Fixes #18848.
This commit is contained in:
parent
5f74e78bee
commit
bb816e1998
|
@ -22,7 +22,7 @@ function test(label, f) {
|
|||
}
|
||||
|
||||
test("basics", () => {
|
||||
const hash1 = "#settings/your-account";
|
||||
const hash1 = "#settings/profile";
|
||||
const hash2 = "#narrow/is/private";
|
||||
browser_history.go_to_location(hash1);
|
||||
assert.equal(location.hash, hash1);
|
||||
|
|
|
@ -86,26 +86,26 @@ run_test("test_get_hash_category", () => {
|
|||
assert.deepEqual(hash_util.get_hash_category("#drafts"), "drafts");
|
||||
assert.deepEqual(hash_util.get_hash_category("invites"), "invites");
|
||||
|
||||
location.hash = "#settings/your-account";
|
||||
location.hash = "#settings/profile";
|
||||
assert.deepEqual(hash_util.get_current_hash_category(), "settings");
|
||||
});
|
||||
|
||||
run_test("test_get_hash_section", () => {
|
||||
assert.equal(hash_util.get_hash_section("streams/subscribed"), "subscribed");
|
||||
assert.equal(hash_util.get_hash_section("#settings/your-account"), "your-account");
|
||||
assert.equal(hash_util.get_hash_section("#settings/profile"), "profile");
|
||||
|
||||
assert.equal(hash_util.get_hash_section("settings/10/general/"), "10");
|
||||
|
||||
assert.equal(hash_util.get_hash_section("#drafts"), "");
|
||||
assert.equal(hash_util.get_hash_section(""), "");
|
||||
|
||||
location.hash = "#settings/your-account";
|
||||
assert.deepEqual(hash_util.get_current_hash_section(), "your-account");
|
||||
location.hash = "#settings/profile";
|
||||
assert.deepEqual(hash_util.get_current_hash_section(), "profile");
|
||||
});
|
||||
|
||||
run_test("build_reload_url", () => {
|
||||
location.hash = "#settings/your-account";
|
||||
assert.equal(hash_util.build_reload_url(), "+oldhash=settings%2Fyour-account");
|
||||
location.hash = "#settings/profile";
|
||||
assert.equal(hash_util.build_reload_url(), "+oldhash=settings%2Fprofile");
|
||||
|
||||
location.hash = "#test";
|
||||
assert.equal(hash_util.build_reload_url(), "+oldhash=test");
|
||||
|
|
|
@ -27,7 +27,7 @@ async function open_settings(page: Page): Promise<void> {
|
|||
await page.waitForSelector(settings_selector, {visible: true});
|
||||
await page.click(settings_selector);
|
||||
|
||||
await page.waitForSelector("#settings_content .account-settings-form", {visible: true});
|
||||
await page.waitForSelector("#settings_content .profile-settings-form", {visible: true});
|
||||
const page_url = await common.page_url_with_fragment(page);
|
||||
assert.ok(
|
||||
page_url.includes("/#settings/"),
|
||||
|
@ -36,23 +36,18 @@ async function open_settings(page: Page): Promise<void> {
|
|||
}
|
||||
|
||||
async function test_change_full_name(page: Page): Promise<void> {
|
||||
await page.click("#change_full_name");
|
||||
|
||||
const change_full_name_button_selector = "#change_full_name_button";
|
||||
await page.waitForSelector(change_full_name_button_selector, {visible: true});
|
||||
await page.click("#full_name");
|
||||
|
||||
const full_name_input_selector = 'input[name="full_name"]';
|
||||
await page.$eval(full_name_input_selector, (el) => {
|
||||
(el as HTMLInputElement).value = "";
|
||||
});
|
||||
await page.waitForFunction(() => $(":focus").attr("id") === "change_full_name_modal");
|
||||
await page.type(full_name_input_selector, "New name");
|
||||
await page.click(change_full_name_button_selector);
|
||||
await page.waitForFunction(() => $("#change_full_name").text().trim() === "New name");
|
||||
await common.wait_for_modal_to_close(page);
|
||||
await common.clear_and_type(page, full_name_input_selector, "New name");
|
||||
|
||||
await page.click("#settings_content .profile-settings-form");
|
||||
await page.waitForSelector(".full-name-change-form .alert-success", {visible: true});
|
||||
await page.waitForFunction(() => $("#full_name").val() === "New name");
|
||||
}
|
||||
|
||||
async function test_change_password(page: Page): Promise<void> {
|
||||
await page.click('[data-section="account-and-privacy"]');
|
||||
await page.click("#change_password");
|
||||
|
||||
const change_password_button_selector = "#change_password_button";
|
||||
|
|
|
@ -95,7 +95,7 @@ export function build_user_avatar_widget(upload_function) {
|
|||
},
|
||||
});
|
||||
}
|
||||
const modal_parent = $("#account-settings");
|
||||
const modal_parent = $("#profile-settings");
|
||||
|
||||
const html_body = render_confirm_delete_user_avatar();
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@ export function get_hash_category(hash) {
|
|||
}
|
||||
|
||||
export function get_hash_section(hash) {
|
||||
// given "#settings/your-account", returns "your-account"
|
||||
// given "#settings/profile", returns "profile"
|
||||
// given '#streams/5/social", returns "5"
|
||||
if (!hash) {
|
||||
return "";
|
||||
|
|
|
@ -36,15 +36,10 @@ export function update_email(new_email) {
|
|||
}
|
||||
|
||||
export function update_full_name(new_full_name) {
|
||||
const full_name_field = $("#full_name_value");
|
||||
if (full_name_field) {
|
||||
full_name_field.text(new_full_name);
|
||||
}
|
||||
|
||||
// Arguably, this should work more like how the `update_email`
|
||||
// flow works, where we update the name in the modal on open,
|
||||
// rather than updating it here, but this works.
|
||||
const full_name_input = $(".full_name_change_container input[name='full_name']");
|
||||
const full_name_input = $(".full-name-change-form input[name='full_name']");
|
||||
if (full_name_input) {
|
||||
full_name_input.val(new_full_name);
|
||||
}
|
||||
|
@ -279,13 +274,8 @@ export function add_custom_profile_fields_to_settings() {
|
|||
return;
|
||||
}
|
||||
|
||||
const element_id = "#account-settings .custom-profile-fields-form";
|
||||
const element_id = "#profile-settings .custom-profile-fields-form";
|
||||
$(element_id).html("");
|
||||
if (page_params.custom_profile_fields.length > 0) {
|
||||
$("#account-settings #custom-field-header").show();
|
||||
} else {
|
||||
$("#account-settings #custom-field-header").hide();
|
||||
}
|
||||
|
||||
append_custom_profile_fields(element_id, people.my_current_user_id());
|
||||
initialize_custom_user_type_fields(element_id, people.my_current_user_id(), true, true);
|
||||
|
@ -403,15 +393,6 @@ export function set_up() {
|
|||
|
||||
clear_password_change();
|
||||
|
||||
$("#change_full_name").on("click", (e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
if (settings_data.user_can_change_name()) {
|
||||
$("#change_full_name_modal").find("input[name='full_name']").val(page_params.full_name);
|
||||
overlays.open_modal("#change_full_name_modal");
|
||||
}
|
||||
});
|
||||
|
||||
$("#change_password").on("click", async (e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
@ -487,28 +468,18 @@ export function set_up() {
|
|||
password_quality?.(field.val(), $("#pw_strength .bar"), field);
|
||||
});
|
||||
|
||||
$("#change_full_name_button").on("click", (e) => {
|
||||
$("#full_name").on("change", (e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
const change_full_name_error = $("#change_full_name_modal")
|
||||
.find(".change_full_name_info")
|
||||
.expectOne();
|
||||
const data = {};
|
||||
|
||||
data.full_name = $(".full_name_change_container").find("input[name='full_name']").val();
|
||||
data.full_name = $("#full_name").val();
|
||||
|
||||
const opts = {
|
||||
success_continuation() {
|
||||
overlays.close_modal("#change_full_name_modal");
|
||||
},
|
||||
error_msg_element: change_full_name_error,
|
||||
};
|
||||
settings_ui.do_settings_change(
|
||||
channel.patch,
|
||||
"/json/settings",
|
||||
data,
|
||||
$("#account-settings-status").expectOne(),
|
||||
opts,
|
||||
$(".full-name-status").expectOne(),
|
||||
);
|
||||
});
|
||||
|
||||
|
@ -556,7 +527,7 @@ export function set_up() {
|
|||
}
|
||||
});
|
||||
|
||||
$("#account-settings").on("click", ".custom_user_field .remove_date", (e) => {
|
||||
$("#profile-settings").on("click", ".custom_user_field .remove_date", (e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
const field = $(e.target).closest(".custom_user_field").expectOne();
|
||||
|
@ -564,7 +535,7 @@ export function set_up() {
|
|||
update_user_custom_profile_fields([field_id], channel.del);
|
||||
});
|
||||
|
||||
$("#account-settings").on("change", ".custom_user_field_value", function (e) {
|
||||
$("#profile-settings").on("change", ".custom_user_field_value", function (e) {
|
||||
const fields = [];
|
||||
const value = $(this).val();
|
||||
const field_id = Number.parseInt(
|
||||
|
|
|
@ -38,6 +38,10 @@ export function get_group(section) {
|
|||
case "deactivated-users-admin":
|
||||
return "org_users";
|
||||
|
||||
case "profile":
|
||||
case "account-and-privacy":
|
||||
return "your-account";
|
||||
|
||||
default:
|
||||
return section;
|
||||
}
|
||||
|
|
|
@ -62,7 +62,8 @@ h3 .fa-question-circle-o {
|
|||
text-align: left;
|
||||
}
|
||||
}
|
||||
#account-settings {
|
||||
#account-settings,
|
||||
#profile-field-settings {
|
||||
.grid {
|
||||
label {
|
||||
min-width: 120px;
|
||||
|
@ -108,8 +109,7 @@ h3 .fa-question-circle-o {
|
|||
}
|
||||
|
||||
#change_password_modal,
|
||||
#change_email_modal,
|
||||
#change_full_name_modal {
|
||||
#change_email_modal {
|
||||
max-width: 480px;
|
||||
}
|
||||
|
||||
|
@ -587,12 +587,14 @@ input[type="checkbox"] {
|
|||
}
|
||||
}
|
||||
|
||||
#account-settings {
|
||||
.custom-profile-fields-form .custom_user_field label {
|
||||
#profile-settings {
|
||||
.custom-profile-fields-form .custom_user_field label,
|
||||
.full-name-change-form label {
|
||||
min-width: fit-content;
|
||||
}
|
||||
|
||||
.alert-notification.custom-field-status {
|
||||
.alert-notification.custom-field-status,
|
||||
.alert-notification.full-name-status {
|
||||
padding-top: 0;
|
||||
padding-bottom: 0;
|
||||
margin-top: 0;
|
||||
|
@ -1511,7 +1513,6 @@ input[type="checkbox"] {
|
|||
width: 245px;
|
||||
}
|
||||
|
||||
#change_full_name_modal .change_full_name_info,
|
||||
#change_email_modal .change_email_info,
|
||||
#change_password_modal .change_password_info,
|
||||
#api_key_modal #api_key_status {
|
||||
|
@ -1519,7 +1520,7 @@ input[type="checkbox"] {
|
|||
}
|
||||
}
|
||||
|
||||
#account-settings,
|
||||
#profile-settings,
|
||||
#edit-user-form {
|
||||
.user-role button {
|
||||
cursor: default;
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
<div id="account-settings" class="settings-section show" data-name="your-account">
|
||||
<div id="account-settings" class="settings-section show" data-name="account-and-privacy">
|
||||
<div class="alert" id="dev-account-settings-status"></div>
|
||||
<div class="account-settings-form">
|
||||
<div class="inline-block">
|
||||
<div id="user_details_section">
|
||||
<h3 class="inline-block">{{t "User settings" }}</h3>
|
||||
<h3 class="inline-block">{{t "Account" }}</h3>
|
||||
<form class="email-change-form grid">
|
||||
<div class="alert-notification" id="account-settings-status"></div>
|
||||
<div class="input-group">
|
||||
|
@ -43,41 +43,6 @@
|
|||
</p>
|
||||
{{/if}}
|
||||
|
||||
<form class="form-horizontal full-name-change-form">
|
||||
<div class="input-group inline-block grid user-name-parent">
|
||||
<div class="user-name-section inline-block">
|
||||
<label for="full_name" class="inline-block title">{{t "Full name" }}</label>
|
||||
<button type="button" id='change_full_name' class="button btn-link small white rounded inline-block" id="full_name"
|
||||
{{#unless user_can_change_name}}disabled="disabled"{{/unless}}>
|
||||
<span id="full_name_value">{{page_params.full_name}}</span>
|
||||
<i class="fa fa-pencil"></i>
|
||||
</button>
|
||||
<i class="fa fa-question-circle change_name_tooltip tippy-zulip-tooltip settings-info-icon"
|
||||
{{#if user_can_change_name}}style="display:none"{{/if}}
|
||||
data-tippy-content="{{t 'Name changes are disabled in this organization. Contact an administrator to change your name.' }}">
|
||||
</i>
|
||||
</div>
|
||||
<div id="change_full_name_modal" class="modal modal-bg hide fade" tabindex="-1" role="dialog"
|
||||
aria-labelledby="change_full_name_modal_label" aria-hidden="true">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="{{t 'Close' }}"><span aria-hidden="true">×</span></button>
|
||||
<h3 class="inline-block" id="change_full_name_modal_label">{{t "Change full name" }}</h3>
|
||||
<div class="alert-notification change_full_name_info"></div>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="input-group full_name_change_container">
|
||||
<label for="email">{{t "New full name" }}</label>
|
||||
<input type="text" name="full_name" value="{{ page_params.full_name }}" autocomplete="off" spellcheck="false" autofocus="autofocus"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button class="button white rounded" type="button" data-dismiss="modal">{{t "Cancel" }}</button>
|
||||
<button id='change_full_name_button' class="button rounded sea-green" data-dismiss="modal">{{t "Change" }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<form class="password-change-form grid">
|
||||
{{#if page_params.realm_email_auth_enabled}}
|
||||
<div>
|
||||
|
@ -126,44 +91,14 @@
|
|||
<label for="user_role" class="inline-block title">{{t "Role" }}</label>
|
||||
<span>{{user_role_text}}</span>
|
||||
</div>
|
||||
|
||||
<form class="deactivate_account grid">
|
||||
<div class="input-group">
|
||||
<button type="submit" class="button rounded btn-danger" id="user_deactivate_account_button">
|
||||
{{t 'Deactivate account' }}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
<div class="input-group">
|
||||
<button type="submit" class="button rounded btn-danger" id="user_deactivate_account_button">
|
||||
{{t 'Deactivate account' }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="inline-block user-avatar-section">
|
||||
<h3>
|
||||
{{t "Profile picture" }}
|
||||
<i class="fa fa-question-circle change_name_tooltip tippy-zulip-tooltip settings-info-icon"
|
||||
{{#if user_can_change_avatar}}style="display:none"{{/if}}
|
||||
data-tippy-content="{{t 'Avatar changes are disabled in this organization.' }}">
|
||||
</i>
|
||||
</h3>
|
||||
{{> image_upload_widget
|
||||
widget = "user-avatar"
|
||||
upload_text = (t "Upload new profile picture")
|
||||
delete_text = (t "Delete profile picture")
|
||||
is_editable_by_current_user = user_can_change_avatar
|
||||
image = page_params.avatar_url_medium}}
|
||||
<div id="user-avatar-source">
|
||||
<a href="https://en.gravatar.com/" target="_blank" rel="noopener noreferrer">{{t "Avatar from Gravatar" }}</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="clear-float"></div>
|
||||
|
||||
<h3 class="inline-block" id="custom-field-header" {{#unless page_params.custom_profile_fields}}style="display: none"{{/unless}}>{{t "Profile" }}</h3>
|
||||
<form class="form-horizontal custom-profile-fields-form grid"></form>
|
||||
<button class="button rounded sea-green w-200 block" id="show_my_user_profile_modal">
|
||||
{{t 'Preview profile' }}
|
||||
<i class="fa fa-external-link" aria-hidden="true" title="{{t 'Preview profile' }}"></i>
|
||||
</button>
|
||||
|
||||
<hr class="settings_separator" />
|
||||
|
||||
<div class="form-horizontal" id="api_key_button_box">
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
<div id="profile-settings" class="settings-section show" data-name="profile">
|
||||
<div class="profile-settings-form">
|
||||
<div class="inline-block">
|
||||
<h3 class="inline-block hide" id="user-profile-header">{{t "Profile" }}</h3>
|
||||
<div id="user_details_section">
|
||||
<form class="form-horizontal full-name-change-form">
|
||||
<div class="input-group inline-block grid user-name-parent">
|
||||
<div class="user-name-section inline-block">
|
||||
<label for="full_name" class="title inline-block">{{t "Full name" }}</label>
|
||||
<i class="fa fa-question-circle change_name_tooltip tippy-zulip-tooltip settings-info-icon"
|
||||
{{#if user_can_change_name}}style="display:none"{{/if}}
|
||||
data-tippy-content="{{t 'Name changes are disabled in this organization. Contact an administrator to change your name.' }}">
|
||||
</i>
|
||||
<div class="alert-notification full-name-status"></div>
|
||||
<div class="name-input">
|
||||
<input id="full_name" name="full_name" type="text" value="{{ page_params.full_name }}" {{#unless user_can_change_name}}disabled="disabled"{{/unless}} maxlength="60" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<form class="form-horizontal custom-profile-fields-form grid"></form>
|
||||
<button class="button rounded sea-green w-200 block" id="show_my_user_profile_modal">
|
||||
{{t 'Preview profile' }}
|
||||
<i class="fa fa-external-link" aria-hidden="true" title="{{t 'Preview profile' }}"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="inline-block user-avatar-section">
|
||||
<h3>
|
||||
{{t "Profile picture" }}
|
||||
<i class="fa fa-question-circle change_name_tooltip tippy-zulip-tooltip settings-info-icon"
|
||||
{{#if user_can_change_avatar}}style="display:none"{{/if}}
|
||||
data-tippy-content="{{t 'Avatar changes are disabled in this organization.' }}">
|
||||
</i>
|
||||
</h3>
|
||||
{{> image_upload_widget
|
||||
widget = "user-avatar"
|
||||
upload_text = (t "Upload new profile picture")
|
||||
delete_text = (t "Delete profile picture")
|
||||
is_editable_by_current_user = user_can_change_avatar
|
||||
image = page_params.avatar_url_medium}}
|
||||
<div id="user-avatar-source">
|
||||
<a href="https://en.gravatar.com/" target="_blank" rel="noopener noreferrer">{{t "Avatar from Gravatar" }}</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
|
@ -1,4 +1,6 @@
|
|||
<div id="settings-change-box" class="new-style">
|
||||
{{> settings/profile_settings }}
|
||||
|
||||
{{> settings/account_settings }}
|
||||
|
||||
{{> settings/display_settings }}
|
||||
|
|
|
@ -129,7 +129,7 @@
|
|||
{{/unless}}
|
||||
{{#if is_me}}
|
||||
<li>
|
||||
<a href="/#settings/your-account">
|
||||
<a href="/#settings/profile">
|
||||
<i class="fa fa-edit" aria-hidden="true"></i> {{#tr}}Edit your profile{{/tr}}
|
||||
</a>
|
||||
</li>
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<div id="name">
|
||||
{{full_name}}
|
||||
{{#if is_me}}
|
||||
<a href="/#settings/your-account">
|
||||
<a href="/#settings/profile">
|
||||
<i class="fa fa-edit" id="edit-button" aria-hidden="true"></i>
|
||||
</a>
|
||||
{{/if}}
|
||||
|
|
|
@ -11,9 +11,13 @@
|
|||
<div class="sidebar-list dark-grey small-text">
|
||||
<div class="center tab-container"></div>
|
||||
<ul class="normal-settings-list">
|
||||
<li tabindex="0" data-section="your-account">
|
||||
<li tabindex="0" data-section="profile">
|
||||
<i class="icon fa fa-user" aria-hidden="true"></i>
|
||||
<div class="text">{{ _('Your account') }}</div>
|
||||
<div class="text">{{ _('Profile') }}</div>
|
||||
</li>
|
||||
<li tabindex="0" data-section="account-and-privacy">
|
||||
<i class="icon fa fa-lock" aria-hidden="true"></i>
|
||||
<div class="text">{{ _('Account & privacy') }}</div>
|
||||
</li>
|
||||
<li tabindex="0" data-section="display-settings">
|
||||
<i class="icon fa fa-clock-o" aria-hidden="true"></i>
|
||||
|
|
Loading…
Reference in New Issue