[UI] Improved notification links (#13159)

Handle internal notification links which are stored as a fully qualified URL. These can now be routed internally rather than reloading the whole page
This commit is contained in:
Oliver authored and GitHub committed 2026-11-02 14:47:24 +11:00
1 parent dcec25f777
commit b4cdbf3d07
2 files changed
+52 -2

No files matched your search

@@ -63,6 +63,24 @@ function NotificationEntry({
}
const base = `/${getBaseUrl()}`;
// The backend may provide an absolute URL (e.g. https://host/web/part/1/)
// If it points to a page within this frontend, reduce it to a path,
// so that it can be routed internally rather than reloading the page
if (link && !link.startsWith('/')) {
try {
const url = new URL(link);
if (
url.origin === window.location.origin &&
url.pathname.startsWith(`${base}/`)
) {
link = `${url.pathname}${url.search}${url.hash}`;
}
} catch {
// Not a valid URL - leave as-is
}
}
const href =
link?.startsWith('/') && !link.startsWith(base) ? `${base}${link}` : link;
+34 -2
View File
@@ -62,14 +62,32 @@ test('Notifications - link targets', async ({ page }) => {
return;
}
// Absolute link to a page on the same server (as provided by the backend)
const origin = new URL(page.url()).origin;
const results = [
...notifications,
{
...notifications[1],
pk: 4,
target: {
...notifications[1].target,
link: `${origin}/web/part/category/index/`
},
category: 'test_absolute',
name: 'Absolute Notification',
message: 'Absolute notification link'
}
];
await route.fulfill({
status: 200,
contentType: 'application/json',
body: JSON.stringify({
count: notifications.length,
count: results.length,
next: null,
previous: null,
results: notifications
results: results
})
});
});
@@ -89,4 +107,18 @@ test('Notifications - link targets', async ({ page }) => {
await expect(
page.getByRole('link', { name: 'Base Notification' })
).toHaveAttribute('href', '/web/settings/admin/');
await expect(
page.getByRole('link', { name: 'Absolute Notification' })
).toHaveAttribute('href', '/web/part/category/index/');
// Clicking an internal link should route within the app (no page reload)
await page.evaluate(() => {
(window as any).__noReload = true;
});
await page.getByRole('link', { name: 'Absolute Notification' }).click();
await page.waitForURL('**/web/part/category/index/**');
expect(await page.evaluate(() => (window as any).__noReload)).toBe(true);
});