parent
829ad5d3f2
commit
bdd92f63d8
|
@ -148,7 +148,7 @@ export default [
|
||||||
},
|
},
|
||||||
// Admin interface
|
// Admin interface
|
||||||
{
|
{
|
||||||
input: "./src/admin/AdminInterface/AdminInterface.ts",
|
input: "./src/admin/AdminInterface.ts",
|
||||||
output: [
|
output: [
|
||||||
{
|
{
|
||||||
format: "es",
|
format: "es",
|
||||||
|
|
|
@ -26,7 +26,6 @@ import { spread } from "@open-wc/lit-helpers";
|
||||||
import { msg, str } from "@lit/localize";
|
import { msg, str } from "@lit/localize";
|
||||||
import { CSSResult, TemplateResult, css, html, nothing } from "lit";
|
import { CSSResult, TemplateResult, css, html, nothing } from "lit";
|
||||||
import { customElement, property, state } from "lit/decorators.js";
|
import { customElement, property, state } from "lit/decorators.js";
|
||||||
import { classMap } from "lit/directives/class-map.js";
|
|
||||||
import { map } from "lit/directives/map.js";
|
import { map } from "lit/directives/map.js";
|
||||||
|
|
||||||
import PFButton from "@patternfly/patternfly/components/Button/button.css";
|
import PFButton from "@patternfly/patternfly/components/Button/button.css";
|
||||||
|
@ -34,9 +33,14 @@ import PFDrawer from "@patternfly/patternfly/components/Drawer/drawer.css";
|
||||||
import PFPage from "@patternfly/patternfly/components/Page/page.css";
|
import PFPage from "@patternfly/patternfly/components/Page/page.css";
|
||||||
import PFBase from "@patternfly/patternfly/patternfly-base.css";
|
import PFBase from "@patternfly/patternfly/patternfly-base.css";
|
||||||
|
|
||||||
import { AdminApi, CoreApi, SessionUser, UiThemeEnum, Version } from "@goauthentik/api";
|
import {
|
||||||
|
AdminApi,
|
||||||
import "./AdminSidebar";
|
CapabilitiesEnum,
|
||||||
|
CoreApi,
|
||||||
|
SessionUser,
|
||||||
|
UiThemeEnum,
|
||||||
|
Version,
|
||||||
|
} from "@goauthentik/api";
|
||||||
|
|
||||||
@customElement("ak-interface-admin")
|
@customElement("ak-interface-admin")
|
||||||
export class AdminInterface extends Interface {
|
export class AdminInterface extends Interface {
|
||||||
|
@ -122,26 +126,23 @@ export class AdminInterface extends Interface {
|
||||||
}
|
}
|
||||||
|
|
||||||
render(): TemplateResult {
|
render(): TemplateResult {
|
||||||
const sidebarClasses = {
|
|
||||||
"pf-m-expanded": this.sidebarOpen,
|
|
||||||
"pf-m-collapsed": !this.sidebarOpen,
|
|
||||||
"pf-m-light": this.activeTheme === UiThemeEnum.Light,
|
|
||||||
};
|
|
||||||
|
|
||||||
const drawerOpen = this.notificationDrawerOpen || this.apiDrawerOpen;
|
|
||||||
const drawerClasses = {
|
|
||||||
"pf-m-expanded": drawerOpen,
|
|
||||||
"pf-m-collapsed": !drawerOpen,
|
|
||||||
};
|
|
||||||
|
|
||||||
return html` <ak-locale-context>
|
return html` <ak-locale-context>
|
||||||
<div class="pf-c-page">
|
<div class="pf-c-page">
|
||||||
<ak-admin-sidebar
|
<ak-sidebar
|
||||||
?open=${this.sidebarOpen}
|
class="pf-c-page__sidebar ${this.sidebarOpen
|
||||||
class="pf-c-page__sidebar ${classMap(sidebarClasses)}"
|
? "pf-m-expanded"
|
||||||
></ak-admin-sidebar>
|
: "pf-m-collapsed"} ${this.activeTheme === UiThemeEnum.Light
|
||||||
|
? "pf-m-light"
|
||||||
|
: ""}"
|
||||||
|
>
|
||||||
|
${this.renderSidebarItems()}
|
||||||
|
</ak-sidebar>
|
||||||
<div class="pf-c-page__drawer">
|
<div class="pf-c-page__drawer">
|
||||||
<div class="pf-c-drawer ${classMap(drawerClasses)}">
|
<div
|
||||||
|
class="pf-c-drawer ${this.notificationDrawerOpen || this.apiDrawerOpen
|
||||||
|
? "pf-m-expanded"
|
||||||
|
: "pf-m-collapsed"}"
|
||||||
|
>
|
||||||
<div class="pf-c-drawer__main">
|
<div class="pf-c-drawer__main">
|
||||||
<div class="pf-c-drawer__content">
|
<div class="pf-c-drawer__content">
|
||||||
<div class="pf-c-drawer__body">
|
<div class="pf-c-drawer__body">
|
||||||
|
@ -176,4 +177,120 @@ export class AdminInterface extends Interface {
|
||||||
</div></div
|
</div></div
|
||||||
></ak-locale-context>`;
|
></ak-locale-context>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
renderSidebarItems(): TemplateResult {
|
||||||
|
// The second attribute type is of string[] to help with the 'activeWhen' control, which was
|
||||||
|
// commonplace and singular enough to merit its own handler.
|
||||||
|
type SidebarEntry = [
|
||||||
|
path: string | null,
|
||||||
|
label: string,
|
||||||
|
attributes?: Record<string, any> | string[] | null, // eslint-disable-line
|
||||||
|
children?: SidebarEntry[],
|
||||||
|
];
|
||||||
|
|
||||||
|
// prettier-ignore
|
||||||
|
const sidebarContent: SidebarEntry[] = [
|
||||||
|
["/if/user/", msg("User interface"), { "?isAbsoluteLink": true, "?highlight": true }],
|
||||||
|
[null, msg("Dashboards"), { "?expanded": true }, [
|
||||||
|
["/administration/overview", msg("Overview")],
|
||||||
|
["/administration/dashboard/users", msg("User Statistics")],
|
||||||
|
["/administration/system-tasks", msg("System Tasks")]]],
|
||||||
|
[null, msg("Applications"), null, [
|
||||||
|
["/core/providers", msg("Providers"), [`^/core/providers/(?<id>${ID_REGEX})$`]],
|
||||||
|
["/core/applications", msg("Applications"), [`^/core/applications/(?<slug>${SLUG_REGEX})$`]],
|
||||||
|
["/outpost/outposts", msg("Outposts")]]],
|
||||||
|
[null, msg("Events"), null, [
|
||||||
|
["/events/log", msg("Logs"), [`^/events/log/(?<id>${UUID_REGEX})$`]],
|
||||||
|
["/events/rules", msg("Notification Rules")],
|
||||||
|
["/events/transports", msg("Notification Transports")]]],
|
||||||
|
[null, msg("Customisation"), null, [
|
||||||
|
["/policy/policies", msg("Policies")],
|
||||||
|
["/core/property-mappings", msg("Property Mappings")],
|
||||||
|
["/blueprints/instances", msg("Blueprints")],
|
||||||
|
["/policy/reputation", msg("Reputation scores")]]],
|
||||||
|
[null, msg("Flows and Stages"), null, [
|
||||||
|
["/flow/flows", msg("Flows"), [`^/flow/flows/(?<slug>${SLUG_REGEX})$`]],
|
||||||
|
["/flow/stages", msg("Stages")],
|
||||||
|
["/flow/stages/prompts", msg("Prompts")]]],
|
||||||
|
[null, msg("Directory"), null, [
|
||||||
|
["/identity/users", msg("Users"), [`^/identity/users/(?<id>${ID_REGEX})$`]],
|
||||||
|
["/identity/groups", msg("Groups"), [`^/identity/groups/(?<id>${UUID_REGEX})$`]],
|
||||||
|
["/identity/roles", msg("Roles"), [`^/identity/roles/(?<id>${UUID_REGEX})$`]],
|
||||||
|
["/core/sources", msg("Federation and Social login"), [`^/core/sources/(?<slug>${SLUG_REGEX})$`]],
|
||||||
|
["/core/tokens", msg("Tokens and App passwords")],
|
||||||
|
["/flow/stages/invitations", msg("Invitations")]]],
|
||||||
|
[null, msg("System"), null, [
|
||||||
|
["/core/tenants", msg("Tenants")],
|
||||||
|
["/crypto/certificates", msg("Certificates")],
|
||||||
|
["/outpost/integrations", msg("Outpost Integrations")]]]
|
||||||
|
];
|
||||||
|
|
||||||
|
// Typescript requires the type here to correctly type the recursive path
|
||||||
|
type SidebarRenderer = (_: SidebarEntry) => TemplateResult;
|
||||||
|
|
||||||
|
const renderOneSidebarItem: SidebarRenderer = ([path, label, attributes, children]) => {
|
||||||
|
const properties = Array.isArray(attributes)
|
||||||
|
? { ".activeWhen": attributes }
|
||||||
|
: attributes ?? {};
|
||||||
|
if (path) {
|
||||||
|
properties["path"] = path;
|
||||||
|
}
|
||||||
|
return html`<ak-sidebar-item ${spread(properties)}>
|
||||||
|
${label ? html`<span slot="label">${label}</span>` : nothing}
|
||||||
|
${map(children, renderOneSidebarItem)}
|
||||||
|
</ak-sidebar-item>`;
|
||||||
|
};
|
||||||
|
|
||||||
|
// prettier-ignore
|
||||||
|
return html`
|
||||||
|
${this.renderNewVersionMessage()}
|
||||||
|
${this.renderImpersonationMessage()}
|
||||||
|
${map(sidebarContent, renderOneSidebarItem)}
|
||||||
|
${this.renderEnterpriseMessage()}
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
renderNewVersionMessage() {
|
||||||
|
return this.version && this.version.versionCurrent !== VERSION
|
||||||
|
? html`
|
||||||
|
<ak-sidebar-item ?highlight=${true}>
|
||||||
|
<span slot="label"
|
||||||
|
>${msg("A newer version of the frontend is available.")}</span
|
||||||
|
>
|
||||||
|
</ak-sidebar-item>
|
||||||
|
`
|
||||||
|
: nothing;
|
||||||
|
}
|
||||||
|
|
||||||
|
renderImpersonationMessage() {
|
||||||
|
return this.user?.original
|
||||||
|
? html`<ak-sidebar-item
|
||||||
|
?highlight=${true}
|
||||||
|
@click=${() => {
|
||||||
|
new CoreApi(DEFAULT_CONFIG).coreUsersImpersonateEndRetrieve().then(() => {
|
||||||
|
window.location.reload();
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<span slot="label"
|
||||||
|
>${msg(
|
||||||
|
str`You're currently impersonating ${this.user.user.username}. Click to stop.`,
|
||||||
|
)}</span
|
||||||
|
>
|
||||||
|
</ak-sidebar-item>`
|
||||||
|
: nothing;
|
||||||
|
}
|
||||||
|
|
||||||
|
renderEnterpriseMessage() {
|
||||||
|
return this.config?.capabilities.includes(CapabilitiesEnum.IsEnterprise)
|
||||||
|
? html`
|
||||||
|
<ak-sidebar-item>
|
||||||
|
<span slot="label">${msg("Enterprise")}</span>
|
||||||
|
<ak-sidebar-item path="/enterprise/licenses">
|
||||||
|
<span slot="label">${msg("Licenses")}</span>
|
||||||
|
</ak-sidebar-item>
|
||||||
|
</ak-sidebar-item>
|
||||||
|
`
|
||||||
|
: nothing;
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -1,183 +0,0 @@
|
||||||
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
|
|
||||||
import { VERSION } from "@goauthentik/common/constants";
|
|
||||||
import { me } from "@goauthentik/common/users";
|
|
||||||
import { authentikConfigContext } from "@goauthentik/elements/AuthentikContexts";
|
|
||||||
import { AKElement } from "@goauthentik/elements/Base";
|
|
||||||
import { ID_REGEX, SLUG_REGEX, UUID_REGEX } from "@goauthentik/elements/router/Route";
|
|
||||||
import { spread } from "@open-wc/lit-helpers";
|
|
||||||
|
|
||||||
import { consume } from "@lit-labs/context";
|
|
||||||
import { msg, str } from "@lit/localize";
|
|
||||||
import { TemplateResult, html, nothing } from "lit";
|
|
||||||
import { customElement, property, state } from "lit/decorators.js";
|
|
||||||
import { map } from "lit/directives/map.js";
|
|
||||||
|
|
||||||
import {
|
|
||||||
AdminApi,
|
|
||||||
CapabilitiesEnum,
|
|
||||||
type Config,
|
|
||||||
CoreApi,
|
|
||||||
ProvidersApi,
|
|
||||||
type SessionUser,
|
|
||||||
UiThemeEnum,
|
|
||||||
type UserSelf,
|
|
||||||
TypeCreate,
|
|
||||||
Version,
|
|
||||||
} from "@goauthentik/api";
|
|
||||||
|
|
||||||
@customElement("ak-admin-sidebar")
|
|
||||||
export class AkAdminSidebar extends AKElement {
|
|
||||||
@property({ type: Boolean })
|
|
||||||
open = true;
|
|
||||||
|
|
||||||
@state()
|
|
||||||
version: Version["versionCurrent"] | null = null;
|
|
||||||
|
|
||||||
@state()
|
|
||||||
impersonation: UserSelf["username"] | null = null;
|
|
||||||
|
|
||||||
@state()
|
|
||||||
providerTypes: TypeCreate[] = [];
|
|
||||||
|
|
||||||
@consume({ context: authentikConfigContext })
|
|
||||||
public config!: Config;
|
|
||||||
|
|
||||||
firstUpdated() {
|
|
||||||
new AdminApi(DEFAULT_CONFIG).adminVersionRetrieve().then((version) => {
|
|
||||||
this.version = version.versionCurrent;
|
|
||||||
});
|
|
||||||
me().then((user: SessionUser) => {
|
|
||||||
this.impersonation = user.original ? user.user.username : null;
|
|
||||||
});
|
|
||||||
new ProvidersApi(DEFAULT_CONFIG).providersAllTypesList().then((types) => {
|
|
||||||
this.providerTypes = types;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
|
||||||
return html`
|
|
||||||
<ak-sidebar
|
|
||||||
class="pf-c-page__sidebar ${this.open ? "pf-m-expanded" : "pf-m-collapsed"} ${this
|
|
||||||
.activeTheme === UiThemeEnum.Light
|
|
||||||
? "pf-m-light"
|
|
||||||
: ""}"
|
|
||||||
>
|
|
||||||
${this.renderSidebarItems()}
|
|
||||||
</ak-sidebar>
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
|
|
||||||
renderSidebarItems(): TemplateResult {
|
|
||||||
// The second attribute type is of string[] to help with the 'activeWhen' control, which was
|
|
||||||
// commonplace and singular enough to merit its own handler.
|
|
||||||
type SidebarEntry = [
|
|
||||||
path: string | null,
|
|
||||||
label: string,
|
|
||||||
attributes?: Record<string, any> | string[] | null, // eslint-disable-line
|
|
||||||
children?: SidebarEntry[],
|
|
||||||
];
|
|
||||||
|
|
||||||
// prettier-ignore
|
|
||||||
const sidebarContent: SidebarEntry[] = [
|
|
||||||
["/if/user/", msg("User interface"), { "?isAbsoluteLink": true, "?highlight": true }],
|
|
||||||
[null, msg("Dashboards"), { "?expanded": true }, [
|
|
||||||
["/administration/overview", msg("Overview")],
|
|
||||||
["/administration/dashboard/users", msg("User Statistics")],
|
|
||||||
["/administration/system-tasks", msg("System Tasks")]]],
|
|
||||||
[null, msg("Applications"), null, [
|
|
||||||
["/core/applications", msg("Applications"), [`^/core/applications/(?<slug>${SLUG_REGEX})$`]],
|
|
||||||
["/core/providers", msg("Providers"), [`^/core/providers/(?<id>${ID_REGEX})$`]],
|
|
||||||
["/outpost/outposts", msg("Outposts")]]],
|
|
||||||
[null, msg("Events"), null, [
|
|
||||||
["/events/log", msg("Logs"), [`^/events/log/(?<id>${UUID_REGEX})$`]],
|
|
||||||
["/events/rules", msg("Notification Rules")],
|
|
||||||
["/events/transports", msg("Notification Transports")]]],
|
|
||||||
[null, msg("Customisation"), null, [
|
|
||||||
["/policy/policies", msg("Policies")],
|
|
||||||
["/core/property-mappings", msg("Property Mappings")],
|
|
||||||
["/blueprints/instances", msg("Blueprints")],
|
|
||||||
["/policy/reputation", msg("Reputation scores")]]],
|
|
||||||
[null, msg("Flows and Stages"), null, [
|
|
||||||
["/flow/flows", msg("Flows"), [`^/flow/flows/(?<slug>${SLUG_REGEX})$`]],
|
|
||||||
["/flow/stages", msg("Stages")],
|
|
||||||
["/flow/stages/prompts", msg("Prompts")]]],
|
|
||||||
[null, msg("Directory"), null, [
|
|
||||||
["/identity/users", msg("Users"), [`^/identity/users/(?<id>${ID_REGEX})$`]],
|
|
||||||
["/identity/groups", msg("Groups"), [`^/identity/groups/(?<id>${UUID_REGEX})$`]],
|
|
||||||
["/identity/roles", msg("Roles"), [`^/identity/roles/(?<id>${UUID_REGEX})$`]],
|
|
||||||
["/core/sources", msg("Federation and Social login"), [`^/core/sources/(?<slug>${SLUG_REGEX})$`]],
|
|
||||||
["/core/tokens", msg("Tokens and App passwords")],
|
|
||||||
["/flow/stages/invitations", msg("Invitations")]]],
|
|
||||||
[null, msg("System"), null, [
|
|
||||||
["/core/tenants", msg("Tenants")],
|
|
||||||
["/crypto/certificates", msg("Certificates")],
|
|
||||||
["/outpost/integrations", msg("Outpost Integrations")]]]
|
|
||||||
];
|
|
||||||
|
|
||||||
// Typescript requires the type here to correctly type the recursive path
|
|
||||||
type SidebarRenderer = (_: SidebarEntry) => TemplateResult;
|
|
||||||
|
|
||||||
const renderOneSidebarItem: SidebarRenderer = ([path, label, attributes, children]) => {
|
|
||||||
const properties = Array.isArray(attributes)
|
|
||||||
? { ".activeWhen": attributes }
|
|
||||||
: attributes ?? {};
|
|
||||||
if (path) {
|
|
||||||
properties["path"] = path;
|
|
||||||
}
|
|
||||||
return html`<ak-sidebar-item ${spread(properties)}>
|
|
||||||
${label ? html`<span slot="label">${label}</span>` : nothing}
|
|
||||||
${map(children, renderOneSidebarItem)}
|
|
||||||
</ak-sidebar-item>`;
|
|
||||||
};
|
|
||||||
|
|
||||||
// prettier-ignore
|
|
||||||
return html`
|
|
||||||
${this.renderNewVersionMessage()}
|
|
||||||
${this.renderImpersonationMessage()}
|
|
||||||
${map(sidebarContent, renderOneSidebarItem)}
|
|
||||||
${this.renderEnterpriseMessage()}
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
|
|
||||||
renderNewVersionMessage() {
|
|
||||||
return this.version && this.version !== VERSION
|
|
||||||
? html`
|
|
||||||
<ak-sidebar-item ?highlight=${true}>
|
|
||||||
<span slot="label"
|
|
||||||
>${msg("A newer version of the frontend is available.")}</span
|
|
||||||
>
|
|
||||||
</ak-sidebar-item>
|
|
||||||
`
|
|
||||||
: nothing;
|
|
||||||
}
|
|
||||||
|
|
||||||
renderImpersonationMessage() {
|
|
||||||
const reload = () =>
|
|
||||||
new CoreApi(DEFAULT_CONFIG).coreUsersImpersonateEndRetrieve().then(() => {
|
|
||||||
window.location.reload();
|
|
||||||
});
|
|
||||||
|
|
||||||
return this.impersonation
|
|
||||||
? html`<ak-sidebar-item ?highlight=${true} @click=${reload}>
|
|
||||||
<span slot="label"
|
|
||||||
>${msg(
|
|
||||||
str`You're currently impersonating ${this.impersonation}. Click to stop.`
|
|
||||||
)}</span
|
|
||||||
>
|
|
||||||
</ak-sidebar-item>`
|
|
||||||
: nothing;
|
|
||||||
}
|
|
||||||
|
|
||||||
renderEnterpriseMessage() {
|
|
||||||
return this.config?.capabilities.includes(CapabilitiesEnum.IsEnterprise)
|
|
||||||
? html`
|
|
||||||
<ak-sidebar-item>
|
|
||||||
<span slot="label">${msg("Enterprise")}</span>
|
|
||||||
<ak-sidebar-item path="/enterprise/licenses">
|
|
||||||
<span slot="label">${msg("Licenses")}</span>
|
|
||||||
</ak-sidebar-item>
|
|
||||||
</ak-sidebar-item>
|
|
||||||
`
|
|
||||||
: nothing;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,3 +0,0 @@
|
||||||
import { AdminInterface } from "./AdminInterface";
|
|
||||||
import "./AdminInterface";
|
|
||||||
export { AdminInterface };
|
|
|
@ -1,8 +0,0 @@
|
||||||
import { createContext } from "@lit-labs/context";
|
|
||||||
import { type Config } from "@goauthentik/api";
|
|
||||||
|
|
||||||
export const authentikConfigContext = createContext<Config>(
|
|
||||||
Symbol("authentik-config-context")
|
|
||||||
);
|
|
||||||
|
|
||||||
export default authentikConfigContext;
|
|
|
@ -1,7 +1,6 @@
|
||||||
import { config, tenant } from "@goauthentik/common/api/config";
|
import { config, tenant } from "@goauthentik/common/api/config";
|
||||||
import { EVENT_THEME_CHANGE } from "@goauthentik/common/constants";
|
import { EVENT_THEME_CHANGE } from "@goauthentik/common/constants";
|
||||||
import { UIConfig, uiConfig } from "@goauthentik/common/ui/config";
|
import { UIConfig, uiConfig } from "@goauthentik/common/ui/config";
|
||||||
import { ContextProvider } from "@lit-labs/context";
|
|
||||||
import { adaptCSS } from "@goauthentik/common/utils";
|
import { adaptCSS } from "@goauthentik/common/utils";
|
||||||
|
|
||||||
import { localized } from "@lit/localize";
|
import { localized } from "@lit/localize";
|
||||||
|
@ -13,7 +12,6 @@ import ThemeDark from "@goauthentik/common/styles/theme-dark.css";
|
||||||
import PFBase from "@patternfly/patternfly/patternfly-base.css";
|
import PFBase from "@patternfly/patternfly/patternfly-base.css";
|
||||||
|
|
||||||
import { Config, CurrentTenant, UiThemeEnum } from "@goauthentik/api";
|
import { Config, CurrentTenant, UiThemeEnum } from "@goauthentik/api";
|
||||||
import { authentikConfigContext } from "@goauthentik/elements/AuthentikContexts";
|
|
||||||
|
|
||||||
type AkInterface = HTMLElement & {
|
type AkInterface = HTMLElement & {
|
||||||
getTheme: () => Promise<UiThemeEnum>;
|
getTheme: () => Promise<UiThemeEnum>;
|
||||||
|
@ -183,25 +181,8 @@ export class Interface extends AKElement implements AkInterface {
|
||||||
@state()
|
@state()
|
||||||
uiConfig?: UIConfig;
|
uiConfig?: UIConfig;
|
||||||
|
|
||||||
_configContext = new ContextProvider(this, {
|
|
||||||
context: authentikConfigContext,
|
|
||||||
initialValue: undefined
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
_config?: Config;
|
|
||||||
|
|
||||||
@state()
|
@state()
|
||||||
set config(c: Config) {
|
config?: Config;
|
||||||
this._config = c;
|
|
||||||
this._configContext.setValue(c);
|
|
||||||
this.requestUpdate();
|
|
||||||
}
|
|
||||||
|
|
||||||
get config(): Config | undefined {
|
|
||||||
return this._config;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
|
|
|
@ -144,84 +144,47 @@ export class SidebarItem extends AKElement {
|
||||||
return this.renderInner();
|
return this.renderInner();
|
||||||
}
|
}
|
||||||
|
|
||||||
renderWithChildren() {
|
renderInner(): TemplateResult {
|
||||||
return html`<li
|
|
||||||
class="pf-c-nav__item ${this.expanded ? "pf-m-expandable pf-m-expanded" : ""}"
|
|
||||||
>
|
|
||||||
<button
|
|
||||||
class="pf-c-nav__link"
|
|
||||||
aria-expanded="true"
|
|
||||||
@click=${() => {
|
|
||||||
this.expanded = !this.expanded;
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<slot name="label"></slot>
|
|
||||||
<span class="pf-c-nav__toggle">
|
|
||||||
<span class="pf-c-nav__toggle-icon">
|
|
||||||
<i class="fas fa-angle-right" aria-hidden="true"></i>
|
|
||||||
</span>
|
|
||||||
</span>
|
|
||||||
</button>
|
|
||||||
<section class="pf-c-nav__subnav" ?hidden=${!this.expanded}>
|
|
||||||
<ul class="pf-c-nav__list">
|
|
||||||
<slot></slot>
|
|
||||||
</ul>
|
|
||||||
</section>
|
|
||||||
</li>`;
|
|
||||||
}
|
|
||||||
|
|
||||||
renderWithPathAndChildren() {
|
|
||||||
return html`<li
|
|
||||||
class="pf-c-nav__item ${this.expanded ? "pf-m-expandable pf-m-expanded" : ""}"
|
|
||||||
>
|
|
||||||
<slot name="label"></slot>
|
|
||||||
<button
|
|
||||||
class="pf-c-nav__link"
|
|
||||||
aria-expanded="true"
|
|
||||||
@click=${() => {
|
|
||||||
this.expanded = !this.expanded;
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<span class="pf-c-nav__toggle">
|
|
||||||
<span class="pf-c-nav__toggle-icon">
|
|
||||||
<i class="fas fa-angle-right" aria-hidden="true"></i>
|
|
||||||
</span>
|
|
||||||
</span>
|
|
||||||
</button>
|
|
||||||
<section class="pf-c-nav__subnav" ?hidden=${!this.expanded}>
|
|
||||||
<ul class="pf-c-nav__list">
|
|
||||||
<slot></slot>
|
|
||||||
</ul>
|
|
||||||
</section>
|
|
||||||
</li>`;
|
|
||||||
}
|
|
||||||
|
|
||||||
renderWithPath() {
|
|
||||||
return html`
|
|
||||||
<a
|
|
||||||
href="${this.isAbsoluteLink ? "" : "#"}${this.path}"
|
|
||||||
class="pf-c-nav__link ${this.isActive ? "pf-m-current" : ""}"
|
|
||||||
>
|
|
||||||
<slot name="label"></slot>
|
|
||||||
</a>
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
|
|
||||||
renderWithLabel() {
|
|
||||||
html`
|
|
||||||
<span class="pf-c-nav__link">
|
|
||||||
<slot name="label"></slot>
|
|
||||||
</span>
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
|
|
||||||
renderInner() {
|
|
||||||
if (this.childItems.length > 0) {
|
if (this.childItems.length > 0) {
|
||||||
return this.path ? this.renderWithPathAndChildren() : this.renderWithChildren();
|
return html`<li
|
||||||
|
class="pf-c-nav__item ${this.expanded ? "pf-m-expandable pf-m-expanded" : ""}"
|
||||||
|
>
|
||||||
|
<button
|
||||||
|
class="pf-c-nav__link"
|
||||||
|
aria-expanded="true"
|
||||||
|
@click=${() => {
|
||||||
|
this.expanded = !this.expanded;
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<slot name="label"></slot>
|
||||||
|
<span class="pf-c-nav__toggle">
|
||||||
|
<span class="pf-c-nav__toggle-icon">
|
||||||
|
<i class="fas fa-angle-right" aria-hidden="true"></i>
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
</button>
|
||||||
|
<section class="pf-c-nav__subnav" ?hidden=${!this.expanded}>
|
||||||
|
<ul class="pf-c-nav__list">
|
||||||
|
<slot></slot>
|
||||||
|
</ul>
|
||||||
|
</section>
|
||||||
|
</li>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
return html`<li class="pf-c-nav__item">
|
return html`<li class="pf-c-nav__item">
|
||||||
${this.path ? this.renderWithPath() : this.renderWithLabel()}
|
${this.path
|
||||||
|
? html`
|
||||||
|
<a
|
||||||
|
href="${this.isAbsoluteLink ? "" : "#"}${this.path}"
|
||||||
|
class="pf-c-nav__link ${this.isActive ? "pf-m-current" : ""}"
|
||||||
|
>
|
||||||
|
<slot name="label"></slot>
|
||||||
|
</a>
|
||||||
|
`
|
||||||
|
: html`
|
||||||
|
<span class="pf-c-nav__link">
|
||||||
|
<slot name="label"></slot>
|
||||||
|
</span>
|
||||||
|
`}
|
||||||
</li>`;
|
</li>`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Reference in New Issue