web: remove sidebar items from sidebar class, add admin-interface
This commit is contained in:
parent
832a3dda41
commit
821458373d
|
@ -3,7 +3,7 @@
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
|
|
||||||
{% block body %}
|
{% block body %}
|
||||||
<pb-messages url="{% url 'passbook_api:messages-list' %}"></pb-messages>
|
<pb-messages></pb-messages>
|
||||||
<div class="pf-c-page">
|
<div class="pf-c-page">
|
||||||
<a class="pf-c-skip-to-content pf-c-button pf-m-primary" href="#main-content">{% trans 'Skip to content' %}</a>
|
<a class="pf-c-skip-to-content pf-c-button pf-m-primary" href="#main-content">{% trans 'Skip to content' %}</a>
|
||||||
{% block page_content %}
|
{% block page_content %}
|
||||||
|
|
|
@ -1,10 +1,5 @@
|
||||||
{% extends "base/page.html" %}
|
{% extends "base/skeleton.html" %}
|
||||||
|
|
||||||
{% block page_content %}
|
{% block body %}
|
||||||
<pb-sidebar class="pf-c-page__sidebar">
|
<pb-interface-admin></pb-interface-admin>
|
||||||
</pb-sidebar>
|
|
||||||
<main class="pf-c-page__main">
|
|
||||||
<pb-router-outlet role="main" class="pf-c-page__main" tabindex="-1" id="main-content" defaultUrl="/library/">
|
|
||||||
</pb-router-outlet>
|
|
||||||
</main>
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
import { DefaultClient, PBResponse } from "./client";
|
import { DefaultClient, PBResponse } from "./client";
|
||||||
|
|
||||||
|
let me: User;
|
||||||
|
|
||||||
export class User {
|
export class User {
|
||||||
pk: number;
|
pk: number;
|
||||||
username: string;
|
username: string;
|
||||||
|
@ -13,7 +15,10 @@ export class User {
|
||||||
}
|
}
|
||||||
|
|
||||||
static me(): Promise<User> {
|
static me(): Promise<User> {
|
||||||
return DefaultClient.fetch<User>(["core", "users", "me"]);
|
if (me) {
|
||||||
|
return Promise.resolve<User>(me);
|
||||||
|
}
|
||||||
|
return DefaultClient.fetch<User>(["core", "users", "me"]).then(u => me = u);
|
||||||
}
|
}
|
||||||
|
|
||||||
static count(): Promise<number> {
|
static count(): Promise<number> {
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import { LitElement, html, customElement, property, TemplateResult } from "lit-element";
|
import { LitElement, html, customElement, TemplateResult } from "lit-element";
|
||||||
|
import { DefaultClient } from "../api/client";
|
||||||
|
|
||||||
const LEVEL_ICON_MAP: { [key: string]: string } = {
|
const LEVEL_ICON_MAP: { [key: string]: string } = {
|
||||||
error: "fas fa-exclamation-circle",
|
error: "fas fa-exclamation-circle",
|
||||||
|
@ -19,8 +20,7 @@ interface Message {
|
||||||
|
|
||||||
@customElement("pb-messages")
|
@customElement("pb-messages")
|
||||||
export class Messages extends LitElement {
|
export class Messages extends LitElement {
|
||||||
@property()
|
url = DefaultClient.makeUrl(["root", "messages"]);
|
||||||
url = "";
|
|
||||||
|
|
||||||
messageSocket?: WebSocket;
|
messageSocket?: WebSocket;
|
||||||
retryDelay = 200;
|
retryDelay = 200;
|
||||||
|
|
|
@ -6,136 +6,22 @@ import NavStyle from "@patternfly/patternfly/components/Nav/nav.css";
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
import GlobalsStyle from "@patternfly/patternfly/base/patternfly-globals.css";
|
import GlobalsStyle from "@patternfly/patternfly/base/patternfly-globals.css";
|
||||||
|
|
||||||
import { User } from "../../api/user";
|
import { until } from "lit-html/directives/until";
|
||||||
|
|
||||||
export interface SidebarItem {
|
export interface SidebarItem {
|
||||||
name: string;
|
name: string;
|
||||||
path?: string[];
|
path?: string[];
|
||||||
children?: SidebarItem[];
|
children?: SidebarItem[];
|
||||||
condition?: (sb: Sidebar) => boolean;
|
condition?: () => Promise<boolean>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const SIDEBAR_ITEMS: SidebarItem[] = [
|
|
||||||
{
|
|
||||||
name: "Library",
|
|
||||||
path: ["/library/"],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Monitor",
|
|
||||||
path: ["/audit/audit/"],
|
|
||||||
condition: (sb: Sidebar): boolean => {
|
|
||||||
return sb.user?.is_superuser || false;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Administration",
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
name: "Overview",
|
|
||||||
path: ["/administration/overview-ng/"],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "System Tasks",
|
|
||||||
path: ["/administration/tasks/"],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Applications",
|
|
||||||
path: ["/administration/applications/"],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Sources",
|
|
||||||
path: ["/administration/sources/"],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Providers",
|
|
||||||
path: ["/administration/providers/"],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "User Management",
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
name: "User",
|
|
||||||
path: ["/administration/users/"],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Groups",
|
|
||||||
path: ["/administration/groups/"],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Outposts",
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
name: "Outposts",
|
|
||||||
path: ["/administration/outposts/"],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Service Connections",
|
|
||||||
path: ["/administration/outposts/service_connections/"],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Policies",
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
name: "Policies",
|
|
||||||
path: ["/administration/policies/"],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Bindings",
|
|
||||||
path: ["/administration/policies/bindings/"],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Property Mappings",
|
|
||||||
path: ["/administration/property-mappings/"],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Flows",
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
name: "Flows",
|
|
||||||
path: ["/administration/flows/"],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Stages",
|
|
||||||
path: ["/administration/stages/"],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Prompts",
|
|
||||||
path: ["/administration/stages/prompts/"],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Invitations",
|
|
||||||
path: ["/administration/stages/invitations/"],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Certificates",
|
|
||||||
path: ["/administration/crypto/certificates/"],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Tokens",
|
|
||||||
path: ["/administration/tokens/"],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
condition: (sb: Sidebar): boolean => {
|
|
||||||
return sb.user?.is_superuser || false;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
@customElement("pb-sidebar")
|
@customElement("pb-sidebar")
|
||||||
export class Sidebar extends LitElement {
|
export class Sidebar extends LitElement {
|
||||||
@property()
|
@property({attribute: false})
|
||||||
activePath: string;
|
items: SidebarItem[] = [];
|
||||||
|
|
||||||
@property()
|
@property()
|
||||||
user?: User;
|
activePath: string;
|
||||||
|
|
||||||
static get styles(): CSSResult[] {
|
static get styles(): CSSResult[] {
|
||||||
return [
|
return [
|
||||||
|
@ -145,7 +31,7 @@ export class Sidebar extends LitElement {
|
||||||
css`
|
css`
|
||||||
.pf-c-nav__list .sidebar-brand {
|
.pf-c-nav__list .sidebar-brand {
|
||||||
max-height: 82px;
|
max-height: 82px;
|
||||||
margin-bottom: 0.5rem;
|
margin-bottom: -0.5rem;
|
||||||
}
|
}
|
||||||
.pf-c-nav__link {
|
.pf-c-nav__link {
|
||||||
--pf-c-nav__link--PaddingTop: 0.5rem;
|
--pf-c-nav__link--PaddingTop: 0.5rem;
|
||||||
|
@ -167,16 +53,15 @@ export class Sidebar extends LitElement {
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
User.me().then((u) => (this.user = u));
|
|
||||||
this.activePath = window.location.hash.slice(1, Infinity);
|
this.activePath = window.location.hash.slice(1, Infinity);
|
||||||
window.addEventListener("hashchange", () => {
|
window.addEventListener("hashchange", () => {
|
||||||
this.activePath = window.location.hash.slice(1, Infinity);
|
this.activePath = window.location.hash.slice(1, Infinity);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
renderItem(item: SidebarItem): TemplateResult {
|
async renderItem(item: SidebarItem): Promise<TemplateResult> {
|
||||||
if (item.condition) {
|
if (item.condition) {
|
||||||
const result = item.condition(this);
|
const result = await item.condition();
|
||||||
if (!result) {
|
if (!result) {
|
||||||
return html``;
|
return html``;
|
||||||
}
|
}
|
||||||
|
@ -194,7 +79,7 @@ export class Sidebar extends LitElement {
|
||||||
</a>
|
</a>
|
||||||
<section class="pf-c-nav__subnav">
|
<section class="pf-c-nav__subnav">
|
||||||
<ul class="pf-c-nav__simple-list">
|
<ul class="pf-c-nav__simple-list">
|
||||||
${item.children?.map((i) => this.renderItem(i))}
|
${item.children?.map((i) => until(this.renderItem(i), html``))}
|
||||||
</ul>
|
</ul>
|
||||||
</section>`}
|
</section>`}
|
||||||
</li>`;
|
</li>`;
|
||||||
|
@ -207,9 +92,9 @@ export class Sidebar extends LitElement {
|
||||||
<li class="pf-c-nav__item sidebar-brand">
|
<li class="pf-c-nav__item sidebar-brand">
|
||||||
<pb-sidebar-brand></pb-sidebar-brand>
|
<pb-sidebar-brand></pb-sidebar-brand>
|
||||||
</li>
|
</li>
|
||||||
${SIDEBAR_ITEMS.map((i) => this.renderItem(i))}
|
${this.items.map((i) => until(this.renderItem(i), html``))}
|
||||||
<li class="pf-c-nav__item pf-c-nav__item-bottom">
|
<li class="pf-c-nav__item pf-c-nav__item-bottom">
|
||||||
<pb-sidebar-user .user=${this.user}></pb-sidebar-user>
|
<pb-sidebar-user></pb-sidebar-user>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { css, CSSResult, customElement, html, LitElement, property, TemplateResult } from "lit-element";
|
import { css, CSSResult, customElement, html, LitElement, TemplateResult } from "lit-element";
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
import NavStyle from "@patternfly/patternfly/components/Nav/nav.css";
|
import NavStyle from "@patternfly/patternfly/components/Nav/nav.css";
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
|
@ -9,9 +9,6 @@ import { User } from "../../api/user";
|
||||||
|
|
||||||
@customElement("pb-sidebar-user")
|
@customElement("pb-sidebar-user")
|
||||||
export class SidebarUser extends LitElement {
|
export class SidebarUser extends LitElement {
|
||||||
@property()
|
|
||||||
user?: User;
|
|
||||||
|
|
||||||
static get styles(): CSSResult[] {
|
static get styles(): CSSResult[] {
|
||||||
return [
|
return [
|
||||||
fa,
|
fa,
|
||||||
|
@ -44,14 +41,12 @@ export class SidebarUser extends LitElement {
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
render(): TemplateResult {
|
async render(): Promise<TemplateResult> {
|
||||||
if (!this.user) {
|
const user = await User.me();
|
||||||
return html``;
|
|
||||||
}
|
|
||||||
return html`
|
return html`
|
||||||
<a href="#/-/user/" class="pf-c-nav__link user-avatar" id="user-settings">
|
<a href="#/-/user/" class="pf-c-nav__link user-avatar" id="user-settings">
|
||||||
<img class="pf-c-avatar" src="${this.user?.avatar}" alt="" />
|
<img class="pf-c-avatar" src="${user.avatar}" alt="" />
|
||||||
<span>${this.user?.username}</span>
|
<span>${user.username}</span>
|
||||||
</a>
|
</a>
|
||||||
<a href="/flows/-/default/invalidation/" class="pf-c-nav__link user-logout" id="logout">
|
<a href="/flows/-/default/invalidation/" class="pf-c-nav__link user-logout" id="logout">
|
||||||
<i class="fas fa-sign-out-alt" aria-hidden="true"></i>
|
<i class="fas fa-sign-out-alt" aria-hidden="true"></i>
|
||||||
|
|
127
web/src/interfaces/AdminInterface.ts
Normal file
127
web/src/interfaces/AdminInterface.ts
Normal file
|
@ -0,0 +1,127 @@
|
||||||
|
import { customElement } from "lit-element";
|
||||||
|
import { User } from "../api/user";
|
||||||
|
import { SidebarItem } from "../elements/sidebar/Sidebar";
|
||||||
|
import { Interface } from "./Interface";
|
||||||
|
|
||||||
|
export const SIDEBAR_ITEMS: SidebarItem[] = [
|
||||||
|
{
|
||||||
|
name: "Library",
|
||||||
|
path: ["/library/"],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Monitor",
|
||||||
|
path: ["/audit/audit/"],
|
||||||
|
condition: (): Promise<boolean> => {
|
||||||
|
return User.me().then(u => u.is_superuser);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Administration",
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
name: "Overview",
|
||||||
|
path: ["/administration/overview-ng/"],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "System Tasks",
|
||||||
|
path: ["/administration/tasks/"],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Applications",
|
||||||
|
path: ["/administration/applications/"],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Sources",
|
||||||
|
path: ["/administration/sources/"],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Providers",
|
||||||
|
path: ["/administration/providers/"],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "User Management",
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
name: "User",
|
||||||
|
path: ["/administration/users/"],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Groups",
|
||||||
|
path: ["/administration/groups/"],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Outposts",
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
name: "Outposts",
|
||||||
|
path: ["/administration/outposts/"],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Service Connections",
|
||||||
|
path: ["/administration/outposts/service_connections/"],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Policies",
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
name: "Policies",
|
||||||
|
path: ["/administration/policies/"],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Bindings",
|
||||||
|
path: ["/administration/policies/bindings/"],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Property Mappings",
|
||||||
|
path: ["/administration/property-mappings/"],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Flows",
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
name: "Flows",
|
||||||
|
path: ["/administration/flows/"],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Stages",
|
||||||
|
path: ["/administration/stages/"],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Prompts",
|
||||||
|
path: ["/administration/stages/prompts/"],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Invitations",
|
||||||
|
path: ["/administration/stages/invitations/"],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Certificates",
|
||||||
|
path: ["/administration/crypto/certificates/"],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Tokens",
|
||||||
|
path: ["/administration/tokens/"],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
condition: (): Promise<boolean> => {
|
||||||
|
return User.me().then(u => u.is_superuser);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
@customElement("pb-interface-admin")
|
||||||
|
export class AdminInterface extends Interface {
|
||||||
|
|
||||||
|
get sidebar(): SidebarItem[] {
|
||||||
|
return SIDEBAR_ITEMS;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
28
web/src/interfaces/Interface.ts
Normal file
28
web/src/interfaces/Interface.ts
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
import { gettext } from "django";
|
||||||
|
import { CSSResult, html, LitElement, TemplateResult } from "lit-element";
|
||||||
|
import { COMMON_STYLES } from "../common/styles";
|
||||||
|
import { SidebarItem } from "../elements/sidebar/Sidebar";
|
||||||
|
|
||||||
|
// @customElement("pb-interface")
|
||||||
|
export abstract class Interface extends LitElement {
|
||||||
|
|
||||||
|
abstract get sidebar(): SidebarItem[];
|
||||||
|
|
||||||
|
static get styles(): CSSResult[] {
|
||||||
|
return COMMON_STYLES;
|
||||||
|
}
|
||||||
|
|
||||||
|
render(): TemplateResult {
|
||||||
|
return html`<pb-messages></pb-messages>
|
||||||
|
<div class="pf-c-page">
|
||||||
|
<a class="pf-c-skip-to-content pf-c-button pf-m-primary" href="#main-content">${gettext("Skip to content")}</a>
|
||||||
|
<pb-sidebar class="pf-c-page__sidebar" .items=${this.sidebar}>
|
||||||
|
</pb-sidebar>
|
||||||
|
<main class="pf-c-page__main">
|
||||||
|
<pb-router-outlet role="main" class="pf-c-page__main" tabindex="-1" id="main-content" defaultUrl="/library/">
|
||||||
|
</pb-router-outlet>
|
||||||
|
</main>
|
||||||
|
</div>`;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -30,3 +30,5 @@ import "./pages/admin-overview/TopApplicationsTable";
|
||||||
import "./pages/applications/ApplicationListPage";
|
import "./pages/applications/ApplicationListPage";
|
||||||
import "./pages/applications/ApplicationViewPage";
|
import "./pages/applications/ApplicationViewPage";
|
||||||
import "./pages/LibraryPage";
|
import "./pages/LibraryPage";
|
||||||
|
|
||||||
|
import "./interfaces/AdminInterface";
|
||||||
|
|
|
@ -114,7 +114,3 @@ select[multiple] {
|
||||||
.pf-c-content h1 :first-child {
|
.pf-c-content h1 :first-child {
|
||||||
margin-right: var(--pf-global--spacer--sm);
|
margin-right: var(--pf-global--spacer--sm);
|
||||||
}
|
}
|
||||||
|
|
||||||
.pf-c-empty-state {
|
|
||||||
height: 100vh;
|
|
||||||
}
|
|
||||||
|
|
Reference in a new issue