web: rewrite aggregate cards to separate components
This commit is contained in:
parent
1179ba4ef2
commit
9e33b49d29
|
@ -1,9 +1,20 @@
|
||||||
import { DefaultClient, PBResponse, QueryArguments } from "./client";
|
import { DefaultClient, PBResponse, QueryArguments } from "./client";
|
||||||
|
|
||||||
export interface Policy {
|
export class Policy {
|
||||||
pk: string;
|
pk: string;
|
||||||
name: string;
|
name: string;
|
||||||
[key: string]: unknown;
|
|
||||||
|
constructor() {
|
||||||
|
throw Error();
|
||||||
|
}
|
||||||
|
|
||||||
|
static get(pk: string): Promise<PolicyBinding> {
|
||||||
|
return DefaultClient.fetch<PolicyBinding>(["policies", "all", pk]);
|
||||||
|
}
|
||||||
|
|
||||||
|
static list(filter?: QueryArguments): Promise<PBResponse<PolicyBinding>> {
|
||||||
|
return DefaultClient.fetch<PBResponse<PolicyBinding>>(["policies", "all"], filter);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class PolicyBinding {
|
export class PolicyBinding {
|
|
@ -0,0 +1,19 @@
|
||||||
|
import { DefaultClient, PBResponse, QueryArguments } from "./client";
|
||||||
|
|
||||||
|
export class Provider {
|
||||||
|
pk: number;
|
||||||
|
name: string;
|
||||||
|
authorization_flow: string;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
throw Error();
|
||||||
|
}
|
||||||
|
|
||||||
|
static get(slug: string): Promise<Provider> {
|
||||||
|
return DefaultClient.fetch<Provider>(["providers", "all", slug]);
|
||||||
|
}
|
||||||
|
|
||||||
|
static list(filter?: QueryArguments): Promise<PBResponse<Provider>> {
|
||||||
|
return DefaultClient.fetch<PBResponse<Provider>>(["providers", "all"], filter);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,7 +1,7 @@
|
||||||
import { gettext } from "django";
|
import { gettext } from "django";
|
||||||
import { customElement, html, property, TemplateResult } from "lit-element";
|
import { customElement, html, property, TemplateResult } from "lit-element";
|
||||||
import { PBResponse } from "../../api/client";
|
import { PBResponse } from "../../api/client";
|
||||||
import { PolicyBinding } from "../../api/policy_binding";
|
import { PolicyBinding } from "../../api/policy";
|
||||||
import { Table } from "../../elements/table/Table";
|
import { Table } from "../../elements/table/Table";
|
||||||
|
|
||||||
import "../../elements/Tabs";
|
import "../../elements/Tabs";
|
||||||
|
|
|
@ -4,50 +4,11 @@ import { AdminOverview } from "../../api/admin_overview";
|
||||||
import { DefaultClient } from "../../api/client";
|
import { DefaultClient } from "../../api/client";
|
||||||
import { User } from "../../api/user";
|
import { User } from "../../api/user";
|
||||||
import { COMMON_STYLES } from "../../common/styles";
|
import { COMMON_STYLES } from "../../common/styles";
|
||||||
import { AggregatePromiseCard } from "../../elements/cards/AggregatePromiseCard";
|
|
||||||
import { SpinnerSize } from "../../elements/Spinner";
|
import { SpinnerSize } from "../../elements/Spinner";
|
||||||
|
|
||||||
import "../../elements/AdminLoginsChart";
|
import "../../elements/AdminLoginsChart";
|
||||||
import "./TopApplicationsTable";
|
import "./TopApplicationsTable";
|
||||||
|
import "./OverviewCards";
|
||||||
@customElement("ak-admin-status-card")
|
|
||||||
export class AdminStatusCard extends AggregatePromiseCard {
|
|
||||||
|
|
||||||
@property({type: Number})
|
|
||||||
value?: number;
|
|
||||||
|
|
||||||
@property()
|
|
||||||
warningText?: string;
|
|
||||||
|
|
||||||
@property({type: Number})
|
|
||||||
lessThanThreshold?: number;
|
|
||||||
|
|
||||||
renderNone(): TemplateResult {
|
|
||||||
return html`<ak-spinner size=${SpinnerSize.Large}></ak-spinner>`;
|
|
||||||
}
|
|
||||||
|
|
||||||
renderGood(): TemplateResult {
|
|
||||||
return html`<p class="ak-aggregate-card">
|
|
||||||
<i class="fa fa-check-circle"></i> ${this.value}
|
|
||||||
</p>`;
|
|
||||||
}
|
|
||||||
|
|
||||||
renderBad(): TemplateResult {
|
|
||||||
return html`<p class="ak-aggregate-card">
|
|
||||||
<i class="fa fa-exclamation-triangle"></i> ${this.value}
|
|
||||||
</p>
|
|
||||||
<p class="subtext">${this.warningText ? gettext(this.warningText) : ""}</p>`;
|
|
||||||
}
|
|
||||||
|
|
||||||
renderInner(): TemplateResult {
|
|
||||||
if (!this.value) {
|
|
||||||
return this.renderNone();
|
|
||||||
}
|
|
||||||
|
|
||||||
return html``;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@customElement("ak-admin-overview")
|
@customElement("ak-admin-overview")
|
||||||
export class AdminOverviewPage extends LitElement {
|
export class AdminOverviewPage extends LitElement {
|
||||||
|
@ -92,30 +53,10 @@ export class AdminOverviewPage extends LitElement {
|
||||||
</p>`
|
</p>`
|
||||||
: html`<ak-spinner size=${SpinnerSize.Large}></ak-spinner>`}
|
: html`<ak-spinner size=${SpinnerSize.Large}></ak-spinner>`}
|
||||||
</ak-aggregate-card>
|
</ak-aggregate-card>
|
||||||
<ak-aggregate-card class="pf-l-gallery__item pf-m-4-col" icon="pf-icon pf-icon-plugged" header="Providers" headerLink="#/administration/providers/">
|
<ak-admin-status-card-provider class="pf-l-gallery__item pf-m-4-col" icon="pf-icon pf-icon-plugged" header="Providers" headerLink="#/administration/providers/">
|
||||||
${this.data ?
|
</ak-admin-status-card-provider>
|
||||||
this.data?.providers_without_application > 1 ?
|
<ak-admin-status-card-policy class="pf-l-gallery__item pf-m-4-col" icon="pf-icon pf-icon-plugged" header="Policies" headerLink="#/administration/policies/">
|
||||||
html`<p class="ak-aggregate-card">
|
</ak-admin-status-card-policy>
|
||||||
<i class="fa fa-exclamation-triangle"></i> 0
|
|
||||||
</p>
|
|
||||||
<p class="subtext">${gettext("At least one Provider has no application assigned.")}</p>` :
|
|
||||||
html`<p class="ak-aggregate-card">
|
|
||||||
<i class="fa fa-check-circle"></i> 0
|
|
||||||
</p>`
|
|
||||||
: html`<ak-spinner size=${SpinnerSize.Large}></ak-spinner>`}
|
|
||||||
</ak-aggregate-card>
|
|
||||||
<ak-aggregate-card class="pf-l-gallery__item pf-m-4-col" icon="pf-icon pf-icon-plugged" header="Policies" headerLink="#/administration/policies/">
|
|
||||||
${this.data ?
|
|
||||||
this.data?.policies_without_binding > 1 ?
|
|
||||||
html`<p class="ak-aggregate-card">
|
|
||||||
<i class="fa fa-exclamation-triangle"></i> 0
|
|
||||||
</p>
|
|
||||||
<p class="subtext">${gettext("Policies without binding exist.")}</p>` :
|
|
||||||
html`<p class="ak-aggregate-card">
|
|
||||||
<i class="fa fa-check-circle"></i> 0
|
|
||||||
</p>`
|
|
||||||
: html`<ak-spinner size=${SpinnerSize.Large}></ak-spinner>`}
|
|
||||||
</ak-aggregate-card>
|
|
||||||
<ak-aggregate-card-promise
|
<ak-aggregate-card-promise
|
||||||
icon="pf-icon pf-icon-user"
|
icon="pf-icon pf-icon-user"
|
||||||
header="Users"
|
header="Users"
|
||||||
|
|
|
@ -0,0 +1,90 @@
|
||||||
|
import { gettext } from "django";
|
||||||
|
import { customElement, property } from "lit-element";
|
||||||
|
import { html, TemplateResult } from "lit-html";
|
||||||
|
import { until } from "lit-html/directives/until";
|
||||||
|
import { Policy } from "../../api/policy";
|
||||||
|
import { Provider } from "../../api/provider";
|
||||||
|
import { AggregateCard } from "../../elements/cards/AggregateCard";
|
||||||
|
import { SpinnerSize } from "../../elements/Spinner";
|
||||||
|
|
||||||
|
interface AdminStatus {
|
||||||
|
icon: string;
|
||||||
|
message?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class AdminStatusCard extends AggregateCard {
|
||||||
|
|
||||||
|
abstract getPrimaryCounter(): Promise<number>;
|
||||||
|
|
||||||
|
abstract getStatus(counter: number): Promise<AdminStatus>;
|
||||||
|
|
||||||
|
@property({type: Number})
|
||||||
|
counter = 0;
|
||||||
|
|
||||||
|
renderInner(): TemplateResult {
|
||||||
|
return html`<p class="center-value">
|
||||||
|
${until(this.getPrimaryCounter().then((c) => {
|
||||||
|
this.counter = c;
|
||||||
|
return this.getStatus(c);
|
||||||
|
}).then((status) => {
|
||||||
|
return html`<p class="ak-aggregate-card">
|
||||||
|
<i class="${status.icon}"></i> ${this.counter}
|
||||||
|
</p>
|
||||||
|
${status.message ? html`<p class="subtext">${status.message}</p>` : html``}`;
|
||||||
|
}), html`<ak-spinner size="${SpinnerSize.Large}"></ak-spinner>`)}
|
||||||
|
</p>`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@customElement("ak-admin-status-card-provider")
|
||||||
|
export class ProviderStatusCard extends AdminStatusCard {
|
||||||
|
|
||||||
|
getPrimaryCounter(): Promise<number> {
|
||||||
|
return Provider.list({
|
||||||
|
"application__isnull": true
|
||||||
|
}).then((response) => {
|
||||||
|
return response.pagination.count;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
getStatus(counter: number): Promise<AdminStatus> {
|
||||||
|
if (counter > 0) {
|
||||||
|
return Promise.resolve<AdminStatus>({
|
||||||
|
icon: "fa fa-exclamation-triangle",
|
||||||
|
message: gettext("Warning: At least one Provider has no application assigned."),
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
return Promise.resolve<AdminStatus>({
|
||||||
|
icon: "fa fa-check-circle"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@customElement("ak-admin-status-card-policy")
|
||||||
|
export class PolicyStatusCard extends AdminStatusCard {
|
||||||
|
|
||||||
|
getPrimaryCounter(): Promise<number> {
|
||||||
|
return Policy.list({
|
||||||
|
"bindings__isnull": true,
|
||||||
|
"promptstage__isnull": true,
|
||||||
|
}).then((response) => {
|
||||||
|
return response.pagination.count;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
getStatus(counter: number): Promise<AdminStatus> {
|
||||||
|
if (counter > 0) {
|
||||||
|
return Promise.resolve<AdminStatus>({
|
||||||
|
icon: "fa fa-exclamation-triangle",
|
||||||
|
message: gettext("Policies without binding exist."),
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
return Promise.resolve<AdminStatus>({
|
||||||
|
icon: "fa fa-check-circle"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Reference in New Issue