Preserve originating views through detail navigation
This commit is contained in:
@@ -0,0 +1,35 @@
|
||||
const origin = 'https://electric-cherry.invalid';
|
||||
const pagePath = /^\/(?:$|operations|account|capacity|metrics|server-keys|settings(?:\/users)?|servers\/[^/]+|hosts(?:\/[^/]+)?|collections(?:\/launches\/[^/]+)?|(?:scripts|configs|plugins|betas|campaigns|maintenance|provisioning|matches)(?:\/[^/]+)?|game-files|leaderboard(?:\/players\/[^/]+(?:\/[^/]+)?)?)$/;
|
||||
|
||||
/** Only return to application pages, never an external URL or a mutation/API endpoint. */
|
||||
export function safeReturnHref(value: string | null | undefined, fallback: string): string {
|
||||
if (!value || value.length > 12000 || !value.startsWith('/') || value.startsWith('//') || /[\\\x00-\x1f\x7f]/.test(value)) return fallback;
|
||||
try {
|
||||
const url = new URL(value, origin);
|
||||
if (url.origin !== origin || !pagePath.test(url.pathname)) return fallback;
|
||||
return url.pathname + url.search + url.hash;
|
||||
} catch { return fallback; }
|
||||
}
|
||||
|
||||
export function contextHref(destination: string, source: URL | string): string {
|
||||
const current = source instanceof URL ? source.pathname + source.search + source.hash : source;
|
||||
const url = new URL(destination, origin);
|
||||
const returnTo = safeReturnHref(current, '/');
|
||||
url.searchParams.set('returnTo', returnTo);
|
||||
return url.pathname + url.search + url.hash;
|
||||
}
|
||||
|
||||
export function returnLabel(href: string): string {
|
||||
const url = new URL(href, origin);
|
||||
const path = url.pathname;
|
||||
if (path.startsWith('/servers/')) return 'Back to server';
|
||||
if (path.startsWith('/leaderboard/players/')) return 'Back to player';
|
||||
if (path.startsWith('/collections/launches/')) return 'Back to collection launch';
|
||||
if (path === '/collections' && url.searchParams.get('view') === 'active') return 'Back to active launches';
|
||||
if (path === '/collections' && url.searchParams.get('view') === 'history') return 'Back to launch history';
|
||||
if (path.startsWith('/matches/')) return 'Back to match';
|
||||
if (path === '/hosts/operations') return 'Back to host operation history';
|
||||
if (path.startsWith('/hosts/')) return 'Back to host';
|
||||
const names: Record<string, string> = { '': 'Fleet', operations: 'Operations', collections: 'Collections', hosts: 'Hosts', capacity: 'Capacity', scripts: 'Scripts', configs: 'Configs', plugins: 'Plugins', 'game-files': 'Game Files', betas: 'Betas', campaigns: 'Campaigns', maintenance: 'Maintenance', provisioning: 'Provisioning', leaderboard: 'Leaderboard', matches: 'Match History', metrics: 'Metrics' };
|
||||
return `Back to ${names[path.split('/')[1]] ?? 'previous page'}`;
|
||||
}
|
||||
Reference in New Issue
Block a user