mirror of
https://github.com/OpenHands/OpenHands.git
synced 2026-03-22 13:47:19 +08:00
This PR adds a Usage page to the Settings menu that displays organization
usage statistics including:
- Total number of conversations
- Number of merged PRs
- Average cost per conversation
- A chart showing conversation counts over the last 90 days
The page is only visible to users with admin or owner roles in team organizations.
Backend changes:
- Add /api/organizations/{org_id}/usage endpoint in enterprise/server/routes/usage.py
- Register usage_router in enterprise/saas_server.py
Frontend changes:
- Add usage-service API client and types
- Add useUsageStats React Query hook
- Add Usage nav item to settings navigation (admin/owner only, team orgs only)
- Create usage-settings.tsx page with stat cards and conversation chart
- Add i18n translations for Usage page (all supported languages)
- Add route configuration for /settings/usage
Co-authored-by: openhands <openhands@all-hands.dev>
66 lines
2.2 KiB
TypeScript
66 lines
2.2 KiB
TypeScript
import { useConfig } from "#/hooks/query/use-config";
|
|
import {
|
|
SAAS_NAV_ITEMS,
|
|
OSS_NAV_ITEMS,
|
|
SettingsNavItem,
|
|
} from "#/constants/settings-nav";
|
|
import { OrganizationUserRole } from "#/types/org";
|
|
import { isBillingHidden } from "#/utils/org/billing-visibility";
|
|
import { isSettingsPageHidden } from "#/utils/settings-utils";
|
|
import { useMe } from "./query/use-me";
|
|
import { usePermission } from "./organizations/use-permissions";
|
|
import { useOrgTypeAndAccess } from "./use-org-type-and-access";
|
|
|
|
/**
|
|
* Build Settings navigation items based on:
|
|
* - app mode (saas / oss)
|
|
* - feature flags
|
|
* - active user's role
|
|
* - org type (personal vs team)
|
|
* @returns Settings Nav Items []
|
|
*/
|
|
export function useSettingsNavItems(): SettingsNavItem[] {
|
|
const { data: config } = useConfig();
|
|
const { data: user } = useMe();
|
|
const userRole: OrganizationUserRole = user?.role ?? "member";
|
|
const { hasPermission } = usePermission(userRole);
|
|
const { isPersonalOrg, isTeamOrg, organizationId } = useOrgTypeAndAccess();
|
|
|
|
const shouldHideBilling = isBillingHidden(
|
|
config,
|
|
hasPermission("view_billing"),
|
|
);
|
|
const isSaasMode = config?.app_mode === "saas";
|
|
const featureFlags = config?.feature_flags;
|
|
|
|
let items = isSaasMode ? SAAS_NAV_ITEMS : OSS_NAV_ITEMS;
|
|
|
|
// First apply feature flag-based hiding
|
|
items = items.filter((item) => !isSettingsPageHidden(item.to, featureFlags));
|
|
|
|
// Hide billing when billing is not accessible OR when in team org
|
|
if (shouldHideBilling || isTeamOrg) {
|
|
items = items.filter((item) => item.to !== "/settings/billing");
|
|
}
|
|
|
|
// Hide org routes for personal orgs, missing permissions, or no org selected
|
|
if (!hasPermission("view_billing") || !organizationId || isPersonalOrg) {
|
|
items = items.filter((item) => item.to !== "/settings/org");
|
|
}
|
|
|
|
if (
|
|
!hasPermission("invite_user_to_organization") ||
|
|
!organizationId ||
|
|
isPersonalOrg
|
|
) {
|
|
items = items.filter((item) => item.to !== "/settings/org-members");
|
|
}
|
|
|
|
// Hide usage page for users without view_billing permission or personal orgs
|
|
if (!hasPermission("view_billing") || !organizationId || isPersonalOrg) {
|
|
items = items.filter((item) => item.to !== "/settings/usage");
|
|
}
|
|
|
|
return items;
|
|
}
|