Skip to content
Snippets Groups Projects
Commit 052ef866 authored by Reiter, Christoph's avatar Reiter, Christoph :snake:
Browse files

Merge branch 'router-lax' into 'master'

app-shell: allow trailing paths in the router

See merge request !179
parents 212ad03e f5581c78
No related branches found
No related tags found
1 merge request!179app-shell: allow trailing paths in the router
Pipeline #106388 passed
...@@ -62,6 +62,7 @@ export class AppShell extends ScopedElementsMixin(DBPLitElement) { ...@@ -62,6 +62,7 @@ export class AppShell extends ScopedElementsMixin(DBPLitElement) {
this._roles = []; this._roles = [];
this._i18n = createInstance(); this._i18n = createInstance();
this.lang = this._i18n.language; this.lang = this._i18n.language;
this._extra = [];
this.matomoUrl = ''; this.matomoUrl = '';
this.matomoSiteId = -1; this.matomoSiteId = -1;
...@@ -179,6 +180,7 @@ export class AppShell extends ScopedElementsMixin(DBPLitElement) { ...@@ -179,6 +180,7 @@ export class AppShell extends ScopedElementsMixin(DBPLitElement) {
return { return {
lang: this.lang, lang: this.lang,
component: '', component: '',
extra: [],
}; };
}, },
}, },
...@@ -191,18 +193,20 @@ export class AppShell extends ScopedElementsMixin(DBPLitElement) { ...@@ -191,18 +193,20 @@ export class AppShell extends ScopedElementsMixin(DBPLitElement) {
return { return {
lang: params.lang, lang: params.lang,
component: '', component: '',
extra: [],
}; };
}, },
}, },
{ {
name: 'mainRoute', name: 'mainRoute',
path: '/:component', path: ['/:component', '/:component/(.*)'],
action: (context, params) => { action: (context, params) => {
// remove the additional parameters added by Keycloak let componentTag = params.component.toLowerCase();
let componentTag = params.component.toLowerCase().replace(/&.+/, ''); let extra = params[0] ? params[0].split('/') : [];
return { return {
lang: params.lang, lang: params.lang,
component: componentTag, component: componentTag,
extra: extra,
}; };
}, },
}, },
...@@ -218,17 +222,20 @@ export class AppShell extends ScopedElementsMixin(DBPLitElement) { ...@@ -218,17 +222,20 @@ export class AppShell extends ScopedElementsMixin(DBPLitElement) {
let state = { let state = {
component: this.activeView, component: this.activeView,
lang: this.lang, lang: this.lang,
extra: this._extra,
}; };
return state; return state;
}, },
setState: (state) => { setState: (state) => {
this.updateLangIfChanged(state.lang); this.updateLangIfChanged(state.lang);
this.switchComponent(state.component); this.switchComponent(state.component);
this._extra = state.extra;
}, },
getDefaultState: () => { getDefaultState: () => {
return { return {
lang: 'de', lang: 'de',
component: this.routes[0], component: this.routes[0],
extra: [],
}; };
}, },
}, },
...@@ -270,8 +277,10 @@ export class AppShell extends ScopedElementsMixin(DBPLitElement) { ...@@ -270,8 +277,10 @@ export class AppShell extends ScopedElementsMixin(DBPLitElement) {
connectedCallback() { connectedCallback() {
super.connectedCallback(); super.connectedCallback();
if (this.src) this.fetchMetadata(this.src);
this.initRouter(); this.initRouter();
if (this.src) {
this.fetchMetadata(this.src);
}
} }
/** /**
......
...@@ -61,7 +61,7 @@ class AppShellWelcome extends ScopedElementsMixin(LitElement) { ...@@ -61,7 +61,7 @@ class AppShellWelcome extends ScopedElementsMixin(LitElement) {
cursor: pointer; cursor: pointer;
text-decoration: none; text-decoration: none;
} }
h2 a { h2 a {
white-space: nowrap; white-space: nowrap;
} }
......
import UniversalRouter from 'universal-router'; import UniversalRouter from 'universal-router';
import generateUrls from 'universal-router/generateUrls'; import generateUrls from 'universal-router/generateUrls';
function stateMatches(a, b) {
return JSON.stringify(a, Object.keys(a).sort()) === JSON.stringify(b, Object.keys(b).sort());
}
/** /**
* A wrapper around UniversalRouter which adds history integration * A wrapper around UniversalRouter which adds history integration
*/ */
...@@ -31,28 +35,24 @@ export class Router { ...@@ -31,28 +35,24 @@ export class Router {
window.addEventListener('popstate', (event) => { window.addEventListener('popstate', (event) => {
this.setStateFromCurrentLocation(); this.setStateFromCurrentLocation();
this.dispatchLocationChanged(); this._dispatchLocationChanged();
}); });
} }
async _getStateForPath(pathname) {
let isBasePath = pathname.replace(/\/$/, '') === this.router.baseUrl.replace(/\/$/, '');
if (isBasePath) {
return this.getDefaultState();
}
return this.router.resolve({pathname: pathname});
}
/** /**
* In case something else has changed the location, update the app state accordingly. * In case something else has changed the location, update the app state accordingly.
*/ */
setStateFromCurrentLocation() { setStateFromCurrentLocation() {
const oldPathName = location.pathname; this._getStateForPath(location.pathname)
this.router
.resolve({pathname: oldPathName})
.then((page) => { .then((page) => {
const newPathname = this.getPathname(page);
// In case of a router redirect, set the new location
if (newPathname !== oldPathName) {
const referrerUrl = location.href;
window.history.replaceState({}, '', newPathname);
this.dispatchLocationChanged(referrerUrl);
} else if (this.isBasePath(oldPathName)) {
page = this.getDefaultState();
}
this.setState(page); this.setState(page);
}) })
.catch((e) => { .catch((e) => {
...@@ -61,10 +61,6 @@ export class Router { ...@@ -61,10 +61,6 @@ export class Router {
}); });
} }
isBasePath(pathname) {
return pathname.replace(/\/$/, '') === this.router.baseUrl.replace(/\/$/, '');
}
/** /**
* Update the router after some internal state change. * Update the router after some internal state change.
*/ */
...@@ -72,18 +68,21 @@ export class Router { ...@@ -72,18 +68,21 @@ export class Router {
// Queue updates so we can call this multiple times when changing state // Queue updates so we can call this multiple times when changing state
// without it resulting in multiple location changes // without it resulting in multiple location changes
setTimeout(() => { setTimeout(() => {
const newPathname = this.getPathname(); this._getStateForPath(location.pathname)
const oldPathname = location.pathname; .then((page) => {
if (newPathname === oldPathname) return; const newState = this.getState();
// if the state has changed we update
const defaultPathname = this.getPathname(this.getDefaultState()); if (!stateMatches(newState, page)) {
if (newPathname === defaultPathname && this.isBasePath(oldPathname)) { const newPathname = this.getPathname();
return; const referrerUrl = location.href;
} window.history.pushState({}, '', newPathname);
this._dispatchLocationChanged(referrerUrl);
const referrerUrl = location.href; }
window.history.pushState({}, '', newPathname); })
this.dispatchLocationChanged(referrerUrl); .catch((e) => {
// In case we can't resolve the location, just leave things as is.
// This happens when a user enters a wrong URL or when testing with karma.
});
}); });
} }
...@@ -93,14 +92,15 @@ export class Router { ...@@ -93,14 +92,15 @@ export class Router {
* @param {string} pathname * @param {string} pathname
*/ */
updateFromPathname(pathname) { updateFromPathname(pathname) {
this.router this._getStateForPath(pathname)
.resolve({pathname: pathname})
.then((page) => { .then((page) => {
if (location.pathname === pathname) return; const oldState = this.getState();
const referrerUrl = location.href; if (!stateMatches(oldState, page)) {
window.history.pushState({}, '', pathname); const referrerUrl = location.href;
this.setState(page); window.history.pushState({}, '', pathname);
this.dispatchLocationChanged(referrerUrl); this.setState(page);
this._dispatchLocationChanged(referrerUrl);
}
}) })
.catch((err) => { .catch((err) => {
throw new Error(`Route not found: ${pathname}: ${err}`); throw new Error(`Route not found: ${pathname}: ${err}`);
...@@ -117,7 +117,9 @@ export class Router { ...@@ -117,7 +117,9 @@ export class Router {
*/ */
getPathname(partialState) { getPathname(partialState) {
const currentState = this.getState(); const currentState = this.getState();
if (partialState === undefined) partialState = {}; if (partialState === undefined) {
partialState = {};
}
let combined = {...currentState, ...partialState}; let combined = {...currentState, ...partialState};
try { try {
...@@ -128,7 +130,7 @@ export class Router { ...@@ -128,7 +130,7 @@ export class Router {
} }
} }
dispatchLocationChanged(referrerUrl = '') { _dispatchLocationChanged(referrerUrl = '') {
// fire a locationchanged event // fire a locationchanged event
window.dispatchEvent( window.dispatchEvent(
new CustomEvent('locationchanged', { new CustomEvent('locationchanged', {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment