enterprise: add more info to enterprise forecast (#6292)
* add more info to enterprise forecast Signed-off-by: Jens Langhammer <jens@goauthentik.io> * fix banner colour Signed-off-by: Jens Langhammer <jens@goauthentik.io> * fix some layout Signed-off-by: Jens Langhammer <jens@goauthentik.io> * fix layout for warning banner Signed-off-by: Jens Langhammer <jens@goauthentik.io> --------- Signed-off-by: Jens Langhammer <jens@goauthentik.io>
This commit is contained in:
parent
c1eef9278d
commit
b6e8342466
|
@ -64,6 +64,8 @@ class LicenseForecastSerializer(PassiveSerializer):
|
|||
|
||||
users = IntegerField(required=True)
|
||||
external_users = IntegerField(required=True)
|
||||
forecasted_users = IntegerField(required=True)
|
||||
forecasted_external_users = IntegerField(required=True)
|
||||
|
||||
|
||||
class LicenseViewSet(UsedByMixin, ModelViewSet):
|
||||
|
@ -142,8 +144,10 @@ class LicenseViewSet(UsedByMixin, ModelViewSet):
|
|||
forecast_for_months = 12
|
||||
response = LicenseForecastSerializer(
|
||||
data={
|
||||
"users": users_in_last_month * forecast_for_months,
|
||||
"external_users": external_in_last_month * forecast_for_months,
|
||||
"users": LicenseKey.get_default_user_count(),
|
||||
"external_users": LicenseKey.get_external_user_count(),
|
||||
"forecasted_users": (users_in_last_month * forecast_for_months),
|
||||
"forecasted_external_users": (external_in_last_month * forecast_for_months),
|
||||
}
|
||||
)
|
||||
response.is_valid(raise_exception=True)
|
||||
|
|
|
@ -31746,8 +31746,14 @@ components:
|
|||
type: integer
|
||||
external_users:
|
||||
type: integer
|
||||
forecasted_users:
|
||||
type: integer
|
||||
forecasted_external_users:
|
||||
type: integer
|
||||
required:
|
||||
- external_users
|
||||
- forecasted_external_users
|
||||
- forecasted_users
|
||||
- users
|
||||
LicenseRequest:
|
||||
type: object
|
||||
|
|
|
@ -75,17 +75,7 @@ export class AdminInterface extends Interface {
|
|||
.display-none {
|
||||
display: none;
|
||||
}
|
||||
:host {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
}
|
||||
ak-locale-context {
|
||||
display: flex;
|
||||
flex-grow: 1;
|
||||
}
|
||||
.pf-c-page {
|
||||
flex-grow: 1;
|
||||
background-color: var(--pf-c-page--BackgroundColor) !important;
|
||||
}
|
||||
/* Global page background colour */
|
||||
|
@ -130,8 +120,7 @@ export class AdminInterface extends Interface {
|
|||
}
|
||||
|
||||
render(): TemplateResult {
|
||||
return html` <ak-locale-context
|
||||
><ak-enterprise-status interface="admin"></ak-enterprise-status>
|
||||
return html` <ak-locale-context>
|
||||
<div class="pf-c-page">
|
||||
<ak-sidebar
|
||||
class="pf-c-page__sidebar ${this.sidebarOpen
|
||||
|
|
|
@ -11,7 +11,7 @@ import { PaginatedResponse } from "@goauthentik/elements/table/Table";
|
|||
import { TableColumn } from "@goauthentik/elements/table/Table";
|
||||
import { TablePage } from "@goauthentik/elements/table/TablePage";
|
||||
|
||||
import { msg } from "@lit/localize";
|
||||
import { msg, str } from "@lit/localize";
|
||||
import { CSSResult, TemplateResult, css, html } from "lit";
|
||||
import { customElement, property, state } from "lit/decorators.js";
|
||||
|
||||
|
@ -148,17 +148,23 @@ export class EnterpriseLicenseListPage extends TablePage<License> {
|
|||
class="pf-l-grid__item"
|
||||
icon="pf-icon pf-icon-user"
|
||||
header=${msg("Forecast default users")}
|
||||
subtext=${msg("Estimated user count one year from now")}
|
||||
subtext=${msg(
|
||||
str`Estimated user count one year from now based on ${this.forecast?.users} current users and ${this.forecast?.forecastedUsers} forecasted users.`,
|
||||
)}
|
||||
>
|
||||
~ ${this.forecast?.users}
|
||||
~ ${(this.forecast?.users || 0) +
|
||||
(this.forecast?.forecastedUsers || 0)}
|
||||
</ak-aggregate-card>
|
||||
<ak-aggregate-card
|
||||
class="pf-l-grid__item"
|
||||
icon="pf-icon pf-icon-user"
|
||||
header=${msg("Forecast external users")}
|
||||
subtext=${msg("Estimated external user count one year from now")}
|
||||
subtext=${msg(
|
||||
str`Estimated user count one year from now based on ${this.forecast?.externalUsers} current external users and ${this.forecast?.forecastedExternalUsers} forecasted external users.`,
|
||||
)}
|
||||
>
|
||||
~ ${this.forecast?.externalUsers}
|
||||
~ ${(this.forecast?.externalUsers || 0) +
|
||||
(this.forecast?.forecastedExternalUsers || 0)}
|
||||
</ak-aggregate-card>
|
||||
<ak-aggregate-card
|
||||
class="pf-l-grid__item"
|
||||
|
|
|
@ -63,7 +63,7 @@ export class PageHeader extends AKElement {
|
|||
PFPage,
|
||||
PFContent,
|
||||
css`
|
||||
:host {
|
||||
.bar {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
min-height: 114px;
|
||||
|
@ -126,55 +126,58 @@ export class PageHeader extends AKElement {
|
|||
}
|
||||
|
||||
render(): TemplateResult {
|
||||
return html`<button
|
||||
class="sidebar-trigger pf-c-button pf-m-plain"
|
||||
@click=${() => {
|
||||
this.dispatchEvent(
|
||||
new CustomEvent(EVENT_SIDEBAR_TOGGLE, {
|
||||
bubbles: true,
|
||||
composed: true,
|
||||
}),
|
||||
);
|
||||
}}
|
||||
>
|
||||
<i class="fas fa-bars"></i>
|
||||
</button>
|
||||
<section class="pf-c-page__main-section pf-m-light">
|
||||
<div class="pf-c-content">
|
||||
<h1>
|
||||
${this.renderIcon()}
|
||||
<slot name="header"> ${this.header} </slot>
|
||||
</h1>
|
||||
${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_DRAWER_TOGGLE, {
|
||||
bubbles: true,
|
||||
composed: true,
|
||||
}),
|
||||
);
|
||||
}}
|
||||
>
|
||||
<i class="fas fa-bell"></i>
|
||||
</button> `;
|
||||
return html` <ak-enterprise-status interface="admin"></ak-enterprise-status>
|
||||
<div class="bar">
|
||||
<button
|
||||
class="sidebar-trigger pf-c-button pf-m-plain"
|
||||
@click=${() => {
|
||||
this.dispatchEvent(
|
||||
new CustomEvent(EVENT_SIDEBAR_TOGGLE, {
|
||||
bubbles: true,
|
||||
composed: true,
|
||||
}),
|
||||
);
|
||||
}}
|
||||
>
|
||||
<i class="fas fa-bars"></i>
|
||||
</button>
|
||||
<section class="pf-c-page__main-section pf-m-light">
|
||||
<div class="pf-c-content">
|
||||
<h1>
|
||||
${this.renderIcon()}
|
||||
<slot name="header"> ${this.header} </slot>
|
||||
</h1>
|
||||
${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_DRAWER_TOGGLE, {
|
||||
bubbles: true,
|
||||
composed: true,
|
||||
}),
|
||||
);
|
||||
}}
|
||||
>
|
||||
<i class="fas fa-bell"></i>
|
||||
</button>
|
||||
</div>`;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,7 +28,7 @@ export class EnterpriseStatusBanner extends AKElement {
|
|||
}
|
||||
|
||||
renderBanner(): TemplateResult {
|
||||
return html`<div class="pf-c-banner ${this.summary?.readOnly ? "pf-m-red" : "pf-m-orange"}">
|
||||
return html`<div class="pf-c-banner ${this.summary?.readOnly ? "pf-m-red" : "pf-m-gold"}">
|
||||
${msg("Warning: The current user count has exceeded the configured licenses.")}
|
||||
<a href="/if/admin/#/enterprise/licenses"> ${msg("Click here for more info.")} </a>
|
||||
</div>`;
|
||||
|
|
|
@ -94,6 +94,12 @@ export class UserInterface extends Interface {
|
|||
width: 100vw;
|
||||
position: absolute;
|
||||
z-index: -1;
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
ak-locale-context {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
`,
|
||||
];
|
||||
|
|
Reference in New Issue