web/admin: simplify sidebar renderer (#6797)
* Added a 'Hard-Core' lint mode to pre-commit; this will not automagically fix all your problems, but it will show you where some deeper issues arise. * web: streamline sidebar renderer The sidebar renderer had a lot of repetitive code that could easily be templatized, so I extracted the content from it and turned it into a table. * web: complexity of the Sidebar now below 10. This commit incorporates SonarJS into the pre-commit (and *only* the pre-commit) linting pass; SonarJS is much more comprehensive in its complaints, and it's helpful in breaking long functions down to their simplest forms. In this case, the `renderSidebarItems()` function was considered "unreadable," and I've managed to boil it down to its three special cases (new version, impersonation, and enterprise notification) and its routine case (the rest of the sidebar). Going forward, I'd like all our commits to correspond to the SonarJS settings I've established in .eslint.precommit.json, but I'm not gonna hate on others if they don't quite hit it. :-) * web: modernization continues. Three of our four Babel plug-ins have moved from 'proposed' to 'accepted'; I have updated package.json and the .babelrc file to accept those. Node's ability to set its max_old_space_size via the environment variable was enable in 2019; using it here makes it easier to move this code toward a multi-package monorepo in the future. * Adding 'cross-env' so that the uses of the NODE_OPTIONS environment will work (theoretically) on Windows.
This commit is contained in:
parent
7dc2bf119b
commit
6eb33f4f6c
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"presets": ["@babel/env", "@babel/typescript"],
|
"presets": ["@babel/env", "@babel/typescript"],
|
||||||
"plugins": [
|
"plugins": [
|
||||||
["@babel/plugin-proposal-private-methods", { "loose": true }],
|
["@babel/plugin-transform-private-methods", { "loose": true }],
|
||||||
["babel-plugin-tsconfig-paths", {}],
|
["babel-plugin-tsconfig-paths", {}],
|
||||||
[
|
[
|
||||||
"@babel/plugin-proposal-decorators",
|
"@babel/plugin-proposal-decorators",
|
||||||
|
@ -10,7 +10,7 @@
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"@babel/plugin-proposal-class-properties",
|
"@babel/plugin-transform-class-properties",
|
||||||
{
|
{
|
||||||
"loose": true
|
"loose": true
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,7 @@
|
||||||
],
|
],
|
||||||
"macros",
|
"macros",
|
||||||
[
|
[
|
||||||
"@babel/plugin-proposal-private-property-in-object",
|
"@babel/plugin-transform-private-property-in-object",
|
||||||
{
|
{
|
||||||
"loose": true
|
"loose": true
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
{
|
||||||
|
"env": {
|
||||||
|
"browser": true,
|
||||||
|
"es2021": true
|
||||||
|
},
|
||||||
|
"extends": [
|
||||||
|
"eslint:recommended",
|
||||||
|
"plugin:@typescript-eslint/recommended",
|
||||||
|
"plugin:lit/recommended",
|
||||||
|
"plugin:custom-elements/recommended",
|
||||||
|
"plugin:storybook/recommended",
|
||||||
|
"plugin:sonarjs/recommended"
|
||||||
|
],
|
||||||
|
"parser": "@typescript-eslint/parser",
|
||||||
|
"parserOptions": {
|
||||||
|
"ecmaVersion": 12,
|
||||||
|
"sourceType": "module"
|
||||||
|
},
|
||||||
|
"plugins": ["@typescript-eslint", "lit", "custom-elements", "sonarjs"],
|
||||||
|
"rules": {
|
||||||
|
"indent": "off",
|
||||||
|
"linebreak-style": ["error", "unix"],
|
||||||
|
"quotes": ["error", "double", { "avoidEscape": true }],
|
||||||
|
"semi": ["error", "always"],
|
||||||
|
"@typescript-eslint/ban-ts-comment": "off",
|
||||||
|
"sonarjs/cognitive-complexity": ["error", 9]
|
||||||
|
}
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
|
@ -8,22 +8,23 @@
|
||||||
"build-locales": "run-s build-locales:build",
|
"build-locales": "run-s build-locales:build",
|
||||||
"build-locales:build": "lit-localize build",
|
"build-locales:build": "lit-localize build",
|
||||||
"build-locales:repair": "prettier --write ./src/locale-codes.ts",
|
"build-locales:repair": "prettier --write ./src/locale-codes.ts",
|
||||||
"rollup:build": "node --max-old-space-size=4096 node_modules/.bin/rollup -c ./rollup.config.mjs",
|
"rollup:build": "cross-env NODE_OPTIONS='--max_old_space_size=4096' rollup -c ./rollup.config.mjs",
|
||||||
"rollup:build-proxy": "node --max-old-space-size=4096 node_modules/.bin/rollup -c ./rollup.proxy.mjs",
|
"rollup:build-proxy": "cross-env NODE_OPTIONS='--max_old_space_size=4096' rollup -c ./rollup.proxy.mjs",
|
||||||
"rollup:watch": "node --max-old-space-size=8192 node_modules/.bin/rollup -c -w",
|
"rollup:watch": "cross-env NODE_OPTIONS='--max_old_space_size=4096' rollup -c -w",
|
||||||
"build": "run-s build-locales rollup:build",
|
"build": "run-s build-locales rollup:build",
|
||||||
"build-proxy": "run-s build-locales rollup:build-proxy",
|
"build-proxy": "run-s build-locales rollup:build-proxy",
|
||||||
"watch": "run-s build-locales rollup:watch",
|
"watch": "run-s build-locales rollup:watch",
|
||||||
"lint": "eslint . --max-warnings 0 --fix",
|
"lint": "eslint . --max-warnings 0 --fix",
|
||||||
|
"lint:precommit": "eslint --max-warnings 0 --config ./.eslintrc.precommit.json $(git status --porcelain | cut -c2- | grep '^[M?]' | cut -c7- | grep -E '\\.(ts|js|tsx|jsx)$') ",
|
||||||
"lint:spelling": "codespell -D - -D ../.github/codespell-dictionary.txt -I ../.github/codespell-words.txt -S './src/locales/**' ./src -s",
|
"lint:spelling": "codespell -D - -D ../.github/codespell-dictionary.txt -I ../.github/codespell-words.txt -S './src/locales/**' ./src -s",
|
||||||
"lit-analyse": "lit-analyzer src",
|
"lit-analyse": "lit-analyzer src",
|
||||||
"precommit": "run-s tsc lit-analyse lint lint:spelling prettier",
|
"precommit": "run-s tsc lit-analyse lint:precommit lint:spelling prettier",
|
||||||
"prettier-check": "prettier --check .",
|
"prettier-check": "prettier --check .",
|
||||||
"prettier": "prettier --write .",
|
"prettier": "prettier --write .",
|
||||||
"tsc:execute": "tsc --noEmit -p .",
|
"tsc:execute": "tsc --noEmit -p .",
|
||||||
"tsc": "run-s build-locales tsc:execute",
|
"tsc": "run-s build-locales tsc:execute",
|
||||||
"storybook": "storybook dev -p 6006",
|
"storybook": "storybook dev -p 6006",
|
||||||
"storybook:build": "node --max-old-space-size=4096 ./node_modules/.bin/storybook build"
|
"storybook:build": "cross-env NODE_OPTIONS='--max_old_space_size=4096' storybook build"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@codemirror/lang-html": "^6.4.6",
|
"@codemirror/lang-html": "^6.4.6",
|
||||||
|
@ -38,6 +39,7 @@
|
||||||
"@lit-labs/context": "^0.4.0",
|
"@lit-labs/context": "^0.4.0",
|
||||||
"@lit-labs/task": "^3.0.2",
|
"@lit-labs/task": "^3.0.2",
|
||||||
"@lit/localize": "^0.11.4",
|
"@lit/localize": "^0.11.4",
|
||||||
|
"@open-wc/lit-helpers": "^0.6.0",
|
||||||
"@patternfly/elements": "^2.4.0",
|
"@patternfly/elements": "^2.4.0",
|
||||||
"@patternfly/patternfly": "^4.224.2",
|
"@patternfly/patternfly": "^4.224.2",
|
||||||
"@sentry/browser": "^7.68.0",
|
"@sentry/browser": "^7.68.0",
|
||||||
|
@ -62,8 +64,8 @@
|
||||||
"@babel/core": "^7.22.17",
|
"@babel/core": "^7.22.17",
|
||||||
"@babel/plugin-proposal-class-properties": "^7.18.6",
|
"@babel/plugin-proposal-class-properties": "^7.18.6",
|
||||||
"@babel/plugin-proposal-decorators": "^7.22.15",
|
"@babel/plugin-proposal-decorators": "^7.22.15",
|
||||||
"@babel/plugin-proposal-private-methods": "^7.18.6",
|
"@babel/plugin-transform-private-methods": "^7.22.5",
|
||||||
"@babel/plugin-proposal-private-property-in-object": "^7.21.11",
|
"@babel/plugin-transform-private-property-in-object": "^7.22.11",
|
||||||
"@babel/plugin-transform-runtime": "^7.22.15",
|
"@babel/plugin-transform-runtime": "^7.22.15",
|
||||||
"@babel/preset-env": "^7.22.15",
|
"@babel/preset-env": "^7.22.15",
|
||||||
"@babel/preset-typescript": "^7.22.15",
|
"@babel/preset-typescript": "^7.22.15",
|
||||||
|
@ -90,10 +92,12 @@
|
||||||
"@typescript-eslint/parser": "^6.6.0",
|
"@typescript-eslint/parser": "^6.6.0",
|
||||||
"babel-plugin-macros": "^3.1.0",
|
"babel-plugin-macros": "^3.1.0",
|
||||||
"babel-plugin-tsconfig-paths": "^1.0.3",
|
"babel-plugin-tsconfig-paths": "^1.0.3",
|
||||||
|
"cross-env": "^7.0.3",
|
||||||
"eslint": "^8.49.0",
|
"eslint": "^8.49.0",
|
||||||
"eslint-config-google": "^0.14.0",
|
"eslint-config-google": "^0.14.0",
|
||||||
"eslint-plugin-custom-elements": "0.0.8",
|
"eslint-plugin-custom-elements": "0.0.8",
|
||||||
"eslint-plugin-lit": "^1.9.1",
|
"eslint-plugin-lit": "^1.9.1",
|
||||||
|
"eslint-plugin-sonarjs": "^0.21.0",
|
||||||
"eslint-plugin-storybook": "^0.6.13",
|
"eslint-plugin-storybook": "^0.6.13",
|
||||||
"lit-analyzer": "^1.2.1",
|
"lit-analyzer": "^1.2.1",
|
||||||
"npm-run-all": "^4.1.5",
|
"npm-run-all": "^4.1.5",
|
||||||
|
|
|
@ -21,10 +21,12 @@ import { getURLParam, updateURLParams } from "@goauthentik/elements/router/Route
|
||||||
import "@goauthentik/elements/router/RouterOutlet";
|
import "@goauthentik/elements/router/RouterOutlet";
|
||||||
import "@goauthentik/elements/sidebar/Sidebar";
|
import "@goauthentik/elements/sidebar/Sidebar";
|
||||||
import "@goauthentik/elements/sidebar/SidebarItem";
|
import "@goauthentik/elements/sidebar/SidebarItem";
|
||||||
|
import { spread } from "@open-wc/lit-helpers";
|
||||||
|
|
||||||
import { msg, str } from "@lit/localize";
|
import { msg, str } from "@lit/localize";
|
||||||
import { CSSResult, TemplateResult, css, html } 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 { map } from "lit/directives/map.js";
|
||||||
|
|
||||||
import PFButton from "@patternfly/patternfly/components/Button/button.css";
|
import PFButton from "@patternfly/patternfly/components/Button/button.css";
|
||||||
import PFDrawer from "@patternfly/patternfly/components/Drawer/drawer.css";
|
import PFDrawer from "@patternfly/patternfly/components/Drawer/drawer.css";
|
||||||
|
@ -173,8 +175,78 @@ export class AdminInterface extends Interface {
|
||||||
}
|
}
|
||||||
|
|
||||||
renderSidebarItems(): TemplateResult {
|
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("Users")],
|
||||||
|
["/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})$`]],
|
||||||
|
["/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`
|
return html`
|
||||||
${this.version && this.version.versionCurrent !== VERSION
|
${this.renderNewVersionMessage()}
|
||||||
|
${this.renderImpersonationMessage()}
|
||||||
|
${map(sidebarContent, renderOneSidebarItem)}
|
||||||
|
${this.renderEnterpriseMessage()}
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
renderNewVersionMessage() {
|
||||||
|
return this.version && this.version.versionCurrent !== VERSION
|
||||||
? html`
|
? html`
|
||||||
<ak-sidebar-item ?highlight=${true}>
|
<ak-sidebar-item ?highlight=${true}>
|
||||||
<span slot="label"
|
<span slot="label"
|
||||||
|
@ -182,8 +254,11 @@ export class AdminInterface extends Interface {
|
||||||
>
|
>
|
||||||
</ak-sidebar-item>
|
</ak-sidebar-item>
|
||||||
`
|
`
|
||||||
: html``}
|
: nothing;
|
||||||
${this.user?.original
|
}
|
||||||
|
|
||||||
|
renderImpersonationMessage() {
|
||||||
|
return this.user?.original
|
||||||
? html`<ak-sidebar-item
|
? html`<ak-sidebar-item
|
||||||
?highlight=${true}
|
?highlight=${true}
|
||||||
@click=${() => {
|
@click=${() => {
|
||||||
|
@ -198,125 +273,11 @@ export class AdminInterface extends Interface {
|
||||||
)}</span
|
)}</span
|
||||||
>
|
>
|
||||||
</ak-sidebar-item>`
|
</ak-sidebar-item>`
|
||||||
: html``}
|
: nothing;
|
||||||
<ak-sidebar-item path="/if/user/" ?isAbsoluteLink=${true} ?highlight=${true}>
|
}
|
||||||
<span slot="label">${msg("User interface")}</span>
|
|
||||||
</ak-sidebar-item>
|
renderEnterpriseMessage() {
|
||||||
<ak-sidebar-item .expanded=${true}>
|
return this.config?.capabilities.includes(CapabilitiesEnum.IsEnterprise)
|
||||||
<span slot="label">${msg("Dashboards")}</span>
|
|
||||||
<ak-sidebar-item path="/administration/overview">
|
|
||||||
<span slot="label">${msg("Overview")}</span>
|
|
||||||
</ak-sidebar-item>
|
|
||||||
<ak-sidebar-item path="/administration/dashboard/users">
|
|
||||||
<span slot="label">${msg("Users")}</span>
|
|
||||||
</ak-sidebar-item>
|
|
||||||
<ak-sidebar-item path="/administration/system-tasks">
|
|
||||||
<span slot="label">${msg("System Tasks")}</span>
|
|
||||||
</ak-sidebar-item>
|
|
||||||
</ak-sidebar-item>
|
|
||||||
<ak-sidebar-item>
|
|
||||||
<span slot="label">${msg("Applications")}</span>
|
|
||||||
<ak-sidebar-item
|
|
||||||
path="/core/providers"
|
|
||||||
.activeWhen=${[`^/core/providers/(?<id>${ID_REGEX})$`]}
|
|
||||||
>
|
|
||||||
<span slot="label">${msg("Providers")}</span>
|
|
||||||
</ak-sidebar-item>
|
|
||||||
<ak-sidebar-item
|
|
||||||
path="/core/applications"
|
|
||||||
.activeWhen=${[`^/core/applications/(?<slug>${SLUG_REGEX})$`]}
|
|
||||||
>
|
|
||||||
<span slot="label">${msg("Applications")}</span>
|
|
||||||
</ak-sidebar-item>
|
|
||||||
<ak-sidebar-item path="/outpost/outposts">
|
|
||||||
<span slot="label">${msg("Outposts")}</span>
|
|
||||||
</ak-sidebar-item>
|
|
||||||
</ak-sidebar-item>
|
|
||||||
<ak-sidebar-item>
|
|
||||||
<span slot="label">${msg("Events")}</span>
|
|
||||||
<ak-sidebar-item
|
|
||||||
path="/events/log"
|
|
||||||
.activeWhen=${[`^/events/log/(?<id>${UUID_REGEX})$`]}
|
|
||||||
>
|
|
||||||
<span slot="label">${msg("Logs")}</span>
|
|
||||||
</ak-sidebar-item>
|
|
||||||
<ak-sidebar-item path="/events/rules">
|
|
||||||
<span slot="label">${msg("Notification Rules")}</span>
|
|
||||||
</ak-sidebar-item>
|
|
||||||
<ak-sidebar-item path="/events/transports">
|
|
||||||
<span slot="label">${msg("Notification Transports")}</span>
|
|
||||||
</ak-sidebar-item>
|
|
||||||
</ak-sidebar-item>
|
|
||||||
<ak-sidebar-item>
|
|
||||||
<span slot="label">${msg("Customisation")}</span>
|
|
||||||
<ak-sidebar-item path="/policy/policies">
|
|
||||||
<span slot="label">${msg("Policies")}</span>
|
|
||||||
</ak-sidebar-item>
|
|
||||||
<ak-sidebar-item path="/core/property-mappings">
|
|
||||||
<span slot="label">${msg("Property Mappings")}</span>
|
|
||||||
</ak-sidebar-item>
|
|
||||||
<ak-sidebar-item path="/blueprints/instances">
|
|
||||||
<span slot="label">${msg("Blueprints")}</span>
|
|
||||||
</ak-sidebar-item>
|
|
||||||
<ak-sidebar-item path="/policy/reputation">
|
|
||||||
<span slot="label">${msg("Reputation scores")}</span>
|
|
||||||
</ak-sidebar-item>
|
|
||||||
</ak-sidebar-item>
|
|
||||||
<ak-sidebar-item>
|
|
||||||
<span slot="label">${msg("Flows and Stages")}</span>
|
|
||||||
<ak-sidebar-item
|
|
||||||
path="/flow/flows"
|
|
||||||
.activeWhen=${[`^/flow/flows/(?<slug>${SLUG_REGEX})$`]}
|
|
||||||
>
|
|
||||||
<span slot="label">${msg("Flows")}</span>
|
|
||||||
</ak-sidebar-item>
|
|
||||||
<ak-sidebar-item path="/flow/stages">
|
|
||||||
<span slot="label">${msg("Stages")}</span>
|
|
||||||
</ak-sidebar-item>
|
|
||||||
<ak-sidebar-item path="/flow/stages/prompts">
|
|
||||||
<span slot="label">${msg("Prompts")}</span>
|
|
||||||
</ak-sidebar-item>
|
|
||||||
</ak-sidebar-item>
|
|
||||||
<ak-sidebar-item>
|
|
||||||
<span slot="label">${msg("Directory")}</span>
|
|
||||||
<ak-sidebar-item
|
|
||||||
path="/identity/users"
|
|
||||||
.activeWhen=${[`^/identity/users/(?<id>${ID_REGEX})$`]}
|
|
||||||
>
|
|
||||||
<span slot="label">${msg("Users")}</span>
|
|
||||||
</ak-sidebar-item>
|
|
||||||
<ak-sidebar-item
|
|
||||||
path="/identity/groups"
|
|
||||||
.activeWhen=${[`^/identity/groups/(?<id>${UUID_REGEX})$`]}
|
|
||||||
>
|
|
||||||
<span slot="label">${msg("Groups")}</span>
|
|
||||||
</ak-sidebar-item>
|
|
||||||
<ak-sidebar-item
|
|
||||||
path="/core/sources"
|
|
||||||
.activeWhen=${[`^/core/sources/(?<slug>${SLUG_REGEX})$`]}
|
|
||||||
>
|
|
||||||
<span slot="label">${msg("Federation and Social login")}</span>
|
|
||||||
</ak-sidebar-item>
|
|
||||||
<ak-sidebar-item path="/core/tokens">
|
|
||||||
<span slot="label">${msg("Tokens and App passwords")}</span>
|
|
||||||
</ak-sidebar-item>
|
|
||||||
<ak-sidebar-item path="/flow/stages/invitations">
|
|
||||||
<span slot="label">${msg("Invitations")}</span>
|
|
||||||
</ak-sidebar-item>
|
|
||||||
</ak-sidebar-item>
|
|
||||||
<ak-sidebar-item>
|
|
||||||
<span slot="label">${msg("System")}</span>
|
|
||||||
<ak-sidebar-item path="/core/tenants">
|
|
||||||
<span slot="label">${msg("Tenants")}</span>
|
|
||||||
</ak-sidebar-item>
|
|
||||||
<ak-sidebar-item path="/crypto/certificates">
|
|
||||||
<span slot="label">${msg("Certificates")}</span>
|
|
||||||
</ak-sidebar-item>
|
|
||||||
<ak-sidebar-item path="/outpost/integrations">
|
|
||||||
<span slot="label">${msg("Outpost Integrations")}</span>
|
|
||||||
</ak-sidebar-item>
|
|
||||||
</ak-sidebar-item>
|
|
||||||
${this.config?.capabilities.includes(CapabilitiesEnum.IsEnterprise)
|
|
||||||
? html`
|
? html`
|
||||||
<ak-sidebar-item>
|
<ak-sidebar-item>
|
||||||
<span slot="label">${msg("Enterprise")}</span>
|
<span slot="label">${msg("Enterprise")}</span>
|
||||||
|
@ -325,7 +286,6 @@ export class AdminInterface extends Interface {
|
||||||
</ak-sidebar-item>
|
</ak-sidebar-item>
|
||||||
</ak-sidebar-item>
|
</ak-sidebar-item>
|
||||||
`
|
`
|
||||||
: html``}
|
: nothing;
|
||||||
`;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Reference in New Issue