static: rewrite tabs to not use hash and render in shadow root
This commit is contained in:
parent
c7b6eac33d
commit
1e640fac76
|
@ -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
|
@ -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);
|
||||
|
|
|
@ -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>`;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
});
|
||||
|
|
|
@ -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">
|
||||
|
|
Reference in New Issue