web: improve file structure, separate routes from outlet

This commit is contained in:
Jens Langhammer 2020-12-01 17:41:27 +01:00
parent e6391b64f0
commit 8c8ff4643a
9 changed files with 103 additions and 85 deletions

View File

@ -32,7 +32,7 @@ export const SIDEBAR_ITEMS: SidebarItem[] = [
children: [ children: [
{ {
name: "Overview", name: "Overview",
path: ["/administration/overview/"], path: ["/administration/overview-ng/"],
}, },
{ {
name: "System Tasks", name: "System Tasks",

View File

@ -1,23 +1,29 @@
import "construct-style-sheets-polyfill"; import "construct-style-sheets-polyfill";
import "./elements/AdminLoginsChart";
import "./elements/buttons/ActionButton"; import "./elements/buttons/ActionButton";
import "./elements/buttons/Dropdown"; import "./elements/buttons/Dropdown";
import "./elements/buttons/ModalButton"; import "./elements/buttons/ModalButton";
import "./elements/buttons/SpinnerButton"; import "./elements/buttons/SpinnerButton";
import "./elements/buttons/TokenCopyButton"; import "./elements/buttons/TokenCopyButton";
import "./elements/CodeMirror";
import "./elements/Messages";
import "./elements/sidebar/Sidebar"; import "./elements/sidebar/Sidebar";
import "./elements/sidebar/SidebarBrand"; import "./elements/sidebar/SidebarBrand";
import "./elements/sidebar/SidebarUser"; import "./elements/sidebar/SidebarUser";
import "./elements/Tabs";
import "./elements/Spinner";
import "./elements/table/TablePagination"; import "./elements/table/TablePagination";
import "./pages/applications/ApplicationViewPage";
import "./pages/applications/ApplicationListPage"; import "./elements/AdminLoginsChart";
import "./elements/CodeMirror";
import "./elements/Messages";
import "./elements/Spinner";
import "./elements/Tabs";
import "./pages/generic/FlowShellCard";
import "./pages/generic/SiteShell";
import "./pages/router/RouterOutlet";
import "./pages/AdminOverviewPage"; import "./pages/AdminOverviewPage";
import "./pages/applications/ApplicationListPage";
import "./pages/applications/ApplicationViewPage";
import "./pages/LibraryPage"; import "./pages/LibraryPage";
import "./pages/FlowShellCard";
import "./pages/RouterOutlet";
import "./pages/SiteShell";

View File

@ -15,6 +15,9 @@ export class ApplicationViewPage extends LitElement {
img.pf-icon { img.pf-icon {
max-height: 24px; max-height: 24px;
} }
.pf-c-avatar {
--pf-c-avatar--BorderRadius: 0;
}
` `
); );
} }

View File

@ -0,0 +1,43 @@
import { html, TemplateResult } from "lit-html";
export const SLUG_REGEX = "[-a-zA-Z0-9_]+";
export class Route {
url: RegExp;
private element?: TemplateResult;
private callback?: (args: { [key: string]: string }) => TemplateResult;
constructor(url: RegExp, element?: TemplateResult) {
this.url = url;
this.element = element;
}
redirect(to: string): Route {
this.callback = () => {
console.debug(`passbook/router: redirecting ${to}`);
window.location.hash = `#${to}`;
return html``;
};
return this;
}
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(args);
}
if (this.element) {
return this.element;
}
throw new Error("Route does not have callback or element");
}
toString(): string {
return `<Route url=${this.url} callback=${this.callback ? "true" : "false"}>`;
}
}

View File

@ -0,0 +1,21 @@
import { TemplateResult } from "lit-html";
import { Route } from "./Route";
export class RouteMatch {
route: Route;
arguments: { [key: string]: string; };
fullUrl?: string;
constructor(route: Route) {
this.route = route;
this.arguments = {};
}
render(): TemplateResult {
return this.route.render(this.arguments);
}
toString(): string {
return `<RouteMatch url=${this.fullUrl} route=${this.route} arguments=${this.arguments}>`;
}
}

View File

@ -3,80 +3,11 @@ import { css, CSSResult, customElement, html, LitElement, property, TemplateResu
import CodeMirrorStyle from "codemirror/lib/codemirror.css"; import CodeMirrorStyle from "codemirror/lib/codemirror.css";
// @ts-ignore // @ts-ignore
import CodeMirrorTheme from "codemirror/theme/monokai.css"; import CodeMirrorTheme from "codemirror/theme/monokai.css";
import { ColorStyles } from "../constants"; import { ColorStyles } from "../../constants";
import { COMMON_STYLES } from "../common/styles"; import { COMMON_STYLES } from "../../common/styles";
import { Route } from "./Route";
export class Route { import { ROUTES } from "../../routes";
url: RegExp; import { RouteMatch } from "./RouteMatch";
private element?: TemplateResult;
private callback?: (args: { [key: string]: string }) => TemplateResult;
constructor(url: RegExp, element?: TemplateResult) {
this.url = url;
this.element = element;
}
redirect(to: string): Route {
this.callback = () => {
console.debug(`passbook/router: redirecting ${to}`);
window.location.hash = `#${to}`;
return html``;
};
return this;
}
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(args);
}
if (this.element) {
return this.element;
}
throw new Error("Route does not have callback or element");
}
toString(): string {
return `<Route url=${this.url} callback=${this.callback ? "true" : "false"}>`;
}
}
export const SLUG_REGEX = "[-a-zA-Z0-9_]+";
export const ROUTES: Route[] = [
// Prevent infinite Shell loops
new Route(new RegExp("^/$")).redirect("/library/"),
new Route(new RegExp("^#.*")).redirect("/library/"),
new Route(new RegExp("^/library/$"), html`<pb-library></pb-library>`),
new Route(new RegExp("^/administration/overview/$"), html`<pb-admin-overview></pb-admin-overview>`),
new Route(new RegExp("^/applications/$"), html`<pb-application-list></pb-application-list>`),
new Route(new RegExp(`^/applications/(?<slug>${SLUG_REGEX})/$`)).then((args) => {
return html`<pb-application-view .args=${args}></pb-application-view>`;
}),
];
class RouteMatch {
route: Route;
arguments: { [key: string]: string; };
fullUrl?: string;
constructor(route: Route) {
this.route = route;
this.arguments = {};
}
render(): TemplateResult {
return this.route.render(this.arguments);
}
toString(): string {
return `<RouteMatch url=${this.fullUrl} route=${this.route} arguments=${this.arguments}>`;
}
}
@customElement("pb-router-outlet") @customElement("pb-router-outlet")
export class RouterOutlet extends LitElement { export class RouterOutlet extends LitElement {

14
web/src/routes.ts Normal file
View File

@ -0,0 +1,14 @@
import { html } from "lit-html";
import { Route, SLUG_REGEX } from "./pages/router/Route";
export const ROUTES: Route[] = [
// Prevent infinite Shell loops
new Route(new RegExp("^/$")).redirect("/library/"),
new Route(new RegExp("^#.*")).redirect("/library/"),
new Route(new RegExp("^/library/$"), html`<pb-library></pb-library>`),
new Route(new RegExp("^/administration/overview-ng/$"), html`<pb-admin-overview></pb-admin-overview>`),
new Route(new RegExp("^/applications/$"), html`<pb-application-list></pb-application-list>`),
new Route(new RegExp(`^/applications/(?<slug>${SLUG_REGEX})/$`)).then((args) => {
return html`<pb-application-view .args=${args}></pb-application-view>`;
}),
];