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: [
|
children: [
|
||||||
{
|
{
|
||||||
name: "Overview",
|
name: "Overview",
|
||||||
path: ["/administration/overview/"],
|
path: ["/administration/overview-ng/"],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "System Tasks",
|
name: "System Tasks",
|
||||||
|
|
|
@ -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";
|
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
`
|
`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
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";
|
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
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