settings: Allow switching between user and org settings manually.

Since the base hash for org settings and user settings are
different (organization and settings), the hashchange module
gets confused that we are going from one overlay to other.

A reproducer for this flow is to visit the organization "Bots" page,
click on your own profile as the owner of a bot, and then click "Edit
profile" from there.

So, we fix this by making an exception for this particular case
in the module.

Fixes part of #18011.
This commit is contained in:
Aman Agrawal 2021-03-16 06:22:28 +00:00 committed by Tim Abbott
parent cd62b40f20
commit eb72f77d0a
4 changed files with 41 additions and 1 deletions

View File

@ -3,6 +3,7 @@
const {strict: assert} = require("assert"); const {strict: assert} = require("assert");
const {set_global, zrequire} = require("../zjsunit/namespace"); const {set_global, zrequire} = require("../zjsunit/namespace");
const {make_stub} = require("../zjsunit/stub");
const {run_test} = require("../zjsunit/test"); const {run_test} = require("../zjsunit/test");
const blueslip = require("../zjsunit/zblueslip"); const blueslip = require("../zjsunit/zblueslip");
@ -49,3 +50,20 @@ test("error for bad hashes", () => {
blueslip.expect("error", "programming error: prefix hashes with #: bogus"); blueslip.expect("error", "programming error: prefix hashes with #: bogus");
browser_history.update(hash); browser_history.update(hash);
}); });
test("update internal hash if required", (override) => {
const hash = "#test/hash";
const stub = make_stub();
override(browser_history, "update", stub.f);
browser_history.update_hash_internally_if_required(hash);
assert.equal(stub.num_calls, 1);
location.hash = "#test/hash";
// update with same hash
browser_history.update_hash_internally_if_required(hash);
// but no update was made since the
// hash was already updated.
// Evident by no increase in number of
// calls to stub.
assert.equal(stub.num_calls, 1);
});

View File

@ -66,3 +66,9 @@ export function go_to_location(hash) {
// function to run. // function to run.
window.location.hash = hash; window.location.hash = hash;
} }
export function update_hash_internally_if_required(hash) {
if (window.location.hash !== hash) {
update(hash);
}
}

View File

@ -18,6 +18,7 @@ import * as recent_topics from "./recent_topics";
import * as search from "./search"; import * as search from "./search";
import * as settings from "./settings"; import * as settings from "./settings";
import * as settings_panel_menu from "./settings_panel_menu"; import * as settings_panel_menu from "./settings_panel_menu";
import * as settings_toggle from "./settings_toggle";
import * as subs from "./subs"; import * as subs from "./subs";
import * as top_left_corner from "./top_left_corner"; import * as top_left_corner from "./top_left_corner";
import * as ui_util from "./ui_util"; import * as ui_util from "./ui_util";
@ -211,6 +212,19 @@ function do_hashchange_overlay(old_hash) {
return; return;
} }
// This is a special case when user clicks on a URL that makes the overlay switch
// from org settings to user settings or user edits the URL to switch between them.
const settings_hashes = new Set(["settings", "organization"]);
// Ensure that we are just switching between user and org settings and the settings
// overlay is open.
const is_hashchange_internal =
settings_hashes.has(base) && settings_hashes.has(old_base) && overlays.settings_open();
if (is_hashchange_internal) {
settings_toggle.highlight_toggle(base);
settings_panel_menu.normal_settings.activate_section_or_default(section);
return;
}
// It's not super likely that an overlay is already open, // It's not super likely that an overlay is already open,
// but you can jump from /settings to /streams by using // but you can jump from /settings to /streams by using
// the browser's history menu or hand-editing the URL or // the browser's history menu or hand-editing the URL or

View File

@ -114,7 +114,9 @@ export class SettingsPanelMenu {
this.curr_li.addClass("active"); this.curr_li.addClass("active");
const settings_section_hash = "#" + this.hash_prefix + section; const settings_section_hash = "#" + this.hash_prefix + section;
browser_history.update(settings_section_hash);
// It could be that the hash has already been set.
browser_history.update_hash_internally_if_required(settings_section_hash);
$(".settings-section").removeClass("show"); $(".settings-section").removeClass("show");