web: add API Drawer
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
This commit is contained in:
parent
562eb8af95
commit
fdd8e66b91
|
@ -1,6 +1,6 @@
|
|||
import { Config, Configuration, CoreApi, CurrentTenant, Middleware, ResponseContext, RootApi, Tenant } from "authentik-api";
|
||||
import { getCookie } from "../utils";
|
||||
import { API_DRAWER_MIDDLEWARE } from "../elements/notifications/APIDrawer";
|
||||
import { APIMiddleware } from "../elements/notifications/APIDrawer";
|
||||
import { MessageMiddleware } from "../elements/messages/Middleware";
|
||||
|
||||
export class LoggingMiddleware implements Middleware {
|
||||
|
@ -62,7 +62,7 @@ export const DEFAULT_CONFIG = new Configuration({
|
|||
"X-CSRFToken": getCookie("authentik_csrf"),
|
||||
},
|
||||
middleware: [
|
||||
API_DRAWER_MIDDLEWARE,
|
||||
new APIMiddleware(),
|
||||
new MessageMiddleware(),
|
||||
new LoggingMiddleware(),
|
||||
],
|
||||
|
|
|
@ -230,6 +230,9 @@ body {
|
|||
.pf-c-form-control[readonly] {
|
||||
background-color: var(--ak-dark-background-light);
|
||||
}
|
||||
.pf-c-button.pf-m-plain:hover {
|
||||
color: var(--ak-dark-foreground);
|
||||
}
|
||||
.pf-c-button.pf-m-control {
|
||||
--pf-c-button--after--BorderColor: var(--ak-dark-background-lighter)
|
||||
var(--ak-dark-background-lighter)
|
||||
|
|
|
@ -9,7 +9,8 @@ export const TITLE_DEFAULT = "authentik";
|
|||
export const ROUTE_SEPARATOR = ";";
|
||||
|
||||
export const EVENT_REFRESH = "ak-refresh";
|
||||
export const EVENT_NOTIFICATION_TOGGLE = "ak-notification-toggle";
|
||||
export const EVENT_NOTIFICATION_DRAWER_TOGGLE = "ak-notification-toggle";
|
||||
export const EVENT_API_DRAWER_TOGGLE = "ak-api-drawer-toggle";
|
||||
export const EVENT_SIDEBAR_TOGGLE = "ak-sidebar-toggle";
|
||||
export const EVENT_API_DRAWER_REFRESH = "ak-api-drawer-refresh";
|
||||
export const EVENT_WS_MESSAGE = "ak-ws-message";
|
||||
|
|
|
@ -12,7 +12,7 @@ import PFContent from "@patternfly/patternfly/components/Content/content.css";
|
|||
import AKGlobal from "../authentik.css";
|
||||
import PFBase from "@patternfly/patternfly/patternfly-base.css";
|
||||
import PFButton from "@patternfly/patternfly/components/Button/button.css";
|
||||
import { EVENT_NOTIFICATION_TOGGLE, EVENT_SIDEBAR_TOGGLE, TITLE_DEFAULT } from "../constants";
|
||||
import { EVENT_API_DRAWER_TOGGLE, EVENT_NOTIFICATION_DRAWER_TOGGLE, EVENT_SIDEBAR_TOGGLE, TITLE_DEFAULT } from "../constants";
|
||||
import { DEFAULT_CONFIG, tenant } from "../api/Config";
|
||||
import { EventsApi } from "../../api/dist";
|
||||
|
||||
|
@ -127,13 +127,26 @@ export class PageHeader extends LitElement {
|
|||
${this.description ? html`<p>${this.description}</p>` : html``}
|
||||
</div>
|
||||
</section>
|
||||
<button
|
||||
class="notification-trigger pf-c-button pf-m-plain"
|
||||
@click=${() => {
|
||||
this.dispatchEvent(
|
||||
new CustomEvent(EVENT_API_DRAWER_TOGGLE, {
|
||||
bubbles: true,
|
||||
composed: true,
|
||||
}),
|
||||
);
|
||||
}}
|
||||
>
|
||||
<i class="fas fa-code"></i>
|
||||
</button>
|
||||
<button
|
||||
class="notification-trigger pf-c-button pf-m-plain ${this.hasNotifications
|
||||
? "has-notifications"
|
||||
: ""}"
|
||||
@click=${() => {
|
||||
this.dispatchEvent(
|
||||
new CustomEvent(EVENT_NOTIFICATION_TOGGLE, {
|
||||
new CustomEvent(EVENT_NOTIFICATION_DRAWER_TOGGLE, {
|
||||
bubbles: true,
|
||||
composed: true,
|
||||
}),
|
||||
|
@ -141,6 +154,7 @@ export class PageHeader extends LitElement {
|
|||
}}
|
||||
>
|
||||
<i class="fas fa-bell"></i>
|
||||
</button>`;
|
||||
</button>
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,77 +1,114 @@
|
|||
import { Middleware, ResponseContext } from "authentik-api";
|
||||
import { CSSResult, customElement, html, LitElement, TemplateResult } from "lit-element";
|
||||
import { css, CSSResult, customElement, html, LitElement, property, TemplateResult } from "lit-element";
|
||||
import PFBase from "@patternfly/patternfly/patternfly-base.css";
|
||||
import PFNotificationDrawer from "@patternfly/patternfly/components/NotificationDrawer/notification-drawer.css";
|
||||
import PFDropdown from "@patternfly/patternfly/components/Dropdown/dropdown.css";
|
||||
import AKGlobal from "../../authentik.css";
|
||||
import PFButton from "@patternfly/patternfly/components/Button/button.css";
|
||||
import PFContent from "@patternfly/patternfly/components/Content/content.css";
|
||||
import AKGlobal from "../../authentik.css";
|
||||
import { t } from "@lingui/macro";
|
||||
import { EVENT_API_DRAWER_REFRESH } from "../../constants";
|
||||
import { EVENT_API_DRAWER_REFRESH, EVENT_API_DRAWER_TOGGLE } from "../../constants";
|
||||
|
||||
export interface RequestInfo {
|
||||
method: string;
|
||||
path: string;
|
||||
status: number;
|
||||
}
|
||||
|
||||
export class APIMiddleware implements Middleware {
|
||||
requests: RequestInfo[];
|
||||
|
||||
constructor() {
|
||||
this.requests = [];
|
||||
}
|
||||
|
||||
post?(context: ResponseContext): Promise<Response | void> {
|
||||
this.requests.push({
|
||||
const request: RequestInfo = {
|
||||
method: (context.init.method || "GET").toUpperCase(),
|
||||
path: context.url,
|
||||
});
|
||||
if (this.requests.length > MAX_REQUESTS) {
|
||||
this.requests.shift();
|
||||
}
|
||||
status: context.response.status,
|
||||
};
|
||||
window.dispatchEvent(
|
||||
new CustomEvent(EVENT_API_DRAWER_REFRESH, {
|
||||
bubbles: true,
|
||||
composed: true,
|
||||
detail: request,
|
||||
}),
|
||||
);
|
||||
return Promise.resolve(context.response);
|
||||
}
|
||||
}
|
||||
|
||||
export const MAX_REQUESTS = 50;
|
||||
export const API_DRAWER_MIDDLEWARE = new APIMiddleware();
|
||||
}
|
||||
|
||||
@customElement("ak-api-drawer")
|
||||
export class APIDrawer extends LitElement {
|
||||
|
||||
@property({attribute: false})
|
||||
requests: RequestInfo[] = [];
|
||||
|
||||
static get styles(): CSSResult[] {
|
||||
return [PFBase, PFNotificationDrawer, PFContent, PFDropdown, AKGlobal];
|
||||
return [PFBase, PFNotificationDrawer, PFButton, PFContent, PFDropdown, AKGlobal, css`
|
||||
.pf-c-notification-drawer__header {
|
||||
height: 114px;
|
||||
align-items: center;
|
||||
}
|
||||
.pf-c-notification-drawer__header-action,
|
||||
.pf-c-notification-drawer__header-action-close,
|
||||
.pf-c-notification-drawer__header-action-close > .pf-c-button.pf-m-plain {
|
||||
height: 100%;
|
||||
}
|
||||
.pf-c-notification-drawer__list-item-description {
|
||||
white-space: pre-wrap;
|
||||
font-family: monospace;
|
||||
}
|
||||
`];
|
||||
}
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.addEventListener(EVENT_API_DRAWER_REFRESH, () => {
|
||||
window.addEventListener(EVENT_API_DRAWER_REFRESH, ((e: CustomEvent<RequestInfo>) => {
|
||||
this.requests.splice(0, 0, e.detail);
|
||||
if (this.requests.length > 50) {
|
||||
this.requests.shift();
|
||||
}
|
||||
this.requestUpdate();
|
||||
});
|
||||
}) as EventListener);
|
||||
}
|
||||
|
||||
renderItem(item: RequestInfo): TemplateResult {
|
||||
return html`<li class="pf-c-notification-drawer__list-item pf-m-read">
|
||||
<div class="pf-c-notification-drawer__list-item-header">
|
||||
<h2 class="pf-c-notification-drawer__list-item-header-title">${item.method}</h2>
|
||||
<h2 class="pf-c-notification-drawer__list-item-header-title">${item.method}: ${item.status}</h2>
|
||||
</div>
|
||||
<p class="pf-c-notification-drawer__list-item-description">${item.path}</p>
|
||||
<a class="pf-c-notification-drawer__list-item-description" href=${item.path}>${item.path}</a>
|
||||
</li>`;
|
||||
}
|
||||
|
||||
render(): TemplateResult {
|
||||
return html`<div class="pf-c-drawer__body pf-m-no-padding">
|
||||
<div class="pf-c-notification-drawer">
|
||||
<div class="pf-c-notification-drawer__header pf-c-content">
|
||||
<h1>${t`API Requests`}</h1>
|
||||
<div class="pf-c-notification-drawer__header">
|
||||
<div class="text">
|
||||
<h1 class="pf-c-notification-drawer__header-title">${t`API Requests`}</h1>
|
||||
</div>
|
||||
<div class="pf-c-notification-drawer__header-action">
|
||||
<div class="pf-c-notification-drawer__header-action-close">
|
||||
<button
|
||||
@click=${() => {
|
||||
this.dispatchEvent(
|
||||
new CustomEvent(EVENT_API_DRAWER_TOGGLE, {
|
||||
bubbles: true,
|
||||
composed: true,
|
||||
}),
|
||||
);
|
||||
}}
|
||||
class="pf-c-button pf-m-plain"
|
||||
type="button"
|
||||
aria-label="Close"
|
||||
>
|
||||
<i class="fas fa-times" aria-hidden="true"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="pf-c-notification-drawer__body">
|
||||
<ul class="pf-c-notification-drawer__list">
|
||||
${API_DRAWER_MIDDLEWARE.requests.map((n) => this.renderItem(n))}
|
||||
${this.requests.map((n) => this.renderItem(n))}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -17,7 +17,7 @@ import PFDropdown from "@patternfly/patternfly/components/Dropdown/dropdown.css"
|
|||
import PFButton from "@patternfly/patternfly/components/Button/button.css";
|
||||
import AKGlobal from "../../authentik.css";
|
||||
import PFContent from "@patternfly/patternfly/components/Content/content.css";
|
||||
import { EVENT_NOTIFICATION_TOGGLE } from "../../constants";
|
||||
import { EVENT_NOTIFICATION_DRAWER_TOGGLE } from "../../constants";
|
||||
import { ActionToLabel } from "../../pages/events/utils";
|
||||
|
||||
@customElement("ak-notification-drawer")
|
||||
|
@ -135,7 +135,7 @@ export class NotificationDrawer extends LitElement {
|
|||
<button
|
||||
@click=${() => {
|
||||
this.dispatchEvent(
|
||||
new CustomEvent(EVENT_NOTIFICATION_TOGGLE, {
|
||||
new CustomEvent(EVENT_NOTIFICATION_DRAWER_TOGGLE, {
|
||||
bubbles: true,
|
||||
composed: true,
|
||||
}),
|
||||
|
|
|
@ -24,7 +24,7 @@ import "../elements/messages/MessageContainer";
|
|||
import "../elements/notifications/NotificationDrawer";
|
||||
import "../elements/sidebar/Sidebar";
|
||||
import { until } from "lit-html/directives/until";
|
||||
import { EVENT_NOTIFICATION_TOGGLE, EVENT_SIDEBAR_TOGGLE, VERSION } from "../constants";
|
||||
import { EVENT_API_DRAWER_TOGGLE, EVENT_NOTIFICATION_DRAWER_TOGGLE, EVENT_SIDEBAR_TOGGLE, VERSION } from "../constants";
|
||||
import { AdminApi } from "authentik-api";
|
||||
import { DEFAULT_CONFIG } from "../api/Config";
|
||||
import { WebsocketClient } from "../common/ws";
|
||||
|
@ -37,6 +37,9 @@ export class AdminInterface extends LitElement {
|
|||
@property({ type: Boolean })
|
||||
notificationOpen = false;
|
||||
|
||||
@property({ type: Boolean })
|
||||
apiDrawerOpen = false;
|
||||
|
||||
ws: WebsocketClient;
|
||||
|
||||
static get styles(): CSSResult[] {
|
||||
|
@ -67,9 +70,12 @@ export class AdminInterface extends LitElement {
|
|||
window.addEventListener(EVENT_SIDEBAR_TOGGLE, () => {
|
||||
this.sidebarOpen = !this.sidebarOpen;
|
||||
});
|
||||
window.addEventListener(EVENT_NOTIFICATION_TOGGLE, () => {
|
||||
window.addEventListener(EVENT_NOTIFICATION_DRAWER_TOGGLE, () => {
|
||||
this.notificationOpen = !this.notificationOpen;
|
||||
});
|
||||
window.addEventListener(EVENT_API_DRAWER_TOGGLE, () => {
|
||||
this.apiDrawerOpen = !this.apiDrawerOpen;
|
||||
});
|
||||
}
|
||||
|
||||
render(): TemplateResult {
|
||||
|
@ -81,7 +87,7 @@ export class AdminInterface extends LitElement {
|
|||
</ak-sidebar>
|
||||
<div class="pf-c-page__drawer">
|
||||
<div
|
||||
class="pf-c-drawer ${this.notificationOpen
|
||||
class="pf-c-drawer ${this.notificationOpen || this.apiDrawerOpen
|
||||
? "pf-m-expanded"
|
||||
: "pf-m-collapsed"}"
|
||||
>
|
||||
|
@ -100,8 +106,8 @@ export class AdminInterface extends LitElement {
|
|||
</main>
|
||||
</div>
|
||||
</div>
|
||||
<ak-notification-drawer class="pf-c-drawer__panel pf-m-width-33">
|
||||
</ak-notification-drawer>
|
||||
${this.notificationOpen ? html`<ak-notification-drawer class="pf-c-drawer__panel pf-m-width-33"></ak-notification-drawer>` : html``}
|
||||
${this.apiDrawerOpen ? html`<ak-api-drawer class="pf-c-drawer__panel pf-m-width-33"></ak-api-drawer>` : html``}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -77,16 +77,7 @@ export class TransportListPage extends TablePage<NotificationTransport> {
|
|||
return [
|
||||
html`${item.name}`,
|
||||
html`${item.modeVerbose}`,
|
||||
html` <ak-action-button
|
||||
.apiRequest=${() => {
|
||||
return new EventsApi(DEFAULT_CONFIG).eventsTransportsTestCreate({
|
||||
uuid: item.pk || "",
|
||||
});
|
||||
}}
|
||||
>
|
||||
${t`Test`}
|
||||
</ak-action-button>
|
||||
<ak-forms-modal>
|
||||
html`<ak-forms-modal>
|
||||
<span slot="submit"> ${t`Update`} </span>
|
||||
<span slot="header"> ${t`Update Notification Transport`} </span>
|
||||
<ak-event-transport-form slot="form" .instancePk=${item.pk}>
|
||||
|
@ -94,7 +85,16 @@ export class TransportListPage extends TablePage<NotificationTransport> {
|
|||
<button slot="trigger" class="pf-c-button pf-m-plain">
|
||||
<i class="fas fa-edit"></i>
|
||||
</button>
|
||||
</ak-forms-modal>`,
|
||||
</ak-forms-modal>
|
||||
<ak-action-button
|
||||
.apiRequest=${() => {
|
||||
return new EventsApi(DEFAULT_CONFIG).eventsTransportsTestCreate({
|
||||
uuid: item.pk || "",
|
||||
});
|
||||
}}
|
||||
>
|
||||
<i class="fas fa-vial" aria-hidden="true"></i>
|
||||
</ak-action-button>`,
|
||||
];
|
||||
}
|
||||
|
||||
|
|
Reference in New Issue