feat(site): show license utilization in general settings (#15683)

This PR is the first iteration towards #15297

We cannot yet show license utilization over time, so we show current
license utilization.
This is because we don't track user states over time. We only track the
current user state. A graph over time filtering by active users would
therefore not account for day to day changes in user state and be
inaccurate.
DB schema migrations and related updates will follow that allow us to
show license utilization over time.


![image](https://github.com/user-attachments/assets/91bd6e8c-e74c-4ef5-aa6b-271fd245da37)

---------

Co-authored-by: ケイラ <mckayla@hey.com>
This commit is contained in:
Sas Swart
2024-12-02 21:27:43 +02:00
committed by GitHub
co-authored by ケイラ
parent d5d306f01d
commit 7e1ac2e22b
2 changed files with 110 additions and 0 deletions
@@ -42,6 +42,7 @@ const meta: Meta<typeof GeneralSettingsPageView> = {
deploymentDAUs: MockDeploymentDAUResponse,
invalidExperiments: [],
safeExperiments: [],
entitlements: undefined,
},
};
@@ -136,3 +137,74 @@ export const invalidExperimentsEnabled: Story = {
invalidExperiments: ["invalid"],
},
};
export const WithLicenseUtilization: Story = {
args: {
entitlements: {
...MockEntitlementsWithUserLimit,
features: {
...MockEntitlementsWithUserLimit.features,
user_limit: {
...MockEntitlementsWithUserLimit.features.user_limit,
enabled: true,
actual: 75,
limit: 100,
entitlement: "entitled",
},
},
},
},
};
export const HighLicenseUtilization: Story = {
args: {
entitlements: {
...MockEntitlementsWithUserLimit,
features: {
...MockEntitlementsWithUserLimit.features,
user_limit: {
...MockEntitlementsWithUserLimit.features.user_limit,
enabled: true,
actual: 95,
limit: 100,
entitlement: "entitled",
},
},
},
},
};
export const ExceedsLicenseUtilization: Story = {
args: {
entitlements: {
...MockEntitlementsWithUserLimit,
features: {
...MockEntitlementsWithUserLimit.features,
user_limit: {
...MockEntitlementsWithUserLimit.features.user_limit,
enabled: true,
actual: 100,
limit: 95,
entitlement: "entitled",
},
},
},
},
};
export const NoLicenseLimit: Story = {
args: {
entitlements: {
...MockEntitlementsWithUserLimit,
features: {
...MockEntitlementsWithUserLimit.features,
user_limit: {
...MockEntitlementsWithUserLimit.features.user_limit,
enabled: false,
actual: 0,
limit: 0,
entitlement: "entitled",
},
},
},
},
};
@@ -1,4 +1,5 @@
import AlertTitle from "@mui/material/AlertTitle";
import LinearProgress from "@mui/material/LinearProgress";
import type {
DAUsResponse,
Entitlements,
@@ -36,6 +37,12 @@ export const GeneralSettingsPageView: FC<GeneralSettingsPageViewProps> = ({
safeExperiments,
invalidExperiments,
}) => {
const licenseUtilizationPercentage =
entitlements?.features?.user_limit?.actual &&
entitlements?.features?.user_limit?.limit
? entitlements.features.user_limit.actual /
entitlements.features.user_limit.limit
: undefined;
return (
<>
<SettingsHeader
@@ -54,6 +61,37 @@ export const GeneralSettingsPageView: FC<GeneralSettingsPageViewProps> = ({
</ChartSection>
</div>
)}
{licenseUtilizationPercentage && (
<ChartSection title="License Utilization">
<LinearProgress
variant="determinate"
value={Math.min(licenseUtilizationPercentage * 100, 100)}
color={
licenseUtilizationPercentage < 0.9
? "primary"
: licenseUtilizationPercentage < 1
? "warning"
: "error"
}
css={{
height: 24,
borderRadius: 4,
marginBottom: 8,
}}
/>
<span
css={{
fontSize: "0.75rem",
display: "block",
textAlign: "right",
}}
>
{Math.round(licenseUtilizationPercentage * 100)}% used (
{entitlements!.features.user_limit.actual}/
{entitlements!.features.user_limit.limit} users)
</span>
</ChartSection>
)}
{invalidExperiments.length > 0 && (
<Alert severity="warning">
<AlertTitle>Invalid experiments in use:</AlertTitle>