static: add argument support to Router and add RouteMatch

This commit is contained in:
Jens Langhammer 2020-11-26 13:58:45 +01:00
parent 1432f0648f
commit feabd38173
3 changed files with 49 additions and 17 deletions
passbook/static/static

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -24,7 +24,7 @@ export class Route {
url: RegExp;
private element?: TemplateResult;
private callback?: () => TemplateResult;
private callback?: (args: { [key: string]: string; }) => TemplateResult;
constructor(url: RegExp, element?: TemplateResult) {
this.url = url;
@ -40,9 +40,14 @@ export class Route {
return this;
}
render(): TemplateResult {
then(render: (args: { [key: string]: string; }) => TemplateResult): Route {
this.callback = render;
return this;
}
render(args: { [key: string]: string; }): TemplateResult {
if (this.callback) {
return this.callback();
return this.callback(args);
}
if (this.element) {
return this.element;
@ -51,16 +56,36 @@ export class Route {
}
}
export const SLUG_REGEX = "[-a-zA-Z0-9_]+";
export const ROUTES: Route[] = [
// Prevent infinite Shell loops
new Route(new RegExp("^/$")).redirect("/-/overview/"),
new Route(new RegExp("^/applications/$"), html`<h1>test</h1>`),
new Route(new RegExp(`^/$`)).redirect("/-/overview/"),
new Route(new RegExp(`^/applications/$`), html`<h1>test</h1>`),
new Route(new RegExp(`^/-/applications/(?<slug>${SLUG_REGEX})/$`)).then((args) => {
return html`<h1>test</h1>
<span>${args.slug}</span>`;
}),
];
class RouteMatch {
route: Route;
arguments?: RegExpExecArray;
fullUrl?: string;
constructor(route: Route) {
this.route = route;
}
render(): TemplateResult {
return this.route.render(this.arguments!.groups || {});
}
}
@customElement("pb-router-outlet")
export class RouterOutlet extends LitElement {
@property()
activeRoute?: Route;
current?: RouteMatch;
@property()
defaultUrl?: string;
@ -98,28 +123,35 @@ export class RouterOutlet extends LitElement {
window.location.hash = `#${activeUrl}`;
return;
}
let selectedRoute: Route | null = null;
let matchedRoute: RouteMatch | null = null;
ROUTES.forEach((route) => {
if (route.url.exec(activeUrl)) {
selectedRoute = route;
console.log(`matching ${activeUrl} against ${route.url}`);
const match = route.url.exec(activeUrl);
if (match != null) {
matchedRoute = new RouteMatch(route);
matchedRoute.arguments = match;
matchedRoute.fullUrl = activeUrl;
return;
}
});
if (!selectedRoute) {
if (!matchedRoute) {
console.log(
`passbook/router: route "${activeUrl}" not defined, defaulting to shell`
);
selectedRoute = new Route(
const route = new Route(
RegExp(""),
html`<pb-site-shell url=${activeUrl}>
<div slot="body"></div>
</pb-site-shell>`
);
matchedRoute = new RouteMatch(route);
matchedRoute.arguments = route.url.exec(activeUrl)!;
matchedRoute.fullUrl = activeUrl;
}
this.activeRoute = selectedRoute;
this.current = matchedRoute;
}
render() {
return this.activeRoute?.render();
return this.current?.render();
}
}