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:
Jens L 2023-07-18 23:24:44 +02:00 committed by GitHub
parent c1eef9278d
commit b6e8342466
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 85 additions and 71 deletions

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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.`,
)}
>
~&nbsp;${this.forecast?.users}
~&nbsp;${(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.`,
)}
>
~&nbsp;${this.forecast?.externalUsers}
~&nbsp;${(this.forecast?.externalUsers || 0) +
(this.forecast?.forecastedExternalUsers || 0)}
</ak-aggregate-card>
<ak-aggregate-card
class="pf-l-grid__item"

View File

@ -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>`;
}
}

View File

@ -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>`;

View File

@ -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;
}
`,
];