Skip to content

Commit 0832d05

Browse files
fix: prefix external nav links inside mapNavOptions so home tile + footer + sidebar also use env.host (#87 follow-up)
The earlier resolveExternalLinks lived only on NavigationBarComponent, but thirteen other components (home-api-data, info-footer, sidebar, home-help, etc.) each independently re-import nav-options.json and call mapNavOptions without ever prepending the host. So the homepage "API and Data Access" tile and the info-footer's "Tools" column both kept rendering `/AnalysisService` and `/ContentService` as relative paths, which on prod still bounce to the legacy Joomla chrome. Move the host-prefixing into mapNavOptions itself so all callers get it for free. Drop the now-redundant resolveExternalLinks helper. Verified with chromium --headless --dump-dom: external links now render as https://dev.reactome.org/AnalysisService etc. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 01ada90 commit 0832d05

2 files changed

Lines changed: 18 additions & 35 deletions

File tree

projects/website-angular/src/app/navigation-bar/navigation-bar.component.ts

Lines changed: 0 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import { FormsModule } from '@angular/forms';
77
import { mapNavOptions } from '../../utils/nav-options-mapper';
88
import { NavLink, NavOption } from '../../types/link';
99
import { DarkService } from '../../../../pathway-browser/src/app/services/dark.service';
10-
import { environment } from '../../../../pathway-browser/src/environments/environment';
1110

1211
@Component({
1312
standalone: true,
@@ -50,31 +49,9 @@ export class NavigationBarComponent implements OnInit, AfterViewInit {
5049
loadNavOptions() {
5150
import('../../config/nav-options.json').then((navData) => {
5251
this.navOptions = mapNavOptions(navData.default);
53-
this.resolveExternalLinks(environment.host);
5452
});
5553
}
5654

57-
/**
58-
* Prepend baseUrl to external links so they resolve to the correct domain
59-
*/
60-
private resolveExternalLinks(baseUrl: string) {
61-
const resolve = (links: Record<string, NavLink> | undefined) => {
62-
if (!links) return;
63-
for (const link of Object.values(links)) {
64-
if (link.external) {
65-
link.link = baseUrl + link.link;
66-
}
67-
resolve(link.dropdownLinks);
68-
}
69-
};
70-
for (const option of Object.values(this.navOptions)) {
71-
if (option.external) {
72-
option.link = baseUrl + option.link;
73-
}
74-
resolve(option.dropdownLinks);
75-
}
76-
}
77-
7855
toggleHamburgerMenu() {
7956
this.activeHamburgerMenu = !this.activeHamburgerMenu;
8057
}
Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,28 @@
11
import {NavLink, NavOption} from "../types/link";
2+
import { environment } from "../../../pathway-browser/src/environments/environment";
3+
4+
// Links marked external: true in nav-options.json point at WAR endpoints
5+
// (/AnalysisService, /ContentService, ...) and need the active host
6+
// prepended; otherwise they resolve relative to the current page and on
7+
// hosts where Apache wraps those paths in legacy chrome the user gets
8+
// bounced out of the new site. See issue #87.
9+
function resolveLink(link: string, external: boolean): string {
10+
return external ? `${environment.host}${link}` : link;
11+
}
212

3-
/**
4-
* Recursively maps JSON dropdown-links to typed NavLink objects
5-
*/
613
function mapDropdownLinks(raw: any): Record<string, NavLink> | undefined {
714
if (!raw || typeof raw !== 'object') {
815
return undefined;
916
}
10-
17+
1118
const mapped: Record<string, NavLink> = {};
1219
Object.entries(raw).forEach(([key, value]: [string, any]) => {
1320
if (value && typeof value === 'object') {
21+
const external = value.external || false;
1422
mapped[key] = {
1523
label: value.label || '',
16-
link: value.link || '',
17-
external: value.external || false,
24+
link: resolveLink(value.link || '', external),
25+
external,
1826
dropdownLinks: mapDropdownLinks(value['dropdown-links'])
1927
};
2028
}
@@ -23,23 +31,21 @@ function mapDropdownLinks(raw: any): Record<string, NavLink> | undefined {
2331
return Object.keys(mapped).length > 0 ? mapped : undefined;
2432
}
2533

26-
/**
27-
* Maps nav-options JSON (with dropdown-links) to typed NavOption objects (with dropdownLinks)
28-
*/
2934
export function mapNavOptions(raw: Record<string, any>): Record<string, NavOption> {
3035
const mapped: Record<string, NavOption> = {};
3136

3237
Object.entries(raw).forEach(([key, value]: [string, any]) => {
3338
if (value && typeof value === 'object') {
39+
const external = value.external || false;
3440
mapped[key] = {
3541
label: value.label || '',
36-
link: value.link || '',
42+
link: resolveLink(value.link || '', external),
3743
icon: value.icon,
38-
external: value.external || false,
44+
external,
3945
dropdownLinks: mapDropdownLinks(value['dropdown-links'])
4046
};
4147
}
4248
});
43-
49+
4450
return mapped;
4551
}

0 commit comments

Comments
 (0)