web: start implementing admin overview page
This commit is contained in:
parent
760dca0f76
commit
93bf977709
|
@ -3,7 +3,7 @@
|
|||
"scripts": {
|
||||
"build": "rollup -c ./rollup.config.js",
|
||||
"watch": "rollup -c -w",
|
||||
"format": "prettier --write ."
|
||||
"lint": "eslint . --ext .js,.jsx,.ts,.tsx --fix"
|
||||
},
|
||||
"dependencies": {
|
||||
"@fortawesome/fontawesome-free": "^5.15.1",
|
||||
|
|
|
@ -43,6 +43,6 @@ export default [
|
|||
watch: {
|
||||
clearScreen: false,
|
||||
},
|
||||
external: ['django']
|
||||
external: ["django"]
|
||||
},
|
||||
];
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
import { DefaultClient } from "./client";
|
||||
|
||||
export class AdminOverview {
|
||||
version?: string;
|
||||
version_latest?: string;
|
||||
worker_count?: number;
|
||||
providers_without_application?: number;
|
||||
policies_without_binding?: number;
|
||||
cached_policies?: number;
|
||||
cached_flows?: number;
|
||||
|
||||
static get(): Promise<AdminOverview> {
|
||||
return DefaultClient.fetch<AdminOverview>(["admin", "overview"]);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
declare module 'django' {
|
||||
declare module "django" {
|
||||
export = django;
|
||||
}
|
||||
declare namespace django {
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
import { gettext } from "django";
|
||||
import { customElement, html, LitElement, property, TemplateResult } from "lit-element";
|
||||
// @ts-ignore
|
||||
import SpinnerStyle from "@patternfly/patternfly/components/Spinner/spinner.css";
|
||||
|
||||
export enum SpinnerSize {
|
||||
Small = "pf-m-sm",
|
||||
Medium = "pf-m-md",
|
||||
Large = "pf-m-lg",
|
||||
XLarge = "pf-m-xl",
|
||||
}
|
||||
|
||||
@customElement("pb-spinner")
|
||||
export class Spinner extends LitElement {
|
||||
@property()
|
||||
size: SpinnerSize = SpinnerSize.Medium;
|
||||
|
||||
static get styles() {
|
||||
return [SpinnerStyle];
|
||||
}
|
||||
|
||||
render(): TemplateResult {
|
||||
return html`<span
|
||||
class="pf-c-spinner ${this.size.toString()}"
|
||||
role="progressbar"
|
||||
aria-valuetext="${gettext("Loading...")}">
|
||||
<span class="pf-c-spinner__clipper"></span>
|
||||
<span class="pf-c-spinner__lead-ball"></span>
|
||||
<span class="pf-c-spinner__tail-ball"></span>
|
||||
</span>`;
|
||||
}
|
||||
|
||||
}
|
|
@ -86,8 +86,8 @@ export abstract class Table<T> extends LitElement {
|
|||
<thead>
|
||||
<tr role="row">
|
||||
${this.columns().map(
|
||||
(col) => html`<th role="columnheader" scope="col">${gettext(col)}</th>`
|
||||
)}
|
||||
(col) => html`<th role="columnheader" scope="col">${gettext(col)}</th>`
|
||||
)}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody role="rowgroup">
|
||||
|
|
|
@ -13,9 +13,11 @@ import "./elements/sidebar/Sidebar";
|
|||
import "./elements/sidebar/SidebarBrand";
|
||||
import "./elements/sidebar/SidebarUser";
|
||||
import "./elements/Tabs";
|
||||
import "./elements/Spinner";
|
||||
import "./elements/table/TablePagination";
|
||||
import "./pages/applications/ApplicationViewPage";
|
||||
import "./pages/applications/ApplicationListPage";
|
||||
import "./pages/AdminOverviewPage";
|
||||
import "./pages/LibraryPage";
|
||||
import "./pages/FlowShellCard";
|
||||
import "./pages/RouterOutlet";
|
||||
|
|
|
@ -0,0 +1,74 @@
|
|||
import { gettext } from "django";
|
||||
import { customElement, html, LitElement, property, TemplateResult } from "lit-element";
|
||||
import { AdminOverview } from "../api/admin_overview";
|
||||
import { DefaultClient } from "../api/client";
|
||||
import { COMMON_STYLES } from "../common/styles";
|
||||
|
||||
@customElement("pb-aggregate-card")
|
||||
export class AggregateCard extends LitElement {
|
||||
@property()
|
||||
icon?: string;
|
||||
|
||||
@property()
|
||||
header?: string;
|
||||
|
||||
static get styles() {
|
||||
return COMMON_STYLES;
|
||||
}
|
||||
|
||||
render(): TemplateResult {
|
||||
return html`<div class="pf-c-card pf-c-card-aggregate pf-l-gallery__item pf-m-4-col" >
|
||||
<div class="pf-c-card__header">
|
||||
<div class="pf-c-card__header-main">
|
||||
<i class="${this.icon}"></i> ${this.header ? gettext(this.header) : ""}
|
||||
</div>
|
||||
</div>
|
||||
<div class="pf-c-card__body">
|
||||
<slot></slot>
|
||||
</div>
|
||||
</div>`;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@customElement("pb-admin-overview")
|
||||
export class AdminOverviewPage extends LitElement {
|
||||
@property()
|
||||
data?: AdminOverview;
|
||||
|
||||
static get styles() {
|
||||
return COMMON_STYLES;
|
||||
}
|
||||
|
||||
firstUpdated(): void {
|
||||
AdminOverview.get().then(value => this.data = value);
|
||||
}
|
||||
|
||||
render(): TemplateResult {
|
||||
return html`<section class="pf-c-page__main-section pf-m-light">
|
||||
<div class="pf-c-content">
|
||||
<h1>${gettext("System Overview")}</h1>
|
||||
</div>
|
||||
</section>
|
||||
<section class="pf-c-page__main-section">
|
||||
<div class="pf-l-gallery pf-m-gutter">
|
||||
<pb-aggregate-card icon="pf-icon pf-icon-server" header="Logins over the last 24 hours" style="grid-column-end: span 3;grid-row-end: span 2;">
|
||||
<pb-admin-logins-chart url="${DefaultClient.makeUrl(["admin", "metrics"])}"></pb-admin-logins-chart>
|
||||
</pb-aggregate-card>
|
||||
<pb-aggregate-card icon="pf-icon pf-icon-server" header="Workers">
|
||||
${this.data ?
|
||||
this.data?.worker_count! < 1 ?
|
||||
html`<p class="pb-aggregate-card">
|
||||
<i class="fa fa-exclamation-triangle"></i> ${this.data.worker_count}
|
||||
</p>
|
||||
<p>${gettext("No workers connected.")}</p>` :
|
||||
html`<p class="pb-aggregate-card">
|
||||
<i class="fa fa-check-circle"></i> ${this.data.worker_count}
|
||||
</p>`
|
||||
: html`<pb-spinner></pb-spinner>`}
|
||||
</pb-aggregate-card>
|
||||
</div>
|
||||
</section>`;
|
||||
}
|
||||
|
||||
}
|
|
@ -52,6 +52,7 @@ export const ROUTES: Route[] = [
|
|||
new Route(new RegExp("^/$")).redirect("/library/"),
|
||||
new Route(new RegExp("^#.*")).redirect("/library/"),
|
||||
new Route(new RegExp("^/library/$"), html`<pb-library></pb-library>`),
|
||||
new Route(new RegExp("^/administration/overview/$"), html`<pb-admin-overview></pb-admin-overview>`),
|
||||
new Route(new RegExp("^/applications/$"), html`<pb-application-list></pb-application-list>`),
|
||||
new Route(new RegExp(`^/applications/(?<slug>${SLUG_REGEX})/$`)).then((args) => {
|
||||
return html`<pb-application-view .args=${args}></pb-application-view>`;
|
||||
|
|
|
@ -98,23 +98,15 @@ export class SiteShell extends LitElement {
|
|||
}
|
||||
|
||||
render() {
|
||||
return html` ${this.loading
|
||||
? html`<div class="pf-c-backdrop">
|
||||
<div class="pf-l-bullseye">
|
||||
<div class="pf-l-bullseye__item">
|
||||
<span
|
||||
class="pf-c-spinner pf-m-xl"
|
||||
role="progressbar"
|
||||
aria-valuetext="Loading..."
|
||||
>
|
||||
<span class="pf-c-spinner__clipper"></span>
|
||||
<span class="pf-c-spinner__lead-ball"></span>
|
||||
<span class="pf-c-spinner__tail-ball"></span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>`
|
||||
return html` ${this.loading ?
|
||||
html`<div class="pf-c-backdrop">
|
||||
<div class="pf-l-bullseye">
|
||||
<div class="pf-l-bullseye__item">
|
||||
<pb-spinner></pb-spinner>
|
||||
</div>
|
||||
</div>
|
||||
</div>`
|
||||
: ""}
|
||||
<slot name="body"> </slot>`;
|
||||
<slot name="body"></slot>`;
|
||||
}
|
||||
}
|
||||
|
|
Reference in New Issue