web: allow for non-path elements in hash, store current tab page in hash
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
This commit is contained in:
parent
1a0a62975c
commit
2c4239d79a
|
@ -10,3 +10,4 @@ export const EVENT_NOTIFICATION_TOGGLE = "ak-notification-toggle";
|
||||||
export const EVENT_SIDEBAR_TOGGLE = "ak-sidebar-toggle";
|
export const EVENT_SIDEBAR_TOGGLE = "ak-sidebar-toggle";
|
||||||
export const EVENT_API_DRAWER_REFRESH = "ak-api-drawer-refresh";
|
export const EVENT_API_DRAWER_REFRESH = "ak-api-drawer-refresh";
|
||||||
export const TITLE_SUFFIX = "authentik";
|
export const TITLE_SUFFIX = "authentik";
|
||||||
|
export const ROUTE_SEPARATOR = ";";
|
||||||
|
|
|
@ -3,7 +3,7 @@ import { ifDefined } from "lit-html/directives/if-defined";
|
||||||
import PFTabs from "@patternfly/patternfly/components/Tabs/tabs.css";
|
import PFTabs from "@patternfly/patternfly/components/Tabs/tabs.css";
|
||||||
import PFGlobal from "@patternfly/patternfly/patternfly-base.css";
|
import PFGlobal from "@patternfly/patternfly/patternfly-base.css";
|
||||||
import AKGlobal from "../authentik.css";
|
import AKGlobal from "../authentik.css";
|
||||||
import { CURRENT_CLASS } from "../constants";
|
import { CURRENT_CLASS, ROUTE_SEPARATOR } from "../constants";
|
||||||
import { t } from "@lingui/macro";
|
import { t } from "@lingui/macro";
|
||||||
|
|
||||||
@customElement("ak-tabs")
|
@customElement("ak-tabs")
|
||||||
|
@ -50,10 +50,17 @@ export class Tabs extends LitElement {
|
||||||
super.disconnectedCallback();
|
super.disconnectedCallback();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onClick(slot?: string): void {
|
||||||
|
this.currentPage = slot;
|
||||||
|
const currentUrl = window.location.hash.slice(1, Infinity).split(ROUTE_SEPARATOR)[0];
|
||||||
|
const newUrl = `#${currentUrl};${slot}`;
|
||||||
|
window.location.hash = newUrl;
|
||||||
|
}
|
||||||
|
|
||||||
renderTab(page: Element): TemplateResult {
|
renderTab(page: Element): TemplateResult {
|
||||||
const slot = page.attributes.getNamedItem("slot")?.value;
|
const slot = page.attributes.getNamedItem("slot")?.value;
|
||||||
return html` <li class="pf-c-tabs__item ${slot === this.currentPage ? CURRENT_CLASS : ""}">
|
return html` <li class="pf-c-tabs__item ${slot === this.currentPage ? CURRENT_CLASS : ""}">
|
||||||
<button class="pf-c-tabs__link" @click=${() => { this.currentPage = slot; }}>
|
<button class="pf-c-tabs__link" @click=${() => this.onClick(slot)}>
|
||||||
<span class="pf-c-tabs__item-text">
|
<span class="pf-c-tabs__item-text">
|
||||||
${page.getAttribute("data-tab-title")}
|
${page.getAttribute("data-tab-title")}
|
||||||
</span>
|
</span>
|
||||||
|
@ -67,7 +74,15 @@ export class Tabs extends LitElement {
|
||||||
if (pages.length < 1) {
|
if (pages.length < 1) {
|
||||||
return html`<h1>${t`no tabs defined`}</h1>`;
|
return html`<h1>${t`no tabs defined`}</h1>`;
|
||||||
}
|
}
|
||||||
this.currentPage = pages[0].attributes.getNamedItem("slot")?.value;
|
let wantedPage = pages[0].attributes.getNamedItem("slot")?.value;
|
||||||
|
if (window.location.hash.includes(ROUTE_SEPARATOR)) {
|
||||||
|
const urlParts = window.location.hash.slice(1, Infinity).split(ROUTE_SEPARATOR);
|
||||||
|
if (this.querySelector(`[slot='${urlParts[1]}']`) !== null) {
|
||||||
|
// To update the URL to match with the current slot
|
||||||
|
wantedPage = urlParts[1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.onClick(wantedPage);
|
||||||
}
|
}
|
||||||
return html`<div class="pf-c-tabs ${this.vertical ? "pf-m-vertical pf-m-box" : ""}">
|
return html`<div class="pf-c-tabs ${this.vertical ? "pf-m-vertical pf-m-box" : ""}">
|
||||||
<ul class="pf-c-tabs__list">
|
<ul class="pf-c-tabs__list">
|
||||||
|
|
|
@ -6,7 +6,20 @@ import AKGlobal from "../../authentik.css";
|
||||||
|
|
||||||
import "./Router404";
|
import "./Router404";
|
||||||
import { Page } from "../Page";
|
import { Page } from "../Page";
|
||||||
import { TITLE_SUFFIX } from "../../constants";
|
import { ROUTE_SEPARATOR, TITLE_SUFFIX } from "../../constants";
|
||||||
|
|
||||||
|
// Poliyfill for hashchange.newURL,
|
||||||
|
// https://developer.mozilla.org/en-US/docs/Web/API/WindowEventHandlers/onhashchange
|
||||||
|
window.addEventListener("load", () => {
|
||||||
|
if (!window.HashChangeEvent) (function () {
|
||||||
|
let lastURL = document.URL;
|
||||||
|
window.addEventListener("hashchange", function (event) {
|
||||||
|
Object.defineProperty(event, "oldURL", { enumerable: true, configurable: true, value: lastURL });
|
||||||
|
Object.defineProperty(event, "newURL", { enumerable: true, configurable: true, value: document.URL });
|
||||||
|
lastURL = document.URL;
|
||||||
|
});
|
||||||
|
}());
|
||||||
|
});
|
||||||
|
|
||||||
@customElement("ak-router-outlet")
|
@customElement("ak-router-outlet")
|
||||||
export class RouterOutlet extends LitElement {
|
export class RouterOutlet extends LitElement {
|
||||||
|
@ -34,7 +47,7 @@ export class RouterOutlet extends LitElement {
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
window.addEventListener("hashchange", () => this.navigate());
|
window.addEventListener("hashchange", (ev: HashChangeEvent) => this.navigate(ev));
|
||||||
}
|
}
|
||||||
|
|
||||||
firstUpdated(): void {
|
firstUpdated(): void {
|
||||||
|
@ -53,8 +66,13 @@ export class RouterOutlet extends LitElement {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
navigate(): void {
|
navigate(ev?: HashChangeEvent): void {
|
||||||
let activeUrl = window.location.hash.slice(1, Infinity);
|
let activeUrl = window.location.hash.slice(1, Infinity).split(ROUTE_SEPARATOR)[0];
|
||||||
|
if (ev) {
|
||||||
|
// Check if we've actually changed paths
|
||||||
|
const oldPath = new URL(ev.oldURL).hash.slice(1, Infinity).split(ROUTE_SEPARATOR)[0];
|
||||||
|
if (oldPath === activeUrl) return;
|
||||||
|
}
|
||||||
if (activeUrl === "") {
|
if (activeUrl === "") {
|
||||||
activeUrl = this.defaultUrl || "/";
|
activeUrl = this.defaultUrl || "/";
|
||||||
window.location.hash = `#${activeUrl}`;
|
window.location.hash = `#${activeUrl}`;
|
||||||
|
|
|
@ -8,6 +8,7 @@ import { until } from "lit-html/directives/until";
|
||||||
|
|
||||||
import "./SidebarBrand";
|
import "./SidebarBrand";
|
||||||
import "./SidebarUser";
|
import "./SidebarUser";
|
||||||
|
import { ROUTE_SEPARATOR } from "../../constants";
|
||||||
|
|
||||||
export class SidebarItem {
|
export class SidebarItem {
|
||||||
name: string;
|
name: string;
|
||||||
|
@ -145,9 +146,9 @@ export class Sidebar extends LitElement {
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
this.activePath = window.location.hash.slice(1, Infinity);
|
this.activePath = window.location.hash.slice(1, Infinity).split(ROUTE_SEPARATOR)[0];
|
||||||
window.addEventListener("hashchange", () => {
|
window.addEventListener("hashchange", () => {
|
||||||
this.activePath = window.location.hash.slice(1, Infinity);
|
this.activePath = window.location.hash.slice(1, Infinity).split(ROUTE_SEPARATOR)[0];
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,7 @@ import PFContent from "@patternfly/patternfly/components/Content/content.css";
|
||||||
|
|
||||||
enum target {
|
enum target {
|
||||||
policy, group, user
|
policy, group, user
|
||||||
};
|
}
|
||||||
|
|
||||||
@customElement("ak-policy-binding-form")
|
@customElement("ak-policy-binding-form")
|
||||||
export class PolicyBindingForm extends Form<PolicyBinding> {
|
export class PolicyBindingForm extends Form<PolicyBinding> {
|
||||||
|
@ -41,7 +41,7 @@ export class PolicyBindingForm extends Form<PolicyBinding> {
|
||||||
@property()
|
@property()
|
||||||
targetPk?: string;
|
targetPk?: string;
|
||||||
|
|
||||||
@property()
|
@property({type: Number})
|
||||||
policyGroupUser?: target;
|
policyGroupUser?: target;
|
||||||
|
|
||||||
getSuccessMessage(): string {
|
getSuccessMessage(): string {
|
||||||
|
|
Reference in a new issue