static: rewrite tabs to not use hash and render in shadow root

This commit is contained in:
Jens Langhammer 2020-11-26 23:31:56 +01:00
parent c7b6eac33d
commit 1e640fac76
7 changed files with 84 additions and 71 deletions

View File

@ -47,12 +47,12 @@
{% for application in object_list %}
<tr role="row">
<th role="columnheader">
<div>
<a href="/applications/{{ application.slug }}/">
<div>{{ application.name }}</div>
{% if application.meta_publisher %}
<small>{{ application.meta_publisher }}</small>
{% endif %}
</div>
</a>
</th>
<td role="cell">
<code>{{ application.slug }}</span>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -4,6 +4,7 @@ export const PRIMARY_CLASS = "pf-m-primary";
export const SUCCESS_CLASS = "pf-m-success";
export const ERROR_CLASS = "pf-m-danger";
export const PROGRESS_CLASS = "pf-m-in-progress";
export const CURRENT_CLASS = "pf-m-current";
export const ColorStyles = css`
.pf-m-success {
color: var(--pf-global--success-color--100);

View File

@ -1,62 +1,52 @@
import { LitElement, html, customElement } from "lit-element";
import { LitElement, html, customElement, property } from "lit-element";
// @ts-ignore
import TabsStyle from "@patternfly/patternfly/components/Tabs/tabs.css";
// @ts-ignore
import GlobalsStyle from "@patternfly/patternfly/base/patternfly-globals.css";
import { CURRENT_CLASS } from "../constants";
@customElement("pb-tabs")
export class Tabs extends LitElement {
_currentPage? = "";
_firstPage? = "";
@property()
currentPage?: string;
get currentPage() {
return this._currentPage;
static get styles() {
return [GlobalsStyle, TabsStyle];
}
set currentPage(value) {
try {
// Show active tab page
this.querySelector(
`.pf-c-tab-content[tab-name='${value}']`
)?.removeAttribute("hidden");
// Update active status on buttons
this.querySelector(
`.pf-c-tabs__item[tab-name='${value}']`
)?.classList.add("pf-m-current");
// Hide other tab pages
this.querySelectorAll(
`.pf-c-tab-content:not([tab-name='${value}'])`
).forEach((el) => {
el.setAttribute("hidden", "");
});
// Update active status on other buttons
this.querySelectorAll(
`.pf-c-tabs__item:not([tab-name='${value}'])`
).forEach((el) => {
el.classList.remove("pf-m-current");
});
// Update window hash
window.location.hash = `#${value}`;
this._currentPage = value;
} catch (e) {
this.currentPage = this._firstPage;
render() {
let pages = Array.from(this.querySelectorAll("[slot]")!);
if (!this.currentPage) {
if (pages.length < 1) {
return html`<h1>no tabs defined</h1>`;
}
this.currentPage = pages[0].attributes.getNamedItem("slot")?.value;
}
}
createRenderRoot() {
return this;
}
firstUpdated() {
this._firstPage = this.querySelector(".pf-c-tab-content")?.getAttribute(
"tab-name"
)!;
if (window.location.hash) {
this.currentPage = window.location.hash;
} else {
this.currentPage = this._firstPage;
}
this.querySelectorAll(".pf-c-tabs__item > button").forEach((button) => {
button.addEventListener("click", (e) => {
let tabPage = button.parentElement?.getAttribute("tab-name")!;
this.currentPage = tabPage;
});
});
return html`<div class="pf-c-tabs">
<ul class="pf-c-tabs__list">
${pages.map((page) => {
const slot = page.attributes.getNamedItem("slot")
?.value;
return html` <li
class="pf-c-tabs__item ${slot === this.currentPage
? CURRENT_CLASS
: ""}"
>
<button
class="pf-c-tabs__link"
@click=${() => {
this.currentPage = slot;
}}
>
<span class="pf-c-tabs__item-text">
${page.attributes.getNamedItem("tab-title")
?.value}
</span>
</button>
</li>`;
})}
</ul>
</div>
<slot name="${this.currentPage}"></slot>`;
}
}

View File

@ -47,12 +47,19 @@ export class Route {
}
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("/-/overview/"),
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) => {
@ -75,6 +82,10 @@ class RouteMatch {
render(): TemplateResult {
return this.route.render(this.arguments!.groups || {});
}
toString(): string {
return `<RouteMatch url=${this.fullUrl} route=${this.route} arguments=${this.arguments}>`;
}
}
@customElement("pb-router-outlet")
@ -112,6 +123,7 @@ export class RouterOutlet extends LitElement {
if (activeUrl === "") {
activeUrl = this.defaultUrl!;
window.location.hash = `#${activeUrl}`;
console.debug(`passbook/router: set to ${window.location.hash}`);
return;
}
let matchedRoute: RouteMatch | null = null;
@ -124,6 +136,7 @@ export class RouterOutlet extends LitElement {
matchedRoute = new RouteMatch(route);
matchedRoute.arguments = match;
matchedRoute.fullUrl = activeUrl;
console.debug(`passbook/router: found match ${matchedRoute}`);
return;
}
});

View File

@ -1,4 +1,4 @@
import { customElement, html, LitElement, property } from "lit-element";
import { css, customElement, html, LitElement, property } from "lit-element";
import { Application } from "../../api/application";
import { COMMON_STYLES } from "../../common/styles";
@ -18,24 +18,33 @@ export class ApplicationViewPage extends LitElement {
application?: Application;
static get styles() {
return COMMON_STYLES;
return COMMON_STYLES.concat(
css`
img.pf-icon {
max-height: 24px;
}
`
);
}
render() {
return html`<section class="pf-c-page__main-section pf-m-light">
<div class="pf-c-content">
<h1>
<i class="pf-icon pf-icon-applications"></i>
<img
class="pf-icon"
src="${this.application?.meta_icon || ""}"
/>
${this.application?.name}
</h1>
<p>
External Applications which use passbook as
Identity-Provider, utilizing protocols like OAuth2 and
SAML.
</p>
<p>${this.application?.meta_publisher}</p>
</div>
</section>
<section class="pf-c-page__main-section pf-m-no-padding-mobile">
<pb-tabs>
<div slot="page-1" tab-title="Users">users</div>
<div slot="page-2" tab-title="Containers">foo</div>
</pb-tabs>
<div class="pf-c-card">
<div class="pf-c-toolbar">
<div class="pf-c-toolbar__content">