web: improve file structure, separate routes from outlet
This commit is contained in:
parent
e6391b64f0
commit
8c8ff4643a
|
@ -32,7 +32,7 @@ export const SIDEBAR_ITEMS: SidebarItem[] = [
|
|||
children: [
|
||||
{
|
||||
name: "Overview",
|
||||
path: ["/administration/overview/"],
|
||||
path: ["/administration/overview-ng/"],
|
||||
},
|
||||
{
|
||||
name: "System Tasks",
|
||||
|
|
|
@ -1,23 +1,29 @@
|
|||
import "construct-style-sheets-polyfill";
|
||||
|
||||
import "./elements/AdminLoginsChart";
|
||||
import "./elements/buttons/ActionButton";
|
||||
import "./elements/buttons/Dropdown";
|
||||
import "./elements/buttons/ModalButton";
|
||||
import "./elements/buttons/SpinnerButton";
|
||||
import "./elements/buttons/TokenCopyButton";
|
||||
import "./elements/CodeMirror";
|
||||
import "./elements/Messages";
|
||||
|
||||
import "./elements/sidebar/Sidebar";
|
||||
import "./elements/sidebar/SidebarBrand";
|
||||
import "./elements/sidebar/SidebarUser";
|
||||
import "./elements/Tabs";
|
||||
import "./elements/Spinner";
|
||||
|
||||
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/applications/ApplicationListPage";
|
||||
import "./pages/applications/ApplicationViewPage";
|
||||
import "./pages/LibraryPage";
|
||||
import "./pages/FlowShellCard";
|
||||
import "./pages/RouterOutlet";
|
||||
import "./pages/SiteShell";
|
||||
|
|
|
@ -15,6 +15,9 @@ export class ApplicationViewPage extends LitElement {
|
|||
img.pf-icon {
|
||||
max-height: 24px;
|
||||
}
|
||||
.pf-c-avatar {
|
||||
--pf-c-avatar--BorderRadius: 0;
|
||||
}
|
||||
`
|
||||
);
|
||||
}
|
||||
|
|
43
web/src/pages/router/Route.ts
Normal file
43
web/src/pages/router/Route.ts
Normal 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"}>`;
|
||||
}
|
||||
}
|
21
web/src/pages/router/RouteMatch.ts
Normal file
21
web/src/pages/router/RouteMatch.ts
Normal 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}>`;
|
||||
}
|
||||
}
|
|
@ -3,80 +3,11 @@ import { css, CSSResult, customElement, html, LitElement, property, TemplateResu
|
|||
import CodeMirrorStyle from "codemirror/lib/codemirror.css";
|
||||
// @ts-ignore
|
||||
import CodeMirrorTheme from "codemirror/theme/monokai.css";
|
||||
import { ColorStyles } from "../constants";
|
||||
import { COMMON_STYLES } from "../common/styles";
|
||||
|
||||
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"}>`;
|
||||
}
|
||||
}
|
||||
|
||||
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}>`;
|
||||
}
|
||||
}
|
||||
import { ColorStyles } from "../../constants";
|
||||
import { COMMON_STYLES } from "../../common/styles";
|
||||
import { Route } from "./Route";
|
||||
import { ROUTES } from "../../routes";
|
||||
import { RouteMatch } from "./RouteMatch";
|
||||
|
||||
@customElement("pb-router-outlet")
|
||||
export class RouterOutlet extends LitElement {
|
14
web/src/routes.ts
Normal file
14
web/src/routes.ts
Normal 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>`;
|
||||
}),
|
||||
];
|
Reference in a new issue