mirror of
https://github.com/coder/coder.git
synced 2026-09-22 05:05:20 +08:00
refactor(site): refactor DAU chart to avoid seat consumption focus (#15307)
Related to [https://github.com/coder/coder/issues/15297](https://github.com/coder/coder/issues/15297#issuecomment-2450052538) - Clearly display this as Daily Active Users - Remove the user limit bar at the top for licensed deployments - Explain in the tooltip that this is for measuring user activity and has no connection to license consumption
This commit is contained in:
@@ -22,9 +22,3 @@ export default meta;
|
||||
type Story = StoryObj<typeof ActiveUserChart>;
|
||||
|
||||
export const Example: Story = {};
|
||||
|
||||
export const UserLimit: Story = {
|
||||
args: {
|
||||
userLimit: 10,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -14,7 +14,6 @@ import {
|
||||
Tooltip,
|
||||
defaults,
|
||||
} from "chart.js";
|
||||
import annotationPlugin from "chartjs-plugin-annotation";
|
||||
import {
|
||||
HelpTooltip,
|
||||
HelpTooltipContent,
|
||||
@@ -36,21 +35,16 @@ ChartJS.register(
|
||||
Title,
|
||||
Tooltip,
|
||||
Legend,
|
||||
annotationPlugin,
|
||||
);
|
||||
|
||||
const USER_LIMIT_DISPLAY_THRESHOLD = 60;
|
||||
|
||||
export interface ActiveUserChartProps {
|
||||
data: readonly { date: string; amount: number }[];
|
||||
interval: "day" | "week";
|
||||
userLimit: number | undefined;
|
||||
}
|
||||
|
||||
export const ActiveUserChart: FC<ActiveUserChartProps> = ({
|
||||
data,
|
||||
interval,
|
||||
userLimit,
|
||||
}) => {
|
||||
const theme = useTheme();
|
||||
|
||||
@@ -64,24 +58,6 @@ export const ActiveUserChart: FC<ActiveUserChartProps> = ({
|
||||
responsive: true,
|
||||
animation: false,
|
||||
plugins: {
|
||||
annotation: {
|
||||
annotations: [
|
||||
{
|
||||
type: "line",
|
||||
scaleID: "y",
|
||||
display: shouldDisplayUserLimit(userLimit, chartData),
|
||||
value: userLimit,
|
||||
borderColor: theme.palette.secondary.contrastText,
|
||||
borderWidth: 5,
|
||||
label: {
|
||||
content: "User limit",
|
||||
color: theme.palette.primary.contrastText,
|
||||
display: true,
|
||||
font: { weight: "normal" },
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
legend: {
|
||||
display: false,
|
||||
},
|
||||
@@ -103,7 +79,6 @@ export const ActiveUserChart: FC<ActiveUserChartProps> = ({
|
||||
precision: 0,
|
||||
},
|
||||
},
|
||||
|
||||
x: {
|
||||
grid: { color: theme.palette.divider },
|
||||
ticks: {
|
||||
@@ -138,32 +113,26 @@ export const ActiveUserChart: FC<ActiveUserChartProps> = ({
|
||||
);
|
||||
};
|
||||
|
||||
export const ActiveUsersTitle: FC = () => {
|
||||
type ActiveUsersTitleProps = {
|
||||
interval: "day" | "week";
|
||||
};
|
||||
|
||||
export const ActiveUsersTitle: FC<ActiveUsersTitleProps> = ({ interval }) => {
|
||||
return (
|
||||
<div css={{ display: "flex", alignItems: "center", gap: 8 }}>
|
||||
Active Users
|
||||
{interval === "day" ? "Daily" : "Weekly"} Active Users
|
||||
<HelpTooltip>
|
||||
<HelpTooltipTrigger size="small" />
|
||||
<HelpTooltipContent>
|
||||
<HelpTooltipTitle>How do we calculate active users?</HelpTooltipTitle>
|
||||
<HelpTooltipText>
|
||||
When a connection is initiated to a user's workspace they are
|
||||
considered an active user. e.g. apps, web terminal, SSH
|
||||
considered an active user. e.g. apps, web terminal, SSH. This is for
|
||||
measuring user activity and has no connection to license
|
||||
consumption.
|
||||
</HelpTooltipText>
|
||||
</HelpTooltipContent>
|
||||
</HelpTooltip>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
function shouldDisplayUserLimit(
|
||||
userLimit: number | undefined,
|
||||
activeUsers: number[],
|
||||
): boolean {
|
||||
if (!userLimit || activeUsers.length === 0) {
|
||||
return false;
|
||||
}
|
||||
return (
|
||||
Math.max(...activeUsers) >= (userLimit * USER_LIMIT_DISPLAY_THRESHOLD) / 100
|
||||
);
|
||||
}
|
||||
|
||||
-7
@@ -50,13 +50,6 @@ type Story = StoryObj<typeof GeneralSettingsPageView>;
|
||||
|
||||
export const Page: Story = {};
|
||||
|
||||
export const WithUserLimit: Story = {
|
||||
args: {
|
||||
deploymentDAUs: MockDeploymentDAUResponse,
|
||||
entitlements: MockEntitlementsWithUserLimit,
|
||||
},
|
||||
};
|
||||
|
||||
export const NoDAUs: Story = {
|
||||
args: {
|
||||
deploymentDAUs: undefined,
|
||||
|
||||
+2
-10
@@ -49,16 +49,8 @@ export const GeneralSettingsPageView: FC<GeneralSettingsPageViewProps> = ({
|
||||
)}
|
||||
{deploymentDAUs && (
|
||||
<div css={{ marginBottom: 24, height: 200 }}>
|
||||
<ChartSection title={<ActiveUsersTitle />}>
|
||||
<ActiveUserChart
|
||||
data={deploymentDAUs.entries}
|
||||
interval="day"
|
||||
userLimit={
|
||||
entitlements?.features.user_limit.enabled
|
||||
? entitlements?.features.user_limit.limit
|
||||
: undefined
|
||||
}
|
||||
/>
|
||||
<ChartSection title={<ActiveUsersTitle interval="day" />}>
|
||||
<ActiveUserChart data={deploymentDAUs.entries} interval="day" />
|
||||
</ChartSection>
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -868,11 +868,3 @@ export const Loaded: Story = {
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export const LoadedWithUserLimit: Story = {
|
||||
...Loaded,
|
||||
args: {
|
||||
...Loaded.args,
|
||||
entitlements: MockEntitlementsWithUserLimit,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -249,7 +249,7 @@ const ActiveUsersPanel: FC<ActiveUsersPanelProps> = ({
|
||||
<Panel {...panelProps}>
|
||||
<PanelHeader>
|
||||
<PanelTitle>
|
||||
<ActiveUsersTitle />
|
||||
<ActiveUsersTitle interval={interval} />
|
||||
</PanelTitle>
|
||||
</PanelHeader>
|
||||
<PanelContent>
|
||||
@@ -258,7 +258,6 @@ const ActiveUsersPanel: FC<ActiveUsersPanelProps> = ({
|
||||
{data && data.length > 0 && (
|
||||
<ActiveUserChart
|
||||
interval={interval}
|
||||
userLimit={userLimit}
|
||||
data={data.map((d) => ({
|
||||
amount: d.active_users,
|
||||
date: d.start_time,
|
||||
|
||||
Reference in New Issue
Block a user